sbRemoteLibraryBase.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 "sbRemoteLibraryBase.h"
28 #include "sbRemotePlayer.h"
29 
30 #include <nsICategoryManager.h>
31 #include <nsIDocument.h>
32 #include <nsIDOMDocument.h>
33 #include <nsIDOMDocumentEvent.h>
34 #include <nsIDOMEvent.h>
35 #include <nsIDOMEventTarget.h>
36 #include <nsIDOMWindow.h>
37 #include <nsIFile.h>
38 #include <nsIMutableArray.h>
39 #include <nsIObserver.h>
40 #include <nsIPrefService.h>
41 #include <nsIPresShell.h>
42 #include <nsISimpleEnumerator.h>
43 #include <nsIStringBundle.h>
44 #include <nsIStringEnumerator.h>
45 #include <nsISupportsPrimitives.h>
46 #include <nsIWindowWatcher.h>
47 #include <sbILibrary.h>
48 #include <sbILibraryConstraints.h>
49 #include <sbILibraryManager.h>
50 #include <sbIFilterableMediaListView.h>
51 #include <sbIMediaList.h>
52 #include <sbIMediaListView.h>
53 #include <sbIFileMetadataService.h>
54 #include <sbIPlaylistReader.h>
55 #include <sbIPropertyArray.h>
56 #include <sbIWrappedMediaItem.h>
57 #include <sbIWrappedMediaList.h>
58 #include <sbIJobProgress.h>
59 
60 #include <jsapi.h>
61 #include <nsArrayEnumerator.h>
62 #include <nsCOMArray.h>
63 #include <nsEnumeratorUtils.h>
64 #include <nsEventDispatcher.h>
65 #include <nsNetUtil.h>
66 #include <nsServiceManagerUtils.h>
67 #include <nsStringGlue.h>
68 #include <nsTArray.h>
69 #include <nsTHashtable.h>
70 #include <prlog.h>
71 #include <sbPropertiesCID.h>
72 #include "sbRemoteMediaItem.h"
73 #include "sbRemoteMediaList.h"
74 #include "sbRemoteSiteMediaList.h"
75 #include "sbRemoteAPIUtils.h"
76 #include "sbScriptableFilter.h"
78 #include "sbScriptableFunction.h"
80 #include <sbStandardProperties.h>
81 #include "sbURIChecker.h"
82 #include <sbILibraryStatistics.h>
83 
84 /*
85  * To log this module, set the following environment variable:
86  * NSPR_LOG_MODULES=sbRemoteLibrary:5
87  */
88 #ifdef PR_LOGGING
89 PRLogModuleInfo* gRemoteLibraryLog = nsnull;
90 #endif
91 
92 #undef LOG
93 #define LOG(args) LOG_LIB(args)
94 #define TRACE(args) TRACE_LIBS(args)
95 
96 // Observer for the PlaylistReader that notifies the callback and optionally
97 // launches a metadata job when the playlist is loaded.
99 {
100 public:
102 
104  sbICreateMediaListCallback* aCallback,
105  PRBool aShouldScan) :
106  mRemotePlayer(aRemotePlayer),
107  mCallback(aCallback),
108  mShouldScan(aShouldScan)
109  {
110  NS_ASSERTION(aRemotePlayer, "aRemotePlayer is null");
111  NS_ASSERTION(aCallback, "aCallback is null");
112  }
113 
114  NS_IMETHODIMP Observe( nsISupports *aSubject,
115  const char *aTopic,
116  const PRUnichar *aData)
117  {
118  NS_ENSURE_ARG_POINTER(aSubject);
119  LOG(( "sbPlaylistReaderObserver::Observe(%s)", aTopic ));
120 
121  nsresult rv;
122 
123  nsCOMPtr<sbIMediaList> mediaList ( do_QueryInterface( aSubject, &rv ) );
124  NS_ENSURE_SUCCESS(rv, rv);
125 
126  PRUint32 length;
127  rv = mediaList->GetLength( &length );
128  NS_ENSURE_SUCCESS(rv, rv);
129 
130  if (mShouldScan && length) {
131 
132  nsCOMPtr<nsIMutableArray> mediaItems =
133  do_CreateInstance( "@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv );
134  NS_ENSURE_SUCCESS(rv, rv);
135 
136  for ( PRUint32 index = 0; index < length; index++ ) {
137 
138  nsCOMPtr<sbIMediaItem> item;
139  rv = mediaList->GetItemByIndex( index, getter_AddRefs ( item ) );
140  NS_ENSURE_SUCCESS(rv, rv);
141 
142  rv = mediaItems->AppendElement( item, PR_FALSE );
143  NS_ENSURE_SUCCESS(rv, rv);
144  }
145 
146  nsCOMPtr<sbIFileMetadataService> metadataService =
147  do_GetService( "@songbirdnest.com/Songbird/FileMetadataService;1", &rv );
148  NS_ENSURE_SUCCESS(rv, rv);
149  nsCOMPtr<sbIJobProgress> job;
150 
151  rv = metadataService->Read( mediaItems, getter_AddRefs(job) );
152  NS_ENSURE_SUCCESS(rv, rv);
153  }
154 
155  if (mCallback) {
156  nsCOMPtr<sbIMediaList> wrappedList;
157  rv = SB_WrapMediaList(mRemotePlayer,
158  mediaList,
159  getter_AddRefs(wrappedList));
160  NS_ENSURE_SUCCESS(rv, rv);
161  mCallback->OnCreated(wrappedList); // ignore the return value
162 
163  /* The observer is only ever called on playlist creation, so we don't
164  * need to hang on to the callback; clear it out now to help reduce
165  * leakage (this lets things be GCed earlier).
166  */
167  mCallback = nsnull;
168  }
169 
170  return NS_OK;
171  }
172 
173 private:
174 
175  nsRefPtr<sbRemotePlayer> mRemotePlayer;
176  nsCOMPtr<sbICreateMediaListCallback> mCallback;
177  PRBool mShouldScan;
178 };
180 
182 {
183  public:
185 
186  sbRemoteLibraryEnumCallback( nsCOMArray<sbIMediaItem>& aArray ) :
187  mArray(aArray) { }
188 
189  NS_IMETHODIMP OnEnumerationBegin( sbIMediaList*, PRUint16* _retval )
190  {
191  NS_ENSURE_ARG(_retval);
193  return NS_OK;
194  }
195  NS_IMETHODIMP OnEnumerationEnd( sbIMediaList*, nsresult )
196  {
197  return NS_OK;
198  }
199  NS_IMETHODIMP OnEnumeratedItem( sbIMediaList*, sbIMediaItem* aItem, PRUint16* _retval )
200  {
201  NS_ENSURE_ARG(_retval);
203 
204  mArray.AppendObject( aItem );
205 
206  return NS_OK;
207  }
208  private:
209  nsCOMArray<sbIMediaItem>& mArray;
210 };
212 
213 
217  sbRemoteLibraryScopeURLSet( const nsACString& path,
218  sbIMediaItem* item )
219  : scopePath(path),
220  item(item),
221  length(path.Length())
222  {
223  NS_ASSERTION( item, "Null pointer!");
224  }
225 
226  PRBool operator ==(const sbRemoteLibraryScopeURLSet& rhs) const
227  {
228  return (length == rhs.length) && (scopePath.Equals(rhs.scopePath));
229  }
230 
231  PRBool operator <(const sbRemoteLibraryScopeURLSet& rhs) const
232  {
233  return length < rhs.length;
234  }
235 
236  const nsCString scopePath;
237  const nsCOMPtr<sbIMediaItem> item;
238  const PRUint32 length;
239 };
240 
241 
247  sbIMediaList,
250  sbIMediaItem,
254 
256  mShouldScan(PR_TRUE),
257  mEnumerationResult(NS_ERROR_NOT_INITIALIZED),
258  mRemotePlayer(aRemotePlayer),
259  mIgnoreHiddenPlaylists(PR_TRUE),
260  mAllowDuplicates(PR_FALSE)
261 {
262  NS_ASSERTION(aRemotePlayer, "aRemotePlayer is null");
263 #ifdef PR_LOGGING
264  if (!gRemoteLibraryLog) {
265  gRemoteLibraryLog = PR_NewLogModule("sbRemoteLibrary");
266  }
267  LOG_LIB(("sbRemoteLibraryBase::sbRemoteLibraryBase()"));
268 #endif
269 }
270 
272 {
273  LOG_LIB(("sbRemoteLibraryBase::~sbRemoteLibraryBase()"));
274 }
275 
276 // ---------------------------------------------------------------------------
277 //
278 // sbILibraryResource
279 //
280 // ---------------------------------------------------------------------------
281 
282 NS_IMETHODIMP
283 sbRemoteLibraryBase::SetProperty( const nsAString& aID, const nsAString& aValue )
284 {
285  LOG_LIB(( "sbRemoteLibraryBase::SetProperty( %s, %s )",
286  NS_LossyConvertUTF16toASCII(aID).get(),
287  NS_LossyConvertUTF16toASCII(aValue).get() ));
288 
289  nsresult rv;
290  // rules
291  // 1) Don't allow modification of http://songbird properties for the main library
292  // 2) ONLY allow modificatoin of the hidden property for site libraries
293 
294  // Find out if we are trying to set properties on the main library
295  PRBool isMain;
296  nsCOMPtr<sbIMediaItem> item( do_QueryInterface( (sbIRemoteLibrary*)this, &rv ) );
297  NS_ENSURE_SUCCESS( rv, rv );
298 
299  rv = SB_IsFromLibName( item, NS_LITERAL_STRING("main"), &isMain );
300  NS_ENSURE_SUCCESS( rv, rv );
301 
302  if (isMain) {
303  // are we trying to set a songbird property?
304  if ( StringBeginsWith( aID,
305  NS_LITERAL_STRING("http://songbirdnest.com/") ) ) {
306  // don't allow songbird properties to be modified on main library
307  LOG_LIB(( "sbRemoteLibraryBase::SetProperty() - DENIED" ));
308  return NS_ERROR_FAILURE;
309  }
310  } else {
311  // all libraries that aren't the main library
312 
313  // are we trying to set the hidden??
314  if ( aID.EqualsLiteral(SB_PROPERTY_HIDDEN) ) {
315  // see if we are a sitelib. if not, don't allow hidden to be set.
316  nsCOMPtr<sbIRemoteSiteLibrary> siteLib( do_QueryInterface((sbIRemoteLibrary*) this, &rv ) );
317  if ( NS_FAILED(rv) || !siteLib ) {
318  // don't allow the hidden property set outside of site libraries
319  LOG_LIB(( "sbRemoteLibraryBase::SetProperty() - DENIED" ));
320  return NS_ERROR_FAILURE;
321  }
322  }
323  }
324 
325  // otherwise, just forward on to delegate impl.
326  LOG_LIB(( "sbRemoteLibraryBase::SetProperty() - ALLOWED" ));
327  rv = mRemMediaList->SetProperty( aID, aValue );
328  return rv;
329 }
330 
331 // ---------------------------------------------------------------------------
332 //
333 // sbISecurityAggregator
334 //
335 // ---------------------------------------------------------------------------
336 
337 NS_IMETHODIMP
338 sbRemoteLibraryBase::GetRemotePlayer(sbIRemotePlayer * *aRemotePlayer)
339 {
340  NS_ENSURE_STATE(mRemotePlayer);
341  NS_ENSURE_ARG_POINTER(aRemotePlayer);
342 
343  nsresult rv;
344  *aRemotePlayer = nsnull;
345 
346  nsCOMPtr<sbIRemotePlayer> remotePlayer;
347 
348  rv = mRemotePlayer->QueryInterface( NS_GET_IID( sbIRemotePlayer ), getter_AddRefs( remotePlayer ) );
349  NS_ENSURE_SUCCESS( rv, rv );
350 
351  remotePlayer.swap( *aRemotePlayer );
352 
353  return NS_OK;
354 }
355 
356 // ---------------------------------------------------------------------------
357 //
358 // sbIRemoteLibrary
359 //
360 // ---------------------------------------------------------------------------
361 
362 NS_IMETHODIMP
363 sbRemoteLibraryBase::GetScanMediaOnCreation( PRBool *aShouldScan )
364 {
365  NS_ENSURE_ARG_POINTER(aShouldScan);
366  *aShouldScan = mShouldScan;
367  return NS_OK;
368 }
369 
370 NS_IMETHODIMP
371 sbRemoteLibraryBase::SetScanMediaOnCreation( PRBool aShouldScan )
372 {
373  mShouldScan = aShouldScan;
374  return NS_OK;
375 }
376 
377 NS_IMETHODIMP
378 sbRemoteLibraryBase::ConnectToDefaultLibrary( const nsAString &aLibName )
379 {
380  LOG_LIB(( "sbRemoteLibraryBase::ConnectToDefaultLibrary(guid:%s)",
381  NS_LossyConvertUTF16toASCII(aLibName).get() ));
382 
383  nsAutoString guid;
384  nsresult rv = GetLibraryGUID(aLibName, guid);
385  if ( NS_SUCCEEDED(rv) ) {
386  LOG_LIB(( "sbRemoteLibraryBase::ConnectToDefaultLibrary(%s) -- IS a default library",
387  NS_LossyConvertUTF16toASCII(guid).get() ));
388 
389  // See if the library manager has it lying around.
390  nsCOMPtr<sbILibraryManager> libManager(
391  do_GetService( "@songbirdnest.com/Songbird/library/Manager;1", &rv ) );
392  NS_ENSURE_SUCCESS( rv, rv );
393 
394  rv = libManager->GetLibrary( guid, getter_AddRefs(mLibrary) );
395  NS_ENSURE_SUCCESS( rv, rv );
396 
397  rv = InitInternalMediaList();
398  NS_ENSURE_SUCCESS(rv, rv);
399  }
400  return rv;
401 }
402 
403 NS_IMETHODIMP
404 sbRemoteLibraryBase::CreateMediaItem( const nsAString& aURL,
405  sbIMediaItem** _retval )
406 {
407  NS_ENSURE_ARG_POINTER(_retval);
408  NS_ENSURE_STATE(mLibrary);
409 
410  LOG_LIB(("sbRemoteLibraryBase::CreateMediaItem()"));
411 
412  nsCOMPtr<nsIURI> uri;
413  nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL);
414  NS_ENSURE_SUCCESS(rv, rv);
415 
416  // Only allow the creation of media items with http(s) schemes
417  PRBool validScheme;
418  uri->SchemeIs("http", &validScheme);
419  if (!validScheme) {
420  uri->SchemeIs("https", &validScheme);
421  if (!validScheme) {
422  return NS_ERROR_INVALID_ARG;
423  }
424  }
425 
426  // We use PR_TRUE here so that 2 sites can create a media item to the same
427  // URI and get 2 different objects in the database and don't overwrite
428  // each other.
429  nsCOMPtr<sbIMediaItem> mediaItem;
430  rv = mLibrary->CreateMediaItem(uri,
431  nsnull,
433  getter_AddRefs(mediaItem));
434  NS_ENSURE_SUCCESS(rv, rv);
435 
436  // Set the OriginPage property so we know where it came from
437  rv = mRemotePlayer->SetOriginScope( mediaItem, aURL );
438  NS_ENSURE_SUCCESS(rv, rv);
439 
440  if (mShouldScan) {
441 
442  nsCOMPtr<sbIFileMetadataService> metadataService =
443  do_GetService( "@songbirdnest.com/Songbird/FileMetadataService;1", &rv );
444  NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get FileMetadataService!");
445 
446  if(NS_SUCCEEDED(rv)) {
447  LOG_LIB(("sbRemoteLibraryBase::CreateMediaItem() -- doing a MD scan"));
448 
449  nsCOMPtr<nsIMutableArray> mediaItems =
450  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
451  NS_ENSURE_SUCCESS(rv, rv);
452 
453  rv = mediaItems->AppendElement(mediaItem, PR_FALSE);
454  NS_ENSURE_SUCCESS(rv, rv);
455 
456  nsCOMPtr<sbIJobProgress> job;
457  rv = metadataService->Read( mediaItems, getter_AddRefs(job) );
458  NS_ENSURE_SUCCESS(rv, rv);
459  }
460  }
461 
462  // This will wrap in the appropriate site/regular RemoteMediaItem
463  rv = SB_WrapMediaItem(mRemotePlayer, mediaItem, _retval);
464  NS_ENSURE_SUCCESS(rv, rv);
465 
466  mRemotePlayer->GetNotificationManager()
468 
469  return NS_OK;
470 }
471 
472 NS_IMETHODIMP
473 sbRemoteLibraryBase::CreateSimpleMediaList( const nsAString& aName,
474  const nsAString& aSiteID,
475  sbIRemoteMediaList** _retval )
476 {
477  NS_ENSURE_ARG(!aName.IsEmpty());
478  NS_ENSURE_ARG_POINTER(_retval);
479 
480  nsString siteID;
481  if (aSiteID.IsEmpty()) {
482  siteID.Assign(aName);
483  }
484  else {
485  siteID.Assign(aSiteID);
486  }
487 
488  nsresult rv;
489  nsCOMPtr<sbIMediaList> mediaList;
490  nsCOMPtr<sbIRemoteMediaList> remMediaList = GetMediaListBySiteID(siteID);
491  if (remMediaList) {
492  nsCOMPtr<sbIWrappedMediaList> wrappedList =
493  do_QueryInterface( remMediaList, &rv );
494  NS_ENSURE_SUCCESS( rv, rv );
495 
496  mediaList = wrappedList->GetMediaList();
497  NS_ENSURE_TRUE( mediaList, NS_ERROR_FAILURE );
498  }
499  else {
500  // Now we create one.
501  rv = mLibrary->CreateMediaList( NS_LITERAL_STRING("simple"), nsnull,
502  getter_AddRefs(mediaList) );
503  NS_ENSURE_SUCCESS( rv, rv );
504 
505  // Set the OriginPage property so we know where it came from
506  nsCOMPtr<sbIMediaItem> listAsItem( do_QueryInterface( mediaList, &rv ) );
507  NS_ENSURE_SUCCESS( rv, rv) ;
508 
509  rv = mRemotePlayer->SetOriginScope( listAsItem, siteID );
510  NS_ENSURE_SUCCESS( rv, rv );
511 
512  rv = SB_WrapMediaList( mRemotePlayer, mediaList,
513  getter_AddRefs(remMediaList) );
514  NS_ENSURE_SUCCESS( rv, rv );
515  }
516 
517  rv = mediaList->SetProperty( NS_LITERAL_STRING(SB_PROPERTY_MEDIALISTNAME),
518  aName );
519  NS_ENSURE_SUCCESS( rv, rv );
520 
521  mRemotePlayer->GetNotificationManager()->
523 
524  NS_ADDREF(*_retval = remMediaList);
525  return NS_OK;
526 }
527 
528 NS_IMETHODIMP
529 sbRemoteLibraryBase::CreateMediaListFromURL( const nsAString& aName,
530  const nsAString& aURL,
531  sbICreateMediaListCallback* aCallback,
532  const nsAString& aSiteID )
533 {
534  NS_ENSURE_ARG(!aName.IsEmpty());
535  NS_ENSURE_ARG(!aURL.IsEmpty());
536  NS_ENSURE_STATE(mLibrary);
537 
538  LOG_LIB(("sbRemoteLibraryBase::CreateMediaListFromURL(%s)",
539  NS_LossyConvertUTF16toASCII(aURL).get() ));
540 
541  nsString siteID;
542  if (aSiteID.IsEmpty()) {
543  siteID.Assign(aName);
544  }
545  else {
546  siteID.Assign(aSiteID);
547  }
548 
549  nsresult rv;
550  nsCOMPtr<sbIMediaList> mediaList;
551  nsCOMPtr<sbIRemoteMediaList> remMediaList = GetMediaListBySiteID(siteID);
552  if (remMediaList) {
553  nsCOMPtr<sbIWrappedMediaList> wrappedList =
554  do_QueryInterface( remMediaList, &rv );
555  NS_ENSURE_SUCCESS( rv, rv );
556 
557  mediaList = wrappedList->GetMediaList();
558  NS_ENSURE_TRUE( mediaList, NS_ERROR_FAILURE );
559  }
560  else {
561  rv = mLibrary->CreateMediaList( NS_LITERAL_STRING("simple"), nsnull,
562  getter_AddRefs(mediaList) );
563  NS_ENSURE_SUCCESS(rv, rv);
564 
565  // Set the OriginPage property so we know where it came from
566  nsCOMPtr<sbIMediaItem> mediaItem(do_QueryInterface(mediaList));
567  NS_ENSURE_TRUE(mediaItem, NS_ERROR_FAILURE);
568 
569  rv = mRemotePlayer->SetOriginScope( mediaItem, siteID );
570  NS_ENSURE_SUCCESS(rv, rv);
571  }
572 
573  rv = mediaList->SetProperty( NS_LITERAL_STRING(SB_PROPERTY_MEDIALISTNAME),
574  aName );
575  NS_ENSURE_SUCCESS( rv, rv );
576 
577  mRemotePlayer->GetNotificationManager()
579 
580  nsCOMPtr<sbIPlaylistReaderManager> manager =
581  do_GetService( "@songbirdnest.com/Songbird/PlaylistReaderManager;1",
582  &rv );
583  NS_ENSURE_SUCCESS(rv, rv);
584 
585  nsCOMPtr<nsIURI> uri;
586  rv = NS_NewURI(getter_AddRefs(uri), aURL);
587  NS_ENSURE_SUCCESS(rv, rv);
588 
589  // Only allow the creation of media lists with http(s) schemes
590  PRBool validScheme;
591  uri->SchemeIs("http", &validScheme);
592  if (!validScheme) {
593  uri->SchemeIs("https", &validScheme);
594  if (!validScheme) {
595  return NS_ERROR_INVALID_ARG;
596  }
597  }
598 
599  nsCOMPtr<sbIPlaylistReaderListener> lstnr =
600  do_CreateInstance( "@songbirdnest.com/Songbird/PlaylistReaderListener;1",
601  &rv );
602  NS_ENSURE_SUCCESS(rv, rv);
603 
604  nsRefPtr<sbPlaylistReaderObserver> readerObserver =
606  NS_ENSURE_TRUE( readerObserver, NS_ERROR_OUT_OF_MEMORY );
607 
608  nsCOMPtr<nsIObserver> observer( do_QueryInterface( readerObserver, &rv ) );
609  NS_ENSURE_SUCCESS(rv, rv);
610 
611  rv = lstnr->SetObserver( observer );
612  NS_ENSURE_SUCCESS(rv, rv);
613 
614  PRInt32 dummy;
615  rv = manager->LoadPlaylist( uri, mediaList, EmptyString(), true, lstnr, &dummy );
616  NS_ENSURE_SUCCESS(rv, rv);
617 
618  return NS_OK;
619 }
620 
621 NS_IMETHODIMP
623  sbIRemoteMediaList **_retval )
624 {
625  NS_ENSURE_ARG(!aSiteID.IsEmpty());
626  NS_ENSURE_ARG_POINTER(_retval);
627 
628  nsCOMPtr<sbIRemoteMediaList> list = GetMediaListBySiteID(aSiteID);
629  NS_IF_ADDREF(*_retval = list);
630  return NS_OK;
631 }
632 
636 static PRBool IsSiteLibrary(sbILibrary *aLibrary, sbIRemotePlayer *aRemotePlayer) {
637  PRBool result = PR_FALSE;
638  nsCOMPtr<sbIRemoteLibrary> siteLibrary;
639  nsresult rv = aRemotePlayer->GetSiteLibrary( getter_AddRefs(siteLibrary) );
640  if ( NS_SUCCEEDED(rv) ) {
641  nsCOMPtr<sbIMediaItem> siteLibraryAsItem = do_QueryInterface(siteLibrary);
642  nsCOMPtr<sbIMediaItem> libraryAsItem = do_QueryInterface(aLibrary);
643  PRBool equal = PR_FALSE;
644  result = ( siteLibraryAsItem &&
645  libraryAsItem &&
646  NS_SUCCEEDED( siteLibraryAsItem->Equals( libraryAsItem, &equal ) ) &&
647  equal );
648  }
649  return result;
650 }
651 
652 NS_IMETHODIMP
653 sbRemoteLibraryBase::GetPlaylists( nsISimpleEnumerator** _retval )
654 {
655  LOG_LIB(("sbRemoteLibraryBase::GetPlaylists()"));
656 
657  NS_ENSURE_ARG_POINTER(_retval);
658  NS_ENSURE_STATE(mLibrary);
659 
660  nsresult rv;
661  nsCOMPtr<sbIMediaList> mediaList = do_QueryInterface( mLibrary, &rv );
662  NS_ENSURE_SUCCESS( rv, rv );
663 
665 
666  rv = mediaList->EnumerateItemsByProperty( NS_LITERAL_STRING(SB_PROPERTY_ISLIST),
667  NS_LITERAL_STRING("1"),
668  this,
670  NS_ENSURE_SUCCESS( rv, rv );
671 
672  nsCOMPtr<nsISimpleEnumerator> playlistEnum;
673  if ( NS_SUCCEEDED(mEnumerationResult) ) {
674  // Make an enumerator for the contents of mEnumerationArray.
675  playlistEnum =
677  if ( !playlistEnum ) {
678  NS_WARNING("Failed to make array enumerator");
679  }
680  }
681  else {
682  NS_WARNING("Item enumeration failed!");
683  rv = mEnumerationResult;
684  }
685 
686  if (!playlistEnum) {
687  *_retval = nsnull;
688  return NS_OK;
689  }
690 
691  NS_ADDREF( *_retval = playlistEnum );
692 
693  // Reset the array and result codes for next time.
694  mEnumerationArray.Clear();
695  mEnumerationResult = NS_ERROR_NOT_INITIALIZED;
696 
697  return rv;
698 }
699 
700 // ---------------------------------------------------------------------------
701 //
702 // sbIScriptableFilterResult
703 //
704 // ---------------------------------------------------------------------------
705 
706 NS_IMETHODIMP
707 sbRemoteLibraryBase::GetArtists( nsIStringEnumerator** _retval )
708 {
709  LOG_LIB(("sbRemoteLibraryBase::GetArtists()"));
710  NS_ENSURE_ARG_POINTER(_retval);
711  nsresult rv;
712 
713  nsCOMPtr<sbIMediaListView> view;
714  rv = mRemMediaList->CreateView( nsnull, getter_AddRefs(view) );
715  NS_ENSURE_SUCCESS( rv, rv );
716 
717  nsCOMPtr<sbIFilterableMediaListView> filterView =
718  do_QueryInterface( view, &rv );
719  NS_ENSURE_SUCCESS( rv, rv );
720 
721  nsRefPtr<sbScriptableFilter> filter =
722  new sbScriptableFilter( filterView,
723  NS_LITERAL_STRING(SB_PROPERTY_ARTISTNAME),
724  mRemotePlayer );
725  NS_ENSURE_TRUE( filter, NS_ERROR_OUT_OF_MEMORY );
726 
727  NS_ADDREF(*_retval = filter);
728  return NS_OK;
729 }
730 
731 NS_IMETHODIMP
732 sbRemoteLibraryBase::GetAlbums( nsIStringEnumerator** _retval )
733 {
734  LOG_LIB(("sbRemoteLibraryBase::GetAlbums()"));
735  NS_ENSURE_ARG_POINTER(_retval);
736  nsresult rv;
737 
738  nsCOMPtr<sbIMediaListView> view;
739  rv = mRemMediaList->CreateView( nsnull, getter_AddRefs(view) );
740  NS_ENSURE_SUCCESS( rv, rv );
741 
742  nsCOMPtr<sbIFilterableMediaListView> filterView =
743  do_QueryInterface( view, &rv );
744  NS_ENSURE_SUCCESS( rv, rv );
745 
746  nsRefPtr<sbScriptableFilter> filter =
747  new sbScriptableFilter( filterView,
748  NS_LITERAL_STRING(SB_PROPERTY_ALBUMNAME),
749  mRemotePlayer);
750  NS_ENSURE_TRUE( filter, NS_ERROR_OUT_OF_MEMORY );
751 
752  NS_ADDREF(*_retval = filter);
753  return NS_OK;
754 }
755 
756 NS_IMETHODIMP
757 sbRemoteLibraryBase::GetGenres( nsIStringEnumerator** _retval )
758 {
759  LOG_LIB(("sbRemoteLibraryBase::GetGenres()"));
760  NS_ENSURE_ARG_POINTER(_retval);
761  nsresult rv;
762 
763  nsCOMPtr<sbIMediaListView> view;
764  rv = mRemMediaList->CreateView( nsnull, getter_AddRefs(view) );
765  NS_ENSURE_SUCCESS( rv, rv );
766 
767  nsCOMPtr<sbIFilterableMediaListView> filterView =
768  do_QueryInterface( view, &rv );
769  NS_ENSURE_SUCCESS( rv, rv );
770 
771  nsRefPtr<sbScriptableFilter> filter =
772  new sbScriptableFilter( filterView,
773  NS_LITERAL_STRING(SB_PROPERTY_GENRE),
774  mRemotePlayer);
775  NS_ENSURE_TRUE( filter, NS_ERROR_OUT_OF_MEMORY );
776 
777  NS_ADDREF(*_retval = filter);
778  return NS_OK;
779 }
780 
781 NS_IMETHODIMP
782 sbRemoteLibraryBase::GetYears( nsIStringEnumerator** _retval )
783 {
784  LOG_LIB(("sbRemoteLibraryBase::GetYears()"));
785  NS_ENSURE_ARG_POINTER(_retval);
786  nsresult rv;
787 
788  nsCOMPtr<sbIMediaListView> view;
789  rv = mRemMediaList->CreateView( nsnull, getter_AddRefs(view) );
790  NS_ENSURE_SUCCESS( rv, rv );
791 
792  nsCOMPtr<sbIFilterableMediaListView> filterView =
793  do_QueryInterface( view, &rv );
794  NS_ENSURE_SUCCESS( rv, rv );
795 
796  nsRefPtr<sbScriptableFilter> filter =
797  new sbScriptableFilter( filterView,
798  NS_LITERAL_STRING(SB_PROPERTY_YEAR),
799  mRemotePlayer );
800  NS_ENSURE_TRUE( filter, NS_ERROR_OUT_OF_MEMORY );
801 
802  NS_ADDREF(*_retval = filter);
803  return NS_OK;
804 }
805 
806 NS_IMETHODIMP
807 sbRemoteLibraryBase::GetItems( nsISupports** _retval )
808 {
809  LOG_LIB(("sbRemoteLibraryBase::Items()"));
810  NS_ENSURE_ARG_POINTER(_retval);
811  nsresult rv;
812 
813  nsCOMPtr<sbIMediaListView> view;
814  rv = mRemMediaList->CreateView( nsnull, getter_AddRefs(view) );
815  NS_ENSURE_SUCCESS( rv, rv );
816 
817  nsCOMPtr<sbIFilterableMediaListView> filterView =
818  do_QueryInterface( view, &rv );
819  NS_ENSURE_SUCCESS( rv, rv );
820 
821  nsRefPtr<sbScriptableFilterItems> items =
822  new sbScriptableFilterItems( filterView, mRemotePlayer);
823  NS_ENSURE_TRUE( items, NS_ERROR_OUT_OF_MEMORY );
824 
825  *_retval = NS_ISUPPORTS_CAST( nsIXPCScriptable*, items );
826  NS_ADDREF(*_retval);
827  return NS_OK;
828 }
829 
830 NS_IMETHODIMP
831 sbRemoteLibraryBase::GetMostPlayedArtists(nsIVariant** _retval)
832 {
833  LOG_LIB(("sbRemoteLibraryBase::GetMostPlayedArtists()"));
834  NS_ENSURE_ARG_POINTER(_retval);
835  nsresult rv = NS_OK;
836 
837  nsCOMPtr<sbILibraryStatistics> libraryStatistics =
838  do_QueryInterface( mLibrary, &rv );
839  NS_ENSURE_SUCCESS( rv, rv );
840 
841  // get the most played artists in an array of variants
842  nsCOMPtr<nsIArray> mostPlayedArtists;
843  rv = libraryStatistics->CollectDistinctValues(
844  NS_LITERAL_STRING(SB_PROPERTY_ARTISTNAME),
846  NS_LITERAL_STRING(SB_PROPERTY_PLAYCOUNT), PR_FALSE, 100,
847  getter_AddRefs(mostPlayedArtists));
848  NS_ENSURE_SUCCESS( rv, rv );
849 
850  PRUint32 count;
851  rv = mostPlayedArtists->GetLength(&count);
852  NS_ENSURE_SUCCESS(rv, rv);
853 
854  LOG_LIB(("sbRemoteLibraryBase::GetMostPlayedArtists() got %d artists", count));
855 
856  // create a variant to hold the array
857  nsCOMPtr<nsIWritableVariant> variant =
858  do_CreateInstance(NS_VARIANT_CONTRACTID, &rv);
859  NS_ENSURE_SUCCESS(rv, rv);
860 
861  if (count > 0) {
862  // okay, create a variant array to hold these artists
863  nsIVariant** arr = (nsIVariant**)NS_Alloc(sizeof(nsIVariant*)*count);
864  if (!arr) {
865  return NS_ERROR_OUT_OF_MEMORY;
866  }
867 
868  // put nsIVariants from mostPlayedArtists into arr
869  for (PRUint32 i = 0; i < count; i++) {
870  rv = mostPlayedArtists->QueryElementAt(i, NS_GET_IID(nsIVariant),
871  (void**)&arr[i]);
872  NS_ENSURE_SUCCESS(rv, rv);
873  }
874 
875  // put the array into the variant
876  rv = variant->SetAsArray(nsIDataType::VTYPE_INTERFACE_IS,
877  &NS_GET_IID(nsIVariant), count, arr);
878  NS_ENSURE_SUCCESS(rv, rv);
879  } else {
880  // empty arrays are easy
881  rv = variant->SetAsEmptyArray();
882  NS_ENSURE_SUCCESS(rv, rv);
883  }
884 
885  // pass it back
886  return CallQueryInterface(variant, _retval);
887 
888  return NS_OK;
889 }
890 
891 NS_IMETHODIMP
892 sbRemoteLibraryBase::GetConstraint(sbILibraryConstraint * *aConstraint)
893 {
894  nsresult rv;
895  nsCOMPtr<sbILibraryConstraintBuilder> builder =
896  do_CreateInstance( "@songbirdnest.com/Songbird/Library/ConstraintBuilder;1",
897  &rv );
898  NS_ENSURE_SUCCESS( rv, rv );
899  return builder->Get(aConstraint);
900 }
901 
902 // ---------------------------------------------------------------------------
903 //
904 // sbIWrappedMediaList
905 //
906 // ---------------------------------------------------------------------------
907 
908 already_AddRefed<sbIMediaItem>
910 {
911  return mRemMediaList->GetMediaItem();
912 }
913 
914 already_AddRefed<sbIMediaList>
916 {
917  return mRemMediaList->GetMediaList();
918 }
919 
920 // ---------------------------------------------------------------------------
921 //
922 // sbIMediaListEnumerationListener
923 //
924 // ---------------------------------------------------------------------------
925 
926 NS_IMETHODIMP
927 sbRemoteLibraryBase::OnEnumerationBegin( sbIMediaList *aMediaList,
928  PRUint16 *_retval )
929 {
930  NS_ENSURE_ARG_POINTER(_retval);
931 
932  NS_ASSERTION( mEnumerationArray.Count() == 0,
933  "Someone forgot to clear mEnumerationArray!" );
934  NS_ASSERTION( mEnumerationResult == NS_ERROR_NOT_INITIALIZED,
935  "Someone forgot to reset mEnumerationResult!" );
936 
938  return NS_OK;
939 }
940 
941 NS_IMETHODIMP
942 sbRemoteLibraryBase::OnEnumeratedItem( sbIMediaList *aMediaList,
943  sbIMediaItem *aMediaItem,
944  PRUint16 *_retval )
945 {
946  NS_ENSURE_ARG_POINTER(aMediaItem);
947  NS_ENSURE_ARG_POINTER(_retval);
948 
949  // If there is no outer guid then we want this.
950  // (Avoids smart playlists dupes, see bug 14896)
951  nsString propValue;
952  PRBool const isSmartStoragePlaylist =
953  NS_SUCCEEDED(aMediaItem->GetProperty(NS_LITERAL_STRING(SB_PROPERTY_OUTERGUID),
954  propValue)) &&
955  !propValue.IsEmpty();
956 
957  PRBool const isHiddenPlaylist =
958  NS_SUCCEEDED(aMediaItem->GetProperty(NS_LITERAL_STRING(SB_PROPERTY_HIDDEN),
959  propValue)) &&
960  propValue.EqualsLiteral("1");
961  // Only process lists that aren't smart playlist storage lists. And if we're
962  // ignore hidden playlists then don't process hidden ones either
963  if (!isSmartStoragePlaylist && (!mIgnoreHiddenPlaylists || !isHiddenPlaylist)) {
964  if (mEnumerationArray.AppendObject(aMediaItem)) {
966  }
967  else {
969  }
970  }
971  else { // If there was an outer guid, skip this one
973  }
974  return NS_OK;
975 }
976 
977 NS_IMETHODIMP
978 sbRemoteLibraryBase::OnEnumerationEnd( sbIMediaList *aMediaList,
979  nsresult aStatusCode )
980 {
981  mEnumerationResult = aStatusCode;
982  return NS_OK;
983 }
984 
985 // ---------------------------------------------------------------------------
986 //
987 // nsIXPCScriptable
988 //
989 // ---------------------------------------------------------------------------
990 
991 NS_IMETHODIMP
993 {
994  NS_ENSURE_ARG_POINTER(aClassName);
995  *aClassName = ToNewCString( NS_LITERAL_CSTRING("SongbirdLibrary") );
996  NS_ENSURE_TRUE( aClassName, NS_ERROR_OUT_OF_MEMORY );
997  return NS_OK;
998 }
999 
1000 NS_IMETHODIMP
1001 sbRemoteLibraryBase::GetScriptableFlags( PRUint32 *aScriptableFlags )
1002 {
1003  NS_ENSURE_ARG_POINTER(aScriptableFlags);
1004  // XXX Mook: USE_JSSTUB_FOR_ADDPROPERTY is needed to define things on the
1005  // prototype properly; even with it set scripts cannot add
1006  // properties onto the object (because they're not allow to *set*)
1007  *aScriptableFlags = USE_JSSTUB_FOR_ADDPROPERTY |
1008  DONT_ENUM_STATIC_PROPS |
1009  DONT_ENUM_QUERY_INTERFACE |
1010  WANT_GETPROPERTY |
1011  WANT_NEWRESOLVE |
1012  ALLOW_PROP_MODS_DURING_RESOLVE |
1013  DONT_REFLECT_INTERFACE_NAMES ;
1014  return NS_OK;
1015 }
1016 
1017 NS_IMETHODIMP
1018 sbRemoteLibraryBase::NewResolve( nsIXPConnectWrappedNative *wrapper,
1019  JSContext *cx,
1020  JSObject *obj,
1021  jsval id,
1022  PRUint32 flags,
1023  JSObject **objp,
1024  PRBool *_retval )
1025 {
1026  LOG_LIB(("sbRemoteLibraryBase::NewResolve()"));
1027 #ifdef DEBUG
1028  if ( JSVAL_IS_STRING(id) ) {
1029  nsDependentString jsid( (PRUnichar *)::JS_GetStringChars(JSVAL_TO_STRING(id)),
1030  ::JS_GetStringLength(JSVAL_TO_STRING(id)));
1031  TRACE_LIB(( " resolving %s", NS_LossyConvertUTF16toASCII(jsid).get() ));
1032  }
1033 #endif
1034 
1035  NS_ENSURE_TRUE(mRemMediaList, NS_ERROR_FAILURE);
1036 
1037  return mRemMediaList->NewResolve( wrapper, cx, obj, id, flags, objp, _retval );
1038 }
1039 
1040 NS_IMETHODIMP
1041 sbRemoteLibraryBase::GetProperty( nsIXPConnectWrappedNative *wrapper,
1042  JSContext * cx,
1043  JSObject * obj,
1044  jsval id,
1045  jsval * vp,
1046  PRBool *_retval )
1047 {
1048  TRACE_LIB(("sbRemoteLibraryBase::GetProperty()"));
1049  NS_ENSURE_ARG_POINTER(_retval);
1050  NS_ENSURE_ARG_POINTER(vp);
1051 
1052  nsresult rv;
1053 
1054  if ( !JSVAL_IS_STRING(id) ) {
1055  // we don't care about non-strings
1056  return NS_OK;
1057  }
1058 
1059  nsDependentString jsid( (PRUnichar *)::JS_GetStringChars(JSVAL_TO_STRING(id)),
1060  ::JS_GetStringLength(JSVAL_TO_STRING(id)));
1061 
1062  TRACE_LIB(( " Getting property %s", NS_LossyConvertUTF16toASCII(jsid).get() ));
1063 
1064  nsCOMPtr<nsISupports> supports;
1065 
1066  { // getArtists(), getAlbums(), getGenres(), getYears()
1067  nsCOMPtr<nsIStringEnumerator> stringEnum;
1068  if ( jsid.EqualsLiteral("getArtists") ) {
1069  rv = GetArtists( getter_AddRefs(stringEnum) );
1070  NS_ENSURE_SUCCESS( rv, rv );
1071  } else if ( jsid.EqualsLiteral("getAlbums") ) {
1072  rv = GetAlbums( getter_AddRefs(stringEnum) );
1073  NS_ENSURE_SUCCESS( rv, rv );
1074  } else if ( jsid.EqualsLiteral("getGenres") ) {
1075  rv = GetGenres( getter_AddRefs(stringEnum) );
1076  NS_ENSURE_SUCCESS( rv, rv );
1077  } else if ( jsid.EqualsLiteral("getYears") ) {
1078  rv = GetYears( getter_AddRefs(stringEnum) );
1079  NS_ENSURE_SUCCESS( rv, rv );
1080  }
1081 
1082  if ( stringEnum ) {
1083  // make the callable wrapper
1084  nsRefPtr<sbScriptableLibraryFunction> func =
1085  new sbScriptableLibraryFunction( stringEnum, NS_GET_IID(nsIStringEnumerator) );
1086  NS_ENSURE_TRUE( func, NS_ERROR_OUT_OF_MEMORY );
1087 
1088  supports = NS_ISUPPORTS_CAST( nsIXPCScriptable*, func );
1089  }
1090  }
1091 
1092  if ( jsid.EqualsLiteral("getPlaylists") ) {
1093  nsCOMPtr<nsISimpleEnumerator> simpleEnum;
1094  rv = GetPlaylists( getter_AddRefs(simpleEnum) );
1095  NS_ENSURE_SUCCESS( rv, rv );
1096 
1097  nsRefPtr<sbScriptableLibraryFunction> func =
1098  new sbScriptableLibraryFunction( simpleEnum, NS_GET_IID(nsISimpleEnumerator) );
1099  NS_ENSURE_TRUE( simpleEnum, NS_ERROR_OUT_OF_MEMORY );
1100 
1101  supports = NS_ISUPPORTS_CAST( nsIXPCScriptable*, func );
1102  }
1103 
1104  if (supports) {
1105  // do the security check
1106  char* access;
1107  nsIID iid = NS_GET_IID(nsISupports);
1108  // note that an error return value also means access denied
1109  rv = mSecurityMixin->CanCallMethod( &iid,
1110  jsid.BeginReading(),
1111  &access );
1112  PRBool canCallMethod = NS_SUCCEEDED(rv);
1113  if (canCallMethod) {
1114  canCallMethod = !strcmp( access, "AllAccess" );
1115  NS_Free(access);
1116  }
1117 
1118  if ( !canCallMethod ) {
1119  JSAutoRequest ar(cx);
1120 
1121  // get an error message
1122  nsCOMPtr<nsIStringBundleService> bundleService =
1123  do_GetService( NS_STRINGBUNDLE_CONTRACTID, &rv );
1124  NS_ENSURE_SUCCESS( rv, rv );
1125  nsCOMPtr<nsIStringBundle> bundle;
1126  rv = bundleService->CreateBundle( "chrome://global/locale/security/caps.properties",
1127  getter_AddRefs(bundle) );
1128  NS_ENSURE_SUCCESS( rv, rv );
1129 
1130  char* classNameC;
1131  rv = this->GetClassName(&classNameC);
1132  NS_ENSURE_SUCCESS( rv, rv );
1133  nsString className =
1134  NS_ConvertASCIItoUTF16( nsDependentCString(classNameC) );
1135  NS_Free(classNameC);
1136 
1137  nsString errorMessage;
1138  const PRUnichar *formatStrings[] = {
1139  className.get(),
1140  jsid.get()
1141  };
1142  rv = bundle->FormatStringFromName( NS_LITERAL_STRING("CallMethodDenied").get(),
1143  formatStrings,
1144  sizeof(formatStrings) / sizeof(formatStrings[0]),
1145  getter_Copies(errorMessage) );
1146  NS_ENSURE_SUCCESS( rv, rv );
1147 
1148  JSString *jsstr = JS_NewUCStringCopyN( cx,
1149  reinterpret_cast<const jschar*>( errorMessage.get() ),
1150  errorMessage.Length() );
1151  if (jsstr)
1152  JS_SetPendingException( cx, STRING_TO_JSVAL(jsstr) );
1153 
1154  *_retval = JS_FALSE;
1155  return NS_OK;
1156  }
1157 
1158  // send it along to JS
1159  nsCOMPtr<nsIXPConnect> xpc;
1160  rv = wrapper->GetXPConnect( getter_AddRefs(xpc) );
1161  NS_ENSURE_SUCCESS( rv, rv );
1162 
1163  nsCOMPtr<nsIXPConnectJSObjectHolder> objHolder;
1164  rv = xpc->WrapNative( cx,
1165  obj,
1166  supports,
1167  NS_GET_IID(nsISupports),
1168  getter_AddRefs(objHolder) );
1169  NS_ENSURE_SUCCESS( rv, rv );
1170 
1171  JSObject* obj = nsnull;
1172  rv = objHolder->GetJSObject( &obj );
1173  NS_ENSURE_SUCCESS( rv, rv );
1174 
1175  *vp = OBJECT_TO_JSVAL(obj);
1176  *_retval = PR_TRUE;
1177  return NS_SUCCESS_I_DID_SOMETHING;
1178  }
1179 
1180  return NS_OK;
1181 }
1182 
1183 // ---------------------------------------------------------------------------
1184 //
1185 // Helper Methods
1186 //
1187 // ---------------------------------------------------------------------------
1188 
1189 // If the libraryID is one of the default libraries we set the out param
1190 // to the internal GUID of library as understood by the library manager
1191 // and return NS_OK. If it is not one of the default libraries then
1192 // return NS_ERROR_FAILURE. Also returns an error if the pref system is not
1193 // available.
1194 nsresult
1195 sbRemoteLibraryBase::GetLibraryGUID( const nsAString &aLibraryID,
1196  nsAString &aLibraryGUID )
1197 {
1198 #ifdef PR_LOGGING
1199  // This method is static, so the log might not be initialized
1200  if (!gRemoteLibraryLog) {
1201  gRemoteLibraryLog = PR_NewLogModule("sbRemoteLibrary");
1202  }
1203  LOG_LIB(( "sbRemoteLibraryBase::GetLibraryGUID(%s)",
1204  NS_LossyConvertUTF16toASCII(aLibraryID).get() ));
1205 #endif
1206 
1207  nsCAutoString prefKey;
1208 
1209  // match the 'magic' strings to the keys for the prefs
1210  if ( aLibraryID.EqualsLiteral("main") ) {
1211  prefKey.AssignLiteral("songbird.library.main");
1212  } else if ( aLibraryID.EqualsLiteral("web") ) {
1213  prefKey.AssignLiteral("songbird.library.web");
1214  }
1215 
1216  // right now just bail if it isn't a default
1217  if ( prefKey.IsEmpty() ) {
1218  LOG_LIB(("sbRemoteLibraryBase::GetLibraryGUID() -- not a default library"));
1219  // ultimately we need to be able to get the GUID for non-default libraries
1220  // if we are going to allow the library manager to manage them.
1221  // We might want to do the string hashing here and add keys for
1222  // songbird.library.site.hashkey
1223  return NS_ERROR_FAILURE;
1224  }
1225 
1226  // The value of the pref should be a library resourceGUID.
1227  nsresult rv;
1228  nsCOMPtr<nsIPrefBranch> prefService =
1229  do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
1230  NS_ENSURE_SUCCESS(rv, rv);
1231 
1232  nsCOMPtr<nsISupportsString> supportsString;
1233  rv = prefService->GetComplexValue( prefKey.get(),
1234  NS_GET_IID(nsISupportsString),
1235  getter_AddRefs(supportsString) );
1236  // Get the GUID for this library out of the supports string
1237  if (NS_SUCCEEDED(rv)) {
1238  // Use the value stored in the prefs.
1239  rv = supportsString->GetData(aLibraryGUID);
1240  NS_ENSURE_SUCCESS(rv, rv);
1241  }
1242 
1243  return NS_OK;
1244 }
1245 
1246 already_AddRefed<sbIRemoteMediaList>
1247 sbRemoteLibraryBase::GetMediaListBySiteID(const nsAString& aSiteID)
1248 {
1249  NS_ASSERTION(!aSiteID.IsEmpty(), "Don't give me an empty ID!");
1250 
1251  nsresult rv;
1252  nsCOMPtr<sbIMutablePropertyArray> mutableArray =
1253  do_CreateInstance( SB_MUTABLEPROPERTYARRAY_CONTRACTID, &rv );
1254  NS_ENSURE_SUCCESS( rv, nsnull );
1255 
1256  rv = mutableArray->AppendProperty( NS_LITERAL_STRING(SB_PROPERTY_RAPISITEID),
1257  aSiteID );
1258  NS_ENSURE_SUCCESS( rv, nsnull );
1259 
1260  rv = mutableArray->AppendProperty( NS_LITERAL_STRING(SB_PROPERTY_ISLIST),
1261  NS_LITERAL_STRING("1") );
1262  NS_ENSURE_SUCCESS( rv, nsnull );
1263 
1264  nsCOMArray<sbIMediaItem> items;
1265  nsRefPtr<sbRemoteLibraryEnumCallback> listener =
1266  new sbRemoteLibraryEnumCallback(items);
1267  NS_ENSURE_TRUE( listener, nsnull );
1268 
1269  nsCOMPtr<sbIMediaList> libList = do_QueryInterface( mLibrary, &rv );
1270  NS_ENSURE_SUCCESS( rv, nsnull );
1271 
1272  rv = libList->EnumerateItemsByProperties( mutableArray,
1273  listener,
1275  NS_ENSURE_SUCCESS( rv, nsnull );
1276 
1277  if (items.Count() > 0) {
1278  nsCOMPtr<sbIMediaItem> foundItem = FindMediaItemWithMatchingScope(items);
1279  if (foundItem) {
1280  nsCOMPtr<sbIMediaList> list = do_QueryInterface( foundItem, &rv );
1281  NS_ASSERTION( NS_SUCCEEDED(rv), "Failed to QI to sbIMediaList!" );
1282 
1283  nsCOMPtr<sbIRemoteMediaList> retval;
1284  rv = SB_WrapMediaList( mRemotePlayer, list, getter_AddRefs(retval) );
1285  NS_ENSURE_SUCCESS( rv, nsnull );
1286 
1287  return retval.forget();
1288  }
1289  }
1290 
1291  // if we reach this point, we did not find the media list, return nsnull.
1292  return nsnull;
1293 }
1294 
1295 already_AddRefed<sbIMediaItem>
1296 sbRemoteLibraryBase::FindMediaItemWithMatchingScope( const nsCOMArray<sbIMediaItem>& aMediaItems )
1297 {
1298  nsCOMPtr<nsIURI> siteScopeURI = mRemotePlayer->GetSiteScopeURI();
1299  NS_ENSURE_TRUE( siteScopeURI, nsnull );
1300 
1301  nsCString siteHost;
1302  nsresult rv = siteScopeURI->GetHost(siteHost);
1303  NS_ENSURE_SUCCESS( rv, nsnull );
1304 
1305  PRUint32 itemCount = (PRUint32)aMediaItems.Count();
1306  NS_ASSERTION(itemCount > 0, "Empty items list!");
1307 
1308  // Build an array of site scope URLs
1309  nsTArray<sbRemoteLibraryScopeURLSet> scopeURLSet(itemCount);
1310 
1311  for (PRUint32 itemIndex = 0; itemIndex < itemCount; itemIndex++) {
1312  const nsCOMPtr<sbIMediaItem>& item = aMediaItems.ObjectAt(itemIndex);
1313 
1314  nsString scopeURL;
1315  rv = item->GetProperty( NS_LITERAL_STRING(SB_PROPERTY_RAPISCOPEURL),
1316  scopeURL );
1317  NS_ENSURE_SUCCESS( rv, nsnull );
1318 
1319  NS_ASSERTION( !scopeURL.IsEmpty(), "Empty scope URL" );
1320 
1321  nsCOMPtr<nsIURI> scopeURI;
1322  rv = NS_NewURI( getter_AddRefs(scopeURI), scopeURL );
1323  NS_ENSURE_SUCCESS( rv, nsnull );
1324 
1325  nsCString host;
1326  rv = scopeURI->GetHost(host);
1327  NS_ENSURE_SUCCESS( rv, nsnull );
1328 
1329  rv = sbURIChecker::CheckDomain( host, siteScopeURI );
1330  if (NS_FAILED(rv)) {
1331  continue;
1332  }
1333 
1334  nsCString path;
1335  rv = scopeURI->GetPath(path);
1336  NS_ENSURE_SUCCESS( rv, nsnull );
1337 
1338  sbRemoteLibraryScopeURLSet* newSet =
1339  scopeURLSet.AppendElement( sbRemoteLibraryScopeURLSet( path, item ) );
1340  NS_ENSURE_TRUE( newSet, nsnull );
1341  }
1342 
1343  // Yay QuickSort!
1344  scopeURLSet.Sort();
1345 
1346  itemCount = scopeURLSet.Length();
1347  NS_ENSURE_TRUE(itemCount, nsnull);
1348 
1349  for (PRInt64 setIndex = itemCount - 1; setIndex >= 0; setIndex--) {
1350  const sbRemoteLibraryScopeURLSet& set = scopeURLSet.ElementAt((PRUint32)setIndex);
1351 
1352  nsCString path(set.scopePath);
1353  rv = sbURIChecker::CheckPath( path, siteScopeURI );
1354  if (NS_SUCCEEDED(rv)) {
1355  sbIMediaItem* retval = set.item;
1356  NS_ADDREF(retval);
1357  return retval;
1358  }
1359  }
1360 
1361  return nsnull;
1362 }
1363 
bool operator==(sbFraction const &aLeft, sbFraction const &aRight)
Definition: sbFraction.h:166
return foundItem
static nsresult SB_WrapMediaList(sbRemotePlayer *aRemotePlayer, sbIMediaList *aMediaList, sbIMediaList **aRemoteMediaList)
return NS_OK
#define SB_PROPERTY_MEDIALISTNAME
#define SB_PROPERTY_PLAYCOUNT
virtual already_AddRefed< sbIMediaItem > GetMediaItem()
static nsresult CheckDomain(nsACString &aDomain, nsIURI *aSiteURI)
already_AddRefed< sbIRemoteMediaList > GetMediaListBySiteID(const nsAString &aSiteID)
#define SB_PROPERTY_RAPISITEID
Interface used to enumerate the items in a media list.
onPageChanged aValue
Definition: FeedWriter.js:1395
sbOSDControlService prototype className
NS_IMPL_ISUPPORTS1(sbDeviceCapabilitiesUtils, sbIDeviceCapabilitiesUtils) sbDeviceCapabilitiesUtils
NS_IMETHODIMP Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
const NS_PREFSERVICE_CONTRACTID
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-...
#define SB_PROPERTY_HIDDEN
#define SB_MUTABLEPROPERTYARRAY_CONTRACTID
#define SB_PROPERTY_RAPISCOPEURL
NS_IMPL_ISUPPORTS11(sbRemoteLibraryBase, nsISecurityCheckedComponent, nsIXPCScriptable, sbISecurityAggregator, sbIRemoteMediaList, sbIMediaList, sbIWrappedMediaList, sbIWrappedMediaItem, sbIMediaItem, sbILibraryResource, sbIRemoteLibrary, sbIScriptableFilterResult) sbRemoteLibraryBase
const nsCOMPtr< sbIMediaItem > item
A brief description of the contents of this interface.
static PRBool IsSiteLibrary(sbILibrary *aLibrary, sbIRemotePlayer *aRemotePlayer)
nsISecurityCheckedComponent
NS_IMETHOD GetProperty(const nsAString &aName, nsAString &_retval)
readonly attribute AString guid
The guid of this resource.
static nsresult GetLibraryGUID(const nsAString &aLibraryID, nsAString &aLibraryGUID)
NS_IMETHOD SetProperty(const nsAString &aID, const nsAString &aValue)
static nsresult CheckPath(nsACString &aPath, nsIURI *aSiteURI)
readonly attribute nsIVariant mostPlayedArtists
var bundle
var count
Definition: test_bug7406.js:32
NS_IMETHOD GetScriptableFlags(PRUint32 *aScriptableFlags)
#define SB_PROPERTY_OUTERGUID
NS_DECL_ISUPPORTS sbPlaylistReaderObserver(sbRemotePlayer *aRemotePlayer, sbICreateMediaListCallback *aCallback, PRBool aShouldScan)
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)
bool operator<(sbFraction const &aLeft, sbFraction const &aRight)
Definition: sbFraction.h:185
already_AddRefed< sbIMediaItem > FindMediaItemWithMatchingScope(const nsCOMArray< sbIMediaItem > &aMediaItems)
#define SB_PROPERTY_GENRE
const unsigned short ENUMERATIONTYPE_SNAPSHOT
This flag means that the list being enumerated is a copy that may become out of date.
A marker interface for objects that aggregate the security mixin.
nsRefPtr< sbRemoteMediaListBase > mRemMediaList
General interface to data resources.
nsCOMPtr< nsISecurityCheckedComponent > mSecurityMixin
An interface to control a media library from remote web pages.
sbRemoteLibraryScopeURLSet(const nsACString &path, sbIMediaItem *item)
The result of a filtering expression in a library.
Media library abstraction.
Definition: sbILibrary.idl:82
#define SB_PROPERTY_ARTISTNAME
_updateCookies aName
#define TRACE_LIB(args)
nsCOMPtr< sbILibrary > mLibrary
var uri
Definition: FeedWriter.js:1135
NS_IMETHOD GetClassName(char **aClassName)
#define SB_PROPERTY_ALBUMNAME
virtual already_AddRefed< sbIMediaList > GetMediaList()
static nsresult SB_WrapMediaItem(sbRemotePlayer *aRemotePlayer, sbIMediaItem *aMediaItem, sbIMediaItem **aRemoteMediaItem)
#define LOG(args)
#define SB_PROPERTY_YEAR
Interface that defines a single item of media in the system.
nsCOMArray< sbIMediaItem > mEnumerationArray
nsRefPtr< sbRemotePlayer > mRemotePlayer
const nsISupportsString
#define SB_PROPERTY_ISLIST
NS_IMETHODIMP OnEnumeratedItem(sbIMediaList *, sbIMediaItem *aItem, PRUint16 *_retval)
virtual nsresult InitInternalMediaList()=0
NS_IMETHODIMP OnEnumerationBegin(sbIMediaList *, PRUint16 *_retval)
_getSelectedPageStyle s i
Array filter(tab.attributes, function(aAttr){return(_this.xulAttributes.indexOf(aAttr.name) >-1);}).forEach(tab.removeAttribute
NS_IMETHODIMP OnEnumerationEnd(sbIMediaList *, nsresult)
readonly attribute nsISupports items
An interface to control a media list from remote web pages.
let observer
_updateTextAndScrollDataForFrame aData
NS_DECL_ISUPPORTS sbRemoteLibraryEnumCallback(nsCOMArray< sbIMediaItem > &aArray)
#define LOG_LIB(args)