sbRemoteMediaListBase.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://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  */
26 
27 #include "sbRemoteAPIUtils.h"
28 #include "sbRemoteMediaListBase.h"
30 #include "sbRemotePlayer.h"
31 #include "sbScriptableFunction.h"
32 
33 #include <sbClassInfoUtils.h>
34 #include <sbIRemoteMediaList.h>
35 #include <sbIMediaItem.h>
36 #include <sbIMediaList.h>
37 #include <sbIMediaListView.h>
38 #include <sbIMediaListViewTreeView.h>
39 #include <sbIWrappedMediaItem.h>
40 #include <sbIWrappedMediaList.h>
41 #include <sbIPropertyManager.h>
42 #include <sbPropertiesCID.h>
43 #include <sbStandardProperties.h>
44 
45 #include <nsAutoPtr.h>
46 #include <nsITreeSelection.h>
47 #include <nsITreeView.h>
48 #include <nsStringGlue.h>
49 #include <prlog.h>
50 
51 // includes for XPCScriptable impl
52 #include <nsNetUtil.h>
53 #include <nsIXPConnect.h>
54 #include <jsapi.h>
55 #include <jsobj.h>
56 #include <sbIPropertyArray.h>
57 #include <nsServiceManagerUtils.h>
58 #include <nsIScriptSecurityManager.h>
59 
60 /*
61  * To log this module, set the following environment variable:
62  * NSPR_LOG_MODULES=sbRemoteMediaList:5
63  */
64 #ifdef PR_LOGGING
65 PRLogModuleInfo* gRemoteMediaListLog = nsnull;
66 #endif
67 
68 #undef LOG
69 #define LOG(args) LOG_LIST(args)
70 
71 #define SB_ENSURE_WITH_JSTHROW( _cx, _rv, _msg ) \
72  if ( NS_FAILED(_rv) ) { \
73  ThrowJSException( _cx, NS_LITERAL_CSTRING(_msg) ); \
74  return JS_FALSE; \
75  }
76 
77 // derived classes must impl nsIClassInfo
88 
90  sbIMediaList* aMediaList,
91  sbIMediaListView* aMediaListView) :
92  mRemotePlayer(aRemotePlayer),
93  mMediaList(aMediaList),
94  mMediaListView(aMediaListView)
95 {
96  NS_ASSERTION(aRemotePlayer, "Null remote player!");
97  NS_ASSERTION(aMediaList, "Null media list!");
98  NS_ASSERTION(aMediaListView, "Null media list view!");
99 
100  mMediaItem = do_QueryInterface(mMediaList);
101  NS_ASSERTION(mMediaItem, "Could not QI media list to media item");
102 
103  mMediaItem->GetLibrary(getter_AddRefs(mLibrary));
104 
105 #ifdef PR_LOGGING
106  if (!gRemoteMediaListLog) {
107  gRemoteMediaListLog = PR_NewLogModule("sbRemoteMediaList");
108  }
109  LOG_LIST(("sbRemoteMediaListBase::sbRemoteMediaListBase()"));
110 #endif
111 }
112 
114 {
115  LOG_LIST(("sbRemoteMediaListBase::~sbRemoteMediaListBase()"));
116 }
117 
118 // ---------------------------------------------------------------------------
119 //
120 // sbISecurityAggregator
121 //
122 // ---------------------------------------------------------------------------
123 
124 NS_IMETHODIMP
125 sbRemoteMediaListBase::GetRemotePlayer(sbIRemotePlayer * *aRemotePlayer)
126 {
127  NS_ENSURE_STATE(mRemotePlayer);
128  NS_ENSURE_ARG_POINTER(aRemotePlayer);
129 
130  nsresult rv;
131  *aRemotePlayer = nsnull;
132 
133  nsCOMPtr<sbIRemotePlayer> remotePlayer;
134 
135  rv = mRemotePlayer->QueryInterface( NS_GET_IID( sbIRemotePlayer ), getter_AddRefs( remotePlayer ) );
136  NS_ENSURE_SUCCESS( rv, rv );
137 
138  remotePlayer.swap( *aRemotePlayer );
139 
140  return NS_OK;
141 }
142 
143 // ---------------------------------------------------------------------------
144 //
145 // sbIWrappedMediaList
146 //
147 // ---------------------------------------------------------------------------
148 
149 already_AddRefed<sbIMediaItem>
151 {
152  nsresult rv;
153 
154  nsCOMPtr<sbIMediaItem> mediaItem = do_QueryInterface(mMediaList, &rv);
155  NS_ASSERTION(mediaItem, "Could not QI list to item");
156 
157  return mediaItem.forget();
158 }
159 
160 already_AddRefed<sbIMediaList>
162 {
163  sbIMediaList* list = mMediaList;
164  NS_ADDREF(list);
165  return list;
166 }
167 
168 // ---------------------------------------------------------------------------
169 //
170 // nsIXPCScriptable
171 //
172 // ---------------------------------------------------------------------------
173 
174 NS_IMETHODIMP
176 {
177  LOG_LIST(("sbRemoteMediaListBase::GetClassName()"));
178  NS_ENSURE_ARG_POINTER(aClassName);
179  *aClassName = ToNewCString( NS_LITERAL_CSTRING("SongbirdMediaList") );
180  NS_ENSURE_TRUE( aClassName, NS_ERROR_OUT_OF_MEMORY );
181  return NS_OK;
182 }
183 
184 NS_IMETHODIMP
185 sbRemoteMediaListBase::GetScriptableFlags( PRUint32 *aScriptableFlags )
186 {
187  LOG_LIST(("sbRemoteMediaListBase::GetScriptableFlags()"));
188  NS_ENSURE_ARG_POINTER(aScriptableFlags);
189  *aScriptableFlags = WANT_NEWRESOLVE |
190  ALLOW_PROP_MODS_DURING_RESOLVE |
191  DONT_ENUM_STATIC_PROPS |
192  DONT_ENUM_QUERY_INTERFACE |
193  DONT_REFLECT_INTERFACE_NAMES ;
194  return NS_OK;
195 }
196 
197 NS_IMETHODIMP
198 sbRemoteMediaListBase::NewResolve( nsIXPConnectWrappedNative *wrapper,
199  JSContext *cx,
200  JSObject *obj,
201  jsval id,
202  PRUint32 flags,
203  JSObject **objp,
204  PRBool *_retval )
205 {
206  LOG_LIST(("sbRemoteMediaListBase::NewResolve()"));
207  NS_ENSURE_ARG_POINTER(_retval);
208  NS_ENSURE_ARG_POINTER(objp);
209 
210  if ( JSVAL_IS_STRING(id) ) {
211  nsDependentString jsid( (PRUnichar *)
212  ::JS_GetStringChars( JSVAL_TO_STRING(id) ),
213  ::JS_GetStringLength( JSVAL_TO_STRING(id) ) );
214 
215  TRACE_LIB(( " resolving %s", NS_LossyConvertUTF16toASCII(jsid).get() ));
216 
217  // If we're being asked for add, define the function and point the
218  // caller to the AddHelper method.
219  if ( jsid.EqualsLiteral("add") ) {
220  JSString *str = JSVAL_TO_STRING(id);
221  JSFunction *fnc = ::JS_DefineFunction( cx,
222  obj,
223  ::JS_GetStringBytes(str),
224  AddHelper,
225  1,
226  JSPROP_ENUMERATE );
227 
228  *objp = obj;
229 
230  return fnc ? NS_OK : NS_ERROR_UNEXPECTED;
231  }
232  }
233  return NS_OK;
234 }
235 
236 // static
237 nsresult
239  const nsACString &aExceptionMsg ) {
240  JSAutoRequest ar(cx);
241 
242  JSString *str = JS_NewStringCopyN( cx,
243  aExceptionMsg.BeginReading(),
244  aExceptionMsg.Length() );
245  if (!str) {
246  // JS_NewStringCopyN reported the error for us.
247  return NS_OK;
248  }
249 
250  JS_SetPendingException( cx, STRING_TO_JSVAL(str) );
251  return NS_OK;
252 }
253 
254 /*
255  * This method is a general helper for the add functionality. Through this
256  * method we support the following types of adding:
257  *
258  * add( item, (opt) boolean );
259  * add( string, (opt) boolean );
260  * add( [ string... ], (opt) boolean );
261  *
262  * We are argc agnostic here, so if you pass in more than 2 args
263  * we ignore them and if the second arg isn't a media item (QI-able to
264  * sbIMediaItem) then we convert it to its boolean representation and use
265  * it as an arg to determine if we should download. We only hard fail in the
266  * case of:
267  *
268  * add( item, item )
269  * add( string, item )
270  * add( [string...], item )
271  * add( [item...], item )
272  * add( [item...] ) - we don't allow arrays of items yet.
273  *
274  * We silently do nothing for these cases:
275  *
276  * add( [] ) - empty array
277  * add( "" ) - empty string
278  * add( number )
279  *
280  */
281 // static
282 JSBool
284  JSObject *obj,
285  uintN argc,
286  jsval *argv,
287  jsval *rval )
288 {
289  // Returning JS_FALSE from this method without setting an exception will
290  // cause XPConnect to hang. Either call ThrowJSExcpeption first, or
291  // return JS_TRUE if you want to fail silently.
292 
293  LOG_LIST(( "sbRemoteMediaListBase::AddHelper() - argc is %d", argc ));
294  nsresult rv;
295 
296  // we expect one or two arguments, less then one is a hard error, for
297  // extra arguments we just ignore them.
298  if ( argc < 1 ) {
299  ThrowJSException( cx, NS_LITERAL_CSTRING("Wrong number of arguments.") );
300  return JS_FALSE;
301  }
302 
303  //
304  // Make sure the object is cleared to call this method
305  //
306 
307  OBJ_TO_INNER_OBJECT(cx, obj);
308 
309  nsCOMPtr<nsIXPConnect> xpc(
310  do_GetService( "@mozilla.org/js/xpc/XPConnect;1", &rv ) );
311  SB_ENSURE_WITH_JSTHROW( cx, rv, "Failed to get XPConnect service." )
312 
313  nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
314  rv = xpc->GetWrappedNativeOfJSObject( cx, obj, getter_AddRefs(wrapper) );
315  SB_ENSURE_WITH_JSTHROW( cx, rv, "No wrapper for native object." )
316 
317  nsCOMPtr<nsISecurityCheckedComponent> checkedComponent(
318  do_QueryWrappedNative( wrapper, &rv ) );
319  SB_ENSURE_WITH_JSTHROW( cx, rv, "Not a checked object.")
320 
321  // do the security check
322  char* access;
323  nsIID iid = NS_GET_IID(nsISupports);
324  rv = checkedComponent->CanCallMethod( &iid,
325  NS_LITERAL_STRING("add").get(),
326  &access );
327 
328  // note that an error return value or empty access means access denied
329  PRBool canCallMethod = NS_SUCCEEDED(rv);
330  if (canCallMethod) {
331  if (!access) {
332  canCallMethod = PR_FALSE;
333  } else {
334  canCallMethod = !strcmp( access, "AllAccess" );
335  NS_Free(access);
336  }
337  }
338 
339  if (!canCallMethod) {
340  ThrowJSException( cx, NS_LITERAL_CSTRING("Permission Denied to call method RemoteMediaList.add()") );
341  return JS_FALSE;
342  }
343 
344  //
345  // Passed the security check, do the work of calling Add() or doing
346  // the additions by hand from the array of strings passed in
347  //
348 
349  // Need to QI ourself to get to our library, create the item, check target
350  nsCOMPtr<sbIMediaItem> selfItem( do_QueryWrappedNative( wrapper, &rv ) );
351  SB_ENSURE_WITH_JSTHROW( cx, rv, "Not a valid MediaItem.")
352 
353  // Find out if we're targetting the main library early, to know if we should
354  // download the track at the end, and have the arg ready for recursion.
355  PRBool isTargetMain = PR_FALSE;
356  rv = SB_IsFromLibName( selfItem, NS_LITERAL_STRING("main"), &isTargetMain );
357  SB_ENSURE_WITH_JSTHROW( cx, rv, "Not able to determine mainLibrariness." );
358 
359  // Find out if we should download the tracking after adding. Only download if
360  // -- the list being added to is in the main library (isTargetMain).
361  // -- the 2nd arg is set to something true and is not a mediaitem
362  JSBool shouldDownload = JS_FALSE;
363  if ( 1 < argc ) {
364  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - argv[1] exists, make sure it's not an item"));
365  if ( JSVAL_IS_OBJECT( argv[1] ) ) {
366 
367  // see if we can get the wrapped native
368  nsCOMPtr<nsIXPConnectWrappedNative> wn;
369  rv = xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT( argv[1] ), getter_AddRefs(wn) );
370  if ( NS_SUCCEEDED(rv) && wn ) {
371  // There is a wrapped native, find out if it's a media item
372  nsCOMPtr<sbIMediaItem> tempItem;
373  tempItem = do_QueryWrappedNative( wn, &rv );
374  if ( NS_SUCCEEDED(rv) ) {
375  // Hard fail so devs don't expect add(item,item) to add multiple items.
376  ThrowJSException( cx, NS_LITERAL_CSTRING("Second arg should NOT be a media item.") );
377  return JS_FALSE;
378  }
379  }
380  }
381 
382  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - argv[1] exists, is not a mediaitem"));
383  if (!JS_ValueToBoolean(cx, argv[1], &shouldDownload)) {
384  shouldDownload = JS_FALSE;
385  }
386 
387  if ( shouldDownload && !isTargetMain ) {
388  // not targetting main library, no download
389  shouldDownload = PR_FALSE;
390  NS_WARNING(("Non-Fatal Error: Tried to download an item to non-mainLibrary."));
391  }
392  }
393 
394  // Need the Aggregator interface to get to the remotePlayer
395  //nsCOMPtr<sbISecurityAggregator> secAgg( do_QueryWrappedNative( wrapper, &rv ) );
396  nsCOMPtr<sbISecurityAggregator> secAgg( do_QueryInterface( selfItem, &rv ) );
397  SB_ENSURE_WITH_JSTHROW( cx, rv, "Object not valid security aggregator.")
398 
399  // Get the remote player
400  nsCOMPtr<sbIRemotePlayer> remotePlayer;
401  rv = secAgg->GetRemotePlayer( getter_AddRefs(remotePlayer) );
402  SB_ENSURE_WITH_JSTHROW( cx, rv, "Could not get RemotePlayer.")
403 
404  // declare here, it gets set inside the next conditional and used aftewards
405  nsCOMPtr<sbIMediaItem> item;
406 
407  JSAutoRequest ar(cx);
408 
409  // Handle the args passed in. If we are passed an array, recurse over the
410  // contents, otherwise set |item| to be the item to add to the target.
411  if ( JSVAL_IS_STRING(argv[0]) ) {
412 
413  // If we have a string arg it should be a URI, use our library to create
414  // an item.
415 
416  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - argv[0] exists, is a string"));
417  LOG_LIST((" length: %d", ::JS_GetStringLength( JSVAL_TO_STRING(argv[0]) ) ) );
418 
419  if ( ::JS_GetStringLength( JSVAL_TO_STRING(argv[0]) ) == 0 ) {
420  // light, silent failure on empty strings
421  return JS_TRUE;
422  }
423 
424  // Convert the JS string into an XPCOM string.
425  nsDependentString url( (PRUnichar *)
426  ::JS_GetStringChars( JSVAL_TO_STRING(argv[0]) ),
427  ::JS_GetStringLength( JSVAL_TO_STRING(argv[0]) ) );
428 
429  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - argv[0] exists, is a string"));
430  LOG_LIST(( " str %s", NS_LossyConvertUTF16toASCII(url).get() ));
431 
432  // Create a URI object to pass into the library for item creation.
433  nsCOMPtr<nsIURI> uri;
434  rv = NS_NewURI( getter_AddRefs(uri), url );
435  SB_ENSURE_WITH_JSTHROW( cx, rv, "Could not create new URI object.")
436 
437  // The item will return an unwrapped library so find out where we came from
438  // and get the appropriately wrapped library from the remotePlayer.
439  nsCOMPtr<sbIRemoteLibrary> library;
440 
441  // isTargetMain set well above
442  if ( isTargetMain ) {
443  // from Main, get the main library
444  rv = remotePlayer->GetMainLibrary( getter_AddRefs(library) );
445  SB_ENSURE_WITH_JSTHROW( cx, rv, "Could not get remote library.")
446  } else {
447  PRBool isTargetWeb = PR_FALSE;
448  rv = SB_IsFromLibName( selfItem, NS_LITERAL_STRING("web"), &isTargetWeb );
449  SB_ENSURE_WITH_JSTHROW( cx, rv, "Not able to determine webLibrariness." );
450 
451  if ( !isTargetMain ) {
452  // from web, get the web library
453  rv = remotePlayer->GetWebLibrary( getter_AddRefs(library) );
454  SB_ENSURE_WITH_JSTHROW( cx, rv, "Could not get web library.")
455  } else {
456  // get the Site Library
457  rv = remotePlayer->GetSiteLibrary( getter_AddRefs(library) );
458  SB_ENSURE_WITH_JSTHROW( cx, rv, "Could not get site library.")
459  }
460  }
461 
462  nsCString uriCStr;
463  rv = uri->GetSpec(uriCStr);
464  SB_ENSURE_WITH_JSTHROW( cx, rv, "Could not get spec from uri.")
465 
466  // Create the item.
467  rv = library->CreateMediaItem( NS_ConvertUTF8toUTF16(uriCStr),
468  getter_AddRefs(item) );
469  SB_ENSURE_WITH_JSTHROW( cx, rv, "Could not create new Media Item.")
470 
471  } else if ( JSVAL_IS_OBJECT(argv[0]) ) {
472  JSObject* jsobj = JSVAL_TO_OBJECT(argv[0]);
473  if (!jsobj) {
474  ThrowJSException( cx, NS_LITERAL_CSTRING("Failed to convert object.") );
475  return JS_FALSE;
476  }
477 
478  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - argv[0] exists, is an object"));
479 
480  if ( JS_IsArrayObject(cx, jsobj) ) {
481  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - argv[0] exists, is an array"));
482 
483  // loop over the array and take each string, create an item.
484  jsuint len;
485  jsval val;
486  if ( JS_GetArrayLength( cx, jsobj, &len ) ) {
487  for ( JSUint32 index = 0; index < len; index++ ) {
488  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - checking index; %d.", index));
489  if ( JS_GetElement( cx, jsobj, index, &val ) ) {
490  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - found a val in the array."));
491  // got the element
492  if ( JSVAL_IS_STRING(val) ) {
493  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - found a val in the array, recursing"));
494 
495  // We're going to recurse, keep args to a set we support
496  uintN length = (shouldDownload ? 2 : 1);
497  jsval *newval = (jsval*) JS_malloc( cx, sizeof(jsval) * length );
498  newval[0] = val;
499  if (shouldDownload) {
500  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - should download, setting value"));
501  newval[1] = BOOLEAN_TO_JSVAL(shouldDownload);
502  }
503  if ( !AddHelper( cx, obj, length, newval, rval ) ) {
504  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - failed return from recursing"));
505  // AddHelper will already have set the exception for us.
506  JS_free( cx, newval );
507  return JS_FALSE;
508  }
509  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - successful return from recursing"));
510  JS_free( cx, newval );
511  } else {
512  ThrowJSException( cx, NS_LITERAL_CSTRING("Arrays should only contain strings.") );
513  return JS_FALSE;
514  }
515  }
516  }
517  }
518  } else {
519  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - argv[0] exists, is an object, not an array"));
520 
521  // check to make sure it's an sbIRemoteMediaItem
522  nsCOMPtr<nsIXPConnectWrappedNative> wn;
523  rv = xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT( argv[0] ), getter_AddRefs(wn) );
524  SB_ENSURE_WITH_JSTHROW( cx, rv, "Failed to get wrapper for argument." )
525 
526  item = do_QueryWrappedNative( wn, &rv );
527  SB_ENSURE_WITH_JSTHROW( cx, rv, "Argument not a proper MediaItem." );
528 
529  }
530  } else {
531  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - argv[0] not a string, or object, fail silently"));
532  return JS_TRUE;
533  }
534 
535  // If we have an item here, add it to ourself
536  // this works if we are adding an item that was created outside of ourself.
537  // If we are adding a mainlib item to the mainlib/list and downloading then
538  // it doesn't work because an add isn't done, instead we need to just download
539  // it.
540  if ( item ) {
541  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - Have item to add."));
542 
543  nsCOMPtr<sbIMediaList> selfList( do_QueryWrappedNative( wrapper, &rv ) );
544  SB_ENSURE_WITH_JSTHROW( cx, rv, "Object not valid MediaList.")
545 
546  // we only download into the mainLib with the correct param (see above)
547  if (shouldDownload) {
548  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - Downloading item."));
549 
550  // We need to know if this is the main library for downloading
551  PRBool isItemMain = PR_FALSE;
552  rv = SB_IsFromLibName( item, NS_LITERAL_STRING("main"), &isItemMain );
553  SB_ENSURE_WITH_JSTHROW( cx, rv, "Not able to determine mainLibrariness." );
554 
555  if (!isItemMain) {
556  // set autodownload so addition will kick off a download
557  rv = item->SetProperty( NS_LITERAL_STRING(SB_PROPERTY_ENABLE_AUTO_DOWNLOAD),
558  NS_LITERAL_STRING("1") );
559  } else {
560  // item is already in mainLib so just add it to the download list
561  rv = remotePlayer->DownloadItem(item);
562  }
563 
564  if (NS_FAILED(rv)) {
565  // don't throw if we can't download
566  NS_WARNING(("sbRemoteMediaListBase::AddHelper() - Failed to download."));
567  }
568  } else {
569  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - Not downloading"));
570  }
571 
572  rv = selfList->Add(item);
573  if ( NS_FAILED(rv) ) {
574  NS_WARNING(("sbRemoteMediaListBase::AddHelper() - Failed to add the item."));
575  }
576  }
577 
578  LOG_LIST(("sbRemoteMediaListBase::AddHelper() - returning JS_TRUE"));
579  return JS_TRUE;
580 }
581 
582 // ---------------------------------------------------------------------------
583 //
584 // sbIMediaList
585 //
586 // ---------------------------------------------------------------------------
587 
588 NS_IMETHODIMP
590  sbIMediaItem** _retval)
591 {
592  NS_ENSURE_ARG_POINTER(_retval);
593 
594  nsCOMPtr<sbIMediaItem> item;
595  nsresult rv = mMediaList->GetItemByGuid(aGuid, getter_AddRefs(item));
596  if (rv == NS_ERROR_NOT_AVAILABLE) {
597  // This means that the item doesn't exist. Return null to be friendly to the
598  // nice JS callers.
599  *_retval = nsnull;
600  return NS_OK;
601  }
602  NS_ENSURE_SUCCESS(rv, rv);
603 
604  return SB_WrapMediaItem(mRemotePlayer, item, _retval);
605 }
606 
607 NS_IMETHODIMP
609  sbIMediaItem **_retval)
610 {
611  NS_ENSURE_ARG_POINTER(_retval);
612 
613  nsCOMPtr<sbIMediaItem> item;
614  nsresult rv = mMediaList->GetItemByIndex(aIndex, getter_AddRefs(item));
615  if (rv == NS_ERROR_NOT_AVAILABLE) {
616  // This means that the item doesn't exist. Return null to be friendly to the
617  // nice JS callers.
618  *_retval = nsnull;
619  return NS_OK;
620  }
621  NS_ENSURE_SUCCESS(rv, rv);
622 
623  return SB_WrapMediaItem(mRemotePlayer, item, _retval);
624 }
625 
626 NS_IMETHODIMP
627 sbRemoteMediaListBase::GetItemCountByProperty(const nsAString & aPropertyID,
628  const nsAString & aPropertyValue,
629  PRUint32 *_retval)
630 {
631  return NS_ERROR_NOT_IMPLEMENTED;
632 }
633 
634 NS_IMETHODIMP
636 {
637  return NS_ERROR_NOT_IMPLEMENTED;
638 }
639 
640 NS_IMETHODIMP
642  PRUint16 aEnumerationType)
643 {
644  NS_ENSURE_ARG_POINTER(aEnumerationListener);
645 
646  nsRefPtr<sbMediaListEnumerationListenerWrapper> wrapper(
647  new sbMediaListEnumerationListenerWrapper(mRemotePlayer, aEnumerationListener));
648  NS_ENSURE_TRUE(wrapper, NS_ERROR_OUT_OF_MEMORY);
649 
650  nsresult rv = mMediaList->EnumerateAllItems(wrapper, aEnumerationType);
651  NS_ENSURE_SUCCESS(rv, rv);
652 
653  return NS_OK;
654 }
655 
656 NS_IMETHODIMP
658  const nsAString& aPropertyValue,
659  sbIMediaListEnumerationListener* aEnumerationListener,
660  PRUint16 aEnumerationType)
661 {
662  NS_ENSURE_ARG_POINTER(aEnumerationListener);
663 
664  nsRefPtr<sbMediaListEnumerationListenerWrapper> wrapper(
665  new sbMediaListEnumerationListenerWrapper(mRemotePlayer, aEnumerationListener));
666  NS_ENSURE_TRUE(wrapper, NS_ERROR_OUT_OF_MEMORY);
667 
668  nsresult rv = mMediaList->EnumerateItemsByProperty(aPropertyID,
669  aPropertyValue,
670  wrapper,
671  aEnumerationType);
672  NS_ENSURE_SUCCESS(rv, rv);
673 
674  return NS_OK;
675 }
676 
677 NS_IMETHODIMP
679  PRUint32 aStartFrom,
680  PRUint32* _retval)
681 {
682  NS_ENSURE_ARG_POINTER(aMediaItem);
683  NS_ENSURE_ARG_POINTER(_retval);
684 
685  nsCOMPtr<sbIMediaItem> mediaItem;
686  nsresult rv = SB_WrapMediaItem(mRemotePlayer,
687  aMediaItem,
688  getter_AddRefs(mediaItem));
689  NS_ENSURE_SUCCESS(rv, rv);
690 
691  return mMediaList->IndexOf(mediaItem, aStartFrom, _retval);
692 }
693 
694 NS_IMETHODIMP
696  PRUint32 aStartFrom,
697  PRUint32* _retval)
698 {
699  NS_ENSURE_ARG_POINTER(aMediaItem);
700  NS_ENSURE_ARG_POINTER(_retval);
701 
702  nsCOMPtr<sbIMediaItem> mediaItem;
703  nsresult rv = SB_WrapMediaItem(mRemotePlayer,
704  aMediaItem,
705  getter_AddRefs(mediaItem));
706  NS_ENSURE_SUCCESS(rv, rv);
707 
708  return mMediaList->LastIndexOf(mediaItem, aStartFrom, _retval);
709 }
710 
711 NS_IMETHODIMP
712 sbRemoteMediaListBase::Contains(sbIMediaItem* aMediaItem, PRBool* _retval)
713 {
714  NS_ENSURE_ARG_POINTER(aMediaItem);
715  NS_ENSURE_ARG_POINTER(_retval);
716 
717  nsCOMPtr<sbIMediaItem> mediaItem;
718  nsresult rv = SB_WrapMediaItem(mRemotePlayer,
719  aMediaItem,
720  getter_AddRefs(mediaItem));
721  NS_ENSURE_SUCCESS(rv, rv);
722 
723  return mMediaList->Contains(mediaItem, _retval);
724 }
725 
726 NS_IMETHODIMP
728 {
729  return AddItem(aMediaItem, nsnull);
730 }
731 
732 NS_IMETHODIMP
734  sbIMediaItem ** aNewItem)
735 {
736  LOG_LIST(("sbRemoteMediaListBase::Add()"));
737  NS_ENSURE_ARG_POINTER(aMediaItem);
738 
739  nsresult rv;
740  nsCOMPtr<sbIWrappedMediaItem> wrappedMediaItem =
741  do_QueryInterface(aMediaItem, &rv);
742  NS_ENSURE_SUCCESS(rv, rv);
743 
744  nsCOMPtr<sbIMediaItem> internalMediaItem = wrappedMediaItem->GetMediaItem();
745  NS_ENSURE_TRUE(internalMediaItem, NS_ERROR_FAILURE);
746 
747  rv = mMediaList->AddItem(internalMediaItem, aNewItem);
748  if (NS_SUCCEEDED(rv)) {
749  LOG_LIST(("sbRemoteMediaListBase::Add() - added the item"));
750  mRemotePlayer->GetNotificationManager()
752  }
753  NS_ENSURE_SUCCESS(rv, rv);
754 
755  return NS_OK;
756 }
757 
758 NS_IMETHODIMP
760 {
761  NS_ENSURE_ARG_POINTER(aMediaList);
762 
763  nsresult rv;
764  nsCOMPtr<sbIWrappedMediaList> wrappedMediaList =
765  do_QueryInterface(aMediaList, &rv);
766  NS_ENSURE_SUCCESS(rv, rv);
767 
768  nsCOMPtr<sbIMediaList> internalMediaList = wrappedMediaList->GetMediaList();
769  NS_ENSURE_TRUE(internalMediaList, NS_ERROR_FAILURE);
770 
771  rv = mMediaList->AddAll(internalMediaList);
772  if (NS_SUCCEEDED(rv)) {
773  mRemotePlayer->GetNotificationManager()
775  }
776  NS_ENSURE_SUCCESS(rv, rv);
777 
778  return NS_OK;
779 }
780 
781 NS_IMETHODIMP
783 {
784  return AddMediaItems(aMediaItems, nsnull, PR_FALSE);
785 }
786 
787 NS_IMETHODIMP
789  sbIAddMediaItemsListener * aListener,
790  PRBool aAsync)
791 {
792  NS_ENSURE_ARG_POINTER(aMediaItems);
793 
794  // We don't do async, though we might be able to. Since it wasn't implemented
795  // before in AddSomeAsync, I elected not allow it for now.
796  NS_ENSURE_FALSE(aAsync, NS_ERROR_NOT_IMPLEMENTED);
797 
798  nsRefPtr<sbUnwrappingSimpleEnumerator> wrapper(
799  new sbUnwrappingSimpleEnumerator(aMediaItems));
800  NS_ENSURE_TRUE(wrapper, NS_ERROR_OUT_OF_MEMORY);
801 
802  nsresult rv = mMediaList->AddMediaItems(wrapper, aListener, aAsync);
803  if (NS_SUCCEEDED(rv)) {
804  mRemotePlayer->GetNotificationManager()
806  }
807  NS_ENSURE_SUCCESS(rv, rv);
808 
809  return NS_OK;
810 }
811 
812 NS_IMETHODIMP
814 {
815  NS_ENSURE_ARG_POINTER(aMediaItem);
816  LOG_LIST(("sbRemoteMediaListBase::Remove()"));
817 
818  nsresult rv;
819  nsCOMPtr<sbIWrappedMediaItem> wrappedMediaItem =
820  do_QueryInterface(aMediaItem, &rv);
821  NS_ENSURE_SUCCESS(rv, rv);
822 
823  nsCOMPtr<sbIMediaItem> internalMediaItem = wrappedMediaItem->GetMediaItem();
824  NS_ENSURE_TRUE(internalMediaItem, NS_ERROR_FAILURE);
825 
826  rv = mMediaList->Remove(internalMediaItem);
827  if (NS_SUCCEEDED(rv)) {
828  mRemotePlayer->GetNotificationManager()
830  }
831  NS_ENSURE_SUCCESS(rv, rv);
832 
833  return NS_OK;
834 }
835 
836 NS_IMETHODIMP
838  nsIStringEnumerator **_retval)
839 {
840  NS_ENSURE_ARG_POINTER(_retval);
841  LOG_LIST(("sbRemoteMediaListBase::GetDistinctValuesForProperty()"));
842 
843  // get enumeration of stuff
844  nsCOMPtr<nsIStringEnumerator> enumeration;
845  nsresult rv =
846  mMediaList->GetDistinctValuesForProperty( aPropertyID,
847  getter_AddRefs(enumeration) );
848  NS_ENSURE_SUCCESS( rv, rv );
849 
850  nsRefPtr<sbRemoteWrappingStringEnumerator> wrapped(
851  new sbRemoteWrappingStringEnumerator( enumeration, mRemotePlayer ) );
852  NS_ENSURE_TRUE( wrapped, NS_ERROR_OUT_OF_MEMORY );
853 
854  rv = wrapped->Init();
855  NS_ENSURE_SUCCESS( rv, rv );
856 
857  NS_ADDREF( *_retval = wrapped );
858 
859  return NS_OK;
860 }
861 
862 // ---------------------------------------------------------------------------
863 //
864 // sbIRemoteMediaList
865 //
866 // ---------------------------------------------------------------------------
867 
868 NS_IMETHODIMP
869 sbRemoteMediaListBase::GetView( sbIMediaListView **aView )
870 {
871  LOG_LIST(("sbRemoteMediaListBase::GetView()"));
872  NS_ENSURE_ARG_POINTER(aView);
873  NS_ASSERTION(mMediaListView, "No View");
874  NS_ADDREF( *aView = mMediaListView );
875  return NS_OK;
876 }
877 
878 
879 // ---------------------------------------------------------------------------
880 //
881 // sbIMediaListEnumerationListener
882 //
883 // ---------------------------------------------------------------------------
884 
887 
890  mRemotePlayer(aRemotePlayer),
891  mWrapped(aWrapped)
892 {
893  NS_ASSERTION(aRemotePlayer, "Null remote player!");
894  NS_ASSERTION(aWrapped, "Null wrapped enumerator!");
895 }
896 
897 NS_IMETHODIMP
898 sbMediaListEnumerationListenerWrapper::OnEnumerationBegin(sbIMediaList *aMediaList,
899  PRUint16 *_retval)
900 {
901  NS_ENSURE_ARG_POINTER(aMediaList);
902  NS_ENSURE_ARG_POINTER(_retval);
903 
904  nsCOMPtr<sbIMediaList> mediaList;
905  nsresult rv = SB_WrapMediaList(mRemotePlayer,
906  aMediaList,
907  getter_AddRefs(mediaList));
908  NS_ENSURE_SUCCESS(rv, rv);
909 
910  return mWrapped->OnEnumerationBegin(mediaList, _retval);
911 }
912 
913 NS_IMETHODIMP
914 sbMediaListEnumerationListenerWrapper::OnEnumeratedItem(sbIMediaList *aMediaList,
915  sbIMediaItem *aMediaItem,
916  PRUint16 *_retval)
917 {
918  NS_ENSURE_ARG_POINTER(aMediaList);
919  NS_ENSURE_ARG_POINTER(aMediaItem);
920  NS_ENSURE_ARG_POINTER(_retval);
921 
922  nsCOMPtr<sbIMediaList> mediaList;
923  nsresult rv = SB_WrapMediaList(mRemotePlayer,
924  aMediaList,
925  getter_AddRefs(mediaList));
926  NS_ENSURE_SUCCESS(rv, rv);
927 
928  nsCOMPtr<sbIMediaItem> mediaItem;
929  rv = SB_WrapMediaItem(mRemotePlayer, aMediaItem, getter_AddRefs(mediaItem));
930  NS_ENSURE_SUCCESS(rv, rv);
931 
932  return mWrapped->OnEnumeratedItem(mediaList, mediaItem, _retval);
933 }
934 
935 NS_IMETHODIMP
936 sbMediaListEnumerationListenerWrapper::OnEnumerationEnd(sbIMediaList *aMediaList,
937  nsresult aStatusCode)
938 {
939  NS_ENSURE_ARG_POINTER(aMediaList);
940 
941  nsCOMPtr<sbIMediaList> mediaList;
942  nsresult rv = SB_WrapMediaList(mRemotePlayer,
943  aMediaList,
944  getter_AddRefs(mediaList));
945  NS_ENSURE_SUCCESS(rv, rv);
946 
947  return mWrapped->OnEnumerationEnd(mediaList, aStatusCode);;
948 }
949 
950 // ---------------------------------------------------------------------------
951 //
952 // nsISimpleEnumerator
953 //
954 // ---------------------------------------------------------------------------
955 
957 
959  mWrapped(aWrapped)
960 {
961  NS_ASSERTION(aWrapped, "Null wrapped enumerator!");
962 }
963 
964 NS_IMETHODIMP
965 sbUnwrappingSimpleEnumerator::HasMoreElements(PRBool *_retval)
966 {
967  NS_ENSURE_ARG_POINTER(_retval);
968 
969  return mWrapped->HasMoreElements(_retval);
970 }
971 
972 NS_IMETHODIMP
973 sbUnwrappingSimpleEnumerator::GetNext(nsISupports **_retval)
974 {
975  NS_ENSURE_ARG_POINTER(_retval);
976 
977  nsresult rv;
978 
979  nsCOMPtr<nsISupports> supports;
980  rv = mWrapped->GetNext(getter_AddRefs(supports));
981  NS_ENSURE_SUCCESS(rv, rv);
982 
983  // if it's an indexed mediaItem, get the wrapped internal item.
984  nsCOMPtr<sbIIndexedMediaItem> indexedMediaItem = do_QueryInterface(supports, &rv);
985  if (NS_SUCCEEDED(rv)) {
986  nsCOMPtr<sbIMediaItem> item;
987  indexedMediaItem->GetMediaItem( getter_AddRefs(item) );
988  NS_ENSURE_SUCCESS( rv, rv );
989 
990  // make the supports that item
991  supports = do_QueryInterface( item, &rv );
992  NS_ENSURE_SUCCESS( rv, rv );
993  }
994 
995  nsCOMPtr<sbIWrappedMediaList> mediaList = do_QueryInterface(supports, &rv);
996  if (NS_SUCCEEDED(rv)) {
997  *_retval = mediaList->GetMediaList().get();
998  return NS_OK;
999  }
1000 
1001  nsCOMPtr<sbIWrappedMediaItem> mediaItem = do_QueryInterface(supports, &rv);
1002  if (NS_SUCCEEDED(rv)) {
1003  *_retval = mediaItem->GetMediaItem().get();
1004  return NS_OK;
1005  }
1006 
1007  return NS_ERROR_UNEXPECTED;
1008 }
#define SB_ENSURE_WITH_JSTHROW(_cx, _rv, _msg)
static nsresult SB_WrapMediaList(sbRemotePlayer *aRemotePlayer, sbIMediaList *aMediaList, sbIMediaList **aRemoteMediaList)
return NS_OK
nsCOMPtr< sbIMediaListView > mMediaListView
Interface used to enumerate the items in a media list.
NS_IMETHOD LastIndexOf(sbIMediaItem *aMediaItem, PRUint32 aStartFrom, PRUint32 *_retval)
NS_IMPL_ISUPPORTS1(sbMediaListEnumerationListenerWrapper, sbIMediaListEnumerationListener) sbMediaListEnumerationListenerWrapper
NS_IMETHOD GetScriptableFlags(PRUint32 *aScriptableFlags)
sbDeviceFirmwareAutoCheckForUpdate prototype flags
readonly attribute sbIRemotePlayer remotePlayer
This interface is a composition of many of our other interfaces with the goal of exposing a more web-...
readonly attribute sbILibrary library
The library that this media item is contained in.
A brief description of the contents of this interface.
nsISecurityCheckedComponent
A distinct view on a given media list.
NS_IMETHOD AddItem(sbIMediaItem *aMediaItem, sbIMediaItem **aNewItem)
#define LOG_LIST(args)
NS_IMETHOD GetItemCountByProperty(const nsAString &aPropertyID, const nsAString &aPropertyValue, PRUint32 *_retval)
readonly attribute unsigned long length
Returns the length of the list.
NS_IMETHOD EnumerateItemsByProperty(const nsAString &aPropertyID, const nsAString &aPropertyValue, sbIMediaListEnumerationListener *aEnumerationListener, PRUint16 aEnumerationType)
static nsresult SB_IsFromLibName(sbIMediaItem *aMediaItem, const nsAString &aLibName, PRBool *aIsFromLib)
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, jsval id, PRUint32 flags, JSObject **objp, PRBool *_retval)
#define SB_PROPERTY_ENABLE_AUTO_DOWNLOAD
A marker interface for objects that aggregate the security mixin.
nsCOMPtr< sbIMediaList > mMediaList
General interface to data resources.
this _dialogInput val(dateText)
nsCOMPtr< sbILibrary > mLibrary
NS_IMETHOD AddAll(sbIMediaList *aMediaList)
NS_IMETHOD Add(sbIMediaItem *aMediaItem)
NS_IMETHOD GetItemByGuid(const nsAString &aGuid, sbIMediaItem **_retval)
NS_IMETHOD GetListContentType(PRUint16 *_retval)
NS_IMETHOD GetDistinctValuesForProperty(const nsAString &aPropertyID, nsIStringEnumerator **_retval)
#define TRACE_LIB(args)
var uri
Definition: FeedWriter.js:1135
function url(spec)
NS_IMETHOD Remove(sbIMediaItem *aMediaItem)
NS_IMETHOD IndexOf(sbIMediaItem *aMediaItem, PRUint32 aStartFrom, PRUint32 *_retval)
NS_IMPL_ISUPPORTS9(sbRemoteMediaListBase, nsISecurityCheckedComponent, nsIXPCScriptable, sbISecurityAggregator, sbIRemoteMediaList, sbIMediaList, sbIWrappedMediaList, sbIWrappedMediaItem, sbIMediaItem, sbILibraryResource) sbRemoteMediaListBase
NS_IMETHOD AddMediaItems(nsISimpleEnumerator *aMediaItems, sbIAddMediaItemsListener *aListener, PRBool aAsync)
NS_IMETHOD Contains(sbIMediaItem *aMediaItem, PRBool *_retval)
virtual already_AddRefed< sbIMediaList > GetMediaList()
static nsresult SB_WrapMediaItem(sbRemotePlayer *aRemotePlayer, sbIMediaItem *aMediaItem, sbIMediaItem **aRemoteMediaItem)
NS_IMETHOD GetClassName(char **aClassName)
virtual already_AddRefed< sbIMediaItem > GetMediaItem()
Interface that defines a single item of media in the system.
NS_IMETHOD AddSome(nsISimpleEnumerator *aMediaItems)
NS_IMETHOD EnumerateAllItems(sbIMediaListEnumerationListener *aEnumerationListener, PRUint16 aEnumerationType)
nsRefPtr< sbRemotePlayer > mRemotePlayer
static JSBool AddHelper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
An interface to control a media list from remote web pages.
NS_IMETHOD GetItemByIndex(PRUint32 aIndex, sbIMediaItem **_retval)
static nsresult ThrowJSException(JSContext *cx, const nsACString &aExceptionMsg)