sbDeviceXMLInfo.cpp
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 :miv */
3 /*
4  *=BEGIN SONGBIRD GPL
5  *
6  * This file is part of the Songbird web player.
7  *
8  * Copyright(c) 2005-2010 POTI, Inc.
9  * http://www.songbirdnest.com
10  *
11  * This file may be licensed under the terms of of the
12  * GNU General Public License Version 2 (the ``GPL'').
13  *
14  * Software distributed under the License is distributed
15  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
16  * express or implied. See the GPL for the specific language
17  * governing rights and limitations.
18  *
19  * You should have received a copy of the GPL along with this
20  * program. If not, go to http://www.gnu.org/licenses/gpl.html
21  * or write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  *=END SONGBIRD GPL
25  */
26 
27 //------------------------------------------------------------------------------
28 //------------------------------------------------------------------------------
29 //
30 // Songbird device XML info.
31 //
32 //------------------------------------------------------------------------------
33 //------------------------------------------------------------------------------
34 
40 //------------------------------------------------------------------------------
41 //
42 // Songbird device XML info imported services.
43 //
44 //------------------------------------------------------------------------------
45 
46 // Self imports.
47 #include "sbDeviceXMLInfo.h"
48 
49 // Local imports
50 #include "sbDeviceUtils.h"
51 
52 // Songbird imports.
53 #include <sbErrorConsole.h>
54 #include <sbFileUtils.h>
55 #include <sbIDeviceProperties.h>
56 #include <sbIDirectoryEnumerator.h>
58 #include <sbStringUtils.h>
59 #include <sbURIUtils.h>
60 #include <sbVariantUtils.h>
61 #include <sbVariantUtilsLib.h>
62 
63 // Mozilla imports.
64 #include <nsIDOMNamedNodeMap.h>
65 #include <nsIDOMNodeList.h>
66 #include <nsIDOMParser.h>
67 #include <nsIDOMSerializer.h>
68 #include <nsIMutableArray.h>
69 #include <nsIPropertyBag2.h>
70 #include <nsIScriptSecurityManager.h>
71 #include <nsISupportsPrimitives.h>
72 #include <nsIWritablePropertyBag.h>
73 #include <nsIXMLHttpRequest.h>
74 #include <nsMemory.h>
75 #include <nsNetUtil.h>
76 #include <nsServiceManagerUtils.h>
77 #include <nsThreadUtils.h>
78 #include <nsUnicharUtils.h>
79 #include <nsVersionComparator.h>
80 #include <prprf.h>
81 
82 //------------------------------------------------------------------------------
83 //
84 // Public Songbird device XML info services.
85 //
86 //------------------------------------------------------------------------------
87 
88 //-------------------------------------
89 //
90 // Read
91 //
92 
93 nsresult sbDeviceXMLInfo::Read(const char* aDeviceXMLInfoSpecList,
94  const char* aExtensionsList)
95 {
96  NS_ENSURE_ARG_POINTER(aDeviceXMLInfoSpecList);
97 
98  nsresult rv;
99 
100  Log("URI list:\n%s", aDeviceXMLInfoSpecList);
101 
102  // aDeviceXMLInfoSpecList is a space-delimited list of URI strings.
103  // Split it out into an array:
104  nsTArray<nsCString> uris;
105  nsCString_Split(nsDependentCString(aDeviceXMLInfoSpecList),
106  NS_LITERAL_CSTRING(" "),
107  uris);
108 
109  if (!aExtensionsList) {
110  aExtensionsList = "";
111  }
112 
113  // Iterate over the strings and convert each one to a URI to
114  // load device XML info from:
115  const PRUint32 COUNT = uris.Length();
116  for (PRUint32 i = 0; i < COUNT; i++) {
117  const nsCString & uriStr = uris[i];
118 
119  // Skip empty strings:
120  if (uriStr.IsEmpty()) {
121  continue;
122  }
123 
124  // Create an nsIURI:
125  nsCOMPtr<nsIURI> uri;
126  rv = SB_NewURI(getter_AddRefs(uri), uriStr);
127  LogIfFailed(rv, "Invalid URI\n%s", uriStr.get());
128  NS_ENSURE_SUCCESS(rv, rv);
129 
130  // Scan the specified file or directory:
131  rv = Read(uri, NS_ConvertUTF8toUTF16(nsDependentCString(aExtensionsList)));
132  LogIfFailed(rv, "while reading device info from\n%s", uriStr.get());
133  NS_ENSURE_SUCCESS(rv, rv);
134  }
135 
136  return NS_OK;
137 }
138 
139 //-------------------------------------
140 //
141 // Read
142 //
143 
144 nsresult sbDeviceXMLInfo::Read(nsIURI * aDeviceXMLInfoURI,
145  const nsAString & aExtensionsList)
146 {
147  NS_ENSURE_ARG_POINTER(aDeviceXMLInfoURI);
148 
149  nsresult rv;
150 
151  nsCString spec;
152  rv = aDeviceXMLInfoURI->GetSpec(spec);
153  Log("Reading %s", spec.BeginReading());
154 
155  // If the URI is a file URL, pass it to the nsIFile variant of
156  // this function, which has logic to scan directories:
157  nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(aDeviceXMLInfoURI);
158  if (fileUrl) {
159  nsCOMPtr<nsIFile> file;
160  rv = fileUrl->GetFile(getter_AddRefs(file));
161  NS_ENSURE_SUCCESS(rv, rv);
162 
163  rv = Read(file, aExtensionsList);
164  NS_ENSURE_SUCCESS(rv, rv);
165  return NS_OK;
166  }
167 
168  // Open a stream to parse:
169  nsCOMPtr<nsIInputStream> inputStream;
170  rv = NS_OpenURI(getter_AddRefs(inputStream), aDeviceXMLInfoURI);
171  NS_ENSURE_SUCCESS(rv, rv);
172 
173  // Parse the stream and close it:
174  rv = Read(inputStream);
175  inputStream->Close();
176  NS_ENSURE_SUCCESS(rv, rv);
177 
178  return NS_OK;
179 }
180 
181 
182 //-------------------------------------
183 //
184 // Read
185 //
186 
187 nsresult sbDeviceXMLInfo::Read(nsIFile * aDeviceXMLInfoFile,
188  const nsAString & aExtensionsList)
189 {
190  NS_ENSURE_ARG_POINTER(aDeviceXMLInfoFile);
191 
192  nsresult rv;
193 
194  nsString path;
195  rv = aDeviceXMLInfoFile->GetPath(path);
196  if (NS_FAILED(rv)) {
197  path = NS_LITERAL_STRING("Unknown path");
198  }
199 
200  // If aDeviceXMLInfoFile is a directory, scan it recursively for
201  // device XML info files:
202  PRBool isDir = PR_FALSE;
203  rv = aDeviceXMLInfoFile->IsDirectory(&isDir);
204  NS_ENSURE_SUCCESS(rv, rv);
205  if (isDir) {
206  Log("Searching directory %s",
207  NS_LossyConvertUTF16toASCII(path).BeginReading());
208  // aExtensionsList is a space-delimited list of extensions
209  // (e.g., "ex1 ex2 ex3"). Trim any surrounding spaces and
210  // don't scan the directory if the result is empty:
211  nsString acceptExts(aExtensionsList);
212  acceptExts.Trim(" ");
213  Log("Extension List: %s",
214  NS_LossyConvertUTF16toASCII(acceptExts).BeginReading());
215  if (acceptExts.IsEmpty()) {
216  return NS_OK;
217  }
218 
219  // Normalize the extensions list for the comparison logic below.
220  // That is, lower case with spaces before the first extension and
221  // after the last:
222  ToLowerCase(acceptExts);
223  acceptExts.Insert(' ', 0);
224  acceptExts.Append(' ');
225 
226  // Prepare to recursively enumerate all files in the directory:
227  nsCOMPtr<sbIDirectoryEnumerator> scanner =
228  do_CreateInstance(SB_DIRECTORYENUMERATOR_CONTRACTID, &rv);
229  NS_ENSURE_SUCCESS(rv, rv);
230 
231  rv = scanner->SetFilesOnly(PR_TRUE);
232  NS_ENSURE_SUCCESS(rv, rv);
233  rv = scanner->Enumerate(aDeviceXMLInfoFile);
234  NS_ENSURE_SUCCESS(rv, rv);
235 
236  // Enumerate files and filter by extension:
237  PRBool more = PR_FALSE;
238  while(NS_SUCCEEDED(rv = scanner->HasMoreElements(&more)) && more)
239  {
240  // Get the next file:
241  nsCOMPtr<nsIFile> child;
242  rv = scanner->GetNext(getter_AddRefs(child));
243  NS_ENSURE_SUCCESS(rv, rv);
244 
245  // Get its extension and normalize it for comparison:
246  nsString extension;
247  rv = child->GetLeafName(extension);
248  NS_ENSURE_SUCCESS(rv, rv);
249  extension.Cut(0, extension.RFindChar('.') + 1);
250  ToLowerCase(extension);
251  extension.Insert(' ', 0);
252  extension.Append(' ');
253 
254  // Read the file if its extension is on the accept list.
255  // Warn about errors, but keep looping:
256  if (acceptExts.Find(extension) != -1) {
257  rv = Read(child, aExtensionsList);
258  NS_WARN_IF_FALSE(
259  NS_SUCCEEDED(rv),
260  "Could not read device XML info from file in search directory");
261  }
262  }
263  NS_ENSURE_SUCCESS(rv, rv);
264  return NS_OK;
265  }
266 
267  // Open a stream to parse:
268  nsCOMPtr<nsIInputStream> inputStream;
269  rv = sbOpenInputStream(aDeviceXMLInfoFile, getter_AddRefs(inputStream));
270  NS_ENSURE_SUCCESS(rv, rv);
271 
272  Log("Parsing file %s",
273  NS_LossyConvertUTF16toASCII(path).BeginReading());
274  // Parse the stream and close it:
275  rv = Read(inputStream);
276  inputStream->Close();
277  NS_ENSURE_SUCCESS(rv, rv);
278 
279  return NS_OK;
280 }
281 
282 //-------------------------------------
283 //
284 // Read
285 //
286 
287 nsresult sbDeviceXMLInfo::Read(nsIInputStream* aDeviceXMLInfoStream)
288 {
289  NS_ENSURE_ARG_POINTER(aDeviceXMLInfoStream);
290 
291  nsresult rv = NS_ERROR_UNEXPECTED;
292  nsCOMPtr<nsIDOMParser> parser =
293  do_CreateInstance(NS_DOMPARSER_CONTRACTID, &rv);
294  NS_ENSURE_SUCCESS(rv, rv);
295 
296  PRUint32 streamSize = 0;
297  rv = aDeviceXMLInfoStream->Available(&streamSize);
298  NS_ENSURE_SUCCESS(rv, rv);
299 
300  nsCOMPtr<nsIDOMDocument> document;
301  rv = parser->ParseFromStream(aDeviceXMLInfoStream,
302  nsnull,
303  streamSize,
304  "text/xml",
305  getter_AddRefs(document));
306  NS_ENSURE_SUCCESS(rv, rv);
307 
308  rv = Read(document);
309  NS_ENSURE_SUCCESS(rv, rv);
310 
311  return NS_OK;
312 }
313 
314 //-------------------------------------
315 //
316 // Read
317 //
318 
319 nsresult sbDeviceXMLInfo::Read(nsIDOMDocument* aDeviceXMLInfoDocument)
320 {
321  // Validate arguments.
322  NS_ENSURE_ARG_POINTER(aDeviceXMLInfoDocument);
323 
324  // Function variables.
325  nsresult rv;
326 
327  // Get the list of all device info elements.
328  nsCOMPtr<nsIDOMNodeList> nodeList;
329  rv = aDeviceXMLInfoDocument->GetElementsByTagNameNS
330  (NS_LITERAL_STRING(SB_DEVICE_INFO_NS),
331  NS_LITERAL_STRING("deviceinfo"),
332  getter_AddRefs(nodeList));
333  NS_ENSURE_SUCCESS(rv, rv);
334 
335  // Search all device info elements for one that matches target device.
336  PRUint32 nodeCount;
337  rv = nodeList->GetLength(&nodeCount);
338  NS_ENSURE_SUCCESS(rv, rv);
339  for (PRUint32 i = 0; i < nodeCount; i++) {
340  // Get the next device info element.
341  nsCOMPtr<nsIDOMNode> node;
342  rv = nodeList->Item(i, getter_AddRefs(node));
343  NS_ENSURE_SUCCESS(rv, rv);
344 
345  // Use device info node if it matches target device and is
346  // newer than any previous match
347  nsString foundVersion;
348  nsCOMPtr<nsIDOMNode> deviceNode;
349  rv = DeviceMatchesDeviceInfoNode(node,
350  foundVersion,
351  getter_AddRefs(deviceNode));
352  NS_ENSURE_SUCCESS(rv, rv);
353  if (foundVersion.IsEmpty()) {
354  // Not a match
355  continue;
356  }
357 
358  if (mDeviceInfoVersion.IsEmpty() ||
359  NS_CompareVersions(
360  NS_LossyConvertUTF16toASCII(foundVersion).get(),
361  NS_LossyConvertUTF16toASCII(mDeviceInfoVersion).get()) > 0)
362  {
363  // Found version is greater than current version, if any. Keep this
364  // node and replace any previously found node
365 
366  // Log the found device info if logging enabled
367  if (mLogDeviceInfo) {
368  nsCOMPtr<nsIDOMSerializer> serializer =
369  do_CreateInstance("@mozilla.org/xmlextras/xmlserializer;1");
370 
371  // Translate the found deviceinfo element to XML
372  nsString fullXml(NS_LITERAL_STRING("<ERROR PRINTING deviceinfo NODE>"));
373  if (serializer) {
374  serializer->SerializeToString(node, fullXml);
375  }
376 
377  // Translate the device element matching this device to XML, if any
378  nsString deviceXml(NS_LITERAL_STRING("<ERROR PRINTING device NODE>"));
379  if (deviceNode && serializer) {
380  serializer->SerializeToString(deviceNode, deviceXml);
381  }
382 
383  nsCAutoString curVersUtf8 = NS_ConvertUTF16toUTF8(mDeviceInfoVersion);
384  nsCAutoString foundVersUtf8 = NS_ConvertUTF16toUTF8(foundVersion);
385 
386  // Log the device info and version. The first line has two
387  // alternate forms, depending on whether the existing device
388  // info is being replaced:
389  //
390  // FOUND deviceinfo version <found version>:
391  // - OR -
392  // REPLACED deviceinfo version <current version> with <found version>:
393 
394  Log("%s deviceinfo version %s%s%s:\n%s%s%s",
395  mDeviceInfoElement ? "REPLACED" : "FOUND",
396  curVersUtf8.get(), // current version OR blank
397  mDeviceInfoElement ? " with " : "",
398  foundVersUtf8.get(), // found version OR found version
399 
400  NS_ConvertUTF16toUTF8(fullXml).get(),
401 
402  deviceNode ? "\n\nMATCHING device element:\n" : "",
403  deviceNode ? NS_ConvertUTF16toUTF8(deviceXml).get() : "");
404  }
405 
406  mDeviceInfoVersion.Assign(foundVersion);
407  mDeviceInfoElement = do_QueryInterface(node, &rv);
408  NS_ENSURE_SUCCESS(rv, rv);
409  if (deviceNode) {
410  mDeviceElement = do_QueryInterface(deviceNode, &rv);
411  NS_ENSURE_SUCCESS(rv, rv);
412  }
413  else {
414  mDeviceElement = nsnull;
415  }
416  }
417  }
418 
419  return NS_OK;
420 }
421 
422 
423 //-------------------------------------
424 //
425 // GetDeviceInfoPresent
426 //
427 
428 nsresult
429 sbDeviceXMLInfo::GetDeviceInfoPresent(PRBool* aDeviceInfoPresent)
430 {
431  // Validate arguments.
432  NS_ENSURE_ARG_POINTER(aDeviceInfoPresent);
433 
434  // Device info is present if the device info element is available.
435  if (mDeviceInfoElement)
436  *aDeviceInfoPresent = PR_TRUE;
437  else
438  *aDeviceInfoPresent = PR_FALSE;
439 
440  return NS_OK;
441 }
442 
443 
444 //-------------------------------------
445 //
446 // GetDeviceInfoElement
447 //
448 
449 nsresult
450 sbDeviceXMLInfo::GetDeviceInfoElement(nsIDOMElement** aDeviceInfoElement)
451 {
452  NS_ENSURE_ARG_POINTER(aDeviceInfoElement);
453  NS_IF_ADDREF(*aDeviceInfoElement = mDeviceInfoElement);
454  return NS_OK;
455 }
456 
457 //-------------------------------------
458 //
459 // GetDefaultName
460 //
461 
462 nsresult
463 sbDeviceXMLInfo::GetDefaultName(nsAString& aDefaultName)
464 {
465  nsresult rv;
466 
467  aDefaultName.SetIsVoid(PR_TRUE);
468 
469  // Do nothing more if no device info element.
470  if (!mDeviceInfoElement)
471  return NS_OK;
472 
473  nsTArray< nsCOMPtr<nsIDOMNode> > deviceNameNodeList;
474  rv = GetDeviceInfoNodes(NS_LITERAL_STRING("name"),
475  deviceNameNodeList);
476  NS_ENSURE_SUCCESS(rv, rv);
477 
478  // See if there is at least one node.
479  PRUint32 nodeCount = deviceNameNodeList.Length();
480 
481  if (nodeCount > 0) {
482  // Only process the first node value.
483  nsCOMPtr<nsIDOMElement> deviceNameElement =
484  do_QueryInterface(deviceNameNodeList[0], &rv);
485  NS_ENSURE_SUCCESS(rv, rv);
486 
487  // Read the value
488  rv = deviceNameElement->GetAttribute(NS_LITERAL_STRING("value"),
489  aDefaultName);
490  NS_ENSURE_SUCCESS(rv, rv);
491  }
492 
493  return NS_OK;
494 }
495 
496 //-------------------------------------
497 //
498 // GetDeviceFolder
499 //
500 
501 nsresult
502 sbDeviceXMLInfo::GetDeviceFolder(const nsAString& aFolderType,
503  nsAString& aFolderURL)
504 {
505  nsresult rv;
506 
507  // Default to no folder.
508  aFolderURL.SetIsVoid(PR_TRUE);
509 
510  // Do nothing more if no device info element.
511  if (!mDeviceInfoElement)
512  return NS_OK;
513 
514  // Get the list of folder nodes.
515  nsTArray< nsCOMPtr<nsIDOMNode> > folderNodeList;
516  rv = GetDeviceInfoNodes(NS_LITERAL_STRING("folder"), folderNodeList);
517  NS_ENSURE_SUCCESS(rv, rv);
518 
519  // Search for a matching folder element.
520  PRUint32 nodeCount = folderNodeList.Length();
521  for (PRUint32 i = 0; i < nodeCount; i++) {
522  // Get the next folder element.
523  nsCOMPtr<nsIDOMElement> folderElement;
524  folderElement = do_QueryInterface(folderNodeList[i], &rv);
525  if (NS_FAILED(rv))
526  continue;
527 
528  // Return folder URL if the folder element is of the specified type.
529  nsAutoString folderType;
530  rv = folderElement->GetAttribute(NS_LITERAL_STRING("type"), folderType);
531  if (NS_FAILED(rv))
532  continue;
533  if (folderType.Equals(aFolderType)) {
534  rv = folderElement->GetAttribute(NS_LITERAL_STRING("url"), aFolderURL);
535  NS_ENSURE_SUCCESS(rv, rv);
536  return NS_OK;
537  }
538  }
539 
540  return NS_OK;
541 }
542 
543 
544 //-------------------------------------
545 //
546 // GetDeviceFolder
547 //
548 
549 nsresult
550 sbDeviceXMLInfo::GetDeviceFolder(PRUint32 aContentType,
551  nsAString& aFolderURL)
552 {
553  nsresult rv;
554 
555  // Map from content type to device XML info folder element type.
556  static const char* folderContentTypeMap[] = {
557  "",
558  "",
559  "",
560  "music",
561  "photo",
562  "video",
563  "playlist",
564  "album"
565  };
566 
567  // Default to no folder.
568  aFolderURL.Truncate();
569 
570  // Validate content type.
571  if (aContentType >= NS_ARRAY_LENGTH(folderContentTypeMap))
572  return NS_OK;
573 
574  // Get the folder type.
575  nsAutoString folderType;
576  folderType.AssignLiteral(folderContentTypeMap[aContentType]);
577  if (folderType.IsEmpty())
578  return NS_OK;
579 
580  // Get the device folder URL.
581  rv = GetDeviceFolder(folderType, aFolderURL);
582  NS_ENSURE_SUCCESS(rv, rv);
583 
584  return NS_OK;
585 }
586 
587 //-------------------------------------
588 //
589 // GetImportRules
590 //
591 
592 nsresult
593 sbDeviceXMLInfo::GetImportRules(nsIArray ** aImportRules)
594 {
595  NS_ENSURE_ARG_POINTER(aImportRules);
596 
597  nsresult rv;
598 
599  // Default to no rules:
600  *aImportRules = NULL;
601 
602  // Do nothing more if no device info element.
603  if (!mDeviceInfoElement) {
604  return NS_OK;
605  }
606 
607  // Each import rule is defined by an element of the form
608  //
609  // <import url="..." type="..." />
610  //
611  // Get the list of import nodes:
612  nsTArray< nsCOMPtr<nsIDOMNode> > importNodeList;
613  rv = GetDeviceInfoNodes(NS_LITERAL_STRING("import"), importNodeList);
614  NS_ENSURE_SUCCESS(rv, rv);
615 
616  // Create the result array. The result will be an array of import
617  // rules, where each rule is itself an array of two strings: a path
618  // and the import type of files residing (recursively) within that
619  // path:
620  nsCOMPtr<nsIMutableArray> rules =
621  do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
622  NS_ENSURE_SUCCESS(rv, rv);
623 
624  // Iterate through the import nodes and assemble the result array:
625  PRUint32 nodeCount = importNodeList.Length();
626  for (PRUint32 i = 0; i < nodeCount; i++) {
627  // Get the next import element:
628  nsCOMPtr<nsIDOMElement> importElement;
629  importElement = do_QueryInterface(importNodeList[i], &rv);
630  if (NS_FAILED(rv))
631  continue;
632 
633  // Get the folder path from the url attribute. Skip if
634  // empty or unavailable:
635  nsAutoString urlAttr;
636  rv = importElement->GetAttribute(NS_LITERAL_STRING("url"), urlAttr);
637  if (NS_FAILED(rv))
638  continue;
639  if (urlAttr.IsEmpty())
640  continue;
641 
642  // Get the import type. Skip if empty or unavailable:
643  nsAutoString typeAttr;
644  rv = importElement->GetAttribute(NS_LITERAL_STRING("type"), typeAttr);
645  if (NS_FAILED(rv))
646  continue;
647  if (typeAttr.IsEmpty())
648  continue;
649 
650  // Create an array for this import rule:
651  nsCOMPtr<nsIMutableArray> rule =
652  do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
653  NS_ENSURE_SUCCESS(rv, rv);
654 
655  // Append the folder path as the first element of the rule:
656  nsCOMPtr<nsISupportsString> folder =
657  do_CreateInstance("@mozilla.org/supports-string;1", &rv);
658  NS_ENSURE_SUCCESS(rv, rv);
659  rv = folder->SetData(urlAttr);
660  NS_ENSURE_SUCCESS(rv, rv);
661  rv = rule->AppendElement(folder, PR_FALSE);
662  NS_ENSURE_SUCCESS(rv, rv);
663 
664  // Append the import type as the second element of the rule:
665  nsCOMPtr<nsISupportsString> importType =
666  do_CreateInstance("@mozilla.org/supports-string;1", &rv);
667  NS_ENSURE_SUCCESS(rv, rv);
668  rv = importType->SetData(typeAttr);
669  NS_ENSURE_SUCCESS(rv, rv);
670  rv = rule->AppendElement(importType, PR_FALSE);
671  NS_ENSURE_SUCCESS(rv, rv);
672 
673  // Append this rule to the result:
674  rv = rules->AppendElement(rule, PR_FALSE);
675  NS_ENSURE_SUCCESS(rv, rv);
676  }
677 
678  // Return the result array:
679  NS_ADDREF(*aImportRules = rules.get());
680 
681  return NS_OK;
682 }
683 
684 //-------------------------------------
685 //
686 // GetExcludedFolders
687 //
688 nsresult
689 sbDeviceXMLInfo::GetExcludedFolders(nsAString & aExcludedFolders)
690 {
691  nsresult rv;
692 
693  aExcludedFolders.Truncate();
694 
695  // Do nothing more if no device info element.
696  if (!mDeviceInfoElement)
697  return NS_OK;
698 
699  // Get the list of exclude folder nodes.
700  nsTArray< nsCOMPtr<nsIDOMNode> > excludeNodeList;
701  rv = GetDeviceInfoNodes(NS_LITERAL_STRING("excludefolder"), excludeNodeList);
702  NS_ENSURE_SUCCESS(rv, rv);
703 
704  // Get all excluded folders.
705  PRUint32 nodeCount = excludeNodeList.Length();
706  const char * delimiter = "";
707  for (PRUint32 i = 0; i < nodeCount; i++) {
708  // Get the next exclude folder element.
709  nsCOMPtr<nsIDOMElement> excludeElement;
710  excludeElement = do_QueryInterface(excludeNodeList[i], &rv);
711  if (NS_SUCCEEDED(rv)) {
712  nsString excludeStr;
713 
714  // The url attribute, if present, will contain a literal path.
715  // Remove any leading slash to distinguish literal paths from
716  // patterns
717  rv = excludeElement->GetAttribute(NS_LITERAL_STRING("url"), excludeStr);
718  NS_ENSURE_SUCCESS(rv, rv);
719  if (excludeStr.Length() > 0 && excludeStr[0] == L'/') {
720  excludeStr.Cut(0, 1);
721  }
722  if (!excludeStr.IsEmpty()) {
723  aExcludedFolders.AppendLiteral(delimiter);
724  aExcludedFolders.Append(excludeStr);
725  delimiter = ",";
726  }
727 
728  // The match attribute, if present, will contain a folder name pattern.
729  // Add a leading and trailing slash to distinguish patterns from literal
730  // paths. The pattern itself may not contain any slashes
731  rv = excludeElement->GetAttribute(NS_LITERAL_STRING("match"), excludeStr);
732  NS_ENSURE_SUCCESS(rv, rv);
733  if (!excludeStr.IsEmpty() && excludeStr.Find("/") == -1) {
734  aExcludedFolders.AppendLiteral(delimiter);
735  aExcludedFolders.AppendLiteral("/");
736  aExcludedFolders.Append(excludeStr);
737  aExcludedFolders.AppendLiteral("/");
738  delimiter = ",";
739  }
740  }
741  }
742  return NS_OK;
743 }
744 
745 
746 //-------------------------------------
747 //
748 // GetMountTimeout
749 //
750 
751 nsresult
752 sbDeviceXMLInfo::GetMountTimeout(PRUint32* aMountTimeout)
753 {
754  // Validate arguments.
755  NS_ENSURE_ARG_POINTER(aMountTimeout);
756 
757  // Function variables.
758  nsresult rv;
759 
760  // Check if a device info element is available.
761  if (!mDeviceInfoElement)
762  return NS_ERROR_NOT_AVAILABLE;
763 
764  // Get the list of mount timeout nodes.
765  nsTArray< nsCOMPtr<nsIDOMNode> > mountTimeoutNodeList;
766  rv = GetDeviceInfoNodes(NS_LITERAL_STRING("mounttimeout"),
767  mountTimeoutNodeList);
768  NS_ENSURE_SUCCESS(rv, rv);
769 
770  // Check if any mount timeout nodes are available.
771  PRUint32 nodeCount = mountTimeoutNodeList.Length();
772  if (!nodeCount)
773  return NS_ERROR_NOT_AVAILABLE;
774 
775  // Get the first mount timeout element.
776  nsCOMPtr<nsIDOMElement> mountTimeoutElement;
777  mountTimeoutElement = do_QueryInterface(mountTimeoutNodeList[0], &rv);
778  NS_ENSURE_SUCCESS(rv, rv);
779 
780  // Read the mount timeout value.
781  nsAutoString mountTimeoutString;
782  rv = mountTimeoutElement->GetAttribute(NS_LITERAL_STRING("value"),
783  mountTimeoutString);
784  NS_ENSURE_SUCCESS(rv, rv);
785 
786  // Return results.
787  PRUint32 mountTimeout;
788  mountTimeout = mountTimeoutString.ToInteger(&rv);
789  NS_ENSURE_SUCCESS(rv, rv);
790  *aMountTimeout = mountTimeout;
791 
792  return NS_OK;
793 }
794 
795 
796 //-------------------------------------
797 //
798 // GetDoesDeviceSupportReformat
799 //
800 
801 nsresult
803 {
804  NS_ENSURE_ARG_POINTER(aOutSupportsReformat);
805  *aOutSupportsReformat = PR_FALSE;
806 
807  // Check if a device info element is available.
808  NS_ENSURE_TRUE(mDeviceInfoElement, NS_ERROR_NOT_AVAILABLE);
809 
810  nsresult rv;
811  nsTArray< nsCOMPtr<nsIDOMNode> > supportsFormatNodeList;
812  rv = GetDeviceInfoNodes(NS_LITERAL_STRING("supportsreformat"),
813  supportsFormatNodeList);
814  NS_ENSURE_SUCCESS(rv, rv);
815 
816  // See if there is at least one node.
817  PRUint32 nodeCount = supportsFormatNodeList.Length();
818 
819  if (nodeCount > 0) {
820  // Only process the first node value.
821  nsCOMPtr<nsIDOMElement> supportsFormatElement =
822  do_QueryInterface(supportsFormatNodeList[0], &rv);
823  NS_ENSURE_SUCCESS(rv, rv);
824 
825  // Read the value
826  nsString supportsFormatValue;
827  rv = supportsFormatElement->GetAttribute(NS_LITERAL_STRING("value"),
828  supportsFormatValue);
829  NS_ENSURE_SUCCESS(rv, rv);
830 
831  if (supportsFormatValue.Equals(NS_LITERAL_STRING("true"),
832  CaseInsensitiveCompare)) {
833  *aOutSupportsReformat = PR_TRUE;
834  }
835  }
836 
837 
838  return NS_OK;
839 }
840 
841 
842 //-------------------------------------
843 //
844 // GetOnlyMountMediaFolders
845 //
846 
847 nsresult
848 sbDeviceXMLInfo::GetOnlyMountMediaFolders(PRBool* aOnlyMountMediaFolders)
849 {
850  // Validate arguments and ensure this is called on the main thread.
851  NS_ENSURE_ARG_POINTER(aOnlyMountMediaFolders);
852  NS_ASSERTION(NS_IsMainThread(), "not on main thread");
853 
854  // Function variables.
855  nsresult rv;
856 
857  // Default to a false result.
858  *aOnlyMountMediaFolders = PR_FALSE;
859 
860  // Check if a device info element is available.
861  if (!mDeviceInfoElement)
862  return NS_OK;
863 
864  // Get the list of "onlymountmediafolders" nodes.
865  nsTArray< nsCOMPtr<nsIDOMNode> > onlyMountMediaFoldersNodeList;
866  rv = GetDeviceInfoNodes(NS_LITERAL_STRING("onlymountmediafolders"),
867  onlyMountMediaFoldersNodeList);
868  NS_ENSURE_SUCCESS(rv, rv);
869 
870  // Check if any "onlymountmediafolders" nodes are available.
871  PRUint32 nodeCount = onlyMountMediaFoldersNodeList.Length();
872  if (!nodeCount)
873  return NS_OK;
874 
875  // Get the first "onlymountmediafolders" element.
876  nsCOMPtr<nsIDOMElement> onlyMountMediaFoldersElement;
877  onlyMountMediaFoldersElement =
878  do_QueryInterface(onlyMountMediaFoldersNodeList[0], &rv);
879  NS_ENSURE_SUCCESS(rv, rv);
880 
881  // Read the "onlymountmediafolders" value.
882  nsAutoString valueString;
883  rv = onlyMountMediaFoldersElement->GetAttribute(NS_LITERAL_STRING("value"),
884  valueString);
885  NS_ENSURE_SUCCESS(rv, rv);
886 
887  // Return results.
888  *aOnlyMountMediaFolders = valueString.Equals(NS_LITERAL_STRING("true"),
889  CaseInsensitiveCompare);
890 
891  return NS_OK;
892 }
893 
894 
895 //-------------------------------------
896 //
897 // GetStorageDeviceInfoList
898 //
899 
900 nsresult
901 sbDeviceXMLInfo::GetStorageDeviceInfoList(nsIArray** aStorageDeviceInfoList)
902 {
903  // Validate arguments and ensure this is called on the main thread.
904  NS_ENSURE_ARG_POINTER(aStorageDeviceInfoList);
905  NS_ASSERTION(NS_IsMainThread(), "not on main thread");
906 
907  // Function variables.
908  nsresult rv;
909 
910  // Check if a device info element is available. There doesn't have to be, so,
911  // if not, just return an error without any warnings.
912  if (!mDeviceInfoElement)
913  return NS_ERROR_NOT_AVAILABLE;
914 
915  // Get the list of storage nodes.
916  nsTArray< nsCOMPtr<nsIDOMNode> > storageNodeList;
917  rv = GetDeviceInfoNodes(NS_LITERAL_STRING("storage"), storageNodeList);
918  NS_ENSURE_SUCCESS(rv, rv);
919 
920  // Create the storage device info list.
921  nsCOMPtr<nsIMutableArray> storageDeviceInfoList =
922  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
923  NS_ENSURE_SUCCESS(rv, rv);
924 
925  // Get the storage device info.
926  PRUint32 nodeCount = storageNodeList.Length();
927  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
928  // Get the storage device node.
929  nsCOMPtr<nsIDOMNode> storageDeviceNode = storageNodeList[nodeIndex];
930 
931  // Get the storage device attributes.
932  nsCOMPtr<nsIDOMNamedNodeMap> attributes;
933  PRUint32 attributeCount;
934  rv = storageDeviceNode->GetAttributes(getter_AddRefs(attributes));
935  NS_ENSURE_SUCCESS(rv, rv);
936  rv = attributes->GetLength(&attributeCount);
937  NS_ENSURE_SUCCESS(rv, rv);
938 
939  // Create the storage device info property bag.
940  nsCOMPtr<nsIWritablePropertyBag> storageDeviceInfo =
941  do_CreateInstance("@mozilla.org/hash-property-bag;1", &rv);
942  NS_ENSURE_SUCCESS(rv, rv);
943 
944  // Get the storage device info.
945  for (PRUint32 attributeIndex = 0;
946  attributeIndex < attributeCount;
947  ++attributeIndex) {
948  // Get the next attribute.
949  nsCOMPtr<nsIDOMNode> attribute;
950  rv = attributes->Item(attributeIndex, getter_AddRefs(attribute));
951  NS_ENSURE_SUCCESS(rv, rv);
952 
953  // Get the attribute name.
954  nsAutoString attributeName;
955  rv = attribute->GetNodeName(attributeName);
956  NS_ENSURE_SUCCESS(rv, rv);
957 
958  // Get the attribute value.
959  nsAutoString attributeValue;
960  rv = attribute->GetNodeValue(attributeValue);
961  NS_ENSURE_SUCCESS(rv, rv);
962 
963  // Set the storage device info.
964  storageDeviceInfo->SetProperty(attributeName,
965  sbNewVariant(attributeValue));
966  NS_ENSURE_SUCCESS(rv, rv);
967  }
968 
969  // Add the storage device info.
970  rv = storageDeviceInfoList->AppendElement(storageDeviceInfo, PR_FALSE);
971  NS_ENSURE_SUCCESS(rv, rv);
972  }
973 
974  // Return results.
975  rv = CallQueryInterface(storageDeviceInfoList, aStorageDeviceInfoList);
976  NS_ENSURE_SUCCESS(rv, rv);
977 
978  return NS_OK;
979 }
980 
981 
982 //-------------------------------------
983 //
984 // GetDeviceIcon
985 //
986 
987 nsresult
988 sbDeviceXMLInfo::GetDeviceIcon(nsAString& aDeviceIconURL)
989 {
990  nsresult rv;
991 
992  // Default to no device icon.
993  aDeviceIconURL.SetIsVoid(PR_TRUE);
994 
995  // Check if a device info element is available.
996  if (!mDeviceInfoElement)
997  return NS_OK;
998 
999  // Get the list of device icon nodes.
1000  nsTArray< nsCOMPtr<nsIDOMNode> > deviceIconNodeList;
1001  rv = GetDeviceInfoNodes(NS_LITERAL_STRING("deviceicon"),
1002  deviceIconNodeList);
1003  NS_ENSURE_SUCCESS(rv, rv);
1004 
1005  // Check if any device icon nodes are available.
1006  PRUint32 nodeCount = deviceIconNodeList.Length();
1007  if (!nodeCount)
1008  return NS_OK;
1009 
1010  // Get the first device icon element.
1011  nsCOMPtr<nsIDOMElement> deviceIconElement;
1012  deviceIconElement = do_QueryInterface(deviceIconNodeList[0], &rv);
1013  NS_ENSURE_SUCCESS(rv, rv);
1014 
1015  // Read the device icon URL value.
1016  rv = deviceIconElement->GetAttribute(NS_LITERAL_STRING("url"),
1017  aDeviceIconURL);
1018  NS_ENSURE_SUCCESS(rv, rv);
1019 
1020  return NS_OK;
1021 }
1022 
1023 
1024 //-------------------------------------
1025 //
1026 // sbDeviceXMLInfo
1027 //
1028 
1030  mDevice(aDevice),
1031  mLogDeviceInfo(sbDeviceUtils::ShouldLogDeviceInfo())
1032 {
1033 }
1034 
1035 
1036 //-------------------------------------
1037 //
1038 // ~sbDeviceXMLInfo
1039 //
1040 
1042 {
1043 }
1044 
1045 
1046 //------------------------------------------------------------------------------
1047 //
1048 // Private Songbird device XML info services.
1049 //
1050 //------------------------------------------------------------------------------
1051 
1052 //-------------------------------------
1053 //
1054 // DeviceMatchesDeviceInfoNode
1055 //
1056 
1057 nsresult
1058 sbDeviceXMLInfo::DeviceMatchesDeviceInfoNode(nsIDOMNode* aDeviceInfoNode,
1059  nsAString & aFoundVersion,
1060  nsIDOMNode** aDeviceNode)
1061 {
1062  // Validate arguments.
1063  NS_ENSURE_ARG_POINTER(aDeviceInfoNode);
1064 
1065  // Function variables.
1066  PRUint32 nodeCount;
1067  nsresult rv;
1068 
1069  // Default to no matching device node.
1070  if (aDeviceNode)
1071  *aDeviceNode = nsnull;
1072 
1073  // Get the devices node. Device matches by default if no devices node is
1074  // specified.
1075  nsCOMPtr<nsIDOMNode> devicesNode;
1076  nsCOMPtr<nsIDOMNodeList> devicesNodeList;
1077  nsCOMPtr<nsIDOMElement>
1078  deviceInfoElement = do_QueryInterface(aDeviceInfoNode, &rv);
1079  NS_ENSURE_SUCCESS(rv, rv);
1080  rv = deviceInfoElement->GetElementsByTagNameNS
1081  (NS_LITERAL_STRING(SB_DEVICE_INFO_NS),
1082  NS_LITERAL_STRING("devices"),
1083  getter_AddRefs(devicesNodeList));
1084  NS_ENSURE_SUCCESS(rv, rv);
1085  rv = devicesNodeList->GetLength(&nodeCount);
1086  NS_ENSURE_SUCCESS(rv, rv);
1087  if (!nodeCount) {
1088  rv = GetDeviceInfoVersion(deviceInfoElement, aFoundVersion);
1089  NS_ENSURE_SUCCESS(rv, rv);
1090  return NS_OK;
1091  }
1092  rv = devicesNodeList->Item(0, getter_AddRefs(devicesNode));
1093  NS_ENSURE_SUCCESS(rv, rv);
1094 
1095  // If no device was specified, the device doesn't match.
1096  if (!mDevice) {
1097  // Return an empty version string to indicate no match
1098  aFoundVersion.Truncate();
1099  return NS_OK;
1100  }
1101 
1102  // Get the device properties.
1103  nsCOMPtr<sbIDeviceProperties> deviceProperties;
1104  rv = mDevice->GetProperties(getter_AddRefs(deviceProperties));
1105  NS_ENSURE_SUCCESS(rv, rv);
1106  nsCOMPtr<nsIPropertyBag2> properties;
1107  rv = deviceProperties->GetProperties(getter_AddRefs(properties));
1108  NS_ENSURE_SUCCESS(rv, rv);
1109 
1110  // Get the devices node child list. Device doesn't match if list is empty.
1111  nsCOMPtr<nsIDOMNodeList> childNodeList;
1112  rv = devicesNode->GetChildNodes(getter_AddRefs(childNodeList));
1113  NS_ENSURE_SUCCESS(rv, rv);
1114  if (!childNodeList) {
1115  // Return an empty version string to indicate no match
1116  aFoundVersion.Truncate();
1117  return NS_OK;
1118  }
1119 
1120  // Check each child node for a matching device node.
1121  rv = childNodeList->GetLength(&nodeCount);
1122  NS_ENSURE_SUCCESS(rv, rv);
1123  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
1124  // Get the next child node.
1125  nsCOMPtr<nsIDOMNode> childNode;
1126  rv = childNodeList->Item(nodeIndex, getter_AddRefs(childNode));
1127  NS_ENSURE_SUCCESS(rv, rv);
1128 
1129  // Skip all but device nodes.
1130  nsString nodeName;
1131  rv = childNode->GetNodeName(nodeName);
1132  NS_ENSURE_SUCCESS(rv, rv);
1133  if (!nodeName.EqualsLiteral("device")) {
1134  continue;
1135  }
1136 
1137  // Check if the device matches the device node.
1138  PRBool matches;
1139  rv = DeviceMatchesDeviceNode(childNode, properties, &matches);
1140  NS_ENSURE_SUCCESS(rv, rv);
1141  if (matches) {
1142  rv = GetDeviceInfoVersion(deviceInfoElement, aFoundVersion);
1143  NS_ENSURE_SUCCESS(rv, rv);
1144  if (aDeviceNode)
1145  childNode.forget(aDeviceNode);
1146  return NS_OK;
1147  }
1148  }
1149 
1150  // No match found. Return an empty version string
1151  aFoundVersion.Truncate();
1152 
1153  return NS_OK;
1154 }
1155 
1156 //-------------------------------------
1157 //
1158 // GetDeviceInfoVersion
1159 //
1160 
1161 nsresult sbDeviceXMLInfo::GetDeviceInfoVersion(
1162  nsIDOMElement * aDeviceInfoElement,
1163  nsAString & aVersion)
1164 {
1165  NS_ENSURE_ARG_POINTER(aDeviceInfoElement);
1166 
1167  nsresult rv;
1168 
1169  NS_NAMED_LITERAL_STRING(VERSION_ATTR, "version");
1170 
1171  // The version attr is optional. Ignore errors and check
1172  // for empty string instead
1173  aVersion.Truncate();
1174  aDeviceInfoElement->GetAttribute(VERSION_ATTR, aVersion);
1175  if (!aVersion.IsEmpty())
1176  {
1177  return NS_OK;
1178  }
1179 
1180  // No version attr on the <deviceinfo> element. Try its parent
1181  nsCOMPtr<nsIDOMNode> parentNode;
1182  rv = aDeviceInfoElement->GetParentNode(getter_AddRefs(parentNode));
1183  NS_ENSURE_SUCCESS(rv, rv);
1184  nsCOMPtr<nsIDOMElement> parent =
1185  do_QueryInterface(parentNode, &rv);
1186  NS_ENSURE_SUCCESS(rv, rv);
1187 
1188  parent->GetAttribute(VERSION_ATTR, aVersion);
1189  if (!aVersion.IsEmpty())
1190  {
1191  return NS_OK;
1192  }
1193 
1194  // No version attr defined. Default to "0"
1195  aVersion.AssignLiteral("0");
1196  return NS_OK;
1197 }
1198 
1199 //-------------------------------------
1200 //
1201 // DeviceMatchesDeviceNode
1202 //
1203 
1204 nsresult
1205 sbDeviceXMLInfo::DeviceMatchesDeviceNode(nsIDOMNode* aDeviceNode,
1206  nsIPropertyBag2* aDeviceProperties,
1207  PRBool* aDeviceMatches)
1208 {
1209  NS_ENSURE_ARG_POINTER(aDeviceNode);
1210  NS_ENSURE_ARG_POINTER(aDeviceProperties);
1211  NS_ENSURE_ARG_POINTER(aDeviceMatches);
1212 
1213  nsresult rv;
1214 
1215  // Get the device node attributes.
1216  nsCOMPtr<nsIDOMNamedNodeMap> attributes;
1217  rv = aDeviceNode->GetAttributes(getter_AddRefs(attributes));
1218  NS_ENSURE_SUCCESS(rv, rv);
1219 
1220  // Check if each device node attribute matches the device.
1221  PRBool matches = PR_TRUE;
1222  PRUint32 attributeCount;
1223  rv = attributes->GetLength(&attributeCount);
1224  NS_ENSURE_SUCCESS(rv, rv);
1225  for (PRUint32 attributeIndex = 0;
1226  attributeIndex < attributeCount;
1227  ++attributeIndex) {
1228  // Get the next attribute.
1229  nsCOMPtr<nsIDOMNode> attribute;
1230  rv = attributes->Item(attributeIndex, getter_AddRefs(attribute));
1231  NS_ENSURE_SUCCESS(rv, rv);
1232 
1233  // Get the attribute name.
1234  nsAutoString attributeName;
1235  rv = attribute->GetNodeName(attributeName);
1236  NS_ENSURE_SUCCESS(rv, rv);
1237 
1238  // Get the attribute value.
1239  nsAutoString attributeValue;
1240  rv = attribute->GetNodeValue(attributeValue);
1241  NS_ENSURE_SUCCESS(rv, rv);
1242 
1243  // Get the corresponding device property key.
1244  nsAutoString deviceKey(NS_LITERAL_STRING(SB_DEVICE_PROPERTY_BASE));
1245  deviceKey.Append(attributeName);
1246 
1247  // If the device property key does not exist, the device does not match.
1248  PRBool hasKey;
1249  rv = aDeviceProperties->HasKey(deviceKey, &hasKey);
1250  NS_ENSURE_SUCCESS(rv, rv);
1251  if (!hasKey) {
1252  matches = PR_FALSE;
1253  break;
1254  }
1255 
1256  // Get the device property value.
1257  nsCOMPtr<nsIVariant> deviceValue;
1258  rv = aDeviceProperties->Get(deviceKey, getter_AddRefs(deviceValue));
1259  NS_ENSURE_SUCCESS(rv, rv);
1260 
1261  // If the device property value and the attribute value are not equal, the
1262  // device does not match.
1263  PRBool equal;
1264  rv = sbVariantsEqual(deviceValue, sbNewVariant(attributeValue), &equal);
1265  NS_ENSURE_SUCCESS(rv, rv);
1266  if (!equal) {
1267  matches = PR_FALSE;
1268  break;
1269  }
1270  }
1271 
1272  // Return results.
1273  *aDeviceMatches = matches;
1274 
1275  return NS_OK;
1276 }
1277 
1278 
1279 //-------------------------------------
1280 //
1281 // GetDeviceInfoNodes
1282 //
1283 
1284 nsresult
1285 sbDeviceXMLInfo::GetDeviceInfoNodes
1286  (const nsAString& aNameSpace,
1287  const nsAString& aTagName,
1288  nsTArray< nsCOMPtr<nsIDOMNode> >& aNodeList)
1289 {
1290  PRBool success;
1291  nsresult rv;
1292 
1293  // Start with an empty node list.
1294  aNodeList.Clear();
1295 
1296  // Check for nodes that descend from the device node.
1297  nsCOMPtr<nsIDOMNodeList> nodeList;
1298  PRUint32 nodeCount = 0;
1299  PRBool areDeviceNodeDescendants = PR_TRUE;
1300  if (mDeviceElement) {
1301  rv = mDeviceElement->GetElementsByTagNameNS(aNameSpace,
1302  aTagName,
1303  getter_AddRefs(nodeList));
1304  NS_ENSURE_SUCCESS(rv, rv);
1305  rv = nodeList->GetLength(&nodeCount);
1306  NS_ENSURE_SUCCESS(rv, rv);
1307  }
1308 
1309  // If no nodes descend from the device node, get them from the device info
1310  // container element. This list may contain nodes descending from
1311  // non-matching device nodes; these will be filtered out later.
1312  if (mDeviceInfoElement && (!nodeList || !nodeCount)) {
1313  areDeviceNodeDescendants = PR_FALSE;
1314  rv = mDeviceInfoElement->GetElementsByTagNameNS(aNameSpace,
1315  aTagName,
1316  getter_AddRefs(nodeList));
1317  NS_ENSURE_SUCCESS(rv, rv);
1318  rv = nodeList->GetLength(&nodeCount);
1319  NS_ENSURE_SUCCESS(rv, rv);
1320  }
1321 
1322  // Get the list of specified device info nodes.
1323  success = aNodeList.SetCapacity(nodeCount);
1324  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1325  for (PRUint32 i = 0; i < nodeCount; ++i) {
1326  // Get the next node.
1327  nsCOMPtr<nsIDOMNode> node;
1328  rv = nodeList->Item(i, getter_AddRefs(node));
1329  NS_ENSURE_SUCCESS(rv, rv);
1330 
1331  // If nodes didn't come from a device node, skip all that do.
1332  if (!areDeviceNodeDescendants) {
1333  PRBool isDeviceNodeDescendant;
1334  rv = IsDeviceNodeDescendant(node, &isDeviceNodeDescendant);
1335  NS_ENSURE_SUCCESS(rv, rv);
1336  if (isDeviceNodeDescendant)
1337  continue;
1338  }
1339 
1340  // Add node to the list.
1341  NS_ENSURE_TRUE(aNodeList.AppendElement(node), NS_ERROR_OUT_OF_MEMORY);
1342  }
1343 
1344  return NS_OK;
1345 }
1346 
1347 
1348 //-------------------------------------
1349 //
1350 // GetDeviceInfoNodes
1351 //
1352 
1353 nsresult
1354 sbDeviceXMLInfo::GetDeviceInfoNodes(const nsAString& aTagName,
1355  nsTArray< nsCOMPtr<nsIDOMNode> >& aNodeList)
1356 {
1357  return GetDeviceInfoNodes(NS_LITERAL_STRING(SB_DEVICE_INFO_NS),
1358  aTagName,
1359  aNodeList);
1360 }
1361 
1362 
1363 //-------------------------------------
1364 //
1365 // IsDeviceNodeDescendant
1366 //
1367 
1368 nsresult
1369 sbDeviceXMLInfo::IsDeviceNodeDescendant(nsIDOMNode* aNode,
1370  PRBool* aIsDeviceNodeDescendant)
1371 {
1372  // Validate arguments.
1373  NS_ENSURE_ARG_POINTER(aNode);
1374  NS_ENSURE_ARG_POINTER(aIsDeviceNodeDescendant);
1375 
1376  // Function variables.
1377  nsresult rv;
1378 
1379  // Default to not being a descendant of a device node.
1380  *aIsDeviceNodeDescendant = PR_FALSE;
1381 
1382  // Search node ancestry for a device node.
1383  nsCOMPtr<nsIDOMNode> node = aNode;
1384  while (node && (node != mDeviceInfoElement)) {
1385  // Get the node namespace and local name.
1386  nsAutoString namespaceURI;
1387  nsAutoString localName;
1388  rv = node->GetNamespaceURI(namespaceURI);
1389  NS_ENSURE_SUCCESS(rv, rv);
1390  rv = node->GetLocalName(localName);
1391  NS_ENSURE_SUCCESS(rv, rv);
1392 
1393  // If node is a device node, return that starting node is a device node
1394  // descendant.
1395  if (namespaceURI.Equals(NS_LITERAL_STRING(SB_DEVICE_INFO_NS)) &&
1396  localName.Equals(NS_LITERAL_STRING("device"))) {
1397  *aIsDeviceNodeDescendant = PR_TRUE;
1398  return NS_OK;
1399  }
1400 
1401  // Check parent node.
1402  nsCOMPtr<nsIDOMNode> parentNode;
1403  rv = node->GetParentNode(getter_AddRefs(parentNode));
1404  NS_ENSURE_SUCCESS(rv, rv);
1405  node = parentNode.forget();
1406  }
1407 
1408  return NS_OK;
1409 }
1410 
1411 
1412 void sbDeviceXMLInfo::Log(const char * aFmt, ...)
1413 {
1414  if (mLogDeviceInfo) {
1415  va_list args;
1416  va_start(args, aFmt);
1417  LogArgs(aFmt, args);
1418  va_end(args);
1419  }
1420 }
1421 
1422 void sbDeviceXMLInfo::LogIfFailed(nsresult aRV, const char * aPrintf, ...)
1423 {
1424  // Do nothing if no failure
1425  if (NS_SUCCEEDED(aRV)) {
1426  return;
1427  }
1428 
1429  // Check logging pref:
1430  if (!mLogDeviceInfo) {
1431  return;
1432  }
1433 
1434  // Resolve the args to a string
1435  va_list etc;
1436  va_start(etc, aPrintf);
1437  char *why =
1438  PR_vsmprintf(aPrintf ? aPrintf : "while loading device info", etc);
1439  va_end(etc);
1440 
1441  // Compose the error message
1442  nsString msg(NS_LITERAL_STRING("sbDeviceXMLInfo "));
1443  msg.AppendLiteral(
1444  sbDeviceUtils::GetDeviceIdentifier(mDevice).BeginReading());
1445  msg.AppendLiteral(":\nERROR [0x");
1446  msg.AppendInt(aRV, 16);
1447  msg.AppendLiteral("]\n");
1448  msg.Append(NS_ConvertUTF8toUTF16(why));
1449  PR_smprintf_free(why);
1450 
1451  // Log the error message
1452  sbErrorConsole::Error("sbDeviceXMLInfo", msg);
1453 }
1454 
1455 
1456 void sbDeviceXMLInfo::LogArgs(const char * aFmt,
1457  va_list aArgs)
1458 {
1459  char *msg = PR_vsmprintf(aFmt, aArgs);
1461  "sbDeviceXMLInfo %s:\n%s",
1462  sbDeviceUtils::GetDeviceIdentifier(mDevice).BeginReading(),
1463  msg);
1464  PR_smprintf_free(msg);
1465 }
nsresult Read(const char *aDeviceXMLInfoSpecList, const char *aExtensionsList=nsnull)
nsresult sbVariantsEqual(nsIVariant *aVariant1, nsIVariant *aVariant2, PRBool *aEqual)
var args
Definition: alert.js:8
return NS_OK
nsresult sbOpenInputStream(nsAString const &aPath, nsIInputStream **aStream)
Definition: sbFileUtils.cpp:47
tabData attributes[name]
Songbird Variant Utility Definitions.
var uris
nsresult GetStorageDeviceInfoList(nsIArray **aStorageDeviceInfoList)
Songbird Variant Utility Definitions.
nsresult GetDeviceInfoElement(nsIDOMElement **aDeviceInfoElement)
static nsresult SB_NewURI(nsIURI **aURI, const nsACString &aSpec, const char *aCharSet=nsnull, nsIURI *aBaseURI=nsnull)
Definition: sbURIUtils.h:139
#define SB_DIRECTORYENUMERATOR_CONTRACTID
nsresult GetDeviceIcon(nsAString &aDeviceIconURL)
nsresult GetDeviceFolder(const nsAString &aFolderType, nsAString &aFolderURL)
static void Error(char const *aCategory, nsAString const &aMessage, nsAString const &aSource=nsString(), PRUint32 aLine=0)
sbDeviceXMLInfo(sbIDevice *aDevice=nsnull)
nsresult GetDefaultName(nsAString &aDefaultName)
nsresult GetDeviceInfoPresent(PRBool *aDeviceInfoPresent)
virtual ~sbDeviceXMLInfo()
#define SB_DEVICE_PROPERTY_BASE
nsresult GetOnlyMountMediaFolders(PRBool *aOnlyMountMediaFolders)
static void Message(char const *aFmt,...)
void nsCString_Split(const nsACString &aString, const nsACString &aDelimiter, nsTArray< nsCString > &aSubStringArray)
static nsCString GetDeviceIdentifier(sbIDevice *aDevice)
let node
nsresult GetDoesDeviceSupportReformat(PRBool *aOutSupportsReformat)
var uri
Definition: FeedWriter.js:1135
nsresult GetMountTimeout(PRUint32 *aMountTimeout)
function msg
#define SB_DEVICE_INFO_NS
nsresult GetImportRules(nsIArray **aImportRules)
Songbird Device XML Info Definitions.
_getSelectedPageStyle s i
var file
nsresult GetExcludedFolders(nsAString &aExcludedFolders)