sbDeviceXMLCapabilities.cpp
Go to the documentation of this file.
1 /* vim: set sw=2 :miv */
2 /*
3  *=BEGIN SONGBIRD GPL
4  *
5  * This file is part of the Songbird web player.
6  *
7  * Copyright(c) 2005-2010 POTI, Inc.
8  * http://www.songbirdnest.com
9  *
10  * This file may be licensed under the terms of of the
11  * GNU General Public License Version 2 (the ``GPL'').
12  *
13  * Software distributed under the License is distributed
14  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
15  * express or implied. See the GPL for the specific language
16  * governing rights and limitations.
17  *
18  * You should have received a copy of the GPL along with this
19  * program. If not, go to http://www.gnu.org/licenses/gpl.html
20  * or write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  *
23  *=END SONGBIRD GPL
24  */
25 
27 
28 // Songbird includes
29 #include <sbIDeviceCapabilities.h>
30 #include <sbIDeviceProperties.h>
31 #include <sbMemoryUtils.h>
33 #include <sbStringUtils.h>
34 #include <sbVariantUtils.h>
35 #include <sbVariantUtilsLib.h>
36 
37 // Mozilla includes
38 #include <nsComponentManagerUtils.h>
39 #include <nsIFile.h>
40 #include <nsIDOMDocument.h>
41 #include <nsIDOMElement.h>
42 #include <nsIDOMNamedNodeMap.h>
43 #include <nsIDOMNode.h>
44 #include <nsIDOMNodeList.h>
45 #include <nsIMutableArray.h>
46 #include <nsIScriptSecurityManager.h>
47 #include <nsIPropertyBag2.h>
48 #include <nsIXMLHttpRequest.h>
49 #include <nsMemory.h>
50 #include <nsServiceManagerUtils.h>
51 #include <nsTArray.h>
52 #include <nsThreadUtils.h>
53 
54 #define SB_DEVICE_CAPS_ELEMENT "devicecaps"
55 #define SB_DEVICE_CAPS_NS "http://songbirdnest.com/devicecaps/1.0"
56 
58  sbIDevice* aDevice) :
59  mDevice(aDevice),
60  mDeviceCaps(nsnull),
61  mRootElement(aRootElement),
62  mHasCapabilities(PR_FALSE)
63 {
64  NS_ASSERTION(mRootElement, "no device capabilities element provided");
65 }
66 
68 {
69 }
70 
71 nsresult
72 sbDeviceXMLCapabilities::AddFunctionType(PRUint32 aFunctionType)
73 {
74  return mDeviceCaps->SetFunctionTypes(&aFunctionType, 1);
75 }
76 
77 nsresult
78 sbDeviceXMLCapabilities::AddContentType(PRUint32 aFunctionType,
79  PRUint32 aContentType)
80 {
81  return mDeviceCaps->AddContentTypes(aFunctionType, &aContentType, 1);
82 }
83 
84 nsresult
85 sbDeviceXMLCapabilities::AddMimeType(PRUint32 aContentType,
86  nsAString const & aMimeType)
87 {
88  nsCString const & mimeTypeString = NS_LossyConvertUTF16toASCII(aMimeType);
89  char const * mimeType = mimeTypeString.BeginReading();
90  return mDeviceCaps->AddMimeTypes(aContentType, &mimeType, 1);
91 }
92 
93 nsresult
95  // This function should only be called on the main thread.
96  NS_ASSERTION(NS_IsMainThread(), "not on main thread");
97 
98  nsresult rv;
99 
100  mDeviceCaps = aCapabilities;
101 
102  rv = ProcessCapabilities(mRootElement);
103  NS_ENSURE_SUCCESS(rv, rv);
104  return NS_OK;
105 }
106 
107 /* static */ nsresult
109  (sbIDeviceCapabilities** aCapabilities,
110  nsIDOMDocument* aDocument,
111  sbIDevice* aDevice)
112 {
113  // Validate arguments.
114  NS_ENSURE_ARG_POINTER(aCapabilities);
115  NS_ENSURE_ARG_POINTER(aDocument);
116 
117  // Function variables.
118  nsresult rv;
119 
120  // No capabilities are available yet.
121  *aCapabilities = nsnull;
122 
123  // Get the document element.
124  nsCOMPtr<nsIDOMElement> documentElem;
125  rv = aDocument->GetDocumentElement(getter_AddRefs(documentElem));
126  NS_ENSURE_SUCCESS(rv, rv);
127 
128  // Get the capabilities.
129  rv = GetCapabilities(aCapabilities, documentElem, aDevice);
130  NS_ENSURE_SUCCESS(rv, rv);
131 
132  return NS_OK;
133 }
134 
135 /* static */ nsresult
137  (sbIDeviceCapabilities** aCapabilities,
138  nsIDOMNode* aDeviceCapsRootNode,
139  sbIDevice* aDevice)
140 {
141  // Validate arguments.
142  NS_ENSURE_ARG_POINTER(aCapabilities);
143  NS_ENSURE_ARG_POINTER(aDeviceCapsRootNode);
144 
145  // Function variables.
146  nsresult rv;
147 
148  // No capabilities are available yet.
149  *aCapabilities = nsnull;
150 
151  // Get the device capabilities root element. There are no capabilities if
152  // root node is not an element.
153  nsCOMPtr<nsIDOMElement>
154  deviceCapsRootElem = do_QueryInterface(aDeviceCapsRootNode, &rv);
155  if (NS_FAILED(rv))
156  return NS_OK;
157 
158  // Read the device capabilities for the device.
159  nsCOMPtr<sbIDeviceCapabilities> deviceCapabilities =
160  do_CreateInstance(SONGBIRD_DEVICECAPABILITIES_CONTRACTID, &rv);
161  NS_ENSURE_SUCCESS(rv, rv);
162  rv = deviceCapabilities->Init();
163  NS_ENSURE_SUCCESS(rv, rv);
164  sbDeviceXMLCapabilities xmlCapabilities(deviceCapsRootElem, aDevice);
165  rv = xmlCapabilities.Read(deviceCapabilities);
166  NS_ENSURE_SUCCESS(rv, rv);
167  rv = deviceCapabilities->ConfigureDone();
168  NS_ENSURE_SUCCESS(rv, rv);
169 
170  // Return results.
171  if (xmlCapabilities.HasCapabilities())
172  deviceCapabilities.forget(aCapabilities);
173 
174  return NS_OK;
175 }
176 
177 /* static */ nsresult
179  (sbIDeviceCapabilities* aCapabilities,
180  const char* aXMLCapabilitiesSpec,
181  PRBool* aAddedCapabilities,
182  sbIDevice* aDevice)
183 {
184  // Validate arguments.
185  NS_ENSURE_ARG_POINTER(aCapabilities);
186  NS_ENSURE_ARG_POINTER(aXMLCapabilitiesSpec);
187 
188  // Function variables.
189  nsresult rv;
190 
191  // No capabilities have yet been added.
192  if (aAddedCapabilities)
193  *aAddedCapabilities = PR_FALSE;
194 
195  // Create an XMLHttpRequest object.
196  nsCOMPtr<nsIXMLHttpRequest>
197  xmlHttpRequest = do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
198  NS_ENSURE_SUCCESS(rv, rv);
199  nsCOMPtr<nsIScriptSecurityManager> ssm =
200  do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
201  NS_ENSURE_SUCCESS(rv, rv);
202  nsCOMPtr<nsIPrincipal> principal;
203  rv = ssm->GetSystemPrincipal(getter_AddRefs(principal));
204  NS_ENSURE_SUCCESS(rv, rv);
205  rv = xmlHttpRequest->Init(principal, nsnull, nsnull, nsnull);
206  NS_ENSURE_SUCCESS(rv, rv);
207 
208  // Read the device capabilities file.
209  rv = xmlHttpRequest->OpenRequest(NS_LITERAL_CSTRING("GET"),
210  nsCString(aXMLCapabilitiesSpec),
211  PR_FALSE, // async
212  SBVoidString(), // user
213  SBVoidString()); // password
214  NS_ENSURE_SUCCESS(rv, rv);
215  rv = xmlHttpRequest->Send(nsnull);
216  NS_ENSURE_SUCCESS(rv, rv);
217 
218  // Get the device capabilities root element.
219  nsCOMPtr<nsIDOMElement> deviceCapsElem;
220  nsCOMPtr<nsIDOMDocument> deviceCapabilitiesDocument;
221  rv = xmlHttpRequest->GetResponseXML
222  (getter_AddRefs(deviceCapabilitiesDocument));
223  NS_ENSURE_SUCCESS(rv, rv);
224  rv = deviceCapabilitiesDocument->GetDocumentElement
225  (getter_AddRefs(deviceCapsElem));
226  NS_ENSURE_SUCCESS(rv, rv);
227 
228  // Add the device capabilities.
229  rv = AddCapabilities(aCapabilities,
230  deviceCapsElem,
231  aAddedCapabilities,
232  aDevice);
233  NS_ENSURE_SUCCESS(rv, rv);
234 
235  return NS_OK;
236 }
237 
238 /* static */ nsresult
240  (sbIDeviceCapabilities* aCapabilities,
241  nsIDOMNode* aDeviceCapsRootNode,
242  PRBool* aAddedCapabilities,
243  sbIDevice* aDevice)
244 {
245  // Validate arguments.
246  NS_ENSURE_ARG_POINTER(aCapabilities);
247  NS_ENSURE_ARG_POINTER(aDeviceCapsRootNode);
248 
249  // Function variables.
250  nsresult rv;
251 
252  // No capabilities have yet been added.
253  if (aAddedCapabilities)
254  *aAddedCapabilities = PR_FALSE;
255 
256  // Get the device capabilities.
257  nsCOMPtr<sbIDeviceCapabilities> deviceCapabilities;
258  rv = GetCapabilities(getter_AddRefs(deviceCapabilities),
259  aDeviceCapsRootNode,
260  aDevice);
261  NS_ENSURE_SUCCESS(rv, rv);
262 
263  // Add any device capabilities.
264  if (deviceCapabilities) {
265  rv = aCapabilities->AddCapabilities(deviceCapabilities);
266  NS_ENSURE_SUCCESS(rv, rv);
267  if (aAddedCapabilities)
268  *aAddedCapabilities = PR_TRUE;
269  }
270 
271  return NS_OK;
272 }
273 
274 nsresult
275 sbDeviceXMLCapabilities::ProcessCapabilities(nsIDOMNode* aRootNode)
276 {
277  // Validate arguments.
278  NS_ENSURE_ARG_POINTER(aRootNode);
279 
280  // Function variables.
281  nsresult rv;
282 
283  // Get the list of all device capabilities nodes. If none exist, there are no
284  // capabilities to process.
285  nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(aRootNode, &rv);
286  if (NS_FAILED(rv))
287  return NS_OK;
288  nsCOMPtr<nsIDOMNodeList> deviceCapsNodeList;
289  rv = rootElement->GetElementsByTagNameNS
290  (NS_LITERAL_STRING(SB_DEVICE_CAPS_NS),
291  NS_LITERAL_STRING(SB_DEVICE_CAPS_ELEMENT),
292  getter_AddRefs(deviceCapsNodeList));
293  if (NS_FAILED(rv) || !deviceCapsNodeList)
294  return NS_OK;
295 
296  // Check each device capabilities node for a matching item.
297  PRUint32 nodeCount;
298  rv = deviceCapsNodeList->GetLength(&nodeCount);
299  NS_ENSURE_SUCCESS(rv, rv);
300  for (PRUint32 i = 0; i < nodeCount; i++) {
301  // Get the next device capabilities node.
302  nsCOMPtr<nsIDOMNode> deviceCapsNode;
303  rv = deviceCapsNodeList->Item(i, getter_AddRefs(deviceCapsNode));
304  NS_ENSURE_SUCCESS(rv, rv);
305 
306  // Process device capabilities if they match device.
307  PRBool deviceMatches;
308  rv = DeviceMatchesCapabilitiesNode(deviceCapsNode, &deviceMatches);
309  NS_ENSURE_SUCCESS(rv, rv);
310  if (deviceMatches) {
311  rv = ProcessDeviceCaps(deviceCapsNode);
312  NS_ENSURE_SUCCESS(rv, rv);
313  mHasCapabilities = PR_TRUE;
314  }
315  }
316 
317  return NS_OK;
318 }
319 
320 nsresult
321 sbDeviceXMLCapabilities::ProcessDeviceCaps(nsIDOMNode * aDevCapNode)
322 {
323  nsCOMPtr<nsIDOMNodeList> nodes;
324  nsresult rv = aDevCapNode->GetChildNodes(getter_AddRefs(nodes));
325  if (nodes) {
326  PRUint32 nodeCount;
327  rv = nodes->GetLength(&nodeCount);
328  NS_ENSURE_SUCCESS(rv, rv);
329  nsCOMPtr<nsIDOMNode> domNode;
330  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
331  rv = nodes->Item(nodeIndex, getter_AddRefs(domNode));
332  NS_ENSURE_SUCCESS(rv, rv);
333 
334  nsString name;
335  rv = domNode->GetNodeName(name);
336  NS_ENSURE_SUCCESS(rv, rv);
337 
338  if (name.Equals(NS_LITERAL_STRING("audio"))) {
339  rv = ProcessAudio(domNode);
340  NS_ENSURE_SUCCESS(rv, rv);
341  }
342  else if (name.Equals(NS_LITERAL_STRING("image"))) {
343  rv = ProcessImage(domNode);
344  NS_ENSURE_SUCCESS(rv, rv);
345  }
346  else if (name.Equals(NS_LITERAL_STRING("video"))) {
347  rv = ProcessVideo(domNode);
348  NS_ENSURE_SUCCESS(rv, rv);
349  }
350  else if (name.Equals(NS_LITERAL_STRING("playlist"))) {
351  rv = ProcessPlaylist(domNode);
352  NS_ENSURE_SUCCESS(rv, rv);
353  }
354  }
355  }
356  return NS_OK;
357 }
358 
363 {
364 public:
368  sbDOMNodeAttributes(nsIDOMNode * aNode)
369  {
370  if (aNode) {
371  aNode->GetAttributes(getter_AddRefs(mAttributes));
372  }
373  }
379  nsresult
380  GetValue(nsAString const & aName,
381  nsAString & aValue)
382  {
383  NS_ENSURE_TRUE(mAttributes, NS_ERROR_FAILURE);
384  nsCOMPtr<nsIDOMNode> node;
385  nsresult rv = mAttributes->GetNamedItem(aName, getter_AddRefs(node));
386  NS_ENSURE_SUCCESS(rv, rv);
387 
388  if (node) {
389  rv = node->GetNodeValue(aValue);
390  NS_ENSURE_SUCCESS(rv, rv);
391  return NS_OK;
392  }
393 
394  return NS_ERROR_NOT_AVAILABLE;
395  }
396 
402  nsresult
403  GetValue(nsAString const & aName,
404  PRInt32 & aValue)
405  {
406  nsString value;
407  nsresult rv = GetValue(aName, value);
408  // If not found then just return the error, no need to log
409  if (rv == NS_ERROR_NOT_AVAILABLE) {
410  return rv;
411  }
412  NS_ENSURE_SUCCESS(rv, rv);
413 
414  aValue = value.ToInteger(&rv, 10);
415  NS_ENSURE_SUCCESS(rv, rv);
416 
417  return NS_OK;
418  }
419 private:
420  nsCOMPtr<nsIDOMNamedNodeMap> mAttributes;
421 };
422 
428 static nsresult
429 GetNodeValue(nsIDOMNode * aValueNode, nsAString & aValue)
430 {
431  NS_ENSURE_ARG_POINTER(aValueNode);
432 
433  nsCOMPtr<nsIDOMNodeList> nodes;
434  nsresult rv = aValueNode->GetChildNodes(getter_AddRefs(nodes));
435  NS_ENSURE_SUCCESS(rv, rv);
436 
437  PRUint32 nodeCount;
438  rv = nodes->GetLength(&nodeCount);
439  NS_ENSURE_SUCCESS(rv, rv);
440 
441  if (nodeCount > 0) {
442  nsCOMPtr<nsIDOMNode> node;
443  rv = nodes->Item(0, getter_AddRefs(node));
444  NS_ENSURE_SUCCESS(rv, rv);
445  rv = node->GetNodeValue(aValue);
446  NS_ENSURE_SUCCESS(rv, rv);
447  }
448  return NS_OK;
449 }
450 
456 static nsresult
457 BuildRange(nsIDOMNode * aRangeNode, sbIDevCapRange ** aRange)
458 {
459  NS_ENSURE_ARG_POINTER(aRangeNode);
460  NS_ENSURE_ARG_POINTER(aRange);
461 
462  nsresult rv;
463  nsCOMPtr<sbIDevCapRange> range =
464  do_CreateInstance(SB_IDEVCAPRANGE_CONTRACTID, &rv);
465  NS_ENSURE_SUCCESS(rv, rv);
466 
467  nsCOMPtr<nsIDOMNodeList> nodes;
468  rv = aRangeNode->GetChildNodes(getter_AddRefs(nodes));
469  NS_ENSURE_SUCCESS(rv, rv);
470 
471  PRUint32 nodeCount;
472  rv = nodes->GetLength(&nodeCount);
473  NS_ENSURE_SUCCESS(rv, rv);
474 
475  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
476  nsCOMPtr<nsIDOMNode> node;
477  rv = nodes->Item(nodeIndex, getter_AddRefs(node));
478  NS_ENSURE_SUCCESS(rv, rv);
479 
480  nsString name;
481  rv = node->GetNodeName(name);
482  NS_ENSURE_SUCCESS(rv, rv);
483 
484  if (name.EqualsLiteral("value")) {
485  nsString bitRate;
486  rv = GetNodeValue(node, bitRate);
487  NS_ENSURE_SUCCESS(rv, rv);
488  PRInt32 bitRateValue = bitRate.ToInteger(&rv, 10);
489  if (NS_SUCCEEDED(rv)) {
490  rv = range->AddValue(bitRateValue);
491  NS_ENSURE_SUCCESS(rv, rv);
492  }
493  }
494  else if (name.EqualsLiteral("range")) {
496  PRInt32 min = 0;
497  rv = attributes.GetValue(NS_LITERAL_STRING("min"), min);
498  if (rv != NS_ERROR_NOT_AVAILABLE) { // not found error is ok, leave at 0
499  NS_ENSURE_SUCCESS(rv, rv);
500  }
501 
502  PRInt32 max = 0;
503  rv = attributes.GetValue(NS_LITERAL_STRING("max"), max);
504  if (rv != NS_ERROR_NOT_AVAILABLE) { // not found error is ok, leave at 0
505  NS_ENSURE_SUCCESS(rv, rv);
506  }
507 
508  PRInt32 step = 0;
509  rv = attributes.GetValue(NS_LITERAL_STRING("step"), step);
510  if (rv != NS_ERROR_NOT_AVAILABLE) { // not found error is ok, leave at 0
511  NS_ENSURE_SUCCESS(rv, rv);
512  }
513 
514  rv = range->Initialize(min, max, step);
515  NS_ENSURE_SUCCESS(rv, rv);
516  }
517  }
518 
519  range.forget(aRange);
520 
521  return NS_OK;
522 }
523 
528 static
529 nsresult
530 GetStringFractionValues(const nsAString & aString,
531  PRUint32 *aOutNumerator,
532  PRUint32 *aOutDenominator)
533 {
534  NS_ENSURE_ARG_POINTER(aOutNumerator);
535  NS_ENSURE_ARG_POINTER(aOutDenominator);
536 
537  nsresult rv;
538  nsTArray<nsString> splitResultArray;
539  nsString_Split(aString, NS_LITERAL_STRING("/"), splitResultArray);
540  NS_ENSURE_TRUE(splitResultArray.Length() > 0, NS_ERROR_UNEXPECTED);
541 
542  *aOutNumerator = splitResultArray[0].ToInteger(&rv);
543  NS_ENSURE_SUCCESS(rv, rv);
544 
545  if (splitResultArray.Length() == 2) {
546  *aOutDenominator = splitResultArray[1].ToInteger(&rv);
547  NS_ENSURE_SUCCESS(rv, rv);
548  }
549  else {
550  *aOutDenominator = 1;
551  }
552 
553  return NS_OK;
554 }
555 
562 static
563 nsresult
564 GetFractionRangeValues(nsIDOMNode * aDOMNode,
565  nsIArray **aOutCapRangeArray,
566  PRBool *aOutIsRange)
567 {
568  NS_ENSURE_ARG_POINTER(aDOMNode);
569  NS_ENSURE_ARG_POINTER(aOutCapRangeArray);
570  NS_ENSURE_ARG_POINTER(aOutIsRange);
571 
572  nsCOMPtr<nsIDOMNodeList> domNodes;
573  nsresult rv = aDOMNode->GetChildNodes(getter_AddRefs(domNodes));
574  NS_ENSURE_SUCCESS(rv, rv);
575  if (!domNodes) {
576  return NS_OK;
577  }
578 
579  PRUint32 nodeCount;
580  rv = domNodes->GetLength(&nodeCount);
581  NS_ENSURE_SUCCESS(rv, rv);
582 
583  if (nodeCount == 0) {
584  return NS_OK;
585  }
586 
587  nsCOMPtr<nsIMutableArray> fractionArray =
588  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
589  NS_ENSURE_SUCCESS(rv, rv);
590 
591  nsString minValue, maxValue;
592  nsTArray<nsString> strings;
593  nsCOMPtr<nsIDOMNode> domNode;
594  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
595  rv = domNodes->Item(nodeIndex, getter_AddRefs(domNode));
596  NS_ENSURE_SUCCESS(rv, rv);
597 
598  nsString name;
599  rv = domNode->GetNodeName(name);
600  NS_ENSURE_SUCCESS(rv, rv);
601 
602  nsString value;
603  rv = GetNodeValue(domNode, value);
604  if (NS_FAILED(rv)) {
605  continue;
606  }
607 
608  if (name.EqualsLiteral("value")) {
609  NS_ENSURE_TRUE(strings.AppendElement(value), NS_ERROR_OUT_OF_MEMORY);
610  }
611  else if (name.EqualsLiteral("min")) {
612  minValue.Assign(value);
613  }
614  else if (name.EqualsLiteral("max")) {
615  maxValue.Assign(value);
616  }
617  }
618 
619  // If the values had at least a min or a max value, use the min/max
620  // attributes on the device cap range. If not, fallback to a set list of
621  // values.
622  PRUint32 numerator, denominator;
623  if (!minValue.Equals(EmptyString()) || !maxValue.Equals(EmptyString())) {
624  nsCOMPtr<sbIDevCapFraction> minCapFraction =
625  do_CreateInstance("@songbirdnest.com/Songbird/Device/sbfraction;1", &rv);
626  NS_ENSURE_SUCCESS(rv, rv);
627 
628  rv = GetStringFractionValues(minValue, &numerator, &denominator);
629  NS_ENSURE_SUCCESS(rv, rv);
630 
631  rv = minCapFraction->Initialize(numerator, denominator);
632  NS_ENSURE_SUCCESS(rv, rv);
633 
634  nsCOMPtr<sbIDevCapFraction> maxCapFraction =
635  do_CreateInstance("@songbirdnest.com/Songbird/Device/sbfraction;1", &rv);
636  NS_ENSURE_SUCCESS(rv, rv);
637 
638  rv = GetStringFractionValues(maxValue, &numerator, &denominator);
639  NS_ENSURE_SUCCESS(rv, rv);
640 
641  rv = maxCapFraction->Initialize(numerator, denominator);
642  NS_ENSURE_SUCCESS(rv, rv);
643 
644  // Per the out-param comment, the first value in the array will be the
645  // minimum fraction range.
646  rv = fractionArray->AppendElement(minCapFraction, PR_FALSE);
647  NS_ENSURE_SUCCESS(rv, rv);
648  // And the second param will be the max value.
649  rv = fractionArray->AppendElement(maxCapFraction, PR_FALSE);
650  NS_ENSURE_SUCCESS(rv, rv);
651  // Mark these values as a range.
652  *aOutIsRange = PR_TRUE;
653  }
654  else {
655  // Mark the list of values as not a range.
656  *aOutIsRange = PR_FALSE;
657  // Loop through all of the values and convert them to cap fractions.
658  for (PRUint32 i = 0; i < strings.Length(); i++) {
659  rv = GetStringFractionValues(strings[i], &numerator, &denominator);
660  if (NS_FAILED(rv)) {
661  continue;
662  }
663 
664  nsCOMPtr<sbIDevCapFraction> curFraction =
665  do_CreateInstance("@songbirdnest.com/Songbird/Device/sbfraction;1", &rv);
666  NS_ENSURE_SUCCESS(rv, rv);
667 
668  rv = curFraction->Initialize(numerator, denominator);
669  NS_ENSURE_SUCCESS(rv, rv);
670 
671  rv = fractionArray->AppendElement(curFraction, PR_FALSE);
672  NS_ENSURE_SUCCESS(rv, rv);
673  }
674  }
675 
676  return CallQueryInterface(fractionArray.get(), aOutCapRangeArray);
677 }
678 
679 nsresult
680 sbDeviceXMLCapabilities::ProcessAudio(nsIDOMNode * aAudioNode)
681 {
682  NS_ENSURE_ARG_POINTER(aAudioNode);
683 
684  nsCOMPtr<nsIDOMNodeList> domNodes;
685  nsresult rv = aAudioNode->GetChildNodes(getter_AddRefs(domNodes));
686  NS_ENSURE_SUCCESS(rv, rv);
687  if (!domNodes) {
688  return NS_OK;
689  }
690 
691  PRUint32 nodeCount;
692  rv = domNodes->GetLength(&nodeCount);
693  NS_ENSURE_SUCCESS(rv, rv);
694 
695  if (nodeCount == 0) {
696  return NS_OK;
697  }
699  NS_ENSURE_SUCCESS(rv, rv);
700 
703  NS_ENSURE_SUCCESS(rv, rv);
704 
705  nsCOMPtr<nsIDOMNode> domNode;
706  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
707  rv = domNodes->Item(nodeIndex, getter_AddRefs(domNode));
708  NS_ENSURE_SUCCESS(rv, rv);
709 
710  nsString name;
711  rv = domNode->GetNodeName(name);
712  NS_ENSURE_SUCCESS(rv, rv);
713 
714  if (!name.EqualsLiteral("format")) {
715  continue;
716  }
717 
719 
720  nsString mimeType;
721  rv = attributes.GetValue(NS_LITERAL_STRING("mime"),
722  mimeType);
723  NS_ENSURE_SUCCESS(rv, rv);
724 
725  nsString container;
726  rv = attributes.GetValue(NS_LITERAL_STRING("container"),
727  container);
728  if (rv != NS_ERROR_NOT_AVAILABLE) { // not found error is ok, leave blank
729  NS_ENSURE_SUCCESS(rv, rv);
730  }
731 
732  nsString codec;
733  rv = attributes.GetValue(NS_LITERAL_STRING("codec"),
734  codec);
735  if (rv != NS_ERROR_NOT_AVAILABLE) { // not found error is ok, leave blank
736  NS_ENSURE_SUCCESS(rv, rv);
737  }
738 
739  nsString isPreferredString;
740  rv = attributes.GetValue(NS_LITERAL_STRING("preferred"),
741  isPreferredString);
742  if (rv != NS_ERROR_NOT_AVAILABLE) { // not found error is ok, leave blank
743  NS_ENSURE_SUCCESS(rv, rv);
744  }
745  PRBool isPreferred = isPreferredString.EqualsLiteral("true");
746 
747  nsCOMPtr<nsIDOMNodeList> ranges;
748  rv = domNode->GetChildNodes(getter_AddRefs(ranges));
749  NS_ENSURE_SUCCESS(rv, rv);
750 
751  PRUint32 rangeCount;
752  rv = ranges->GetLength(&rangeCount);
753  NS_ENSURE_SUCCESS(rv, rv);
754 
755  nsCOMPtr<sbIDevCapRange> bitRates;
756  nsCOMPtr<sbIDevCapRange> sampleRates;
757  nsCOMPtr<sbIDevCapRange> channels;
758  for (PRUint32 rangeIndex = 0; rangeIndex < rangeCount; ++rangeIndex) {
759  nsCOMPtr<nsIDOMNode> range;
760  rv = ranges->Item(rangeIndex, getter_AddRefs(range));
761  NS_ENSURE_SUCCESS(rv, rv);
762 
763  nsString rangeName;
764  rv = range->GetNodeName(rangeName);
765  NS_ENSURE_SUCCESS(rv, rv);
766 
767  if (rangeName.EqualsLiteral("bitrates")) {
768  rv = BuildRange(range, getter_AddRefs(bitRates));
769  NS_ENSURE_SUCCESS(rv, rv);
770  }
771  else if (rangeName.EqualsLiteral("samplerates")) {
772  rv = BuildRange(range, getter_AddRefs(sampleRates));
773  NS_ENSURE_SUCCESS(rv, rv);
774  }
775  else if (rangeName.EqualsLiteral("channels")) {
776  rv = BuildRange(range, getter_AddRefs(channels));
777  NS_ENSURE_SUCCESS(rv, rv);
778  }
779  }
780 
781  nsCOMPtr<sbIAudioFormatType> formatType =
782  do_CreateInstance(SB_IAUDIOFORMATTYPE_CONTRACTID, &rv);
783  NS_ENSURE_SUCCESS(rv, rv);
784 
785  rv = formatType->Initialize(NS_ConvertUTF16toUTF8(container),
786  NS_ConvertUTF16toUTF8(codec),
787  bitRates,
788  sampleRates,
789  channels,
790  nsnull);
791  NS_ENSURE_SUCCESS(rv, rv);
792 
793  rv = AddMimeType(sbIDeviceCapabilities::CONTENT_AUDIO, mimeType);
794  NS_ENSURE_SUCCESS(rv, rv);
795 
796  if (isPreferred) {
797  rv = mDeviceCaps->AddPreferredFormatType(
799  mimeType,
800  formatType);
801  NS_ENSURE_SUCCESS(rv, rv);
802  }
803  else {
805  mimeType,
806  formatType);
807  NS_ENSURE_SUCCESS(rv, rv);
808  }
809  }
810  return NS_OK;
811 }
812 
813 nsresult
814 sbDeviceXMLCapabilities::ProcessImageSizes(
815  nsIDOMNode * aImageSizeNode,
816  nsIMutableArray * aImageSizes)
817 {
818  NS_ENSURE_ARG_POINTER(aImageSizeNode);
819  NS_ENSURE_ARG_POINTER(aImageSizes);
820 
821  nsresult rv;
822 
823  nsCOMPtr<nsIDOMNodeList> nodes;
824  rv = aImageSizeNode->GetChildNodes(getter_AddRefs(nodes));
825  NS_ENSURE_SUCCESS(rv, rv);
826 
827  PRUint32 nodeCount;
828  rv = nodes->GetLength(&nodeCount);
829  NS_ENSURE_SUCCESS(rv, rv);
830 
831  NS_NAMED_LITERAL_STRING(WIDTH, "width");
832  NS_NAMED_LITERAL_STRING(HEIGHT, "height");
833 
834  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
835  nsCOMPtr<nsIDOMNode> node;
836  rv = nodes->Item(nodeIndex, getter_AddRefs(node));
837  NS_ENSURE_SUCCESS(rv, rv);
838 
839  nsString name;
840  rv = node->GetNodeName(name);
841  NS_ENSURE_SUCCESS(rv, rv);
842 
843  if (!name.EqualsLiteral("size")) {
844  continue;
845  }
847 
848  nsCOMPtr<sbIImageSize> imageSize =
849  do_CreateInstance(SB_IMAGESIZE_CONTRACTID, &rv);
850  NS_ENSURE_SUCCESS(rv, rv);
851 
852  PRInt32 width = 0;
853  rv = attributes.GetValue(WIDTH, width);
854  if (NS_FAILED(rv)) {
855  NS_WARNING("Invalid width found in device settings file");
856  continue;
857  }
858 
859  PRInt32 height = 0;
860  rv = attributes.GetValue(HEIGHT, height);
861  if (NS_FAILED(rv)) {
862  continue;
863  }
864  rv = imageSize->Initialize(width, height);
865  NS_ENSURE_SUCCESS(rv, rv);
866  rv = aImageSizes->AppendElement(imageSize, PR_FALSE);
867  NS_ENSURE_SUCCESS(rv, rv);
868  }
869 
870  return NS_OK;
871 }
872 
873 nsresult
874 sbDeviceXMLCapabilities::ProcessImage(nsIDOMNode * aImageNode)
875 {
876  NS_ENSURE_ARG_POINTER(aImageNode);
877 
878  nsCOMPtr<nsIDOMNodeList> domNodes;
879  nsresult rv = aImageNode->GetChildNodes(getter_AddRefs(domNodes));
880  NS_ENSURE_SUCCESS(rv, rv);
881  if (!domNodes) {
882  return NS_OK;
883  }
884 
885  PRUint32 nodeCount;
886  rv = domNodes->GetLength(&nodeCount);
887  NS_ENSURE_SUCCESS(rv, rv);
888 
889  if (nodeCount == 0) {
890  return NS_OK;
891  }
892  rv = AddFunctionType(sbIDeviceCapabilities::FUNCTION_IMAGE_DISPLAY);
893  NS_ENSURE_SUCCESS(rv, rv);
894 
897  NS_ENSURE_SUCCESS(rv, rv);
898 
899  nsCOMPtr<nsIDOMNode> domNode;
900  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
901  rv = domNodes->Item(nodeIndex, getter_AddRefs(domNode));
902  NS_ENSURE_SUCCESS(rv, rv);
903 
904  nsString name;
905  rv = domNode->GetNodeName(name);
906  NS_ENSURE_SUCCESS(rv, rv);
907 
908  if (!name.EqualsLiteral("format")) {
909  continue;
910  }
911 
913 
914  nsString mimeType;
915  rv = attributes.GetValue(NS_LITERAL_STRING("mime"),
916  mimeType);
917  NS_ENSURE_SUCCESS(rv, rv);
918 
919  nsCOMPtr<nsIMutableArray> imageSizes =
920  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1",
921  &rv);
922  NS_ENSURE_SUCCESS(rv, rv);
923 
924  nsCOMPtr<sbIDevCapRange> widths;
925  nsCOMPtr<sbIDevCapRange> heights;
926 
927  nsCOMPtr<nsIDOMNodeList> sections;
928  rv = domNode->GetChildNodes(getter_AddRefs(sections));
929  NS_ENSURE_SUCCESS(rv, rv);
930 
931  PRUint32 sectionCount;
932  rv = sections->GetLength(&sectionCount);
933  NS_ENSURE_SUCCESS(rv, rv);
934 
935  for (PRUint32 sectionIndex = 0;
936  sectionIndex < sectionCount;
937  ++sectionIndex) {
938  nsCOMPtr<nsIDOMNode> section;
939  rv = sections->Item(sectionIndex, getter_AddRefs(section));
940  NS_ENSURE_SUCCESS(rv, rv);
941 
942  nsString sectionName;
943  rv = section->GetNodeName(sectionName);
944  NS_ENSURE_SUCCESS(rv, rv);
945 
946  if (sectionName.EqualsLiteral("explicit-sizes")) {
947  rv = ProcessImageSizes(section, imageSizes);
948  NS_ENSURE_SUCCESS(rv, rv);
949  }
950  else if (sectionName.EqualsLiteral("widths")) {
951  rv = BuildRange(section, getter_AddRefs(widths));
952  NS_ENSURE_SUCCESS(rv, rv);
953  }
954  else if (sectionName.EqualsLiteral("heights")) {
955  rv = BuildRange(section, getter_AddRefs(heights));
956  NS_ENSURE_SUCCESS(rv, rv);
957  }
958  }
959  nsCOMPtr<sbIImageFormatType> imageFormatType =
960  do_CreateInstance(SB_IIMAGEFORMATTYPE_CONTRACTID, &rv);
961  NS_ENSURE_SUCCESS(rv, rv);
962 
963  rv = imageFormatType->Initialize(NS_ConvertUTF16toUTF8(mimeType),
964  imageSizes,
965  widths,
966  heights);
967  NS_ENSURE_SUCCESS(rv, rv);
968 
969  rv = AddMimeType(sbIDeviceCapabilities::CONTENT_IMAGE, mimeType);
970  NS_ENSURE_SUCCESS(rv, rv);
971 
973  mimeType,
974  imageFormatType);
975  NS_ENSURE_SUCCESS(rv, rv);
976  }
977 
978  return NS_OK;
979 }
980 
981 
983 
984 nsresult
985 sbDeviceXMLCapabilities::ProcessVideoStream(nsIDOMNode* aVideoStreamNode,
986  sbIDevCapVideoStream** aVideoStream)
987 {
988  // Retrieve the child nodes for the video node
989  nsCOMPtr<nsIDOMNodeList> domNodes;
990  nsresult rv = aVideoStreamNode->GetChildNodes(getter_AddRefs(domNodes));
991  NS_ENSURE_SUCCESS(rv, rv);
992  if (!domNodes) {
993  return NS_OK;
994  }
995 
996  // See if there are any child nodes, leave if not
997  PRUint32 nodeCount;
998  rv = domNodes->GetLength(&nodeCount);
999  NS_ENSURE_SUCCESS(rv, rv);
1000  if (nodeCount == 0) {
1001  return NS_OK;
1002  }
1003 
1004  nsString type;
1005  sbDOMNodeAttributes attributes(aVideoStreamNode);
1006 
1007  // Failure is an option, leaves type blank
1008  attributes.GetValue(NS_LITERAL_STRING("type"), type);
1009 
1010  nsCOMPtr<nsIMutableArray> sizes =
1011  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1",
1012  &rv);
1013  NS_ENSURE_SUCCESS(rv, rv);
1014  nsCOMPtr<sbIDevCapRange> widths;
1015  nsCOMPtr<sbIDevCapRange> heights;
1016  nsCOMPtr<sbIDevCapRange> bitRates;
1017 
1018  PRBool parValuesAreRange = PR_TRUE;
1019  nsCOMPtr<nsIArray> parValueArray;
1020 
1021  PRBool frameRateValuesAreRange = PR_TRUE;
1022  nsCOMPtr<nsIArray> frameRateValuesArray;
1023 
1024  nsCOMPtr<nsIDOMNode> domNode;
1025  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
1026  rv = domNodes->Item(nodeIndex, getter_AddRefs(domNode));
1027  NS_ENSURE_SUCCESS(rv, rv);
1028  nsString name;
1029  rv = domNode->GetNodeName(name);
1030  if (NS_FAILED(rv)) {
1031  continue;
1032  }
1033  if (name.Equals(NS_LITERAL_STRING("explicit-sizes"))) {
1034  rv = ProcessImageSizes(domNode, sizes);
1035  NS_ENSURE_SUCCESS(rv, rv);
1036  }
1037  else if (name.Equals(NS_LITERAL_STRING("widths"))) {
1038  rv = BuildRange(domNode, getter_AddRefs(widths));
1039  NS_ENSURE_SUCCESS(rv, rv);
1040  }
1041  else if (name.Equals(NS_LITERAL_STRING("heights"))) {
1042  rv = BuildRange(domNode, getter_AddRefs(heights));
1043  NS_ENSURE_SUCCESS(rv, rv);
1044  }
1045  else if (name.Equals(NS_LITERAL_STRING("videoPARs")) ||
1046  name.Equals(NS_LITERAL_STRING("videoPAR")))
1047  {
1048  rv = GetFractionRangeValues(domNode,
1049  getter_AddRefs(parValueArray),
1050  &parValuesAreRange);
1051  NS_ENSURE_SUCCESS(rv, rv);
1052  }
1053  else if (name.Equals(NS_LITERAL_STRING("frame-rates"))) {
1054  rv = GetFractionRangeValues(domNode,
1055  getter_AddRefs(frameRateValuesArray),
1056  &frameRateValuesAreRange);
1057  NS_ENSURE_SUCCESS(rv, rv);
1058  }
1059  else if (name.Equals(NS_LITERAL_STRING("bit-rates"))) {
1060  rv = BuildRange(domNode, getter_AddRefs(bitRates));
1061  NS_ENSURE_SUCCESS(rv, rv);
1062  }
1063  }
1064 
1065  nsCOMPtr<sbIDevCapVideoStream> videoStream =
1066  do_CreateInstance(SB_IDEVCAPVIDEOSTREAM_CONTRACTID, &rv);
1067  NS_ENSURE_SUCCESS(rv, rv);
1068 
1069  rv = videoStream->Initialize(NS_ConvertUTF16toUTF8(type),
1070  sizes,
1071  widths,
1072  heights,
1073  parValueArray,
1074  parValuesAreRange,
1075  frameRateValuesArray,
1076  frameRateValuesAreRange,
1077  bitRates);
1078  NS_ENSURE_SUCCESS(rv, rv);
1079 
1080  videoStream.forget(aVideoStream);
1081 
1082  return NS_OK;
1083 }
1084 
1085 nsresult
1086 sbDeviceXMLCapabilities::ProcessAudioStream(nsIDOMNode* aAudioStreamNode,
1087  sbIDevCapAudioStream** aAudioStream)
1088 {
1089  // Retrieve the child nodes for the video node
1090  nsCOMPtr<nsIDOMNodeList> domNodes;
1091  nsresult rv = aAudioStreamNode->GetChildNodes(getter_AddRefs(domNodes));
1092  NS_ENSURE_SUCCESS(rv, rv);
1093  if (!domNodes) {
1094  return NS_OK;
1095  }
1096 
1097  // See if there are any child nodes, leave if not
1098  PRUint32 nodeCount;
1099  rv = domNodes->GetLength(&nodeCount);
1100  NS_ENSURE_SUCCESS(rv, rv);
1101  if (nodeCount == 0) {
1102  return NS_OK;
1103  }
1104 
1105  nsString type;
1106  sbDOMNodeAttributes attributes(aAudioStreamNode);
1107 
1108  // Failure is an option, leaves type blank
1109  attributes.GetValue(NS_LITERAL_STRING("type"), type);
1110 
1111  nsCOMPtr<sbIDevCapRange> bitRates;
1112  nsCOMPtr<sbIDevCapRange> sampleRates;
1113  nsCOMPtr<sbIDevCapRange> channels;
1114 
1115  nsCOMPtr<nsIDOMNode> domNode;
1116  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
1117  rv = domNodes->Item(nodeIndex, getter_AddRefs(domNode));
1118  NS_ENSURE_SUCCESS(rv, rv);
1119  nsString name;
1120  rv = domNode->GetNodeName(name);
1121  if (NS_FAILED(rv)) {
1122  continue;
1123  }
1124  if (name.Equals(NS_LITERAL_STRING("bit-rates"))) {
1125  rv = BuildRange(domNode, getter_AddRefs(bitRates));
1126  NS_ENSURE_SUCCESS(rv, rv);
1127  }
1128  else if (name.Equals(NS_LITERAL_STRING("sample-rates"))) {
1129  rv = BuildRange(domNode, getter_AddRefs(sampleRates));
1130  NS_ENSURE_SUCCESS(rv, rv);
1131  }
1132  else if (name.Equals(NS_LITERAL_STRING("channels"))) {
1133  rv = BuildRange(domNode, getter_AddRefs(channels));
1134  NS_ENSURE_SUCCESS(rv, rv);
1135  }
1136  }
1137 
1138  nsCOMPtr<sbIDevCapAudioStream> audioStream =
1139  do_CreateInstance(SB_IDEVCAPAUDIOSTREAM_CONTRACTID, &rv);
1140  NS_ENSURE_SUCCESS(rv, rv);
1141 
1142  rv = audioStream->Initialize(NS_ConvertUTF16toUTF8(type),
1143  bitRates,
1144  sampleRates,
1145  channels);
1146  NS_ENSURE_SUCCESS(rv, rv);
1147 
1148  audioStream.forget(aAudioStream);
1149 
1150  return NS_OK;
1151 }
1152 
1153 nsresult
1154 sbDeviceXMLCapabilities::ProcessVideoFormat(nsIDOMNode* aVideoFormatNode)
1155 {
1156  nsresult rv;
1157 
1158  sbDOMNodeAttributes attributes(aVideoFormatNode);
1159 
1160  nsString containerType;
1161  rv = attributes.GetValue(NS_LITERAL_STRING("container-type"),
1162  containerType);
1163  if (NS_FAILED(rv)) {
1164  return NS_OK;
1165  }
1166 
1167  nsString isPreferredString;
1168  rv = attributes.GetValue(NS_LITERAL_STRING("preferred"),
1169  isPreferredString);
1170  if (rv != NS_ERROR_NOT_AVAILABLE) { // not found error is ok, leave blank
1171  NS_ENSURE_SUCCESS(rv, rv);
1172  }
1173  PRBool isPreferred = isPreferredString.EqualsLiteral("true");
1174 
1175  // Retrieve the child nodes for the video node
1176  nsCOMPtr<nsIDOMNodeList> domNodes;
1177  rv = aVideoFormatNode->GetChildNodes(getter_AddRefs(domNodes));
1178  NS_ENSURE_SUCCESS(rv, rv);
1179  if (!domNodes) {
1180  return NS_OK;
1181  }
1182 
1183  // See if there are any child nodes, leave if not
1184  PRUint32 nodeCount;
1185  rv = domNodes->GetLength(&nodeCount);
1186  NS_ENSURE_SUCCESS(rv, rv);
1187 
1188  nsCOMPtr<sbIDevCapVideoStream> videoStream;
1189  nsCOMPtr<sbIDevCapAudioStream> audioStream;
1190  nsCOMPtr<nsIDOMNode> domNode;
1191  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
1192  rv = domNodes->Item(nodeIndex, getter_AddRefs(domNode));
1193  NS_ENSURE_SUCCESS(rv, rv);
1194 
1195  nsString name;
1196  rv = domNode->GetNodeName(name);
1197  if (NS_FAILED(rv)) {
1198  continue;
1199  }
1200  if (name.Equals(NS_LITERAL_STRING("video-stream"))) {
1201  ProcessVideoStream(domNode, getter_AddRefs(videoStream));
1202  }
1203  else if (name.Equals(NS_LITERAL_STRING("audio-stream"))) {
1204  ProcessAudioStream(domNode, getter_AddRefs(audioStream));
1205  }
1206  }
1207 
1208  nsCOMPtr<sbIVideoFormatType> videoFormat =
1209  do_CreateInstance(SB_IVIDEOFORMATTYPE_CONTRACTID, &rv);
1210  NS_ENSURE_SUCCESS(rv, rv);
1211 
1212  rv = videoFormat->Initialize(NS_ConvertUTF16toUTF8(containerType),
1213  videoStream,
1214  audioStream);
1215  NS_ENSURE_SUCCESS(rv, rv);
1216 
1217  rv = AddMimeType(sbIDeviceCapabilities::CONTENT_VIDEO, containerType);
1218  NS_ENSURE_SUCCESS(rv, rv);
1219 
1220  if (isPreferred) {
1221  rv = mDeviceCaps->AddPreferredFormatType(
1223  containerType,
1224  videoFormat);
1225  NS_ENSURE_SUCCESS(rv, rv);
1226  }
1227  else {
1229  containerType,
1230  videoFormat);
1231  NS_ENSURE_SUCCESS(rv, rv);
1232  }
1233 
1234  return NS_OK;
1235 }
1236 
1237 nsresult
1238 sbDeviceXMLCapabilities::ProcessVideo(nsIDOMNode * aVideoNode)
1239 {
1240  NS_ENSURE_ARG_POINTER(aVideoNode);
1241 
1242  // Retrieve the child nodes for the video node
1243  nsCOMPtr<nsIDOMNodeList> domNodes;
1244  nsresult rv = aVideoNode->GetChildNodes(getter_AddRefs(domNodes));
1245  NS_ENSURE_SUCCESS(rv, rv);
1246  if (!domNodes) {
1247  return NS_OK;
1248  }
1249 
1250  // See if there are any child nodes, leave if not
1251  PRUint32 nodeCount;
1252  rv = domNodes->GetLength(&nodeCount);
1253  NS_ENSURE_SUCCESS(rv, rv);
1254  if (nodeCount == 0) {
1255  return NS_OK;
1256  }
1257 
1258  rv = AddFunctionType(sbIDeviceCapabilities::FUNCTION_VIDEO_PLAYBACK);
1259  NS_ENSURE_SUCCESS(rv, rv);
1260 
1263  NS_ENSURE_SUCCESS(rv, rv);
1264 
1265  nsCOMPtr<nsIDOMNode> domNode;
1266  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
1267  rv = domNodes->Item(nodeIndex, getter_AddRefs(domNode));
1268  NS_ENSURE_SUCCESS(rv, rv);
1269 
1270  nsString name;
1271  rv = domNode->GetNodeName(name);
1272  if (NS_FAILED(rv)) {
1273  continue;
1274  }
1275 
1276  // Ignore things we don't know about
1277  if (!name.EqualsLiteral("format")) {
1278  continue;
1279  }
1280 
1281  ProcessVideoFormat(domNode);
1282  }
1283  return NS_OK;
1284 }
1285 
1286 nsresult
1287 sbDeviceXMLCapabilities::ProcessPlaylist(nsIDOMNode * aPlaylistNode)
1288 {
1289  NS_ENSURE_ARG_POINTER(aPlaylistNode);
1290 
1291  nsCOMPtr<nsIDOMNodeList> domNodes;
1292  nsresult rv = aPlaylistNode->GetChildNodes(getter_AddRefs(domNodes));
1293  NS_ENSURE_SUCCESS(rv, rv);
1294  if (!domNodes) {
1295  return NS_OK;
1296  }
1297 
1298  PRUint32 nodeCount;
1299  rv = domNodes->GetLength(&nodeCount);
1300  NS_ENSURE_SUCCESS(rv, rv);
1301 
1302  if (nodeCount == 0) {
1303  return NS_OK;
1304  }
1305  //XXXeps it shouldn't be specific to audio. MEDIA_PLAYBACK???
1306  rv = AddFunctionType(sbIDeviceCapabilities::FUNCTION_AUDIO_PLAYBACK);
1307  NS_ENSURE_SUCCESS(rv, rv);
1308 
1311  NS_ENSURE_SUCCESS(rv, rv);
1312 
1313  nsCOMPtr<nsIDOMNode> domNode;
1314  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
1315  rv = domNodes->Item(nodeIndex, getter_AddRefs(domNode));
1316  NS_ENSURE_SUCCESS(rv, rv);
1317 
1318  nsString name;
1319  rv = domNode->GetNodeName(name);
1320  NS_ENSURE_SUCCESS(rv, rv);
1321 
1322  if (!name.EqualsLiteral("format")) {
1323  continue;
1324  }
1325 
1327 
1328  nsString mimeType;
1329  rv = attributes.GetValue(NS_LITERAL_STRING("mime"),
1330  mimeType);
1331  NS_ENSURE_SUCCESS(rv, rv);
1332 
1333  nsString pathSeparator;
1334  rv = attributes.GetValue(NS_LITERAL_STRING("pathSeparator"), pathSeparator);
1335  // If not found, use a void string
1336  if (rv == NS_ERROR_NOT_AVAILABLE) {
1337  pathSeparator.SetIsVoid(PR_TRUE);
1338  } else {
1339  NS_ENSURE_SUCCESS(rv, rv);
1340  }
1341 
1342  rv = AddMimeType(sbIDeviceCapabilities::CONTENT_PLAYLIST, mimeType);
1343  NS_ENSURE_SUCCESS(rv, rv);
1344 
1345  nsCOMPtr<sbIPlaylistFormatType> formatType =
1346  do_CreateInstance(SB_IPLAYLISTFORMATTYPE_CONTRACTID, &rv);
1347  NS_ENSURE_SUCCESS(rv, rv);
1348 
1349  rv = formatType->Initialize(NS_ConvertUTF16toUTF8(pathSeparator));
1350  NS_ENSURE_SUCCESS(rv, rv);
1351 
1353  mimeType,
1354  formatType);
1355  NS_ENSURE_SUCCESS(rv, rv);
1356  }
1357 
1358  return NS_OK;
1359 }
1360 
1361 nsresult
1362 sbDeviceXMLCapabilities::DeviceMatchesCapabilitiesNode
1363  (nsIDOMNode * aCapabilitiesNode,
1364  PRBool * aDeviceMatches)
1365 {
1366  NS_ENSURE_ARG_POINTER(aCapabilitiesNode);
1367  NS_ENSURE_ARG_POINTER(aDeviceMatches);
1368 
1369  PRUint32 nodeCount;
1370  nsresult rv;
1371 
1372  // Get the devices node. Device matches by default if no devices node is
1373  // specified.
1374  nsCOMPtr<nsIDOMNode> devicesNode;
1375  rv = GetFirstChildByTagName(aCapabilitiesNode,
1376  "devices",
1377  getter_AddRefs(devicesNode));
1378  NS_ENSURE_SUCCESS(rv, rv);
1379  if (!devicesNode) {
1380  *aDeviceMatches = PR_TRUE;
1381  return NS_OK;
1382  }
1383 
1384  // If no device was specified, the device doesn't match.
1385  if (!mDevice) {
1386  *aDeviceMatches = PR_FALSE;
1387  return NS_OK;
1388  }
1389 
1390  // Get the device properties.
1391  nsCOMPtr<sbIDeviceProperties> deviceProperties;
1392  rv = mDevice->GetProperties(getter_AddRefs(deviceProperties));
1393  NS_ENSURE_SUCCESS(rv, rv);
1394  nsCOMPtr<nsIPropertyBag2> properties;
1395  rv = deviceProperties->GetProperties(getter_AddRefs(properties));
1396  NS_ENSURE_SUCCESS(rv, rv);
1397 
1398  // Get the devices node child list. Device doesn't match if list is empty.
1399  nsCOMPtr<nsIDOMNodeList> childNodeList;
1400  rv = devicesNode->GetChildNodes(getter_AddRefs(childNodeList));
1401  NS_ENSURE_SUCCESS(rv, rv);
1402  if (!childNodeList) {
1403  *aDeviceMatches = PR_FALSE;
1404  return NS_OK;
1405  }
1406 
1407  // Check each child node for a matching device node.
1408  rv = childNodeList->GetLength(&nodeCount);
1409  NS_ENSURE_SUCCESS(rv, rv);
1410  for (PRUint32 nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
1411  // Get the next child node.
1412  nsCOMPtr<nsIDOMNode> childNode;
1413  rv = childNodeList->Item(nodeIndex, getter_AddRefs(childNode));
1414  NS_ENSURE_SUCCESS(rv, rv);
1415 
1416  // Skip all but device nodes.
1417  nsString nodeName;
1418  rv = childNode->GetNodeName(nodeName);
1419  NS_ENSURE_SUCCESS(rv, rv);
1420  if (!nodeName.EqualsLiteral("device")) {
1421  continue;
1422  }
1423 
1424  // Check if the device matches the device node.
1425  PRBool matches;
1426  rv = DeviceMatchesDeviceNode(childNode, properties, &matches);
1427  NS_ENSURE_SUCCESS(rv, rv);
1428  if (matches) {
1429  *aDeviceMatches = PR_TRUE;
1430  return NS_OK;
1431  }
1432  }
1433 
1434  // No match found.
1435  *aDeviceMatches = PR_FALSE;
1436 
1437  return NS_OK;
1438 }
1439 
1440 nsresult
1441 sbDeviceXMLCapabilities::DeviceMatchesDeviceNode
1442  (nsIDOMNode * aDeviceNode,
1443  nsIPropertyBag2 * aDeviceProperties,
1444  PRBool * aDeviceMatches)
1445 {
1446  NS_ENSURE_ARG_POINTER(aDeviceNode);
1447  NS_ENSURE_ARG_POINTER(aDeviceProperties);
1448  NS_ENSURE_ARG_POINTER(aDeviceMatches);
1449 
1450  nsresult rv;
1451 
1452  // Get the device node attributes.
1453  nsCOMPtr<nsIDOMNamedNodeMap> attributes;
1454  rv = aDeviceNode->GetAttributes(getter_AddRefs(attributes));
1455  NS_ENSURE_SUCCESS(rv, rv);
1456 
1457  // Check if each device node attribute matches the device.
1458  PRBool matches = PR_TRUE;
1459  PRUint32 attributeCount;
1460  rv = attributes->GetLength(&attributeCount);
1461  NS_ENSURE_SUCCESS(rv, rv);
1462  for (PRUint32 attributeIndex = 0;
1463  attributeIndex < attributeCount;
1464  ++attributeIndex) {
1465  // Get the next attribute.
1466  nsCOMPtr<nsIDOMNode> attribute;
1467  rv = attributes->Item(attributeIndex, getter_AddRefs(attribute));
1468  NS_ENSURE_SUCCESS(rv, rv);
1469 
1470  // Get the attribute name.
1471  nsAutoString attributeName;
1472  rv = attribute->GetNodeName(attributeName);
1473  NS_ENSURE_SUCCESS(rv, rv);
1474 
1475  // Get the attribute value.
1476  nsAutoString attributeValue;
1477  rv = attribute->GetNodeValue(attributeValue);
1478  NS_ENSURE_SUCCESS(rv, rv);
1479 
1480  // Get the corresponding device property key.
1481  nsAutoString deviceKey(NS_LITERAL_STRING(SB_DEVICE_PROPERTY_BASE));
1482  deviceKey.Append(attributeName);
1483 
1484  // If the device property key does not exist, the device does not match.
1485  PRBool hasKey;
1486  rv = aDeviceProperties->HasKey(deviceKey, &hasKey);
1487  NS_ENSURE_SUCCESS(rv, rv);
1488  if (!hasKey) {
1489  matches = PR_FALSE;
1490  break;
1491  }
1492 
1493  // Get the device property value.
1494  nsCOMPtr<nsIVariant> deviceValue;
1495  rv = aDeviceProperties->Get(deviceKey, getter_AddRefs(deviceValue));
1496  NS_ENSURE_SUCCESS(rv, rv);
1497 
1498  // If the device property value and the attribute value are not equal, the
1499  // device does not match.
1500  PRBool equal;
1501  rv = sbVariantsEqual(deviceValue, sbNewVariant(attributeValue), &equal);
1502  NS_ENSURE_SUCCESS(rv, rv);
1503  if (!equal) {
1504  matches = PR_FALSE;
1505  break;
1506  }
1507  }
1508 
1509  // Return results.
1510  *aDeviceMatches = matches;
1511 
1512  return NS_OK;
1513 }
1514 
1515 nsresult
1516 sbDeviceXMLCapabilities::GetFirstChildByTagName(nsIDOMNode* aNode,
1517  const char* aTagName,
1518  nsIDOMNode** aChildNode)
1519 {
1520  NS_ENSURE_ARG_POINTER(aTagName);
1521  NS_ENSURE_ARG_POINTER(aChildNode);
1522 
1523  nsresult rv;
1524 
1525  // Get the list of child nodes.
1526  nsCOMPtr<nsIDOMNodeList> childNodeList;
1527  rv = aNode->GetChildNodes(getter_AddRefs(childNodeList));
1528  NS_ENSURE_SUCCESS(rv, rv);
1529 
1530  // Search the children for a matching tag name.
1531  nsAutoString tagName;
1532  tagName.AssignLiteral(aTagName);
1533  PRUint32 childNodeCount;
1534  rv = childNodeList->GetLength(&childNodeCount);
1535  NS_ENSURE_SUCCESS(rv, rv);
1536  for (PRUint32 nodeIndex = 0; nodeIndex < childNodeCount; ++nodeIndex) {
1537  // Get the next child node.
1538  nsCOMPtr<nsIDOMNode> childNode;
1539  rv = childNodeList->Item(nodeIndex, getter_AddRefs(childNode));
1540  NS_ENSURE_SUCCESS(rv, rv);
1541 
1542  // Get the child node name.
1543  nsString nodeName;
1544  rv = childNode->GetNodeName(nodeName);
1545  NS_ENSURE_SUCCESS(rv, rv);
1546 
1547  // Return child node if the tag name matches.
1548  if (nodeName.Equals(tagName)) {
1549  childNode.forget(aChildNode);
1550  return NS_OK;
1551  }
1552  }
1553 
1554  // No child found.
1555  *aChildNode = nsnull;
1556 
1557  return NS_OK;
1558 }
nsresult sbVariantsEqual(nsIVariant *aVariant1, nsIVariant *aVariant2, PRBool *aEqual)
#define SB_IAUDIOFORMATTYPE_CONTRACTID
static nsresult GetStringFractionValues(const nsAString &aString, PRUint32 *aOutNumerator, PRUint32 *aOutDenominator)
const PRUint32 FUNCTION_AUDIO_PLAYBACK
sbDOMNodeAttributes(nsIDOMNode *aNode)
return NS_OK
const PRUint32 FUNCTION_VIDEO_PLAYBACK
#define SB_IMAGESIZE_CONTRACTID
[UNIMPLEMENTED UNTIL AFTER 0.3]
tabData attributes[name]
Songbird Variant Utility Definitions.
onPageChanged aValue
Definition: FeedWriter.js:1395
nsresult Read(sbIDeviceCapabilities *aCapabilities)
#define SB_DEVICE_CAPS_ELEMENT
Songbird Variant Utility Definitions.
void AddPreferredFormatType(in PRUint32 aContentType, in AString aMimeType, in nsISupports aFormatType)
Add a preferred constraint to a mime type (these are used for target formats when transcoding...
#define SB_IIMAGEFORMATTYPE_CONTRACTID
#define SB_IDEVCAPAUDIOSTREAM_CONTRACTID
void AddFormatType(in PRUint32 aContentType, in AString aMimeType, in nsISupports aFormatType)
Add a constraint to a mime type.
function width(ele) rect(ele).width
#define SB_IDEVCAPVIDEOSTREAM_CONTRACTID
var strings
Definition: Info.js:46
#define SONGBIRD_DEVICECAPABILITIES_CONTRACTID
static nsresult GetFractionRangeValues(nsIDOMNode *aDOMNode, nsIArray **aOutCapRangeArray, PRBool *aOutIsRange)
_collectFormDataForFrame aDocument
void nsString_Split(const nsAString &aString, const nsAString &aDelimiter, nsTArray< nsString > &aSubStringArray)
#define SB_DEVICE_PROPERTY_BASE
nsresult GetValue(nsAString const &aName, PRInt32 &aValue)
sbDeviceXMLCapabilities(nsIDOMElement *aRootElement, sbIDevice *aDevice=nsnull)
static nsresult AddCapabilities(sbIDeviceCapabilities *aCapabilities, const char *aXMLCapabilitiesSpec, PRBool *aAddedCapabilities=nsnull, sbIDevice *aDevice=nsnull)
_updateDatepicker height
#define SB_IDEVCAPRANGE_CONTRACTID
let node
static nsresult GetNodeValue(nsIDOMNode *aValueNode, nsAString &aValue)
_updateCookies aName
nsresult GetValue(nsAString const &aName, nsAString &aValue)
countRef value
Definition: FeedWriter.js:1423
#define SB_IVIDEOFORMATTYPE_CONTRACTID
var imageSize
Definition: pageInfo.js:959
static nsresult BuildRange(nsIDOMNode *aRangeNode, sbIDevCapRange **aRange)
#define SB_IPLAYLISTFORMATTYPE_CONTRACTID
static nsresult GetCapabilities(sbIDeviceCapabilities **aCapabilities, nsIDOMDocument *aDocument, sbIDevice *aDevice=nsnull)
#define min(a, b)
_getSelectedPageStyle s i
#define SB_DEVICE_CAPS_NS
sbAutoFreeXPCOMArrayByRef< char ** > sbAutoStringArray
function range(x, y)
Definition: httpd.js:138