sbRemotePlayer.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 "sbRemotePlayer.h"
28 
29 #include "sbRemoteAPIUtils.h"
30 #include "sbRemoteCommands.h"
31 #include "sbRemoteLibrary.h"
32 #include "sbRemoteLibraryBase.h"
35 #include "sbRemoteSecurityEvent.h"
36 #include "sbRemoteSiteLibrary.h"
37 #include "sbRemoteWebLibrary.h"
38 #include "sbRemoteWebPlaylist.h"
39 #include "sbSecurityMixin.h"
40 #include "sbURIChecker.h"
41 #include <sbClassInfoUtils.h>
42 #include <sbIDataRemote.h>
43 #include <sbIDeviceManager.h>
44 #include <sbIDownloadDevice.h>
45 #include <sbILibrary.h>
46 #include <sbIMediacoreEvent.h>
47 #include <sbIMediacoreEventTarget.h>
48 #include <sbIMediacoreManager.h>
49 #include <sbIMediacorePlaybackControl.h>
50 #include <sbIMediacoreSequencer.h>
51 #include <sbIMediacoreVolumeControl.h>
52 #include <sbIMediaList.h>
53 #include <sbIMediaListView.h>
54 #ifdef METRICS_ENABLED
55 #include <sbIMetrics.h>
56 #endif
57 #include <sbIRemoteAPIService.h>
58 #include <sbIPlaylistClickEvent.h>
59 #include <sbIPlaylistCommands.h>
60 #include <sbITabBrowser.h>
61 #include <sbIPropertyInfo.h>
62 #include <sbIPropertyManager.h>
63 #include <sbPropertiesCID.h>
64 #include <sbStandardProperties.h>
65 #include <sbIPropertyBuilder.h>
66 #include <sbStringUtils.h>
67 
68 #include <nsAutoPtr.h>
69 #include <nsDOMJSUtils.h>
70 #include <nsIArray.h>
71 #include <nsICategoryManager.h>
72 #include <nsIContentViewer.h>
73 #include <nsIDocShell.h>
74 #include <nsIDocShellTreeItem.h>
75 #include <nsIDocShellTreeOwner.h>
76 #include <nsIDocument.h>
77 #include <nsIDOMDocument.h>
78 #include <nsIDOMDocumentEvent.h>
79 #include <nsIDOMElement.h>
80 #include <nsIDOMEvent.h>
81 #include <nsIDOMEventTarget.h>
82 #include <nsIDOMMouseEvent.h>
83 #include <nsIDOMNodeList.h>
84 #include <nsIDOMNSEvent.h>
85 #include <nsIDOMWindow.h>
86 #include <nsPIDOMWindow.h>
87 #include <nsIDOMWindowInternal.h>
88 #include <nsIDOMXULDocument.h>
89 #include <nsIDOMXULElement.h>
90 #include <nsIInterfaceRequestorUtils.h>
91 #include <nsIJSContextStack.h>
92 #include <nsIPrefBranch.h>
93 #include <nsIPresShell.h>
94 #include <nsIPrivateDOMEvent.h>
95 #include <nsIPromptService.h>
96 #include <nsIScriptGlobalObject.h>
97 #include <nsIScriptNameSpaceManager.h>
98 #include <nsIStringBundle.h>
99 #include <nsITreeSelection.h>
100 #include <nsITreeView.h>
101 #include <nsIURI.h>
102 #include <nsIVariant.h>
103 #include <nsIWindowMediator.h>
104 #include <nsMemory.h>
105 #include <nsNetUtil.h>
106 #include <nsServiceManagerUtils.h>
107 #include <nsStringGlue.h>
108 #include <prlog.h>
109 
110 // added for download support. Some will stay after bug 3521 is fixed
111 #include <sbIDeviceBase.h>
112 #include <sbIDeviceManager.h>
113 #include <sbILibraryManager.h>
114 #include <nsIDialogParamBlock.h>
115 #include <nsISupportsPrimitives.h>
116 #include <nsIWindowWatcher.h>
117 
118 /*
119  * To log this module, set the following environment variable:
120  * NSPR_LOG_MODULES=sbRemotePlayer:5
121  */
122 #ifdef PR_LOGGING
123 static PRLogModuleInfo* gRemotePlayerLog = nsnull;
124 #endif
125 
126 #undef LOG
127 #undef TRACE
128 #define LOG(args) PR_LOG(gRemotePlayerLog, PR_LOG_WARN, args)
129 #define TRACE(args) PR_LOG(gRemotePlayerLog, PR_LOG_DEBUG, args)
130 #ifdef __GNUC__
131 #define __FUNCTION__ __PRETTY_FUNCTION__
132 #endif
133 
134 static NS_DEFINE_CID(kRemotePlayerCID, SONGBIRD_REMOTEPLAYER_CID);
135 
136 const static char* sPublicWProperties[] =
137  { "playback_control:position" };
138 
139 const static char* sPublicRProperties[] =
140  { "site:apiVersionMajor",
141  "site:apiVersionMinor",
142  "site:playing",
143  "site:paused",
144  "site:repeat",
145  "site:shuffle",
146  "site:position",
147  "site:duration",
148  "site:volume",
149  "site:mute",
150  "site:name",
151  "library_read:playlists",
152  "site:webLibrary",
153  "site:mainLibrary",
154  "site:siteLibrary",
155  "site:webPlaylist",
156  "site:downloadMediaList",
157  "playback_read:currentArtist",
158  "playback_read:currentAlbum",
159  "playback_read:currentTrack",
160  "site:commands",
161  "classinfo:classDescription",
162  "classinfo:contractID",
163  "classinfo:classID",
164  "classinfo:implementationLanguage",
165  "classinfo:flags" };
166 
167 const static char* sPublicMethods[] =
168  { "playback_control:play",
169  "playback_control:playMediaList",
170  "playback_control:stop",
171  "playback_control:pause",
172  "playback_control:previous",
173  "playback_control:next",
174  "playback_control:playURL",
175  "library_write:downloadItem",
176  "library_write:downloadList",
177  "library_write:downloadSelected",
178  "site:setSiteScope",
179  "library_read:libraries",
180  "playback_read:removeListener",
181  "playback_read:addListener",
182  "site:supportsVersion",
183  "site:createTextProperty",
184  "site:createDateTimeProperty",
185  "site:createURIProperty",
186  "site:createNumberProperty",
187  "site:createImageProperty",
188  "site:createRatingsProperty",
189  "site:createButtonProperty",
190  "site:createDownloadButtonProperty",
191  "site:hasAccess" };
192 
193 // dataremotes keys that can be listened to
194 // when you change this, please update /documentation/ListenerTopics.txt thanks!
195 const static char* sPublicMetadata[] =
196  { "metadata.artist",
197  "metadata.title",
198  "metadata.album",
199  "metadata.genre",
200  "metadata.position",
201  "metadata.length",
202  "metadata.position.str",
203  "metadata.length.str",
204  "playlist.shuffle",
205  "playlist.repeat",
206  "playlist.shuffle.disabled",
207  "faceplate.volume",
208  "faceplate.mute",
209  "faceplate.playing",
210  "faceplate.paused" };
211 
212 // This is a lookup table for converting the human readable catagory names
213 // into our internal names (see sbSecurityMinin.cpp:sScopes).
214 // The first entry is the javascript text, and the second one is for internal,
215 // we add a : at the end of the internal one because that is what is compared.
216 const static char* sPublicCategoryConversions[][2] =
217  { { "Control Playback", "playback_control:" },
218  { "Read Current", "playback_read:" },
219  { "Read Library", "library_read:" },
220  { "Modify Library", "library_write:" } };
221 
222 // needs to be in nsEventDispatcher.cpp
223 #define RAPI_EVENT_CLASS NS_LITERAL_STRING("Events")
224 #define RAPI_EVENT_TYPE NS_LITERAL_STRING("remoteapi")
225 #define RAPI_EVENT_TYPE_DOWNLOADSTART NS_LITERAL_STRING("downloadstart")
226 #define RAPI_EVENT_TYPE_DOWNLOADCOMPLETE NS_LITERAL_STRING("downloadcomplete")
227 #define RAPI_EVENT_TYPE_BEFORETRACKCHANGE NS_LITERAL_STRING("beforetrackchange")
228 #define RAPI_EVENT_TYPE_TRACKCHANGE NS_LITERAL_STRING("trackchange")
229 #define RAPI_EVENT_TYPE_TRACKINDEXCHANGE NS_LITERAL_STRING("trackindexchange")
230 #define RAPI_EVENT_TYPE_BEFOREVIEW NS_LITERAL_STRING("beforeviewchange")
231 #define RAPI_EVENT_TYPE_VIEW NS_LITERAL_STRING("viewchange")
232 #define RAPI_EVENT_TYPE_STOP NS_LITERAL_STRING("playbackstopped")
233 #define SB_PREFS_ROOT NS_LITERAL_STRING("songbird.")
234 #define SB_EVENT_CMNDS_UP NS_LITERAL_STRING("playlist-commands-updated")
235 #define SB_WEB_TABBROWSER NS_LITERAL_STRING("sb-tabbrowser")
236 
237 #define SB_LIB_NAME_MAIN "main"
238 #define SB_LIB_NAME_WEB "web"
239 
240 #define SB_DATAREMOTE_FACEPLATE_STATUS NS_LITERAL_STRING("faceplate.status.override.text")
241 
242 #define RAPI_VERSION_MAJOR 1
243 #define RAPI_VERSION_MINOR 0
244 
245 // callback for destructor to clear out the observer hashtable
246 PR_STATIC_CALLBACK(PLDHashOperator)
247 UnbindAndRelease ( const nsAString &aKey,
248  sbRemoteObserver &aRemObs,
249  void *userArg )
250 {
251  LOG(("UnbindAndRelease(%s, %x %x)", PromiseFlatString(aKey).get(), aRemObs.observer.get(), aRemObs.remote.get()));
252  NS_ASSERTION(&aRemObs, "GAH! Hashtable contains a null entry");
253  NS_ASSERTION(aRemObs.remote, "GAH! Container contains a null remote");
254  NS_ASSERTION(aRemObs.observer, "GAH! Container contains a null observer");
255 
256  aRemObs.remote->Unbind();
257  return PL_DHASH_REMOVE;
258 }
259 
260 // helper class to push a system pricipal so that all calls across xpconnect
261 // will succeed. Similar to nsAutoLock, except for principals
263 {
264  public:
266  {
267  mStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
268  if (mStack) {
269  nsresult rv = mStack->Push(nsnull);
270  if (NS_FAILED(rv)) {
271  // failed to push the stack, don't accidentally pop it later
272  mStack = nsnull;
273  }
274  }
275  }
277  {
278  if (mStack) {
279  JSContext *cx;
280  mStack->Pop(&cx);
281  }
282  }
283  // tell people if we succeeded in pushing the principal
284  operator PRBool() const
285  {
286  return mStack ? PR_TRUE : PR_FALSE ;
287  }
288  protected:
289  nsCOMPtr<nsIJSContextStack> mStack;
290 };
291 
293 {
294  public:
296 
297  sbRemotePlayerEnumCallback( nsCOMArray<sbIMediaItem>& aArray ) :
298  mArray(aArray) { }
299 
300  NS_IMETHODIMP OnEnumerationBegin( sbIMediaList*, PRUint16* _retval )
301  {
302  NS_ENSURE_ARG(_retval);
304  return NS_OK;
305  }
306  NS_IMETHODIMP OnEnumerationEnd( sbIMediaList*, nsresult )
307  {
308  return NS_OK;
309  }
310  NS_IMETHODIMP OnEnumeratedItem( sbIMediaList*, sbIMediaItem* aItem, PRUint16* _retval )
311  {
312  NS_ENSURE_ARG(_retval);
314 
315  mArray.AppendObject( aItem );
316 
317  return NS_OK;
318  }
319  private:
320  nsCOMArray<sbIMediaItem>& mArray;
321 };
323 
325  nsIClassInfo,
332 
333 NS_IMPL_CI_INTERFACE_GETTER6( sbRemotePlayer,
334  nsISecurityCheckedComponent,
335  sbIRemotePlayer,
336  nsIDOMEventListener,
337  nsISupportsWeakReference,
338  sbIMediacoreEventListener,
340 
341 SB_IMPL_CLASSINFO( sbRemotePlayer,
344  nsIProgrammingLanguage::CPLUSPLUS,
345  0,
346  kRemotePlayerCID )
347 
348 sbRemotePlayer::sbRemotePlayer() :
349  mInitialized(PR_FALSE),
350  mPrivileged(PR_FALSE)
351 {
352 #ifdef PR_LOGGING
353  if (!gRemotePlayerLog) {
354  gRemotePlayerLog = PR_NewLogModule("sbRemotePlayer");
355  }
356 #endif
357  LOG(("sbRemotePlayer::sbRemotePlayer()"));
358 }
359 
361 {
362  LOG(("sbRemotePlayer::~sbRemotePlayer()"));
363 
364  if (mRemObsHash.IsInitialized()) {
365  mRemObsHash.Enumerate(UnbindAndRelease, nsnull);
366  mRemObsHash.Clear();
367  }
368 
369  if (mDownloadCallback)
370  mDownloadCallback->Finalize();
371  if (mNotificationMgr)
372  mNotificationMgr->Cancel();
373 }
374 
375 nsresult
377 {
378  LOG(("sbRemotePlayer::Init()"));
379 
380  nsresult rv;
381 
382  // Don't set any scope information here -- wait for either the client to
383  // set it or set it when a site library is requested.
384  mScopeDomain.SetIsVoid(PR_TRUE);
385  mScopePath.SetIsVoid(PR_TRUE);
386  mSiteScopeURL.SetIsVoid(PR_TRUE);
387 
388  // pull the dom window from the js stack and context
389  nsCOMPtr<nsPIDOMWindow> privWindow = sbRemotePlayer::GetWindowFromJS();
390  NS_ENSURE_TRUE(privWindow, NS_ERROR_UNEXPECTED);
391 
392  mPrivileged = PR_FALSE;
393 
394  rv = InitInternal(privWindow);
395  NS_ENSURE_SUCCESS(rv, rv);
396 
397  return NS_OK;
398 }
399 
400 nsresult
401 sbRemotePlayer::InitPrivileged(nsIURI* aCodebase, nsIDOMWindow* aWindow)
402 {
403  LOG(("sbRemotePlayer::InitPrivileged()"));
404 
405  NS_ASSERTION(aCodebase, "aCodebase is null");
406  NS_ASSERTION(aWindow, "aWindow is null");
407 
408  nsresult rv;
409 
411  NS_ENSURE_SUCCESS(rv, rv);
412 
413  nsCString spec;
414  rv = aCodebase->GetSpec(spec);
415  NS_ENSURE_SUCCESS(rv, rv);
416 
417  mSiteScopeURL = NS_ConvertUTF8toUTF16(spec);
418 
419  nsCOMPtr<nsPIDOMWindow> privWindow = do_QueryInterface(aWindow, &rv);
420  NS_ENSURE_SUCCESS(rv, rv);
421 
422  mPrivileged = PR_TRUE;
423 
424  rv = InitInternal(privWindow);
425  NS_ENSURE_SUCCESS(rv, rv);
426 
427  return NS_OK;
428 }
429 
430 nsresult
431 sbRemotePlayer::InitInternal(nsPIDOMWindow* aWindow)
432 {
433  LOG(("sbRemotePlayer::InitInternal()"));
434 
435  NS_ASSERTION(aWindow, "aWindow is null");
436 
437  mPrivWindow = aWindow;
438 
439  nsresult rv;
440  nsCOMPtr<nsISupportsWeakReference> weakRef =
441  do_GetService(SB_MEDIACOREMANAGER_CONTRACTID, &rv);
442  NS_ENSURE_SUCCESS(rv, rv);
443 
444  rv = weakRef->GetWeakReference(getter_AddRefs(mMM));
445  NS_ENSURE_SUCCESS(rv, rv);
446 
447  mIOService = do_GetService("@mozilla.org/network/io-service;1", &rv);
448  NS_ENSURE_SUCCESS( rv, rv );
449 
450  PRBool success = mRemObsHash.Init();
451  NS_ENSURE_TRUE( success, NS_ERROR_FAILURE );
452 
453  success = mCachedLibraries.Init(2);
454  NS_ENSURE_TRUE( success, NS_ERROR_FAILURE );
455 
456  nsRefPtr<sbSecurityMixin> mixin = new sbSecurityMixin();
457  NS_ENSURE_TRUE( mixin, NS_ERROR_OUT_OF_MEMORY );
458 
459  // Get the list of IIDs to pass to the security mixin
460  nsIID ** iids;
461  PRUint32 iidCount;
462  GetInterfaces(&iidCount, &iids);
463 
464  // initialize our mixin with approved interfaces, methods, properties
465  rv = mixin->Init( (sbISecurityAggregator*)this,
466  (const nsIID**)iids, iidCount,
467  sPublicMethods,NS_ARRAY_LENGTH(sPublicMethods),
468  sPublicRProperties,NS_ARRAY_LENGTH(sPublicRProperties),
469  sPublicWProperties, NS_ARRAY_LENGTH(sPublicWProperties),
470  mPrivileged );
471  NS_ENSURE_SUCCESS( rv, rv );
472  NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(iidCount, iids);
473 
474  mSecurityMixin = do_QueryInterface(
475  NS_ISUPPORTS_CAST( sbISecurityMixin*, mixin ), &rv );
476  NS_ENSURE_SUCCESS( rv, rv );
477 
478  //
479  // Get the Content Document
480  //
481  mPrivWindow->GetDocument( getter_AddRefs(mContentDoc) );
482  NS_ENSURE_STATE(mContentDoc);
483 
484  //
485  // Set the content document on our mixin so that it knows where to send
486  // notification events
487  //
488  rv = mixin->SetNotificationDocument( mContentDoc );
489  NS_ENSURE_SUCCESS( rv, rv );
490 
491  //
492  // Get the Chrome Document by going up the docshell tree
493  //
494  nsIDocShell *docShell = mPrivWindow->GetDocShell();
495  NS_ENSURE_STATE(docShell);
496 
497  nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(docShell, &rv);
498  NS_ENSURE_SUCCESS(rv, rv);
499 
500  nsCOMPtr<nsIDocShellTreeItem> rootItem;
501  rv = treeItem->GetRootTreeItem(getter_AddRefs(rootItem));
502  NS_ENSURE_SUCCESS(rv, rv);
503 
504  nsCOMPtr<nsIDocShell> rootShell = do_QueryInterface(rootItem, &rv);
505  NS_ENSURE_SUCCESS(rv, rv);
506 
507  nsCOMPtr<nsIContentViewer> contentViewer;
508  rv = rootShell->GetContentViewer(getter_AddRefs(contentViewer));
509  NS_ENSURE_SUCCESS(rv, rv);
510 
511  rv = contentViewer->GetDOMDocument(getter_AddRefs(mChromeDoc));
512  NS_ENSURE_SUCCESS(rv, rv);
513  NS_ENSURE_STATE(mChromeDoc);
514 
515  LOG(("sbRemotePlayer::Init() -- registering unload listener"));
516  // Have our HandleEvent called on page unloads, so we can unhook commands
517  nsCOMPtr<nsIDOMEventTarget> eventTarget( do_QueryInterface(mChromeDoc) );
518  NS_ENSURE_STATE(eventTarget);
519  eventTarget->AddEventListener( NS_LITERAL_STRING("unload"), this , PR_TRUE );
520 
521  LOG(("sbRemotePlayer::Init() -- registering PlaylistCellClick listener"));
522  eventTarget->AddEventListener( NS_LITERAL_STRING("PlaylistCellClick"), this , PR_TRUE );
523 
524  LOG(("sbRemotePlayer::Init() -- registering RemoteAPIPermissionDenied listener"));
525  eventTarget->AddEventListener( SB_EVENT_RAPI_PERMISSION_DENIED, this , PR_TRUE );
526 
527  LOG(("sbRemotePlayer::Init() -- registering RemoteAPIPermissionChanged listener"));
528  eventTarget->AddEventListener( SB_EVENT_RAPI_PERMISSION_CHANGED, this , PR_TRUE );
529 
531  NS_ENSURE_TRUE(mNotificationMgr, NS_ERROR_OUT_OF_MEMORY);
532 
533  rv = mNotificationMgr->Init();
534  NS_ENSURE_SUCCESS(rv, rv);
535 
536  // Set up listener for playback service
537  LOG(("sbRemotePlayer::Init() -- registering playback listener"));
538  nsCOMPtr<sbIMediacoreEventTarget> target =
539  do_QueryReferent(mMM, &rv);
540  NS_ENSURE_SUCCESS(rv, rv);
541 
542  rv = target->AddListener(this);
543  NS_ENSURE_SUCCESS(rv, rv);
544 
545  // Set up download callbacks
547  NS_ENSURE_TRUE(mDownloadCallback, NS_ERROR_OUT_OF_MEMORY);
548  rv = mDownloadCallback->Initialize(this);
549  NS_ENSURE_SUCCESS(rv, rv);
550 
551 #ifdef METRICS_ENABLED
552  // Set up metrics and count this session
553  mMetrics = do_CreateInstance("@songbirdnest.com/Songbird/Metrics;1", &rv);
554  NS_ENSURE_SUCCESS(rv, rv);
555 
556  // Count this session
557  rv = mMetrics->MetricsInc(NS_LITERAL_STRING("rapi.sessionStarted"),
558  EmptyString(),
559  EmptyString());
560  NS_ENSURE_SUCCESS(rv, rv);
561 #endif
562 
563  mInitialized = PR_TRUE;
564 
565  return NS_OK;
566 }
567 
568 // ---------------------------------------------------------------------------
569 //
570 // sbISecurityAggregator
571 //
572 // ---------------------------------------------------------------------------
573 
574 NS_IMETHODIMP
575 sbRemotePlayer::GetRemotePlayer(sbIRemotePlayer * *aRemotePlayer)
576 {
577  NS_ENSURE_ARG_POINTER(aRemotePlayer);
578 
579  nsresult rv;
580  *aRemotePlayer = nsnull;
581 
582  nsCOMPtr<sbIRemotePlayer> remotePlayer;
583 
584  rv = QueryInterface( NS_GET_IID( sbIRemotePlayer ), getter_AddRefs( remotePlayer ) );
585  NS_ENSURE_SUCCESS( rv, rv );
586 
587  remotePlayer.swap( *aRemotePlayer );
588 
589  return NS_OK;
590 }
591 
592 // ---------------------------------------------------------------------------
593 //
594 // sbIRemotePlayer
595 //
596 // ---------------------------------------------------------------------------
597 
598 NS_IMETHODIMP
599 sbRemotePlayer::SupportsVersion( const nsAString &aAPIVersion,
600  PRBool *aSupportsVersion )
601 {
602  NS_ENSURE_ARG_POINTER(aSupportsVersion);
603  NS_ENSURE_TRUE(!aAPIVersion.IsEmpty(), NS_ERROR_INVALID_ARG);
604 
605  *aSupportsVersion = PR_FALSE;
606 
607  nsTArray<nsString> substrings;
608  nsString_Split(aAPIVersion, NS_LITERAL_STRING("."), substrings);
609 
610  nsresult rv = NS_ERROR_UNEXPECTED;
611  PRInt32 majorVersion = substrings[0].ToInteger(&rv);
612  NS_ENSURE_SUCCESS(rv, rv);
613 
614  // No use keeping on comparing if the major version passed in is greater
615  // the the current major version.
616  if(majorVersion > static_cast<PRInt32>(RAPI_VERSION_MAJOR)) {
617  return NS_OK;
618  }
619 
620  // Make sure we have a minor version. We only use array index 0 and 1, all
621  // other strings we get from the split are ignored as our RAPI versioning
622  // is always in MAJOR.MINOR format.
623  if(substrings.Length() > 1) {
624  PRInt32 minorVersion = substrings[1].ToInteger(&rv);
625  NS_ENSURE_SUCCESS(rv, rv);
626 
627  if(minorVersion <= static_cast<PRInt32>(RAPI_VERSION_MINOR)) {
628  *aSupportsVersion = PR_TRUE;
629  }
630  }
631  else {
632  // User only passed in a major version and it matched the major version
633  // we currently have.
634  *aSupportsVersion = PR_TRUE;
635  }
636 
637  return NS_OK;
638 }
639 
640 NS_IMETHODIMP
641 sbRemotePlayer::GetApiVersionMajor( PRUint32 *aApiVersionMajor )
642 {
643  NS_ENSURE_ARG_POINTER(aApiVersionMajor);
644 
645  *aApiVersionMajor = RAPI_VERSION_MAJOR;
646 
647  return NS_OK;
648 }
649 
650 NS_IMETHODIMP
651 sbRemotePlayer::GetApiVersionMinor( PRUint32 *aApiVersionMinor )
652 {
653  NS_ENSURE_ARG_POINTER(aApiVersionMinor);
654 
655  *aApiVersionMinor = RAPI_VERSION_MINOR;
656 
657  return NS_OK;
658 }
659 
660 NS_IMETHODIMP
661 sbRemotePlayer::GetName( nsAString &aName )
662 {
663  LOG(("sbRemotePlayer::GetName()"));
664  aName.AssignLiteral("Songbird");
665  return NS_OK;
666 }
667 
668 NS_IMETHODIMP
670 {
671  return Libraries( NS_LITERAL_STRING(SB_LIB_NAME_MAIN), aMainLibrary );
672 }
673 
674 NS_IMETHODIMP
675 sbRemotePlayer::GetWebLibrary( sbIRemoteLibrary **aWebLibrary )
676 {
677  return Libraries( NS_LITERAL_STRING(SB_LIB_NAME_WEB), aWebLibrary );
678 }
679 
680 NS_IMETHODIMP
681 sbRemotePlayer::Libraries( const nsAString &aLibraryID,
682  sbIRemoteLibrary **aLibrary )
683 {
684  NS_ENSURE_ARG_POINTER(aLibrary);
685  LOG(( "sbRemotePlayer::Libraries(%s)",
686  NS_LossyConvertUTF16toASCII(aLibraryID).get() ));
687  nsresult rv;
688 
689  // Go ahead and return the cached copy if we have it. This Get call will take
690  // care of AddRef'ing for us.
691  if ( mCachedLibraries.Get( aLibraryID, aLibrary ) ) {
692  return NS_OK;
693  }
694 
695  // for a newly created library
696  nsRefPtr<sbRemoteLibrary> library;
697 
698  // NOTE: if you add special library names here, document them in sbIRemotePlayer.idl
699  if ( aLibraryID.EqualsLiteral(SB_LIB_NAME_MAIN) ) {
700  // No cached main library create a new one.
701  LOG(("sbRemotePlayer::Libraries() - creating main library"));
702  library = new sbRemoteLibrary(this);
703  NS_ENSURE_TRUE( library, NS_ERROR_OUT_OF_MEMORY );
704  }
705  else if ( aLibraryID.EqualsLiteral(SB_LIB_NAME_WEB) ) {
706  // No cached web library create a new one.
707  LOG(("sbRemotePlayer::Libraries() - creating web library"));
708  library = new sbRemoteWebLibrary(this);
709  NS_ENSURE_TRUE( library, NS_ERROR_OUT_OF_MEMORY );
710  }
711  else {
712  // we don't handle anything but "main" and "web" yet.
713  return NS_ERROR_INVALID_ARG;
714  }
715 
716  rv = library->Init();
717  NS_ENSURE_SUCCESS( rv, rv );
718 
719  rv = library->ConnectToDefaultLibrary( aLibraryID );
720  NS_ENSURE_SUCCESS( rv, rv );
721 
722  nsCOMPtr<sbIRemoteLibrary> remoteLibrary =
723  do_QueryInterface( NS_ISUPPORTS_CAST( sbIRemoteLibrary*, library ), &rv );
724  NS_ENSURE_SUCCESS( rv, rv );
725 
726  // Now that initialization and library connection has succeeded cache
727  // the created library in the hashtable.
728  if ( !mCachedLibraries.Put( aLibraryID, remoteLibrary ) ) {
729  NS_WARNING("Failed to cache remoteLibrary!");
730  }
731 
732  NS_ADDREF( *aLibrary = remoteLibrary );
733  return NS_OK;
734 }
735 
736 NS_IMETHODIMP
737 sbRemotePlayer::SetSiteScope(const nsACString & aDomain, const nsACString & aPath)
738 {
739  nsresult rv;
740 
741 #if SB_DEBUG_RAPI
742  NS_WARNING("sbRemotePlayer::SetSiteScope() - skipping multiple site library checks");
743 #else
744  NS_ENSURE_TRUE( mScopeDomain.IsVoid(), NS_ERROR_ALREADY_INITIALIZED );
745  NS_ENSURE_TRUE( mScopePath.IsVoid(), NS_ERROR_ALREADY_INITIALIZED );
746 #endif /* SB_DEBUG_RAPI */
747 
748  nsCString domain(aDomain);
749  nsCString path(aPath);
750  nsCOMPtr<nsIURI> codebaseURI;
751  nsCOMPtr<sbISecurityMixin> mixin = do_QueryInterface( mSecurityMixin, &rv );
752  NS_ENSURE_SUCCESS( rv, rv );
753  rv = mixin->GetCodebase( getter_AddRefs(codebaseURI) );
754  NS_ENSURE_SUCCESS( rv, rv );
755 
756  rv = sbURIChecker::CheckURI(domain, path, codebaseURI);
757  NS_ENSURE_SUCCESS( rv, rv );
758 
759  mScopeDomain = domain;
760  mScopePath = path;
761 
762  return NS_OK;
763 }
764 
765 NS_IMETHODIMP
766 sbRemotePlayer::GetSiteScope(nsIURI * *aURI)
767 {
768  NS_ENSURE_ARG_POINTER(aURI);
769 
770  nsCOMPtr<nsIURI> uri = GetSiteScopeURI();
771  uri.swap(*aURI);
772 
773  return NS_OK;
774 }
775 
776 NS_IMETHODIMP
777 sbRemotePlayer::GetSiteLibrary(sbIRemoteLibrary * *aSiteLibrary)
778 {
779  LOG(( "sbRemotePlayer::GetSiteLibrary(%s)", mScopePath.BeginReading() ));
780 
781  nsresult rv;
782 
783  // check if the site scope has beens set before; if not, set it implicitly
784  if ( mScopeDomain.IsVoid() || mScopePath.IsVoid() ) {
785  SetSiteScope( mScopeDomain, mScopePath );
786  }
787 
788  nsString siteLibraryFilename;
790  mScopePath,
791  siteLibraryFilename );
792  NS_ENSURE_SUCCESS( rv, rv );
793 
794  if ( mCachedLibraries.Get( siteLibraryFilename, aSiteLibrary ) ) {
795  return NS_OK;
796  }
797 
798  nsRefPtr<sbRemoteSiteLibrary> library;
799  library = new sbRemoteSiteLibrary(this);
800  NS_ENSURE_TRUE( library, NS_ERROR_OUT_OF_MEMORY );
801 
802  rv = library->Init();
803  NS_ENSURE_SUCCESS( rv, rv );
804 
805  rv = library->ConnectToSiteLibrary( mScopeDomain, mScopePath );
806  NS_ENSURE_SUCCESS( rv, rv );
807 
808  nsCOMPtr<sbIRemoteLibrary> remoteLibrary(
809  do_QueryInterface( NS_ISUPPORTS_CAST( sbIRemoteSiteLibrary*, library ),
810  &rv ) );
811  NS_ENSURE_SUCCESS( rv, rv );
812 
813  PRBool success = mCachedLibraries.Put( siteLibraryFilename, remoteLibrary );
814  NS_ENSURE_TRUE( success, NS_ERROR_FAILURE );
815 
816  NS_ADDREF( *aSiteLibrary = remoteLibrary );
817  return NS_OK;
818 }
819 
820 NS_IMETHODIMP
821 sbRemotePlayer::GetCommands( sbIRemoteCommands **aCommandsObject )
822 {
823  NS_ENSURE_ARG_POINTER(aCommandsObject);
824 
825  LOG(("sbRemotePlayer::GetCommands()"));
826 
827  nsresult rv;
828  if (!mCommandsObject) {
829  LOG(("sbRemotePlayer::GetCommands() -- creating it"));
830  mCommandsObject = new sbRemoteCommands(this);
831  NS_ENSURE_TRUE( mCommandsObject, NS_ERROR_OUT_OF_MEMORY );
832 
833  rv = mCommandsObject->Init();
834  NS_ENSURE_SUCCESS( rv, rv );
835 
836  mCommandsObject->SetOwner(this);
837  RegisterCommands(PR_TRUE);
838  }
839  NS_ADDREF( *aCommandsObject = mCommandsObject );
840  return NS_OK;
841 }
842 
843 nsresult
844 sbRemotePlayer::RegisterCommands( PRBool aUseDefaultCommands )
845 {
846  NS_ENSURE_STATE(mCommandsObject);
847  nsresult rv;
848 
849  // store the default command usage
850  mUseDefaultCommands = aUseDefaultCommands;
851 
852  // Get the PlaylistCommandsManager object and register commands with it.
853  nsCOMPtr<sbIPlaylistCommandsManager> mgr(
854  do_GetService( "@songbirdnest.com/Songbird/PlaylistCommandsManager;1", &rv ) );
855  NS_ENSURE_SUCCESS( rv, rv );
856 
857  nsCOMPtr<sbIPlaylistCommands> commands = (sbIPlaylistCommands*) mCommandsObject;
858  NS_ENSURE_TRUE( commands, NS_ERROR_UNEXPECTED );
859 
860  // XXXredfive - make this pull the GUID from the web playlist
861  // need sbIRemoteMediaLists online before we can do that.
862  // Registration of commands is changing soon, for now type='library' works
863  NS_ENSURE_SUCCESS( rv, rv );
864  rv = mgr->RegisterPlaylistCommandsMediaItem( NS_LITERAL_STRING("remote-test-guid"),
865  NS_LITERAL_STRING("library"),
866  commands );
867  NS_ASSERTION( NS_SUCCEEDED(rv),
868  "Failed to register commands in playlistcommandsmanager" );
869  rv = mgr->RegisterPlaylistCommandsMediaItem( NS_LITERAL_STRING("remote-test-guid"),
870  NS_LITERAL_STRING("simple"),
871  commands );
872  NS_ASSERTION( NS_SUCCEEDED(rv),
873  "Failed to register commands in playlistcommandsmanager" );
874 
875  OnCommandsChanged();
876 
877  return rv;
878 }
879 
880 NS_IMETHODIMP
881 sbRemotePlayer::OnCommandsChanged()
882 {
883  LOG(("sbRemotePlayer::OnCommandsChanged()"));
884  if (!mRemWebPlaylist) {
885  nsresult rv = InitRemoteWebPlaylist();
886  NS_ENSURE_SUCCESS( rv, rv );
887  }
888 
889  //
890  // This is where we want to add code to register the default commands, when
891  // the api for that comes in to being. Key off of mUseDefaultCommands.
892  //
893 
894  // When the commands system is able to broadcast change notices about
895  // registered commands this can go away. In the meantime we need to tell
896  // the playlist to rescan so it picks up new/deleted commands.
897  // Theoretically we could just fire an event here, but it wasn't getting
898  // caught in the binding, need to look in to that more.
899  mRemWebPlaylist->RescanCommands();
900  return NS_OK;
901 }
902 
903 NS_IMETHODIMP
904 sbRemotePlayer::GetWebPlaylist( sbIRemoteWebPlaylist **aWebPlaylist )
905 {
906  LOG(("sbRemotePlayer::GetWebPlaylist()"));
907  NS_ENSURE_ARG_POINTER(aWebPlaylist);
908  nsresult rv;
909 
910  if (!mRemWebPlaylist) {
911  rv = InitRemoteWebPlaylist();
912  NS_ENSURE_SUCCESS( rv, rv );
913  }
914 
915  nsCOMPtr<sbIRemoteWebPlaylist> remotePlaylist( do_QueryInterface(
916  NS_ISUPPORTS_CAST( sbIRemoteWebPlaylist*, mRemWebPlaylist ), &rv ) );
917  NS_ENSURE_SUCCESS( rv, rv );
918 
919  NS_ADDREF( *aWebPlaylist = remotePlaylist );
920  return NS_OK;
921 }
922 
923 NS_IMETHODIMP
924 sbRemotePlayer::GetDownloadMediaList( sbIRemoteMediaList **aDownloadMediaList )
925 {
926  LOG(("sbRemotePlayer::GetDownloadMediaList()"));
927  NS_ENSURE_ARG_POINTER(aDownloadMediaList);
928 
929  nsresult rv;
930  nsCOMPtr<sbIDownloadDeviceHelper> dh(
931  do_GetService( "@songbirdnest.com/Songbird/DownloadDeviceHelper;1", &rv ));
932  NS_ENSURE_SUCCESS( rv, rv );
933 
934  nsCOMPtr<sbIMediaList> downloadMediaList;
935  rv = dh->GetDownloadMediaList(getter_AddRefs(downloadMediaList));
936  NS_ENSURE_SUCCESS( rv, rv );
937 
938  rv = SB_WrapMediaList( this, downloadMediaList, aDownloadMediaList );
939  NS_ENSURE_SUCCESS( rv, rv );
940 
941  return NS_OK;
942 }
943 
944 NS_IMETHODIMP
945 sbRemotePlayer::DownloadItem( sbIMediaItem *aItem )
946 {
947  LOG(("sbRemotePlayer::DownloadItem()"));
948 
949  NS_ENSURE_ARG_POINTER(aItem);
950 
951  nsresult rv;
952 
953  // Make sure the item is JUST an item, no lists or libraries allowed
954  nsCOMPtr<sbIMediaList> listcheck (do_QueryInterface(aItem));
955  NS_ENSURE_FALSE( listcheck, NS_ERROR_INVALID_ARG );
956 
957  nsCOMPtr<sbIMediaItem> item;
958 
959  // The media item must be unwrapped before handing off to the download helper!
960  nsCOMPtr<sbIWrappedMediaItem> wrappedItem(do_QueryInterface( aItem, &rv ));
961  if (NS_SUCCEEDED(rv)) {
962  item = wrappedItem->GetMediaItem();
963  NS_ASSERTION( item, "GetMediaItem returned null!" );
964  }
965  else {
966  item = aItem;
967  }
968 
969  nsCOMPtr<sbIDownloadDeviceHelper> dh(
970  do_GetService( "@songbirdnest.com/Songbird/DownloadDeviceHelper;1", &rv ));
971  NS_ENSURE_SUCCESS( rv, rv );
972 
973  // no check here, download device helper doesn't return values.
974  dh->DownloadItem(item);
975 
977 
978  return NS_OK;
979 }
980 
981 NS_IMETHODIMP
982 sbRemotePlayer::DownloadList( sbIRemoteMediaList *aList )
983 {
984  LOG(("sbRemotePlayer::DownloadList()"));
985 
986  NS_ENSURE_ARG_POINTER(aList);
987 
988  nsCOMPtr<sbIMediaList> list;
989 
990  // The media list must be unwrapped before handing off to the download helper!
991  nsresult rv;
992  nsCOMPtr<sbIWrappedMediaList> wrappedList(do_QueryInterface( aList, &rv ));
993  if (NS_SUCCEEDED(rv)) {
994  list = wrappedList->GetMediaList();
995  NS_ASSERTION( list, "GetMediaList returned null!" );
996  }
997  else {
998  list = do_QueryInterface( aList, &rv );
999  NS_ENSURE_SUCCESS( rv, rv );
1000  }
1001 
1002  nsCOMPtr<sbIDownloadDeviceHelper> dh(
1003  do_GetService( "@songbirdnest.com/Songbird/DownloadDeviceHelper;1", &rv ));
1004  NS_ENSURE_SUCCESS( rv, rv );
1005 
1006  // no check here, download device helper doesn't return values.
1007  dh->DownloadAll(list);
1008 
1009  return NS_OK;
1010 }
1011 
1012 NS_IMETHODIMP
1013 sbRemotePlayer::DownloadSelected( sbIRemoteWebPlaylist *aWebPlaylist )
1014 {
1015  LOG(("sbRemotePlayer::DownloadSelected()"));
1016 
1017  NS_ENSURE_ARG_POINTER(aWebPlaylist);
1018 
1019  nsCOMPtr<nsISimpleEnumerator> selection;
1020  nsresult rv = aWebPlaylist->GetSelection( getter_AddRefs(selection) );
1021  NS_ENSURE_SUCCESS( rv, rv );
1022 
1023  // The media items must be unwrapped before handing off to the download
1024  // helper!
1025  nsRefPtr<sbUnwrappingSimpleEnumerator> wrapper(
1026  new sbUnwrappingSimpleEnumerator(selection) );
1027  NS_ENSURE_TRUE( wrapper, NS_ERROR_OUT_OF_MEMORY );
1028 
1029  nsCOMPtr<sbIDownloadDeviceHelper> dh =
1030  do_GetService( "@songbirdnest.com/Songbird/DownloadDeviceHelper;1", &rv );
1031  NS_ENSURE_SUCCESS( rv, rv );
1032 
1033  // no check here, download device helper doesn't return values.
1034  dh->DownloadSome(wrapper);
1035 
1036  return NS_OK;
1037 }
1038 
1039 NS_IMETHODIMP
1040 sbRemotePlayer::GetCurrentArtist( nsAString &aCurrentArtist )
1041 {
1042  LOG(("sbRemotePlayer::GetCurrentArtist()"));
1043  if (!mdrCurrentArtist) {
1044  nsresult rv;
1046  do_CreateInstance( "@songbirdnest.com/Songbird/DataRemote;1", &rv );
1047  NS_ENSURE_SUCCESS( rv, rv );
1048  rv = mdrCurrentArtist->Init( NS_LITERAL_STRING("metadata.artist"),
1049  SB_PREFS_ROOT );
1050  NS_ENSURE_SUCCESS( rv, rv );
1051  }
1052  return mdrCurrentArtist->GetStringValue(aCurrentArtist);
1053 }
1054 
1055 NS_IMETHODIMP
1056 sbRemotePlayer::GetCurrentAlbum( nsAString &aCurrentAlbum )
1057 {
1058  LOG(("sbRemotePlayer::GetCurrentAlbum()"));
1059  if (!mdrCurrentAlbum) {
1060  nsresult rv;
1061  mdrCurrentAlbum =
1062  do_CreateInstance( "@songbirdnest.com/Songbird/DataRemote;1", &rv );
1063  NS_ENSURE_SUCCESS( rv, rv );
1064  rv = mdrCurrentAlbum->Init( NS_LITERAL_STRING("metadata.album"),
1065  SB_PREFS_ROOT );
1066  NS_ENSURE_SUCCESS( rv, rv );
1067  }
1068  return mdrCurrentAlbum->GetStringValue(aCurrentAlbum);
1069 }
1070 
1071 NS_IMETHODIMP
1072 sbRemotePlayer::GetCurrentTrack( nsAString &aCurrentTrack )
1073 {
1074  LOG(("sbRemotePlayer::GetCurrentTrack()"));
1075  if (!mdrCurrentTrack) {
1076  nsresult rv;
1077  mdrCurrentTrack =
1078  do_CreateInstance( "@songbirdnest.com/Songbird/DataRemote;1", &rv );
1079  NS_ENSURE_SUCCESS( rv, rv );
1080  rv = mdrCurrentTrack->Init( NS_LITERAL_STRING("metadata.title"),
1081  SB_PREFS_ROOT );
1082  NS_ENSURE_SUCCESS( rv, rv );
1083  }
1084  return mdrCurrentTrack->GetStringValue(aCurrentTrack);
1085 }
1086 
1087 NS_IMETHODIMP
1088 sbRemotePlayer::GetPlaying( PRBool *aPlaying )
1089 {
1090  LOG(("sbRemotePlayer::GetPlaying()"));
1091  NS_ENSURE_ARG_POINTER(aPlaying);
1092  if (!mdrPlaying) {
1093  nsresult rv;
1094  mdrPlaying = do_CreateInstance( "@songbirdnest.com/Songbird/DataRemote;1",
1095  &rv );
1096  NS_ENSURE_SUCCESS( rv, rv );
1097  rv = mdrPlaying->Init( NS_LITERAL_STRING("faceplate.playing"),
1098  SB_PREFS_ROOT );
1099  NS_ENSURE_SUCCESS( rv, rv );
1100  }
1101  return mdrPlaying->GetBoolValue(aPlaying);
1102 }
1103 
1104 NS_IMETHODIMP
1105 sbRemotePlayer::GetPaused( PRBool *aPaused )
1106 {
1107  LOG(("sbRemotePlayer::GetPaused()"));
1108  NS_ENSURE_ARG_POINTER(aPaused);
1109  if (!mdrPaused) {
1110  nsresult rv;
1111  mdrPaused = do_CreateInstance( "@songbirdnest.com/Songbird/DataRemote;1",
1112  &rv );
1113  NS_ENSURE_SUCCESS( rv, rv );
1114  rv = mdrPaused->Init( NS_LITERAL_STRING("faceplate.paused"),
1115  SB_PREFS_ROOT );
1116  NS_ENSURE_SUCCESS( rv, rv );
1117  }
1118  return mdrPaused->GetBoolValue(aPaused);
1119 }
1120 
1121 NS_IMETHODIMP
1122 sbRemotePlayer::GetRepeat( PRInt64 *aRepeat )
1123 {
1124  LOG(("sbRemotePlayer::GetRepeat()"));
1125  NS_ENSURE_ARG_POINTER(aRepeat);
1126  if (!mdrRepeat) {
1127  nsresult rv;
1128  mdrRepeat = do_CreateInstance( "@songbirdnest.com/Songbird/DataRemote;1",
1129  &rv );
1130  NS_ENSURE_SUCCESS( rv, rv );
1131  rv = mdrRepeat->Init( NS_LITERAL_STRING("playlist.repeat"),
1132  SB_PREFS_ROOT );
1133  NS_ENSURE_SUCCESS( rv, rv );
1134  }
1135  return mdrRepeat->GetIntValue(aRepeat);
1136 }
1137 
1138 NS_IMETHODIMP
1139 sbRemotePlayer::GetShuffle( PRBool *aShuffle )
1140 {
1141  LOG(("sbRemotePlayer::GetShuffle()"));
1142  NS_ENSURE_ARG_POINTER(aShuffle);
1143  if (!mdrShuffle) {
1144  nsresult rv;
1145  mdrShuffle = do_CreateInstance( "@songbirdnest.com/Songbird/DataRemote;1",
1146  &rv );
1147  NS_ENSURE_SUCCESS( rv, rv );
1148  rv = mdrShuffle->Init( NS_LITERAL_STRING("playlist.shuffle"),
1149  SB_PREFS_ROOT );
1150  NS_ENSURE_SUCCESS( rv, rv );
1151  }
1152  return mdrShuffle->GetBoolValue(aShuffle);
1153 }
1154 
1155 NS_IMETHODIMP
1156 sbRemotePlayer::GetPosition( PRInt64 *aPosition )
1157 {
1158  LOG(("sbRemotePlayer::GetPosition()"));
1159  NS_ENSURE_ARG_POINTER(aPosition);
1160  if (!mdrPosition) {
1161  nsresult rv;
1162  mdrPosition = do_CreateInstance( "@songbirdnest.com/Songbird/DataRemote;1",
1163  &rv );
1164  NS_ENSURE_SUCCESS( rv, rv );
1165  rv = mdrPosition->Init( NS_LITERAL_STRING("metadata.position"),
1166  SB_PREFS_ROOT );
1167  NS_ENSURE_SUCCESS( rv, rv );
1168  }
1169  return mdrPosition->GetIntValue(aPosition);
1170 }
1171 
1172 NS_IMETHODIMP
1173 sbRemotePlayer::SetPosition( PRInt64 aPosition )
1174 {
1175  LOG(("sbRemotePlayer::SetPosition()"));
1176  NS_ENSURE_ARG_POINTER(aPosition);
1177 
1178  nsresult rv = ConfirmPlaybackControl();
1179  NS_ENSURE_SUCCESS( rv, rv );
1180 
1181  nsCOMPtr<sbIMediacoreManager> mediaCoreMgr =
1182  do_GetService(SB_MEDIACOREMANAGER_CONTRACTID, &rv);
1183  NS_ENSURE_SUCCESS(rv, rv);
1184 
1185  nsCOMPtr<sbIMediacorePlaybackControl> playbackControl;
1186  rv = mediaCoreMgr->GetPlaybackControl(getter_AddRefs(playbackControl));
1187  NS_ENSURE_SUCCESS(rv, rv);
1188 
1189  rv = playbackControl->SetPosition(aPosition);
1190  NS_ENSURE_SUCCESS(rv, rv);
1191 
1192  return TakePlaybackControl( nsnull );
1193 }
1194 
1195 NS_IMETHODIMP
1196 sbRemotePlayer::GetDuration( PRUint64 *aDuration )
1197 {
1198  LOG(("sbRemotePlayer::GetDuration()"));
1199  NS_ENSURE_ARG_POINTER(aDuration);
1200 
1201  nsresult rv;
1202  nsCOMPtr<sbIMediacoreManager> mediaCoreMgr =
1203  do_GetService(SB_MEDIACOREMANAGER_CONTRACTID, &rv);
1204  NS_ENSURE_SUCCESS(rv, rv);
1205 
1206  nsCOMPtr<sbIMediacorePlaybackControl> playbackControl;
1207  rv = mediaCoreMgr->GetPlaybackControl(getter_AddRefs(playbackControl));
1208  NS_ENSURE_SUCCESS(rv, rv);
1209 
1210  *aDuration = 0;
1211 
1212  if ( playbackControl ) {
1213  rv = playbackControl->GetDuration(aDuration);
1214  NS_ENSURE_SUCCESS(rv, rv);
1215  }
1216 
1217  return NS_OK;
1218 }
1219 
1220 NS_IMETHODIMP
1221 sbRemotePlayer::GetVolume( PRInt64 *aVolume )
1222 {
1223  LOG(("sbRemotePlayer::GetVolume()"));
1224  NS_ENSURE_ARG_POINTER(aVolume);
1225 
1226  nsresult rv;
1227  nsCOMPtr<sbIMediacoreManager> mediaCoreMgr =
1228  do_GetService(SB_MEDIACOREMANAGER_CONTRACTID, &rv);
1229  NS_ENSURE_SUCCESS(rv, rv);
1230 
1231  nsCOMPtr<sbIMediacoreVolumeControl> volumeControl;
1232  rv = mediaCoreMgr->GetVolumeControl(getter_AddRefs(volumeControl));
1233  NS_ENSURE_SUCCESS(rv, rv);
1234 
1235  double volume;
1236  rv = volumeControl->GetVolume(&volume);
1237  NS_ENSURE_SUCCESS(rv, rv);
1238 
1239  *aVolume = (PRInt64)(volume * 255); /* normalize to 0..255 */
1240  // constrain things, because the mediacore API says they can be out of range...
1241  if (NS_UNLIKELY(*aVolume < 0)) {
1242  *aVolume = 0;
1243  }
1244  if (NS_UNLIKELY(*aVolume > 255)) {
1245  *aVolume = 255;
1246  }
1247  return NS_OK;
1248 }
1249 
1250 NS_IMETHODIMP
1251 sbRemotePlayer::GetMute( PRBool *aMute )
1252 {
1253  LOG(("sbRemotePlayer::GetMute()"));
1254  NS_ENSURE_ARG_POINTER(aMute);
1255  if (!mdrMute) {
1256  nsresult rv;
1257  mdrMute = do_CreateInstance( "@songbirdnest.com/Songbird/DataRemote;1",
1258  &rv );
1259  NS_ENSURE_SUCCESS( rv, rv );
1260  rv = mdrMute->Init( NS_LITERAL_STRING("faceplate.mute"), SB_PREFS_ROOT );
1261  NS_ENSURE_SUCCESS( rv, rv );
1262  }
1263  return mdrMute->GetBoolValue(aMute);
1264 }
1265 
1266 NS_IMETHODIMP
1267 sbRemotePlayer::AddListener( const nsAString &aKey,
1268  sbIRemoteObserver *aObserver )
1269 {
1270  LOG(("sbRemotePlayer::AddListener()"));
1271  NS_ENSURE_ARG_POINTER(aObserver);
1272 
1273  // Make sure the key passed in is a valid one for attaching to
1274  PRInt32 length = NS_ARRAY_LENGTH(sPublicMetadata);
1275  for (PRInt32 index = 0 ; index < length; index++ ) {
1276  // if we find it break out of the loop and keep going
1277  if ( aKey.EqualsLiteral(sPublicMetadata[index]) )
1278  break;
1279  // if we get to this point it isn't accepted, shortcircuit
1280  if ( index == (length-1) )
1281  return NS_ERROR_FAILURE;
1282  }
1283 
1284  nsresult rv;
1285  nsCOMPtr<sbIDataRemote> dr =
1286  do_CreateInstance( "@songbirdnest.com/Songbird/DataRemote;1", &rv );
1287  NS_ENSURE_SUCCESS( rv, rv );
1288  rv = dr->Init( aKey, SB_PREFS_ROOT );
1289  NS_ENSURE_SUCCESS( rv, rv );
1290  rv = dr->BindRemoteObserver( aObserver, PR_FALSE );
1291  NS_ENSURE_SUCCESS( rv, rv );
1292 
1293  sbRemoteObserver remObs;
1294  remObs.observer = aObserver;
1295  remObs.remote = dr;
1296  PRBool success = mRemObsHash.Put( aKey, remObs );
1297  NS_ENSURE_TRUE( success, NS_ERROR_OUT_OF_MEMORY );
1298 
1299  return NS_OK;
1300 }
1301 
1302 NS_IMETHODIMP
1303 sbRemotePlayer::RemoveListener( const nsAString &aKey,
1304  sbIRemoteObserver *aObserver )
1305 {
1306  NS_ENSURE_ARG_POINTER(aObserver);
1307  LOG(("sbRemotePlayer::RemoveListener(%s %x)",
1308  PromiseFlatString(aKey).get(), aObserver));
1309 
1310  sbRemoteObserver remObs;
1311  mRemObsHash.Get( aKey, &remObs );
1312 
1313  if ( remObs.observer == aObserver ) {
1314  LOG(( "sbRemotePlayer::RemoveListener(%s %x) -- found observer",
1315  NS_LossyConvertUTF16toASCII(aKey).get(), aObserver ));
1316 
1317  remObs.remote->Unbind();
1318  mRemObsHash.Remove(aKey);
1319  }
1320  else {
1321  LOG(( "sbRemotePlayer::RemoveListener(%s %x) -- did NOT find observer",
1322  PromiseFlatString(aKey).get(), aObserver ));
1323  }
1324 
1325  return NS_OK;
1326 }
1327 
1328 static inline
1329 nsresult StandardPlay(nsIWeakReference *aWeakRef) {
1330  NS_ENSURE_ARG_POINTER(aWeakRef);
1331 
1332  // XXXAus: Get Main Library from Library Manager.
1333  // XXXAus: Get View from Main Library.
1334  // XXXAus: Play Main Library View.
1335 
1336  nsresult rv;
1337  nsCOMPtr<sbIMediacoreManager> manager =
1338  do_QueryReferent(aWeakRef, &rv);
1339  NS_ENSURE_SUCCESS(rv, rv);
1340 
1341  return NS_OK;
1342 }
1343 
1344 NS_IMETHODIMP
1345 sbRemotePlayer::Play()
1346 {
1347  LOG(("sbRemotePlayer::Play()"));
1348  NS_ENSURE_STATE(mMM);
1349 
1350  nsresult rv = ConfirmPlaybackControl();
1351  NS_ENSURE_SUCCESS( rv, rv );
1352 
1353  // Check to see if playback is currently paused.
1354  // If currently paused, first attempt to resume.
1355  PRBool isPaused = PR_FALSE;
1356 
1357  rv = GetPaused( &isPaused );
1358  NS_ENSURE_SUCCESS( rv, rv );
1359 
1360  if ( isPaused ) {
1361  nsCOMPtr<sbIMediacoreManager> manager =
1362  do_QueryReferent(mMM, &rv);
1363  NS_ENSURE_SUCCESS(rv, rv);
1364 
1365  nsCOMPtr<sbIMediacorePlaybackControl> playbackControl;
1366  rv = manager->GetPlaybackControl(getter_AddRefs(playbackControl));
1367  NS_ENSURE_SUCCESS(rv, rv);
1368 
1369  if ( playbackControl ) {
1370  rv = playbackControl->Play();
1371  NS_ENSURE_SUCCESS(rv, rv);
1372  }
1373 
1374  return NS_OK;
1375  }
1376 
1377  if (!mRemWebPlaylist) {
1378  rv = InitRemoteWebPlaylist();
1379  NS_ENSURE_SUCCESS( rv, rv );
1380  }
1381 
1382  nsCOMPtr<sbIMediaListView> mediaListView;
1383  rv = mRemWebPlaylist->GetListView( getter_AddRefs(mediaListView) );
1384  NS_ENSURE_SUCCESS( rv, rv );
1385 
1386  // If the page does not have a web playlist, fall back
1387  // to the standard play button functionality.
1388  if (!mediaListView) {
1389  return StandardPlay(mMM);
1390  }
1391 
1392  nsCOMPtr<nsITreeView> treeView;
1393  rv = mediaListView->GetTreeView( getter_AddRefs(treeView) );
1394  if ( NS_FAILED(rv) ) {
1395  NS_WARNING("Got list view but did not get tree view! Falling back to standard play.");
1396  return StandardPlay(mMM);
1397  }
1398 
1399  nsCOMPtr<nsITreeSelection> treeSelection;
1400  rv = treeView->GetSelection( getter_AddRefs(treeSelection) );
1401  if ( NS_FAILED(rv) || !treeSelection ) {
1402  NS_WARNING("Got tree view but did not get selection in view. Falling back to standard play.");
1403  return StandardPlay(mMM);
1404  }
1405 
1406  PRInt32 index;
1407  treeSelection->GetCurrentIndex(&index);
1408  if ( index < 0 )
1409  index = 0;
1410 
1411  nsCOMPtr<sbIMediacoreManager> manager =
1412  do_QueryReferent(mMM, &rv);
1413  NS_ENSURE_SUCCESS(rv, rv);
1414 
1415  nsCOMPtr<sbIMediacoreSequencer> sequencer;
1416  rv = manager->GetSequencer(getter_AddRefs(sequencer));
1417  NS_ENSURE_SUCCESS(rv, rv);
1418 
1419  rv = sequencer->PlayView( mediaListView, index, PR_FALSE);
1420  NS_ENSURE_SUCCESS( rv, rv );
1421 
1422  rv = TakePlaybackControl( nsnull );
1423  NS_ENSURE_SUCCESS( rv, rv );
1424 
1425  return NS_OK;
1426 }
1427 
1428 NS_IMETHODIMP
1429 sbRemotePlayer::PlayMediaList( sbIRemoteMediaList *aList, PRInt32 aIndex )
1430 {
1431  LOG(("sbRemotePlayer::PlayMediaList()"));
1432  NS_ENSURE_ARG_POINTER(aList);
1433  NS_ENSURE_STATE(mMM);
1434 
1435  nsresult rv = ConfirmPlaybackControl();
1436  NS_ENSURE_SUCCESS( rv, rv );
1437 
1438  // Get the existing view if there is one
1439  nsCOMPtr<sbIMediaListView> mediaListView;
1440  rv = aList->GetView( getter_AddRefs(mediaListView) );
1441 
1442  // There isn't a view so create one
1443  if (!mediaListView) {
1444  nsCOMPtr<sbIMediaList> list( do_QueryInterface( aList, &rv ) );
1445  NS_ENSURE_SUCCESS( rv, rv );
1446 
1447  rv = list->CreateView( nsnull, getter_AddRefs(mediaListView) );
1448  NS_ENSURE_SUCCESS( rv, rv );
1449  }
1450 
1451  if ( aIndex < 0 )
1452  aIndex = 0;
1453 
1454  nsCOMPtr<sbIMediacoreManager> manager =
1455  do_QueryReferent(mMM, &rv);
1456  NS_ENSURE_SUCCESS(rv, rv);
1457 
1458  nsCOMPtr<sbIMediacoreSequencer> sequencer;
1459  rv = manager->GetSequencer(getter_AddRefs(sequencer));
1460  NS_ENSURE_SUCCESS(rv, rv);
1461 
1462  rv = sequencer->PlayView( mediaListView, aIndex, PR_FALSE);
1463  NS_ENSURE_SUCCESS( rv, rv );
1464 
1465  rv = TakePlaybackControl( nsnull );
1466  NS_ENSURE_SUCCESS( rv, rv );
1467 
1468  return NS_OK;
1469 }
1470 
1471 NS_IMETHODIMP
1472 sbRemotePlayer::PlayURL( const nsAString &aURL )
1473 {
1474  LOG(("sbRemotePlayer::PlayURL()"));
1475  NS_ENSURE_STATE(mMM);
1476 
1477  nsresult rv = ConfirmPlaybackControl();
1478  NS_ENSURE_SUCCESS( rv, rv );
1479 
1480  nsCOMPtr<sbIMediacoreManager> manager =
1481  do_QueryReferent(mMM, &rv);
1482  NS_ENSURE_SUCCESS(rv, rv);
1483 
1484  nsCOMPtr<sbIMediacoreSequencer> sequencer;
1485  rv = manager->GetSequencer(getter_AddRefs(sequencer));
1486  NS_ENSURE_SUCCESS(rv, rv);
1487 
1488  nsCOMPtr<nsIURI> uri;
1489  rv = mIOService->NewURI(NS_ConvertUTF16toUTF8(aURL),
1490  nsnull,
1491  nsnull,
1492  getter_AddRefs(uri));
1493  NS_ENSURE_SUCCESS(rv, rv);
1494 
1495  rv = sequencer->PlayURL(uri);
1496  NS_ENSURE_SUCCESS( rv, rv );
1497 
1498  rv = TakePlaybackControl( nsnull );
1499  NS_ENSURE_SUCCESS( rv, rv );
1500 
1501  return NS_OK;
1502 }
1503 
1504 NS_IMETHODIMP
1505 sbRemotePlayer::Stop()
1506 {
1507  LOG(("sbRemotePlayer::Stop()"));
1508  NS_ENSURE_STATE(mMM);
1509 
1510  nsresult rv = ConfirmPlaybackControl();
1511  NS_ENSURE_SUCCESS( rv, rv );
1512 
1513  nsCOMPtr<sbIMediacoreManager> manager =
1514  do_QueryReferent(mMM, &rv);
1515  NS_ENSURE_SUCCESS(rv, rv);
1516 
1517  nsCOMPtr<sbIMediacorePlaybackControl> playbackControl;
1518  rv = manager->GetPlaybackControl(getter_AddRefs(playbackControl));
1519  NS_ENSURE_SUCCESS(rv, rv);
1520 
1521  if ( playbackControl ) {
1522  rv = playbackControl->Stop();
1523  NS_ENSURE_SUCCESS(rv, rv);
1524  }
1525 
1526  rv = TakePlaybackControl( nsnull );
1527  NS_ENSURE_SUCCESS( rv, rv );
1528 
1529  return NS_OK;
1530 }
1531 
1532 NS_IMETHODIMP
1533 sbRemotePlayer::Pause()
1534 {
1535  LOG(("sbRemotePlayer::Pause()"));
1536  NS_ENSURE_STATE(mMM);
1537 
1538  nsresult rv = ConfirmPlaybackControl();
1539  NS_ENSURE_SUCCESS( rv, rv );
1540 
1541  nsCOMPtr<sbIMediacoreManager> manager =
1542  do_QueryReferent(mMM, &rv);
1543  NS_ENSURE_SUCCESS(rv, rv);
1544 
1545  nsCOMPtr<sbIMediacorePlaybackControl> playbackControl;
1546  rv = manager->GetPlaybackControl(getter_AddRefs(playbackControl));
1547  NS_ENSURE_SUCCESS(rv, rv);
1548 
1549  if ( playbackControl ) {
1550  rv = playbackControl->Pause();
1551  NS_ENSURE_SUCCESS(rv, rv);
1552  }
1553 
1554  rv = TakePlaybackControl( nsnull );
1555  NS_ENSURE_SUCCESS( rv, rv );
1556 
1557  return NS_OK;
1558 }
1559 
1560 NS_IMETHODIMP
1561 sbRemotePlayer::Next()
1562 {
1563  LOG(("sbRemotePlayer::Next()"));
1564  NS_ENSURE_STATE(mMM);
1565 
1566  nsresult rv = ConfirmPlaybackControl();
1567  NS_ENSURE_SUCCESS( rv, rv );
1568 
1569  nsCOMPtr<sbIMediacoreManager> manager =
1570  do_QueryReferent(mMM, &rv);
1571  NS_ENSURE_SUCCESS(rv, rv);
1572 
1573  nsCOMPtr<sbIMediacoreSequencer> sequencer;
1574  rv = manager->GetSequencer(getter_AddRefs(sequencer));
1575  NS_ENSURE_SUCCESS(rv, rv);
1576 
1577  rv = sequencer->Next(PR_FALSE);
1578  NS_ENSURE_SUCCESS( rv, rv );
1579 
1580  rv = TakePlaybackControl( nsnull );
1581  NS_ENSURE_SUCCESS( rv, rv );
1582 
1583  return NS_OK;
1584 }
1585 
1586 NS_IMETHODIMP
1587 sbRemotePlayer::Previous()
1588 {
1589  LOG(("sbRemotePlayer::Previous()"));
1590  NS_ENSURE_STATE(mMM);
1591 
1592  nsresult rv = ConfirmPlaybackControl();
1593  NS_ENSURE_SUCCESS( rv, rv );
1594 
1595  nsCOMPtr<sbIMediacoreManager> manager =
1596  do_QueryReferent(mMM, &rv);
1597  NS_ENSURE_SUCCESS(rv, rv);
1598 
1599  nsCOMPtr<sbIMediacoreSequencer> sequencer;
1600  rv = manager->GetSequencer(getter_AddRefs(sequencer));
1601  NS_ENSURE_SUCCESS(rv, rv);
1602 
1603  rv = sequencer->Previous(PR_FALSE);
1604  NS_ENSURE_SUCCESS( rv, rv );
1605 
1606  rv = TakePlaybackControl( nsnull );
1607  NS_ENSURE_SUCCESS( rv, rv );
1608 
1609  return NS_OK;
1610 }
1611 
1612 nsresult
1613 sbRemotePlayer::FireEventToContent( const nsAString &aClass,
1614  const nsAString &aType )
1615 {
1616  LOG(( "sbRemotePlayer::FireEventToContent(%s, %s)",
1617  NS_LossyConvertUTF16toASCII(aClass).get(),
1618  NS_LossyConvertUTF16toASCII(aType).get() ));
1619 
1620  return sbRemotePlayer::DispatchEvent(mContentDoc, aClass, aType, PR_FALSE);
1621 }
1622 
1623 NS_IMETHODIMP
1624 sbRemotePlayer::FireMediaItemStatusEventToContent( const nsAString &aClass,
1625  const nsAString &aType,
1626  sbIMediaItem* aMediaItem,
1627  PRInt32 aStatus )
1628 {
1629  LOG(( "sbRemotePlayer::FireMediaItemStatusEventToContent(%s, %s)",
1630  NS_LossyConvertUTF16toASCII(aClass).get(),
1631  NS_LossyConvertUTF16toASCII(aType).get() ));
1632  NS_ENSURE_ARG_POINTER(aMediaItem);
1633 
1634  nsresult rv;
1635 
1636  nsCOMPtr<sbISecurityMixin> mixin = do_QueryInterface(mSecurityMixin, &rv);
1637  NS_ENSURE_SUCCESS(rv, rv);
1638 
1639  nsCOMPtr<nsIDOMDocument> doc;
1640  mixin->GetNotificationDocument(getter_AddRefs(doc));
1641  NS_ENSURE_STATE(doc);
1642 
1643  //change interfaces to create the event
1644  nsCOMPtr<nsIDOMDocumentEvent>
1645  docEvent( do_QueryInterface( doc, &rv ) );
1646  NS_ENSURE_SUCCESS( rv , rv );
1647 
1648  //create the event
1649  nsCOMPtr<nsIDOMEvent> event;
1650  docEvent->CreateEvent( aClass, getter_AddRefs(event) );
1651  NS_ENSURE_STATE(event);
1652  rv = event->InitEvent( aType, PR_TRUE, PR_TRUE );
1653  NS_ENSURE_SUCCESS( rv , rv );
1654 
1655  //use the document for a target.
1656  nsCOMPtr<nsIDOMEventTarget>
1657  eventTarget( do_QueryInterface( doc, &rv ) );
1658  NS_ENSURE_SUCCESS( rv, rv );
1659 
1660  //make the event untrusted
1661  nsCOMPtr<nsIPrivateDOMEvent> privEvt( do_QueryInterface( event, &rv ) );
1662  NS_ENSURE_SUCCESS( rv, rv );
1663  privEvt->SetTrusted(PR_FALSE);
1664 
1665  // make our custom media item wrapper event
1666  nsRefPtr<sbRemoteMediaItemStatusEvent>
1667  remoteEvent(new sbRemoteMediaItemStatusEvent(this) );
1668  rv = remoteEvent->Init();
1669  NS_ENSURE_SUCCESS( rv, rv );
1670  rv = remoteEvent->InitEvent( event, aMediaItem, aStatus );
1671  NS_ENSURE_SUCCESS( rv, rv );
1672 
1673  // Fire an event to the chrome system.
1674  PRBool dummy;
1675  return eventTarget->DispatchEvent( remoteEvent, &dummy );
1676 }
1677 
1678 // ---------------------------------------------------------------------------
1679 //
1680 // sbIMediacoreEventListener
1681 //
1682 // ---------------------------------------------------------------------------
1683 
1684 NS_IMETHODIMP
1685 sbRemotePlayer::OnMediacoreEvent(sbIMediacoreEvent *aEvent)
1686 {
1687  NS_ENSURE_ARG_POINTER(aEvent);
1688 
1689  PRUint32 type = 0;
1690  nsresult rv = aEvent->GetType(&type);
1691  NS_ENSURE_SUCCESS(rv, rv);
1692 
1693  switch(type) {
1696  rv = OnStop();
1697  NS_ENSURE_SUCCESS(rv, rv);
1698  }
1699  break;
1700 
1702  rv = OnTrackChange(aEvent);
1703  NS_ENSURE_SUCCESS(rv, rv);
1704  }
1705  break;
1706 
1708  rv = OnTrackIndexChange(aEvent);
1709  NS_ENSURE_SUCCESS(rv, rv);
1710  }
1711  break;
1712 
1714  rv = OnBeforeViewChange(aEvent);
1715  NS_ENSURE_SUCCESS(rv, rv);
1716  }
1717  break;
1718 
1720  rv = OnViewChange(aEvent);
1721  NS_ENSURE_SUCCESS(rv, rv);
1722  }
1723  break;
1724  }
1725 
1726  return NS_OK;
1727 }
1728 
1729 // ---------------------------------------------------------------------------
1730 //
1731 // Event Handlers for sbIMediacoreEventListener
1732 //
1733 // ---------------------------------------------------------------------------
1734 nsresult
1736 {
1737  LOG(("sbRemotePlayer::OnStop()"));
1738  nsresult rv;
1739 
1740  rv = FireEventToContent( RAPI_EVENT_CLASS, RAPI_EVENT_TYPE_STOP );
1741  NS_ENSURE_SUCCESS( rv, rv );
1742 
1743  return NS_OK;
1744 }
1745 
1746 nsresult
1748 {
1749  LOG(("sbRemotePlayer::OnBeforeTrackChange()"));
1750  NS_ENSURE_ARG_POINTER(aEvent);
1751 
1752  nsCOMPtr<nsIVariant> data;
1753  nsresult rv = aEvent->GetData(getter_AddRefs(data));
1754  NS_ENSURE_SUCCESS(rv, rv);
1755 
1756  nsCOMPtr<nsISupports> supports;
1757  rv = data->GetAsISupports(getter_AddRefs(supports));
1758  NS_ENSURE_SUCCESS(rv, rv);
1759 
1760  nsCOMPtr<sbIMediaItem> item = do_QueryInterface(supports, &rv);
1761  NS_ENSURE_SUCCESS(rv, rv);
1762 
1763  rv = FireMediaItemStatusEventToContent( RAPI_EVENT_CLASS,
1765  item,
1766  NS_OK );
1767  NS_ENSURE_SUCCESS(rv, rv);
1768 
1769  return NS_OK;
1770 }
1771 
1772 nsresult
1774 {
1775  LOG(("sbRemotePlayer::OnTrackChange()"));
1776  NS_ENSURE_ARG_POINTER(aEvent);
1777 
1778  nsCOMPtr<nsIVariant> data;
1779  nsresult rv = aEvent->GetData(getter_AddRefs(data));
1780  NS_ENSURE_SUCCESS(rv, rv);
1781 
1782  nsCOMPtr<nsISupports> supports;
1783  rv = data->GetAsISupports(getter_AddRefs(supports));
1784  NS_ENSURE_SUCCESS(rv, rv);
1785 
1786  nsCOMPtr<sbIMediaItem> item = do_QueryInterface(supports, &rv);
1787  NS_ENSURE_SUCCESS(rv, rv);
1788 
1789  rv = FireMediaItemStatusEventToContent( RAPI_EVENT_CLASS,
1791  item,
1792  NS_OK );
1793  NS_ENSURE_SUCCESS(rv, rv);
1794 
1795  return NS_OK;
1796 }
1797 
1798 nsresult
1800  LOG(("sbRemotePlayer::OnTrackIndexChange()"));
1801  NS_ENSURE_ARG_POINTER(aEvent);
1802 
1803  nsCOMPtr<nsIVariant> data;
1804  nsresult rv = aEvent->GetData(getter_AddRefs(data));
1805  NS_ENSURE_SUCCESS(rv, rv);
1806 
1807  nsCOMPtr<nsISupports> supports;
1808  rv = data->GetAsISupports(getter_AddRefs(supports));
1809  NS_ENSURE_SUCCESS(rv, rv);
1810 
1811  nsCOMPtr<sbIMediaItem> item = do_QueryInterface(supports, &rv);
1812  NS_ENSURE_SUCCESS(rv, rv);
1813 
1814  rv = FireMediaItemStatusEventToContent( RAPI_EVENT_CLASS,
1816  item,
1817  NS_OK );
1818  NS_ENSURE_SUCCESS(rv, rv);
1819 
1820  return NS_OK;
1821 }
1822 
1823 nsresult
1825  LOG(("sbRemotePlayer::OnViewChange()"));
1826  NS_ENSURE_ARG_POINTER(aEvent);
1827 
1828  nsresult rv = FireEventToContent( RAPI_EVENT_CLASS,
1830  NS_ENSURE_SUCCESS(rv, rv);
1831 
1832  return NS_OK;
1833 }
1834 
1835 nsresult
1837  LOG(("sbRemotePlayer::OnViewChange()"));
1838  NS_ENSURE_ARG_POINTER(aEvent);
1839 
1840  nsresult rv = FireEventToContent( RAPI_EVENT_CLASS,
1842  NS_ENSURE_SUCCESS(rv, rv);
1843 
1844  return NS_OK;
1845 }
1846 
1847 // ---------------------------------------------------------------------------
1848 //
1849 // nsIDOMEventListener
1850 //
1851 // ---------------------------------------------------------------------------
1852 
1853 NS_IMETHODIMP
1854 sbRemotePlayer::HandleEvent( nsIDOMEvent *aEvent )
1855 {
1856  LOG(( "sbRemotePlayer::HandleEvent() this: %08x", this ));
1857  NS_ENSURE_ARG_POINTER(aEvent);
1858  nsAutoString type;
1859  aEvent->GetType(type);
1860  if ( type.EqualsLiteral("unload") ) {
1861  LOG(("sbRemotePlayer::HandleEvent() - unload event"));
1862  nsresult rv;
1863 
1864  nsRefPtr<sbRemotePlayer> kungFuDeathGrip(this);
1865 
1866  // check if this is the right document being unloaded (yay tabs)
1867  nsCOMPtr<nsIDOMNSEvent> nsEvent( do_QueryInterface( aEvent, &rv ) );
1868  if ( NS_FAILED(rv) )
1869  return NS_OK;
1870 
1871  nsCOMPtr<nsIDOMEventTarget> originalEventTarget;
1872  rv = nsEvent->GetOriginalTarget( getter_AddRefs(originalEventTarget) );
1873  NS_ENSURE_SUCCESS( rv, rv );
1874 
1875  if ( !SameCOMIdentity( originalEventTarget, mContentDoc ) ) {
1876  // not the content doc we're interested in
1877  return NS_OK;
1878  }
1879 
1880  nsCOMPtr<nsIDOMEventTarget> eventTarget( do_QueryInterface(mChromeDoc) );
1881  NS_ENSURE_STATE(eventTarget);
1882  rv = eventTarget->RemoveEventListener( NS_LITERAL_STRING("unload"),
1883  this ,
1884  PR_TRUE );
1885  NS_ASSERTION( NS_SUCCEEDED(rv),
1886  "Failed to remove unload listener from document" );
1887 
1888  rv = eventTarget->RemoveEventListener( NS_LITERAL_STRING("PlaylistCellClick"),
1889  this ,
1890  PR_TRUE );
1891  NS_ASSERTION( NS_SUCCEEDED(rv),
1892  "Failed to remove PlaylistCellClick listener from document" );
1893 
1894  rv = eventTarget->RemoveEventListener( SB_EVENT_RAPI_PERMISSION_DENIED,
1895  this ,
1896  PR_TRUE );
1897  NS_ASSERTION( NS_SUCCEEDED(rv),
1898  "Failed to remove RemoteAPIPermissionDenied listener from document" );
1899 
1900  rv = eventTarget->RemoveEventListener( SB_EVENT_RAPI_PERMISSION_CHANGED,
1901  this ,
1902  PR_TRUE );
1903  NS_ASSERTION( NS_SUCCEEDED(rv),
1904  "Failed to remove RemoteAPIPermissionChanged listener from document" );
1905 
1906  nsCOMPtr<sbIMediacoreEventTarget> target =
1907  do_QueryReferent(mMM, &rv);
1908  NS_ASSERTION( NS_SUCCEEDED(rv),
1909  "Failed to get event target to remove playback listener" );
1910 
1911  rv = target->RemoveListener(this);
1912  NS_ASSERTION( NS_SUCCEEDED(rv), "Failed to remove playback listener" );
1913 
1914  // the page is going away, clean up things that will cause us to
1915  // not get released.
1917  mCommandsObject = nsnull;
1918  mContentDoc = nsnull;
1919  mChromeDoc = nsnull;
1920 
1921  // Explicitly clear the cached libraries so we can break the reference
1922  // cycle between the library classes and this class
1923  mCachedLibraries.Clear();
1924  } else if ( type.EqualsLiteral("PlaylistCellClick") ) {
1925  LOG(("sbRemotePlayer::HandleEvent() - PlaylistCellClick event"));
1926  nsresult rv;
1927 
1928  // get the event information from the playlist
1929  nsCOMPtr<nsIDOMNSEvent> srcEvent( do_QueryInterface(aEvent, &rv) );
1930  NS_ENSURE_SUCCESS(rv, rv);
1931 
1932  nsCOMPtr<nsIDOMEventTarget> srcEventTarget;
1933  rv = srcEvent->GetOriginalTarget( getter_AddRefs(srcEventTarget) );
1934  NS_ENSURE_SUCCESS(rv, rv);
1935 
1936  nsCOMPtr<sbIPlaylistWidget> playlist( do_QueryInterface(srcEventTarget, &rv) );
1937  // this recurses because we see the event targeted at the content document
1938  // bubble up, so just gracefully ignore it if the event wasn't from a playlist
1939  if (NS_FAILED(rv))
1940  return NS_OK;
1941 
1942  if (!mRemWebPlaylist) {
1943  rv = InitRemoteWebPlaylist();
1944  NS_ENSURE_SUCCESS( rv, rv );
1945  }
1946 
1947  // Get the actual XBL widget from the RemoteWebPlaylist member
1948  nsCOMPtr<sbIPlaylistWidget> playlistWidget;
1949  rv = mRemWebPlaylist->GetPlaylistWidget( getter_AddRefs(playlistWidget) );
1950  NS_ENSURE_SUCCESS(rv, rv);
1951 
1952  // check if this is the right document being clicked on (yay tabs)
1953  if ( !SameCOMIdentity( playlist, playlistWidget ) ) {
1954  // not the playlist for this RemotePlayer
1955  return NS_OK;
1956  }
1957 
1958  nsCOMPtr<sbIPlaylistClickEvent> playlistClickEvent;
1959  rv = playlist->GetLastClickEvent( getter_AddRefs(playlistClickEvent) );
1960  NS_ENSURE_SUCCESS(rv, rv);
1961 
1962  // make a mouse event
1963  nsCOMPtr<nsIDOMDocumentEvent> docEvent( do_QueryInterface(mContentDoc, &rv) );
1964  NS_ENSURE_SUCCESS(rv, rv);
1965 
1966  nsCOMPtr<nsIDOMEvent> newEvent;
1967  rv = docEvent->CreateEvent( NS_LITERAL_STRING("mouseevent"), getter_AddRefs(newEvent) );
1968  NS_ENSURE_SUCCESS(rv, rv);
1969 
1970  PRBool ctrlKey = PR_FALSE, altKey = PR_FALSE,
1971  shiftKey = PR_FALSE, metaKey = PR_FALSE;
1972  PRUint16 button = 0;
1973  nsCOMPtr<nsIDOMMouseEvent> srcMouseEvent( do_QueryInterface(playlistClickEvent, &rv) );
1974  if (NS_SUCCEEDED(rv)) {
1975  srcMouseEvent->GetCtrlKey(&ctrlKey);
1976  srcMouseEvent->GetAltKey(&altKey);
1977  srcMouseEvent->GetShiftKey(&shiftKey);
1978  srcMouseEvent->GetMetaKey(&metaKey);
1979  srcMouseEvent->GetButton(&button);
1980  } else {
1981  LOG(("sbRemotePlayer::HandleEvent() - no mouse event for PlaylistCellClick"));
1982  }
1983 
1984  nsCOMPtr<nsIDOMMouseEvent> newMouseEvent( do_QueryInterface(newEvent, &rv) );
1985  NS_ENSURE_SUCCESS(rv, rv);
1986  rv = newMouseEvent->InitMouseEvent( NS_LITERAL_STRING("PlaylistCellClick"),
1987  PR_TRUE, /* can bubble */
1988  PR_TRUE, /* can cancel */
1989  nsnull,
1990  0, /* detail */
1991  0, 0, /* screen x & y */
1992  0, 0, /* client x & y */
1993  ctrlKey, /* ctrl key */
1994  altKey, /* alt key */
1995  shiftKey, /* shift key */
1996  metaKey, /* meta key */
1997  button, /* button */
1998  nsnull /* related target */
1999  );
2000  NS_ENSURE_SUCCESS(rv, rv);
2001 
2002  //make the event trusted
2003  nsCOMPtr<nsIPrivateDOMEvent> privEvt( do_QueryInterface( newEvent, &rv ) );
2004  NS_ENSURE_SUCCESS( rv, rv );
2005  privEvt->SetTrusted( PR_TRUE );
2006 
2007  // make our custom wrapper event
2008  nsRefPtr<sbRemotePlaylistClickEvent> remoteEvent( new sbRemotePlaylistClickEvent(this) );
2009  NS_ENSURE_TRUE(remoteEvent, NS_ERROR_OUT_OF_MEMORY);
2010 
2011  rv = remoteEvent->Init();
2012  NS_ENSURE_SUCCESS(rv, rv);
2013 
2014  rv = remoteEvent->InitEvent( playlistClickEvent, newMouseEvent );
2015  NS_ENSURE_SUCCESS(rv, rv);
2016 
2017  // dispatch the event the the content document
2018  PRBool dummy;
2019  nsCOMPtr<nsIDOMEventTarget> destEventTarget = do_QueryInterface( mContentDoc, &rv );
2020  NS_ENSURE_SUCCESS(rv, rv);
2021  rv = destEventTarget->DispatchEvent( remoteEvent, &dummy );
2022  NS_ENSURE_SUCCESS(rv, rv);
2023  } else {
2024  // The 2 cases we want to pass the event on.
2025  // 1) The target was the chrome document, happens when the event comes
2026  // from the preferences panel
2027  // 2) The target was a XUL Element, happens when the event comes from
2028  // the notification box.
2029  // The prefPanel event goes to all tabs since it is general information
2030  // that could impact any page. The notification event only goes to the
2031  // page that caused the notification.
2032 
2033  // Get the original target
2034  nsresult rv;
2035  nsCOMPtr<nsIDOMNSEvent> nsEvent( do_QueryInterface( aEvent, &rv ) );
2036  if ( NS_FAILED(rv) )
2037  return NS_OK;
2038 
2039  nsCOMPtr<nsIDOMEventTarget> originalEventTarget;
2040  rv = nsEvent->GetOriginalTarget( getter_AddRefs(originalEventTarget) );
2041  NS_ENSURE_SUCCESS( rv, rv );
2042 
2043  PRBool allow = PR_FALSE;
2044  if ( SameCOMIdentity( originalEventTarget, mChromeDoc ) ) {
2045  LOG(( " - target IS this chromeDoc - ALLOWING " ));
2046  allow = PR_TRUE;
2047  }
2048 
2049  nsCOMPtr<nsIDOMXULElement> domXULElement (
2050  do_QueryInterface(originalEventTarget) );
2051  if (domXULElement) {
2052  // this is the notifcation box sending us an event. make sure it is ours
2053 
2054  // Get the notifcation box for the notification that is the target
2055  nsCOMPtr<nsIDOMNode> targetNotification (
2056  do_QueryInterface(originalEventTarget) );
2057  NS_ENSURE_TRUE( targetNotification, NS_ERROR_OUT_OF_MEMORY );
2058 
2059  nsCOMPtr<nsIDOMNode> targetNotificationBox;
2060  rv = targetNotification->GetParentNode(
2061  getter_AddRefs(targetNotificationBox) );
2062  NS_ENSURE_SUCCESS( rv, rv );
2063 
2064  // Get the notification associated with our tab/browser
2065  nsCOMPtr<nsIDOMElement> selfBrowser;
2066  rv = GetBrowser( getter_AddRefs(selfBrowser) );
2067  NS_ENSURE_SUCCESS( rv, rv );
2068 
2069  nsCOMPtr<nsIDOMNode> selfBrowserNode ( do_QueryInterface( selfBrowser ) );
2070  NS_ENSURE_TRUE( selfBrowserNode, NS_ERROR_OUT_OF_MEMORY );
2071 
2072  nsCOMPtr<nsIDOMNode> selfNotificationBox;
2073  rv = selfBrowserNode->GetParentNode(
2074  getter_AddRefs(selfNotificationBox) );
2075  NS_ENSURE_SUCCESS( rv, rv );
2076 
2077  if ( SameCOMIdentity( selfNotificationBox, targetNotificationBox ) ) {
2078  LOG(( " - target IS this notificationbox - ALLOWING " ));
2079  allow = PR_TRUE;
2080  }
2081  }
2082 
2083  if ( allow ) {
2084 
2085  nsString value;
2086  if ( type.Equals( SB_EVENT_RAPI_PERMISSION_DENIED ) ) {
2087  value.AssignLiteral("dismissed");
2088  }
2089  else {
2090  value.AssignLiteral("preferences");
2091  }
2092 
2093  nsCOMPtr<sbIRemoteSecurityEvent> securityEvent =
2094  do_QueryInterface(aEvent, &rv);
2095 
2096  if ( NS_SUCCEEDED( rv ) ) {
2097 
2098  nsAutoString categoryID;
2099  rv = securityEvent->GetCategoryID(categoryID);
2100  NS_ENSURE_SUCCESS( rv, rv );
2101 
2102  PRBool hasAccess = PR_FALSE;
2103  rv = securityEvent->GetHasAccess(&hasAccess);
2104  NS_ENSURE_SUCCESS( rv, rv );
2105 
2106  nsCOMPtr<sbISecurityMixin> mixin = do_QueryInterface(mSecurityMixin, &rv);
2107  NS_ENSURE_SUCCESS( rv, rv );
2108 
2109  nsCOMPtr<nsIDOMDocument> doc;
2110  rv = mixin->GetNotificationDocument(getter_AddRefs(doc));
2111  NS_ENSURE_SUCCESS( rv, rv );
2112 
2113  rv = DispatchSecurityEvent(doc,
2114  this,
2116  type,
2117  categoryID,
2118  hasAccess,
2119  PR_FALSE );
2120 #ifdef METRICS_ENABLED
2121  rv = mMetrics->MetricsInc(NS_LITERAL_STRING("rapi.notification"),
2122  value,
2123  EmptyString());
2124  NS_ENSURE_SUCCESS( rv, rv );
2125 #endif
2126  }
2127  else {
2128  LOG(( "sbRemotePlayer::HandleEvent() - %s",
2129  NS_LossyConvertUTF16toASCII(type).get() ));
2130 
2131  if ( type.Equals(SB_EVENT_RAPI_PERMISSION_CHANGED) ) {
2132  return FireEventToContent( RAPI_EVENT_CLASS, type );
2133  }
2134  else if ( type.Equals(SB_EVENT_RAPI_PERMISSION_DENIED) ) {
2135 #ifdef METRICS_ENABLED
2136  rv = mMetrics->MetricsInc(NS_LITERAL_STRING("rapi.notification"),
2137  value,
2138  EmptyString());
2139  NS_ENSURE_SUCCESS( rv, rv );
2140 #endif
2141  return FireEventToContent( RAPI_EVENT_CLASS, type );
2142  } else {
2143  LOG(("sbRemotePlayer::HandleEvent() - Some other event"));
2144  }
2145  }
2146  }
2147  }
2148  return NS_OK;
2149 }
2150 
2151 nsresult
2153 {
2154  LOG(("sbRemotePlayer::UnregisterCommands()"));
2155  if (!mCommandsObject)
2156  return NS_OK;
2157 
2158  // Get the PlaylistCommandsManager object to unregister the commands
2159  nsresult rv;
2160  nsCOMPtr<sbIPlaylistCommandsManager> mgr(
2161  do_GetService( "@songbirdnest.com/Songbird/PlaylistCommandsManager;1", &rv ) );
2162  NS_ENSURE_SUCCESS( rv, rv );
2163 
2164  nsCOMPtr<sbIPlaylistCommands> commands = (sbIPlaylistCommands*) mCommandsObject;
2165  NS_ENSURE_TRUE( commands, NS_ERROR_UNEXPECTED );
2166  // Registration of commands is changing soon, for now type='library' is it
2167  rv = mgr->UnregisterPlaylistCommandsMediaItem( NS_LITERAL_STRING("remote-test-guid"),
2168  NS_LITERAL_STRING("library"),
2169  commands );
2170  NS_ASSERTION( NS_SUCCEEDED(rv),
2171  "Failed to unregister commands from playlistcommandsmanager" );
2172 
2173  rv = mgr->UnregisterPlaylistCommandsMediaItem( NS_LITERAL_STRING("remote-test-guid"),
2174  NS_LITERAL_STRING("simple"),
2175  commands );
2176  NS_ASSERTION( NS_SUCCEEDED(rv),
2177  "Failed to unregister commands from playlistcommandsmanager" );
2178 
2179  return NS_OK;
2180 }
2181 
2182 nsresult
2184  // NOTE: Making this function always succeed.
2185  // See bugs 13368 and 13403
2186  return NS_OK;
2187 
2188  // the web site is trying to control the user's playback.
2189  // try to guess if this is likely to annoy the user.
2190 
2191  LOG(("sbRemotePlayer::ConfirmPlaybackControl()"));
2192 
2193  PRBool isPlaying;
2194  nsresult rv;
2195 
2196  // we are safe to run from untrusted script. Since we may end up across
2197  // XPConnect and land in JS again, we need to push a principal so that when
2198  // XPConnect looks it sees that it's a chrome caller.
2199 
2200  // before we do that, however, we need to get any information we need from
2201  // the content document (since that will be unavailable when we push)
2202  nsCOMPtr<sbISecurityMixin> securityMixin =
2203  do_QueryInterface( mSecurityMixin, &rv );
2204  NS_ENSURE_SUCCESS( rv, rv );
2205  nsCOMPtr<nsIURI> codebaseURI;
2206  rv = securityMixin->GetCodebase( getter_AddRefs(codebaseURI) );
2207  NS_ENSURE_SUCCESS( rv, rv );
2208 
2209  // scope the principal push
2210  {
2211  // we can now push the new principal
2212  sbAutoPrincipalPusher principal;
2213  if (!principal) {
2214  return NS_ERROR_FAILURE;
2215  }
2216 
2217  rv = GetPlaying( &isPlaying );
2218  NS_ENSURE_SUCCESS( rv, rv );
2219 
2220  if (!isPlaying) {
2221  // The player is not playing, allow it
2222  LOG(("sbRemotePlayer::ConfirmPlaybackControl() -- not playing, allow"));
2223  return NS_OK;
2224  }
2225 
2226  // check to see if this page has control
2227  nsCOMPtr<sbIRemoteAPIService> remoteAPIService =
2228  do_GetService( "@songbirdnest.com/remoteapi/remoteapiservice;1", &rv );
2229  NS_ENSURE_SUCCESS( rv, rv );
2230  PRBool hasPlaybackControl;
2231  rv = remoteAPIService->HasPlaybackControl( codebaseURI, &hasPlaybackControl );
2232  NS_ENSURE_SUCCESS( rv, rv );
2233  if ( hasPlaybackControl ) {
2234  LOG(("sbRemotePlayer::ConfirmPlaybackControl() -- URI has control, allow"));
2235  return NS_OK;
2236  }
2237  } // pop the principal
2238 
2239  PRBool allowed =
2240  GetUserApprovalForHost( codebaseURI,
2241  NS_LITERAL_STRING("rapi.playback_control.blocked.title"),
2242  NS_LITERAL_STRING("rapi.playback_control.blocked.message") );
2243 
2244  return allowed ? NS_OK : NS_ERROR_ABORT ;
2245 }
2246 
2247 PRBool
2249  const nsAString &aTitleKey,
2250  const nsAString &aMessageKey,
2251  const char* aScopedName )
2252 {
2253  LOG(("sbRemotePlayer::GetUserApprovalForHost(URI)"));
2254  NS_ENSURE_ARG_POINTER(aURI);
2255  NS_ASSERTION(!aTitleKey.IsEmpty(), "Title Key empty!!!!");
2256  NS_ASSERTION(!aMessageKey.IsEmpty(), "Message key empty!!!!");
2257 
2258  // See if we should prompt for approval
2259  nsresult rv;
2260  nsCOMPtr<nsIPrefBranch> prefService =
2261  do_GetService("@mozilla.org/preferences-service;1", &rv);
2262  if (NS_SUCCEEDED(rv)) {
2263  PRBool shouldPrompt;
2264  rv = prefService->GetBoolPref( "songbird.rapi.promptForApproval",
2265  &shouldPrompt );
2266  if (NS_SUCCEEDED(rv) && !shouldPrompt) {
2267  LOG(("sbRemotePlayer::GetUserApprovalForHost(URI) - shouldn't prompt or failed"));
2268  return PR_FALSE;
2269  }
2270  }
2271  LOG(("sbRemotePlayer::GetUserApprovalForHost(URI) - here"));
2272 
2273  nsCString hostUTF8;
2274  rv = aURI->GetHost(hostUTF8);
2275  NS_ENSURE_SUCCESS( rv, rv );
2276 
2277  if ( hostUTF8.IsEmpty() ) {
2278  // no host (e.g. file:///); fall back to full URL
2279  rv = aURI->GetSpec(hostUTF8);
2280  NS_ENSURE_SUCCESS( rv, rv );
2281  }
2282  NS_ConvertUTF8toUTF16 host(hostUTF8);
2283 
2284  nsCOMPtr<nsIStringBundleService> sbs =
2285  do_GetService( NS_STRINGBUNDLE_CONTRACTID, &rv );
2286  NS_ENSURE_SUCCESS( rv, PR_FALSE );
2287 
2288  // get the branding...
2289  nsCOMPtr<nsIStringBundle> bundle;
2290  rv = sbs->CreateBundle( "chrome://branding/locale/brand.properties",
2291  getter_AddRefs(bundle) );
2292  NS_ENSURE_SUCCESS( rv, PR_FALSE );
2293 
2294  nsString branding;
2295  rv = bundle->GetStringFromName( NS_LITERAL_STRING("brandShortName").get(),
2296  getter_Copies(branding) );
2297  NS_ENSURE_SUCCESS( rv, PR_FALSE );
2298 
2299  // and the prompt title and message
2300  rv = sbs->CreateBundle( "chrome://songbird/locale/songbird.properties",
2301  getter_AddRefs(bundle) );
2302  NS_ENSURE_SUCCESS( rv, PR_FALSE );
2303 
2304  const PRUnichar *formatParams[1] = {0};
2305  formatParams[0] = branding.BeginReading();
2306 
2307  nsString message;
2308  rv = bundle->FormatStringFromName( aMessageKey.BeginReading(),
2309  formatParams,
2310  NS_ARRAY_LENGTH(formatParams),
2311  getter_Copies(message) );
2312  NS_ENSURE_SUCCESS( rv, PR_FALSE );
2313 
2314  nsString title;
2315  rv = bundle->GetStringFromName( aTitleKey.BeginReading(),
2316  getter_Copies(title) );
2317  NS_ENSURE_SUCCESS( rv, PR_FALSE );
2318 
2319  nsString allowDeny;
2320  rv = bundle->GetStringFromName( NS_LITERAL_STRING("rapi.permissions.allow.deny").get(),
2321  getter_Copies(allowDeny) );
2322  NS_ENSURE_SUCCESS( rv, PR_FALSE );
2323 
2324  nsString allowAlways;
2325  rv = bundle->GetStringFromName( NS_LITERAL_STRING("rapi.permissions.allow.always").get(),
2326  getter_Copies(allowAlways) );
2327  NS_ENSURE_SUCCESS( rv, PR_FALSE );
2328 
2329  nsString allowOnce;
2330  rv = bundle->GetStringFromName( NS_LITERAL_STRING("rapi.permissions.allow.once").get(),
2331  getter_Copies(allowOnce) );
2332  NS_ENSURE_SUCCESS( rv, PR_FALSE );
2333 
2334  LOG(("sbRemotePlayer::GetUserApprovalForHost(URI) - there"));
2335 
2336  // now we can actually go for the prompt
2337  nsCOMPtr<nsIPromptService> promptService =
2338  do_GetService( "@mozilla.org/embedcomp/prompt-service;1", &rv );
2339  NS_ENSURE_SUCCESS( rv, PR_FALSE );
2340 
2341  // this is launched by the child window, tell Gecko about it.
2342  nsCOMPtr<nsPIDOMWindow> jsWindow = GetWindowFromJS();
2343  nsCOMPtr<nsIDOMWindow> window = do_QueryInterface( jsWindow, &rv );
2344  NS_ENSURE_SUCCESS( rv, PR_FALSE );
2345 
2346  PRUint32 buttons;
2347  if (aScopedName) {
2348  // Used for all the security prompts
2349  buttons = nsIPromptService::BUTTON_POS_0 * nsIPromptService::BUTTON_TITLE_IS_STRING + /* allow for visit */
2350  nsIPromptService::BUTTON_POS_1 * nsIPromptService::BUTTON_TITLE_IS_STRING + /* cancel */
2351  nsIPromptService::BUTTON_POS_2 * nsIPromptService::BUTTON_TITLE_IS_STRING + /* allow always */
2352  nsIPromptService::BUTTON_POS_1_DEFAULT;
2353  }
2354  else {
2355  // Used for playback control only
2356  buttons = nsIPromptService::BUTTON_POS_0 * nsIPromptService::BUTTON_TITLE_YES +
2357  nsIPromptService::BUTTON_POS_1 * nsIPromptService::BUTTON_TITLE_NO;
2358  }
2359  LOG(("sbRemotePlayer::GetUserApprovalForHost(URI) - where"));
2360 
2361  PRInt32 allowed;
2362  // the buttons have to be in this weird order for the cancel button to be
2363  // properly enabled while we delay allowing the user to accept
2364  rv = promptService->ConfirmEx( window,
2365  title.BeginReading(),
2366  message.BeginReading(),
2367  buttons,
2368  allowOnce.BeginReading(),
2369  allowDeny.BeginReading(),
2370  allowAlways.BeginReading(),
2371  nsnull,
2372  nsnull,
2373  &allowed );
2374  NS_ENSURE_SUCCESS( rv, PR_FALSE );
2375 
2376  PRBool retval = PR_FALSE;
2377 #ifdef METRICS_ENABLED
2378  nsString metricsCategory;
2379  metricsCategory.AssignLiteral("rapi.prompt.");
2380  switch(allowed) {
2381  case 2:
2382  // set the permissions permanently
2383  metricsCategory.AppendLiteral("always");
2384  rv = sbSecurityMixin::SetPermission( aURI, nsDependentCString(aScopedName) );
2385  retval = PR_TRUE;
2386  break;
2387  case 0:
2388  // Allow once
2389  metricsCategory.AppendLiteral("once");
2390  retval = PR_TRUE;
2391  break;
2392  case 1:
2393  // Disallow
2394  metricsCategory.AppendLiteral("deny");
2395  break;
2396  }
2397 
2398  if (aScopedName) {
2399  nsCOMPtr<sbIMetrics> metrics =
2400  do_CreateInstance("@songbirdnest.com/Songbird/Metrics;1", &rv);
2401  NS_ENSURE_SUCCESS(rv, rv);
2402 
2403  nsCString name(aScopedName);
2404  rv = metrics->MetricsInc(metricsCategory,
2405  NS_ConvertASCIItoUTF16(name),
2406  EmptyString());
2407  NS_ENSURE_SUCCESS(rv, rv);
2408  }
2409 #endif // METRICS_ENABLED
2410 
2411  return retval;
2412 }
2413 
2414 nsresult
2415 sbRemotePlayer::GetBrowser( nsIDOMElement** aElement )
2416 {
2417  nsresult rv;
2418  // Find the sb-tabbrowser ByTagName()[0] (not ById()!)
2419  NS_ENSURE_STATE(mChromeDoc);
2420  nsCOMPtr<nsIDOMNodeList> tabBrowserElementList;
2421  mChromeDoc->GetElementsByTagName( SB_WEB_TABBROWSER,
2422  getter_AddRefs(tabBrowserElementList) );
2423  NS_ENSURE_STATE(tabBrowserElementList);
2424  nsCOMPtr<nsIDOMNode> tabBrowserElement;
2425  rv = tabBrowserElementList->Item( 0, getter_AddRefs(tabBrowserElement) );
2426  NS_ENSURE_STATE(tabBrowserElement);
2427  NS_ENSURE_SUCCESS( rv, rv );
2428 
2429  // Get our interface
2430  nsCOMPtr<sbITabBrowser> tabbrowser( do_QueryInterface( tabBrowserElement,
2431  &rv ) );
2432  NS_ENSURE_SUCCESS( rv, rv );
2433 
2434  rv = tabbrowser->GetBrowserForDocument( mContentDoc, aElement );
2435  NS_ENSURE_SUCCESS( rv, rv );
2436 
2437  return NS_OK;
2438 }
2439 
2440 nsresult
2442 {
2443  nsresult rv;
2444  nsCOMPtr<nsIURI> uri = aURI;
2445 
2446  // try to guess the URI if we are not given one
2447  if ( NS_UNLIKELY(!uri) ) {
2448  nsCOMPtr<sbISecurityMixin> securityMixin =
2449  do_QueryInterface( mSecurityMixin, &rv );
2450  NS_ENSURE_SUCCESS( rv, rv );
2451  rv = securityMixin->GetCodebase( getter_AddRefs(uri) );
2452  NS_ENSURE_SUCCESS( rv, rv );
2453  }
2454 
2455  nsCOMPtr<sbIRemoteAPIService> remoteAPIService =
2456  do_GetService( "@songbirdnest.com/remoteapi/remoteapiservice;1", &rv );
2457  NS_ENSURE_SUCCESS( rv, rv );
2458 
2459  rv = remoteAPIService->TakePlaybackControl( uri, nsnull );
2460  NS_ENSURE_SUCCESS( rv, rv );
2461  return NS_OK;
2462 }
2463 
2464 
2465 // ---------------------------------------------------------------------------
2466 //
2467 // helpers
2468 //
2469 // ---------------------------------------------------------------------------
2470 
2471 /* static */ already_AddRefed<nsPIDOMWindow>
2473 {
2474  LOG(("sbRemotePlayer::GetWindowFromJS()"));
2475  // Get the js context from the top of the stack. We may need to iterate
2476  // over these at some point in order to make sure we are sending events
2477  // to the correct window, but for now this works.
2478  nsCOMPtr<nsIJSContextStack> stack =
2479  do_GetService("@mozilla.org/js/xpc/ContextStack;1");
2480 
2481  if (!stack) {
2482  LOG(("sbRemotePlayer::GetWindowFromJS() -- NO STACK!!!"));
2483  return nsnull;
2484  }
2485 
2486  JSContext *cx;
2487  if (NS_FAILED(stack->Peek(&cx)) || !cx) {
2488  LOG(("sbRemotePlayer::GetWindowFromJS() -- NO CONTEXT!!!"));
2489  return nsnull;
2490  }
2491 
2492  // Get the script context from the js context
2493  nsCOMPtr<nsIScriptContext> scCx = GetScriptContextFromJSContext(cx);
2494  NS_ENSURE_TRUE(scCx, nsnull);
2495 
2496  // Get the DOMWindow from the script global via the script context
2497  nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface( scCx->GetGlobalObject() );
2498  NS_ENSURE_TRUE( win, nsnull );
2499  NS_ADDREF( win.get() );
2500  return win.get();
2501 }
2502 
2503 already_AddRefed<nsPIDOMWindow>
2505 {
2506  LOG(("sbRemotePlayer::GetWindow()"));
2507  NS_ASSERTION(mPrivWindow, "mPrivWindow is null");
2508 
2509  nsPIDOMWindow* window = mPrivWindow;
2510  NS_ADDREF(window);
2511  return window;
2512 }
2513 
2514 nsresult
2515 sbRemotePlayer::DispatchEvent( nsIDOMDocument *aDoc,
2516  const nsAString &aClass,
2517  const nsAString &aType,
2518  PRBool aIsTrusted )
2519 {
2520  LOG(( "sbRemotePlayer::DispatchEvent(%s, %s)",
2521  NS_LossyConvertUTF16toASCII(aClass).get(),
2522  NS_LossyConvertUTF16toASCII(aType).get() ));
2523 
2524  //change interfaces to create the event
2525  nsresult rv;
2526  nsCOMPtr<nsIDOMDocumentEvent> docEvent( do_QueryInterface( aDoc, &rv ) );
2527  NS_ENSURE_SUCCESS( rv , rv );
2528 
2529  //create the event
2530  nsCOMPtr<nsIDOMEvent> event;
2531  docEvent->CreateEvent( aClass, getter_AddRefs(event) );
2532  NS_ENSURE_STATE(event);
2533  rv = event->InitEvent( aType, PR_TRUE, PR_TRUE );
2534  NS_ENSURE_SUCCESS( rv , rv );
2535 
2536  //use the document for a target.
2537  nsCOMPtr<nsIDOMEventTarget> eventTarget( do_QueryInterface( aDoc, &rv ) );
2538  NS_ENSURE_SUCCESS( rv, rv );
2539 
2540  //make the event trusted
2541  nsCOMPtr<nsIPrivateDOMEvent> privEvt( do_QueryInterface( event, &rv ) );
2542  NS_ENSURE_SUCCESS( rv, rv );
2543  privEvt->SetTrusted(aIsTrusted);
2544 
2545  // Fire an event to the chrome system. This event will NOT get to content.
2546  PRBool dummy;
2547  return eventTarget->DispatchEvent( event, &dummy );
2548 }
2549 
2550 nsresult
2552  sbIRemotePlayer *aPlayer,
2553  const nsAString &aClass,
2554  const nsAString &aType,
2555  const nsAString &aCategoryID,
2556  PRBool aHasAccess,
2557  PRBool aIsTrusted )
2558 {
2559  LOG(( "sbRemotePlayer::DispatchSecurityEvent(%s, %s)",
2560  NS_LossyConvertUTF16toASCII(aClass).get(),
2561  NS_LossyConvertUTF16toASCII(aType).get() ));
2562 
2563  NS_ENSURE_ARG_POINTER(aDoc);
2564  NS_ENSURE_ARG_POINTER(aPlayer);
2565 
2566  nsresult rv;
2567 
2568  //change interfaces to create the event
2569  nsCOMPtr<nsIDOMDocumentEvent>
2570  docEvent( do_QueryInterface( aDoc, &rv ) );
2571  NS_ENSURE_SUCCESS( rv , rv );
2572 
2573  //create the event
2574  nsCOMPtr<nsIDOMEvent> event;
2575  docEvent->CreateEvent( aClass, getter_AddRefs(event) );
2576  NS_ENSURE_STATE(event);
2577  rv = event->InitEvent( aType, PR_TRUE, PR_TRUE );
2578  NS_ENSURE_SUCCESS( rv , rv );
2579 
2580  //use the document for a target.
2581  nsCOMPtr<nsIDOMEventTarget>
2582  eventTarget( do_QueryInterface( aDoc, &rv ) );
2583  NS_ENSURE_SUCCESS( rv, rv );
2584 
2585  //make the event untrusted
2586  nsCOMPtr<nsIPrivateDOMEvent> privEvt( do_QueryInterface( event, &rv ) );
2587  NS_ENSURE_SUCCESS( rv, rv );
2588  privEvt->SetTrusted(aIsTrusted);
2589 
2590  // make our custom media item wrapper event
2591  nsRefPtr<sbRemoteSecurityEvent> securityEvent( new sbRemoteSecurityEvent() );
2592  securityEvent->Init();
2593 
2594  nsAutoString category;
2595  sbRemotePlayer::GetJSScopeNameFromScope( NS_LossyConvertUTF16toASCII( aCategoryID ), category );
2596 
2597  nsCOMPtr<nsIURI> scopeURI;
2598  rv = aPlayer->GetSiteScope( getter_AddRefs( scopeURI ) );
2599  NS_ENSURE_SUCCESS( rv, rv );
2600 
2601  rv = securityEvent->InitEvent( event, scopeURI, category, aCategoryID, aHasAccess );
2602  NS_ENSURE_SUCCESS( rv, rv );
2603 
2604  // Fire an event to the chrome system.
2605  PRBool dummy;
2606  return eventTarget->DispatchEvent( securityEvent, &dummy );
2607 }
2608 
2609 PRBool
2611 {
2612  return mPrivileged;
2613 }
2614 
2615 /*static*/ nsresult
2616 sbRemotePlayer::GetJSScopeNameFromScope( const nsACString &aScopeName,
2617  nsAString &aJSScopeName )
2618 
2619 {
2620  for ( PRUint32 i=0; i < NS_ARRAY_LENGTH(sPublicCategoryConversions); i++ ) {
2621  if ( StringBeginsWith( nsDependentCString(sPublicCategoryConversions[i][1]), aScopeName ) ) {
2622  aJSScopeName.Assign( NS_ConvertASCIItoUTF16( sPublicCategoryConversions[i][0] ) );
2623  return NS_OK;
2624  }
2625  }
2626 
2627  return NS_ERROR_INVALID_ARG;
2628 }
2629 
2630 nsresult
2632 {
2633  nsresult rv;
2634  LOG(("sbRemotePlayer::InitRemoteWebPlaylist()"));
2635 
2636  // These get set in initialization, so if they aren't set, bad news
2637  if (!mChromeDoc || !mContentDoc)
2638  return NS_ERROR_FAILURE;
2639 
2640  // Find the sb-tabbrowser ByTagName()[0] (not ById()!)
2641  nsCOMPtr<nsIDOMNodeList> tabBrowserElementList;
2642  mChromeDoc->GetElementsByTagName( SB_WEB_TABBROWSER,
2643  getter_AddRefs(tabBrowserElementList) );
2644  NS_ENSURE_STATE(tabBrowserElementList);
2645  nsCOMPtr<nsIDOMNode> tabBrowserElement;
2646  rv = tabBrowserElementList->Item( 0, getter_AddRefs(tabBrowserElement) );
2647  NS_ENSURE_STATE(tabBrowserElement);
2648  NS_ENSURE_SUCCESS( rv, rv );
2649 
2650  // Get our interface
2651  nsCOMPtr<sbITabBrowser> tabbrowser( do_QueryInterface( tabBrowserElement,
2652  &rv ) );
2653  NS_ENSURE_SUCCESS( rv, rv );
2654 
2655  // Get the tab for our particular document
2656  nsCOMPtr<sbITabBrowserTab> browserTab;
2657  tabbrowser->GetTabForDocument( mContentDoc, getter_AddRefs(browserTab) );
2658  NS_ENSURE_STATE(browserTab);
2659 
2660  // Get the outer playlist from the tab, it's the web playlist
2661  nsCOMPtr<nsIDOMElement> playlist;
2662  browserTab->GetPlaylist( getter_AddRefs(playlist) );
2663  NS_ENSURE_STATE(playlist);
2664 
2665  nsCOMPtr<sbIPlaylistWidget> playlistWidget ( do_QueryInterface( playlist,
2666  &rv) );
2667  NS_ENSURE_SUCCESS( rv, rv );
2668 
2669  // Create the RemotePlaylistWidget
2670  nsRefPtr<sbRemoteWebPlaylist> pWebPlaylist =
2671  new sbRemoteWebPlaylist( this, playlistWidget, browserTab );
2672  NS_ENSURE_TRUE( pWebPlaylist, NS_ERROR_FAILURE );
2673 
2674  rv = pWebPlaylist->Init();
2675  NS_ENSURE_SUCCESS( rv, rv );
2676 
2677  mRemWebPlaylist = pWebPlaylist;
2678  NS_ENSURE_TRUE( mRemWebPlaylist, NS_ERROR_FAILURE );
2679 
2680  return NS_OK;
2681 }
2682 
2685 {
2686  return mNotificationMgr;
2687 }
2688 
2689 nsresult
2691 {
2692  if (!mSiteScopeURL.IsVoid()) {
2693  aURL.Assign(mSiteScopeURL);
2694  return NS_OK;
2695  }
2696 
2697  nsCOMPtr<nsIURI> scopeURI = GetSiteScopeURI();
2698  NS_ENSURE_TRUE( scopeURI, NS_ERROR_FAILURE );
2699 
2700  nsCString scopeSpec;
2701  nsresult rv = scopeURI->GetSpec(scopeSpec);
2702  NS_ENSURE_SUCCESS( rv, rv );
2703 
2704  mSiteScopeURL.Assign(NS_ConvertUTF8toUTF16(scopeSpec));
2705  aURL.Assign(mSiteScopeURL);
2706  return NS_OK;
2707 }
2708 
2709 already_AddRefed<nsIURI>
2711 {
2712  if (mSiteScopeURI) {
2713  nsIURI* retval = mSiteScopeURI;
2714  NS_ADDREF(retval);
2715  return retval;
2716  }
2717 
2718  nsresult rv;
2719 
2720  // check if the site scope has been set before; if not, set it implicitly
2721  if ( mScopeDomain.IsVoid() || mScopePath.IsVoid() ) {
2722  rv = SetSiteScope( mScopeDomain, mScopePath );
2723  NS_ENSURE_SUCCESS( rv, nsnull);
2724  }
2725 
2726  // get the codebase URI
2727  nsCOMPtr<sbISecurityMixin> mixin = do_QueryInterface( mSecurityMixin, &rv );
2728  NS_ENSURE_SUCCESS( rv, nsnull );
2729 
2730  nsCOMPtr<nsIURI> codebaseURI;
2731  rv = mixin->GetCodebase( getter_AddRefs(codebaseURI) );
2732  NS_ENSURE_SUCCESS( rv, nsnull );
2733 
2734  // construct a download scope URI starting with the codebase URI scheme
2735  nsCString scopeSpec;
2736  rv = codebaseURI->GetScheme(scopeSpec);
2737  NS_ENSURE_SUCCESS( rv, nsnull );
2738 
2739  scopeSpec.AppendLiteral(":");
2740 
2741  nsCOMPtr<nsIURI> scopeURI;
2742  rv = mIOService->NewURI( scopeSpec, nsnull, nsnull, getter_AddRefs(scopeURI) );
2743  NS_ENSURE_SUCCESS( rv, nsnull );
2744 
2745  rv = scopeURI->SetHost(mScopeDomain);
2746  NS_ENSURE_SUCCESS( rv, nsnull );
2747 
2748  rv = scopeURI->SetPath(mScopePath);
2749  NS_ENSURE_SUCCESS( rv, nsnull );
2750 
2751  scopeURI = NS_TryToMakeImmutable( scopeURI, &rv );
2752  NS_ENSURE_SUCCESS( rv, nsnull );
2753 
2754  mSiteScopeURI = scopeURI;
2755  return scopeURI.forget();
2756 }
2757 
2758 nsresult
2760  const nsAString& aSiteID )
2761 {
2762  LOG(( "sbRemotePlayer::SetDownloadScope()" ));
2763  NS_ASSERTION(aItem, "aItem is null");
2764  NS_ASSERTION( !aSiteID.IsEmpty(), "aSiteID is empty!" );
2765 
2766  nsresult rv;
2767 
2768  // get the unwrapped media item
2769  nsCOMPtr<sbIMediaItem> mediaItem;
2770  nsCOMPtr<sbIWrappedMediaItem> wrappedMediaItem = do_QueryInterface( aItem,
2771  &rv );
2772  if (NS_SUCCEEDED(rv)) {
2773  mediaItem = wrappedMediaItem->GetMediaItem();
2774  NS_ENSURE_TRUE( mediaItem, NS_ERROR_FAILURE );
2775  } else {
2776  mediaItem = aItem;
2777  }
2778 
2779  nsString siteScopeURL;
2780  rv = GetSiteScopeURL(siteScopeURL);
2781  NS_ENSURE_SUCCESS(rv, rv);
2782 
2783  rv = mediaItem->SetProperty( NS_LITERAL_STRING(SB_PROPERTY_RAPISCOPEURL),
2784  siteScopeURL );
2785  NS_ENSURE_SUCCESS( rv, rv );
2786 
2787  rv = mediaItem->SetProperty( NS_LITERAL_STRING(SB_PROPERTY_RAPISITEID),
2788  aSiteID );
2789  NS_ENSURE_SUCCESS( rv, rv );
2790 
2791  return NS_OK;
2792 }
2793 
2794 nsresult
2796  const nsAString& aSiteID )
2797 {
2798  LOG(("sbRemotePlayer::SetOriginScope()"));
2799  NS_ASSERTION( aItem, "aItem is null" );
2800  NS_ASSERTION( !aSiteID.IsEmpty(), "aSiteID is empty!" );
2801 
2802  nsresult rv = SetDownloadScope( aItem, aSiteID );
2803  NS_ENSURE_SUCCESS( rv, rv );
2804 
2805  nsString scope;
2806  rv = aItem->GetProperty( NS_LITERAL_STRING(SB_PROPERTY_RAPISCOPEURL), scope);
2807  NS_ENSURE_SUCCESS( rv, rv );
2808 
2809  rv = aItem->SetProperty( NS_LITERAL_STRING(SB_PROPERTY_ORIGINPAGE), scope );
2810  NS_ENSURE_SUCCESS( rv, rv );
2811 
2812  return NS_OK;
2813 }
2814 
2815 // ---------------------------------------------------------------------------
2816 //
2817 // Component stuff
2818 //
2819 // ---------------------------------------------------------------------------
2820 
2821 NS_METHOD
2822 sbRemotePlayer::Register( nsIComponentManager* aCompMgr,
2823  nsIFile* aPath,
2824  const char *aLoaderStr,
2825  const char *aType,
2826  const nsModuleComponentInfo *aInfo )
2827 {
2828  nsresult rv;
2829 
2830  nsCOMPtr<nsICategoryManager> catMan(
2831  do_GetService(NS_CATEGORYMANAGER_CONTRACTID) );
2832  if (!catMan)
2833  return NS_ERROR_FAILURE;
2834 
2835  // allow ourself to be accessed as a js global in webpage
2836  rv = catMan->AddCategoryEntry( JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY,
2837  "songbird", /* use this name to access */
2839  PR_TRUE, /* persist */
2840  PR_TRUE, /* replace existing */
2841  nsnull );
2842 
2843  return rv;
2844 }
2845 
2846 
2847 NS_METHOD
2848 sbRemotePlayer::Unregister( nsIComponentManager* aCompMgr,
2849  nsIFile* aPath,
2850  const char *aLoaderStr,
2851  const nsModuleComponentInfo *aInfo )
2852 {
2853  nsresult rv;
2854 
2855  nsCOMPtr<nsICategoryManager> catMan(
2856  do_GetService(NS_CATEGORYMANAGER_CONTRACTID) );
2857  if (!catMan)
2858  return NS_ERROR_FAILURE;
2859 
2860  rv = catMan->DeleteCategoryEntry( JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY,
2861  "songbird",
2862  PR_TRUE ); /* delete persisted data */
2863  return rv;
2864 }
2865 
2866 nsresult
2867 sbRemotePlayer::CreateProperty( const nsAString& aPropertyType,
2868  const nsAString& aPropertyID,
2869  const nsAString& aDisplayName,
2870  const nsAString& aButtonLabel,
2871  PRInt32 aTimeType,
2872  PRBool aReadonly,
2873  PRBool aUserViewable,
2874  PRUint32 aNullSort )
2875 {
2876 #ifdef PR_LOGGING
2877  nsCString viewable = aUserViewable? NS_LITERAL_CSTRING("TRUE") : NS_LITERAL_CSTRING("FALSE");
2878  nsCString readonly = aReadonly? NS_LITERAL_CSTRING("TRUE") : NS_LITERAL_CSTRING("FALSE");
2879  LOG(( "sbRemotePlayer::CreateProperty(%s, %s, %s, %s, viewable:%s, :reado%s)",
2880  NS_LossyConvertUTF16toASCII(aPropertyType).get(),
2881  NS_LossyConvertUTF16toASCII(aPropertyID).get(),
2882  NS_LossyConvertUTF16toASCII(aDisplayName).get(),
2883  NS_LossyConvertUTF16toASCII(aButtonLabel).get(),
2884  viewable.get(),
2885  readonly.get() ));
2886 #endif
2887 
2888  nsresult rv;
2889  nsCOMPtr<sbIPropertyManager> propMngr(
2890  do_GetService( SB_PROPERTYMANAGER_CONTRACTID, &rv ) );
2891  NS_ENSURE_SUCCESS( rv, rv );
2892 
2893  PRBool hasProp;
2894  nsCOMPtr<sbIPropertyInfo> info;
2895  propMngr->HasProperty( aPropertyID, &hasProp );
2896 
2897  if (!hasProp) {
2898  // property doesn't exist, add it.
2899 
2900  // these types get created directly
2901  if (aPropertyType.EqualsLiteral("text") ||
2902  aPropertyType.EqualsLiteral("datetime") ||
2903  aPropertyType.EqualsLiteral("uri") ||
2904  aPropertyType.EqualsLiteral("number")) {
2905  if ( aPropertyType.EqualsLiteral("text") ){
2906  info = do_CreateInstance( SB_TEXTPROPERTYINFO_CONTRACTID, &rv );
2907  } else if ( aPropertyType.EqualsLiteral("datetime") ) {
2908  info = do_CreateInstance( SB_DATETIMEPROPERTYINFO_CONTRACTID, &rv );
2909  NS_ENSURE_SUCCESS( rv, rv );
2910 
2911  nsCOMPtr<sbIDatetimePropertyInfo> dtInfo( do_QueryInterface( info, &rv ) );
2912  NS_ENSURE_SUCCESS( rv, rv );
2913 
2914  rv = dtInfo->SetTimeType(aTimeType);
2915  NS_ENSURE_SUCCESS( rv, rv );
2916 
2917  } else if ( aPropertyType.EqualsLiteral("uri") ) {
2918  info = do_CreateInstance( SB_URIPROPERTYINFO_CONTRACTID, &rv );
2919  } else if ( aPropertyType.EqualsLiteral("number") ) {
2920  info = do_CreateInstance( SB_NUMBERPROPERTYINFO_CONTRACTID, &rv );
2921  }
2922  NS_ENSURE_SUCCESS( rv, rv );
2923 
2924  if (info) {
2925  // set the data on the propinfo
2926  rv = info->SetId(aPropertyID);
2927  NS_ENSURE_SUCCESS( rv, rv );
2928  rv = info->SetDisplayName(aDisplayName);
2929  NS_ENSURE_SUCCESS( rv, rv );
2930  rv = info->SetUserViewable(aUserViewable);
2931  NS_ENSURE_SUCCESS( rv, rv );
2932  // aReadonly maps inversely to UserEditable
2933  rv = info->SetUserEditable(aReadonly ? PR_FALSE : PR_TRUE);
2934  NS_ENSURE_SUCCESS( rv, rv );
2935  rv = info->SetNullSort(aNullSort);
2936  NS_ENSURE_SUCCESS( rv, rv );
2937  }
2938  }
2939  // these types get created through builders
2940  else {
2941  nsCOMPtr<sbIPropertyBuilder> builder;
2942  if (aPropertyType.EqualsLiteral("button")) {
2943  LOG(( "sbRemotePlayer::CreateProperty() - using a button builder" ));
2944  builder =
2945  do_CreateInstance(SB_SIMPLEBUTTONPROPERTYBUILDER_CONTRACTID, &rv);
2946  NS_ENSURE_SUCCESS(rv, rv);
2947 
2948  nsCOMPtr<sbISimpleButtonPropertyBuilder> buttonBuilder (
2949  do_QueryInterface(builder));
2950  NS_ENSURE_STATE(buttonBuilder);
2951 
2952  rv = buttonBuilder->SetLabel(aButtonLabel);
2953  NS_ENSURE_SUCCESS(rv, rv);
2954  }
2955  else if (aPropertyType.EqualsLiteral("image")) {
2956  LOG(( "sbRemotePlayer::CreateProperty() - using a image builder" ));
2957  builder =
2958  do_CreateInstance(SB_IMAGEPROPERTYBUILDER_CONTRACTID, &rv);
2959  NS_ENSURE_SUCCESS(rv, rv);
2960  }
2961  else if (aPropertyType.EqualsLiteral("downloadbutton")) {
2962  LOG(( "sbRemotePlayer::CreateProperty() - using a downloadbutton builder" ));
2963  builder =
2964  do_CreateInstance(SB_DOWNLOADBUTTONPROPERTYBUILDER_CONTRACTID, &rv);
2965  NS_ENSURE_SUCCESS(rv, rv);
2966 
2967  nsCOMPtr<sbIDownloadButtonPropertyBuilder> dlBuilder (
2968  do_QueryInterface(builder));
2969  NS_ENSURE_STATE(dlBuilder);
2970 
2971  rv = dlBuilder->SetLabel(aButtonLabel);
2972  NS_ENSURE_SUCCESS(rv, rv);
2973  }
2974  else if (aPropertyType.EqualsLiteral("rating")) {
2975  LOG(( "sbRemotePlayer::CreateProperty() - using a rating builder" ));
2976  builder =
2977  do_CreateInstance(SB_RATINGPROPERTYBUILDER_CONTRACTID, &rv);
2978  NS_ENSURE_SUCCESS(rv, rv);
2979  }
2980  else {
2981  // bad type, return an error - Should we just create text by default?
2982  return NS_ERROR_FAILURE;
2983  }
2984 
2985  // set all the common properties together
2986  if (builder) {
2987  rv = builder->SetPropertyID(aPropertyID);
2988  NS_ENSURE_SUCCESS(rv, rv);
2989  rv = builder->SetDisplayName(aDisplayName);
2990  NS_ENSURE_SUCCESS(rv, rv);
2991  rv = builder->SetRemoteReadable(PR_TRUE);
2992  NS_ENSURE_SUCCESS(rv, rv);
2993  rv = builder->SetRemoteWritable(PR_TRUE);
2994  NS_ENSURE_SUCCESS(rv, rv);
2995  rv = builder->SetUserViewable(aUserViewable);
2996  NS_ENSURE_SUCCESS( rv, rv );
2997  rv = builder->SetUserEditable(aReadonly ? PR_FALSE : PR_TRUE);
2998  NS_ENSURE_SUCCESS( rv, rv );
2999  rv = builder->Get(getter_AddRefs(info));
3000  NS_ENSURE_SUCCESS(rv, rv);
3001  }
3002 
3003  }
3004 
3005  // we created a new property in the system so enable remote write/read
3006  if (NS_SUCCEEDED(rv) ) {
3007  LOG(( "sbRemotePlayer::CreateProperty() - we have a propertyInfo item" ));
3008  rv = info->SetRemoteWritable(PR_TRUE);
3009  if ( NS_FAILED(rv) && rv != NS_ERROR_NOT_IMPLEMENTED ) {
3010  return rv;
3011  }
3012 
3013  rv = info->SetRemoteReadable(PR_TRUE);
3014  if ( NS_FAILED(rv) && rv != NS_ERROR_NOT_IMPLEMENTED ) {
3015  return rv;
3016  }
3017  } else {
3018  LOG(( "sbRemotePlayer::CreateProperty() - we DONT have a propertyInfo item" ));
3019  }
3020 
3021  // add to the property manager
3022  rv = propMngr->AddPropertyInfo(info);
3023  NS_ENSURE_SUCCESS( rv, rv );
3024 
3025  }
3026 
3027  return NS_OK;
3028 }
3029 
3030 NS_IMETHODIMP
3031 sbRemotePlayer::CreateTextProperty( const nsAString& aPropertyID,
3032  const nsAString& aDisplayName,
3033  PRBool aReadonly,
3034  PRBool aUserViewable,
3035  PRUint32 aNullSort )
3036 {
3037  return CreateProperty( NS_LITERAL_STRING("text"),
3038  aPropertyID,
3039  aDisplayName,
3040  EmptyString(),
3041  0,
3042  aReadonly,
3043  aUserViewable,
3044  aNullSort );
3045 }
3046 
3047 NS_IMETHODIMP
3048 sbRemotePlayer::CreateDateTimeProperty( const nsAString& aPropertyID,
3049  const nsAString& aDisplayName,
3050  PRInt32 aTimeType,
3051  PRBool aReadonly,
3052  PRBool aUserViewable,
3053  PRUint32 aNullSort )
3054 {
3055  return CreateProperty( NS_LITERAL_STRING("datetime"),
3056  aPropertyID,
3057  aDisplayName,
3058  EmptyString(),
3059  aTimeType,
3060  aReadonly,
3061  aUserViewable,
3062  aNullSort );
3063 }
3064 
3065 NS_IMETHODIMP
3066 sbRemotePlayer::CreateURIProperty( const nsAString& aPropertyID,
3067  const nsAString& aDisplayName,
3068  PRBool aReadonly,
3069  PRBool aUserViewable,
3070  PRUint32 aNullSort)
3071 {
3072  return CreateProperty( NS_LITERAL_STRING("uri"),
3073  aPropertyID,
3074  aDisplayName,
3075  EmptyString(),
3076  0,
3077  aReadonly,
3078  aUserViewable,
3079  aNullSort );
3080 }
3081 
3082 NS_IMETHODIMP
3083 sbRemotePlayer::CreateNumberProperty( const nsAString& aPropertyID,
3084  const nsAString& aDisplayName,
3085  PRBool aReadonly,
3086  PRBool aUserViewable,
3087  PRUint32 aNullSort )
3088 {
3089  return CreateProperty( NS_LITERAL_STRING("number"),
3090  aPropertyID,
3091  aDisplayName,
3092  EmptyString(),
3093  0,
3094  aReadonly,
3095  aUserViewable,
3096  aNullSort );
3097 }
3098 
3099 NS_IMETHODIMP
3100 sbRemotePlayer::CreateImageProperty( const nsAString& aPropertyID,
3101  const nsAString& aDisplayName,
3102  PRBool aReadonly,
3103  PRBool aUserViewable,
3104  PRUint32 aNullSort )
3105 {
3106  return CreateProperty( NS_LITERAL_STRING("image"),
3107  aPropertyID,
3108  aDisplayName,
3109  EmptyString(),
3110  0,
3111  aReadonly,
3112  aUserViewable,
3113  aNullSort );
3114 }
3115 
3116 NS_IMETHODIMP
3117 sbRemotePlayer::CreateRatingsProperty( const nsAString& aPropertyID,
3118  const nsAString& aDisplayName,
3119  PRBool aReadonly,
3120  PRBool aUserViewable,
3121  PRUint32 aNullSort )
3122 {
3123  return CreateProperty( NS_LITERAL_STRING("rating"),
3124  aPropertyID,
3125  aDisplayName,
3126  EmptyString(),
3127  0,
3128  aReadonly,
3129  aUserViewable,
3130  aNullSort );
3131 }
3132 
3133 NS_IMETHODIMP
3134 sbRemotePlayer::CreateButtonProperty( const nsAString& aPropertyID,
3135  const nsAString& aDisplayName,
3136  const nsAString& aButtonLabel,
3137  PRBool aReadonly,
3138  PRBool aUserViewable,
3139  PRUint32 aNullSort )
3140 {
3141  return CreateProperty( NS_LITERAL_STRING("button"),
3142  aPropertyID,
3143  aDisplayName,
3144  aButtonLabel,
3145  0,
3146  aReadonly,
3147  aUserViewable,
3148  aNullSort );
3149 }
3150 
3151 NS_IMETHODIMP
3152 sbRemotePlayer::CreateDownloadButtonProperty( const nsAString& aPropertyID,
3153  const nsAString& aDisplayName,
3154  const nsAString& aButtonLabel,
3155  PRBool aReadonly,
3156  PRBool aUserViewable,
3157  PRUint32 aNullSort )
3158 {
3159  return CreateProperty( NS_LITERAL_STRING("downloadbutton"),
3160  aPropertyID,
3161  aDisplayName,
3162  aButtonLabel,
3163  0,
3164  aReadonly,
3165  aUserViewable,
3166  aNullSort );
3167 }
3168 
3169 NS_IMETHODIMP
3170 sbRemotePlayer::HasAccess( const nsAString& aRemotePermCategory,
3171  PRBool *_retval )
3172 {
3173  nsCOMPtr<sbISecurityMixin> mixin;
3174  mixin = do_QueryInterface(mSecurityMixin);
3175 
3176  // Here we are going to look up the aRemotePermCategory in our
3177  // sPublicCategoryConversions table to convert the more readable version
3178  // into our internal version.
3179  PRInt32 iIndex = -1;
3180  for ( PRUint32 i=0; iIndex < 0 && i < NS_ARRAY_LENGTH(sPublicCategoryConversions); i++ ) {
3181  if ( StringBeginsWith( aRemotePermCategory, NS_ConvertASCIItoUTF16( sPublicCategoryConversions[i][0] ) ) ) {
3182  // Set iIndex which will drop us out of the loop
3183  iIndex = i;
3184  }
3185  }
3186 
3187  // Check that we found a matching catagory, and return false if not.
3188  if (iIndex == -1)
3189  {
3190  *_retval = false;
3191  return NS_OK;
3192  }
3193 
3194  // Now grab the internal category name and get the permissions
3195  nsString mCategory;
3196  mCategory.AssignLiteral(sPublicCategoryConversions[iIndex][1]);
3197  return mixin->GetPermissionForScopedNameWrapper( mCategory, _retval );
3198 }
3199 
3200 // ---------------------------------------------------------------------------
3201 //
3202 // sbRemotePlayerDownloadCallback
3203 //
3204 // ---------------------------------------------------------------------------
3205 
3207 
3209 {
3210  LOG(("sbRemotePlayerDownloadCallback::sbRemotePlayerDownloadCallback()"));
3211 }
3212 
3214 {
3215  LOG(("sbRemotePlayerDownloadCallback::~sbRemotePlayerDownloadCallback()"));
3216 }
3217 
3218 nsresult
3220 {
3221  LOG(("sbRemotePlayerDownloadCallback::Initialize()"));
3222  NS_ASSERTION(aRemotePlayer, "aRemotePlayer is null");
3223 
3224  nsresult rv;
3225 
3226  // Get a weak reference to the remote player
3227  mWeakRemotePlayer = do_GetWeakReference
3228  ( NS_ISUPPORTS_CAST(sbIRemotePlayer*, aRemotePlayer), &rv );
3229  NS_ENSURE_SUCCESS(rv, rv);
3230 
3231  // Get the codebase
3232  nsCOMPtr<sbISecurityMixin> mixin =
3233  do_QueryInterface( aRemotePlayer->mSecurityMixin, &rv );
3234  NS_ENSURE_SUCCESS( rv, rv );
3235  rv = mixin->GetCodebase( getter_AddRefs(mCodebaseURI) );
3236 
3237  // Get the IO service
3238  mIOService = do_GetService("@mozilla.org/network/io-service;1", &rv);
3239 
3240  // Set up download callbacks
3241  nsCOMPtr<sbIDeviceManager> deviceManager;
3242  PRBool hasDeviceForCategory;
3243 
3244  deviceManager = do_GetService("@songbirdnest.com/Songbird/DeviceManager;1",
3245  &rv);
3246  NS_ENSURE_SUCCESS(rv, rv);
3247  rv = deviceManager->HasDeviceForCategory
3248  (NS_LITERAL_STRING("Songbird Download Device"), &hasDeviceForCategory);
3249  NS_ENSURE_SUCCESS(rv, rv);
3250  NS_ENSURE_TRUE(hasDeviceForCategory, NS_ERROR_UNEXPECTED);
3251  rv = deviceManager->GetDeviceByCategory
3252  (NS_LITERAL_STRING("Songbird Download Device"),
3253  getter_AddRefs(mDownloadDevice));
3254  NS_ENSURE_SUCCESS(rv, rv);
3255  rv = mDownloadDevice->AddCallback(this);
3256  NS_ENSURE_SUCCESS(rv, rv);
3257 
3258  return NS_OK;
3259 }
3260 
3261 void
3263 {
3264  LOG(("sbRemotePlayerDownloadCallback::Finalize()"));
3265 
3266  if (mDownloadDevice)
3267  mDownloadDevice->RemoveCallback(this);
3268 }
3269 
3270 // ---------------------------------------------------------------------------
3271 //
3272 // sbIDeviceBaseCallback
3273 //
3274 // ---------------------------------------------------------------------------
3275 
3276 NS_IMETHODIMP
3277 sbRemotePlayerDownloadCallback::OnDeviceConnect
3278  ( const nsAString &aDeviceIdentifier )
3279 {
3280  return NS_OK;
3281 }
3282 
3283 NS_IMETHODIMP
3284 sbRemotePlayerDownloadCallback::OnDeviceDisconnect
3285  ( const nsAString &aDeviceIdentifier )
3286 {
3287  return NS_OK;
3288 }
3289 
3290 NS_IMETHODIMP
3291 sbRemotePlayerDownloadCallback::OnTransferStart( sbIMediaItem* aMediaItem )
3292 {
3293  LOG(("sbRemotePlayer::OnTransferStart()"));
3294  NS_ASSERTION(aMediaItem, "aMediaItem is null");
3295  nsresult rv;
3296 
3297  // Check item scope. Return without error if out of scope
3298  rv = CheckItemScope( aMediaItem );
3299  if (NS_FAILED(rv))
3300  return NS_OK;
3301 
3302  nsCOMPtr<sbIRemotePlayer> remotePlayer =
3303  do_QueryReferent(mWeakRemotePlayer, &rv);
3304  NS_ENSURE_SUCCESS(rv, rv);
3305  if (remotePlayer) {
3306  rv = remotePlayer->FireMediaItemStatusEventToContent
3307  ( RAPI_EVENT_CLASS,
3309  aMediaItem,
3310  NS_OK );
3311  NS_ENSURE_SUCCESS(rv, rv);
3312  }
3313  return NS_OK;
3314 }
3315 
3316 NS_IMETHODIMP
3317 sbRemotePlayerDownloadCallback::OnTransferComplete( sbIMediaItem* aMediaItem,
3318  PRInt32 aStatus )
3319 {
3320  LOG(("sbRemotePlayer::OnTransferComplete()"));
3321  NS_ASSERTION(aMediaItem, "aMediaItem is null");
3322  nsresult rv;
3323 
3324  // Check item scope. Return without error if out of scope
3325  rv = CheckItemScope( aMediaItem );
3326  if (NS_FAILED(rv))
3327  return NS_OK;
3328 
3329  nsCOMPtr<sbIRemotePlayer> remotePlayer =
3330  do_QueryReferent(mWeakRemotePlayer, &rv);
3331  NS_ENSURE_SUCCESS(rv, rv);
3332  if (remotePlayer) {
3333  rv = remotePlayer->FireMediaItemStatusEventToContent
3334  ( RAPI_EVENT_CLASS,
3336  aMediaItem,
3337  aStatus );
3338  NS_ENSURE_SUCCESS(rv, rv);
3339  }
3340  return NS_OK;
3341 }
3342 
3343 NS_IMETHODIMP
3344 sbRemotePlayerDownloadCallback::OnStateChanged
3345  ( const nsAString &aDeviceIdentifier,
3346  PRUint32 aState )
3347 {
3348  return NS_OK;
3349 }
3350 
3351 nsresult
3352 sbRemotePlayerDownloadCallback::CheckItemScope( sbIMediaItem* aMediaItem )
3353 {
3354  LOG(("sbRemotePlayer::CheckItemScope()"));
3355  nsresult rv;
3356 
3357  // Get the item scope
3358  nsCAutoString scopeDomain;
3359  nsCAutoString scopePath;
3360  rv = GetItemScope( aMediaItem, scopeDomain, scopePath );
3361  NS_ENSURE_SUCCESS(rv, rv);
3362 
3363  // Check the item scope against the codebase
3364  rv = sbURIChecker::CheckURI( scopeDomain, scopePath, mCodebaseURI );
3365 
3366  return rv;
3367 }
3368 
3369 nsresult
3370 sbRemotePlayerDownloadCallback::GetItemScope( sbIMediaItem* aMediaItem,
3371  nsACString& aScopeDomain,
3372  nsACString& aScopePath )
3373 {
3374  LOG(("sbRemotePlayer::GetItemScope()"));
3375  NS_ASSERTION(aMediaItem, "aMediaItem is null");
3376  nsresult rv;
3377 
3378  // Get the scope property. If not available, use the origin page property
3379  nsAutoString scopeSpec;
3380  rv = aMediaItem->GetProperty( NS_LITERAL_STRING(SB_PROPERTY_RAPISCOPEURL),
3381  scopeSpec );
3382  if (NS_FAILED(rv) || scopeSpec.IsEmpty()) {
3383  rv = aMediaItem->GetProperty( NS_LITERAL_STRING(SB_PROPERTY_ORIGINPAGE),
3384  scopeSpec );
3385  // It is possible the download was not triggered by us so ignore the notification
3386  if (NS_FAILED(rv) || scopeSpec.IsEmpty())
3387  return rv;
3388  }
3389 
3390  // Get the scope URI
3391  nsCOMPtr<nsIURI> scopeURI;
3392  rv = mIOService->NewURI( NS_ConvertUTF16toUTF8(scopeSpec),
3393  nsnull,
3394  nsnull,
3395  getter_AddRefs(scopeURI) );
3396  NS_ENSURE_SUCCESS(rv, rv);
3397 
3398  // Get the scope domain and path
3399  rv = sbURIChecker::CheckURI(aScopeDomain, aScopePath, scopeURI);
3400  NS_ENSURE_SUCCESS(rv, rv);
3401 
3402  return NS_OK;
3403 }
#define SONGBIRD_REMOTEPLAYER_CLASSNAME
nsresult InitPrivileged(nsIURI *aCodebase, nsIDOMWindow *aWindow)
static const char * sPublicRProperties[]
PRBool mUseDefaultCommands
static nsresult SB_WrapMediaList(sbRemotePlayer *aRemotePlayer, sbIMediaList *aMediaList, sbIMediaList **aRemoteMediaList)
An interface to control a media list from remote web pages.
nsCOMPtr< sbIDataRemote > mdrRepeat
nsresult OnViewChange(sbIMediacoreEvent *aEvent)
static PRBool GetUserApprovalForHost(nsIURI *aURI, const nsAString &aTitleKey, const nsAString &aMessageKey, const char *aScopedName=nsnull)
readonly attribute sbIRemoteMediaList downloadMediaList
nsCOMPtr< sbIDataRemote > mdrCurrentAlbum
return NS_OK
_updateCookies aPath
nsCString mScopePath
friend class sbRemotePlayerDownloadCallback
#define RAPI_EVENT_TYPE_TRACKCHANGE
static already_AddRefed< nsPIDOMWindow > GetWindowFromJS()
browser docShell
nsresult ConfirmPlaybackControl()
#define SB_TEXTPROPERTYINFO_CONTRACTID
#define SB_PROPERTY_RAPISITEID
#define SB_DOWNLOADBUTTONPROPERTYBUILDER_CONTRACTID
nsCOMPtr< sbIDataRemote > mdrMute
Interface used to enumerate the items in a media list.
PR_STATIC_CALLBACK(PRBool) FindElementCallback(void *aElement
NS_IMPL_ISUPPORTS1(sbDeviceCapabilitiesUtils, sbIDeviceCapabilitiesUtils) sbDeviceCapabilitiesUtils
#define SB_URIPROPERTYINFO_CONTRACTID
#define SB_PREFS_ROOT
#define SB_EVENT_RAPI_PERMISSION_DENIED
nsRefPtr< sbRemoteCommands > mCommandsObject
function doc() browser.contentDocument
static nsresult CheckURI(nsACString &aDomain, nsACString &aPath, nsIURI *aURI)
nsCOMPtr< sbIDataRemote > mdrPlaying
readonly attribute long long volume
The volume on a range from 0 to 255.
#define SONGBIRD_REMOTEPLAYER_CONTRACTID
const unsigned long TRACK_CHANGE
Track playing has changed.
boolean hasAccess(in AString aRemotePermCataegory)
Check if the code has access to a category.
nsCOMPtr< nsIJSContextStack > mStack
UnbindAndRelease(const nsAString &aKey, sbRemoteObserver &aRemObs, void *userArg)
#define SB_NUMBERPROPERTYINFO_CONTRACTID
readonly attribute sbIRemotePlayer remotePlayer
nsresult InitInternal(nsPIDOMWindow *aWindow)
var event
This interface is a composition of many of our other interfaces with the goal of exposing a more web-...
#define SB_IMAGEPROPERTYBUILDER_CONTRACTID
already_AddRefed< nsIURI > GetSiteScopeURI()
const NS_ERROR_ABORT
NS_INTERFACE_MAP_END NS_IMPL_CI_INTERFACE_GETTER6(sbDeviceLibrary, nsIClassInfo, sbIDeviceLibrary, sbILibrary, sbIMediaList, sbIMediaItem, sbILibraryResource) sbDeviceLibrary
nsISupportsWeakReference
#define RAPI_EVENT_CLASS
nsCOMPtr< nsIDOMDocument > mContentDoc
nsRefPtr< sbRemoteWebPlaylist > mRemWebPlaylist
#define SB_SIMPLEBUTTONPROPERTYBUILDER_CONTRACTID
var scope
nsCOMPtr< nsPIDOMWindow > mPrivWindow
sbOSDControlService prototype QueryInterface
#define SB_PROPERTY_RAPISCOPEURL
nsCOMPtr< nsIWeakReference > mMM
#define RAPI_VERSION_MAJOR
virtual ~sbRemotePlayer()
nsString mSiteScopeURL
A brief description of the contents of this interface.
static const char * sPublicWProperties[]
nsresult SetOriginScope(sbIMediaItem *aItem, const nsAString &aSiteID)
const unsigned long STREAM_STOP
Stream was stopped.
[SOON TO BE DEPRECATED AFTER 0.3] The callback class for sbIDeviceBase
let window
#define SONGBIRD_REMOTEPLAYER_CID
static NS_METHOD Register(nsIComponentManager *aCompMgr, nsIFile *aPath, const char *aLoaderStr, const char *aType, const nsModuleComponentInfo *aInfo)
nsISecurityCheckedComponent
#define SB_PROPERTYMANAGER_CONTRACTID
An interface for setting up nsISecurityCheckedComponent security checks.
#define RAPI_EVENT_TYPE_BEFORETRACKCHANGE
NS_IMETHODIMP OnEnumerationBegin(sbIMediaList *, PRUint16 *_retval)
#define RAPI_EVENT_TYPE_STOP
nsDataHashtable< nsStringHashKey, sbRemoteObserver > mRemObsHash
#define RAPI_EVENT_TYPE_DOWNLOADSTART
static const char * sPublicMethods[]
static nsresult DispatchEvent(nsIDOMDocument *aDocument, const nsAString &aClass, const nsAString &aType, PRBool aIsTrusted)
Definition of the sbIMediacoreEvent interface.
nsCOMPtr< nsIIOService > mIOService
#define RAPI_VERSION_MINOR
An interface for a sandbox library created by the website.
const nsIDOMWindow
static nsresult StandardPlay(nsIWeakReference *aWeakRef)
#define SB_PROPERTY_ORIGINPAGE
nsresult OnBeforeViewChange(sbIMediacoreEvent *aEvent)
var bundle
nsRefPtr< sbRemoteNotificationManager > mNotificationMgr
nsresult SetDownloadScope(sbIMediaItem *aItem, const nsAString &aSiteID)
#define SB_LIB_NAME_WEB
nsCString mScopeDomain
An interface to specify playlist commands from remote web pages.
nsCOMPtr< nsISecurityCheckedComponent > mSecurityMixin
nsresult InitRemoteWebPlaylist()
var tabbrowser
return e ctrlKey(chr<' '||!chars||chars.indexOf(chr)>-1)
nsCOMPtr< nsIDOMDocument > mChromeDoc
nsCOMPtr< sbIDataRemote > mdrCurrentTrack
const unsigned long TRACK_INDEX_CHANGE
Index in view of item currently playing has changed.
A marker interface for objects that aggregate the security mixin.
void nsString_Split(const nsAString &aString, const nsAString &aDelimiter, nsTArray< nsString > &aSubStringArray)
nsresult OnTrackChange(sbIMediacoreEvent *aEvent)
nsresult OnTrackIndexChange(sbIMediacoreEvent *aEvent)
sbISecurityAggregator SB_IMPL_CLASSINFO(sbRemotePlayer,"@songbirdnest.com/remoteapi/remoteplayer;1","Songbird Remote Player", nsIProgrammingLanguage::CPLUSPLUS, 0, kRemotePlayerCID) sbRemotePlayer
static const char * sPublicMetadata[]
const unsigned long VIEW_CHANGE
Sequencer view changed.
already_AddRefed< nsPIDOMWindow > GetWindow()
nsCOMPtr< sbIDataRemote > mdrShuffle
#define SB_DATETIMEPROPERTYINFO_CONTRACTID
An interface to control a media library from remote web pages.
#define SB_RATINGPROPERTYBUILDER_CONTRACTID
nsCOMPtr< sbIDataRemote > mdrPosition
#define RAPI_EVENT_TYPE_TRACKINDEXCHANGE
NS_IMETHODIMP OnEnumerationEnd(sbIMediaList *, nsresult)
GstMessage * message
#define RAPI_EVENT_TYPE_BEFOREVIEW
readonly attribute sbIRemoteCommands commands
The collection of commands associated with the current page.
nsresult GetBrowser(nsIDOMElement **aElement)
static NS_DEFINE_CID(kRemotePlayerCID,{0x645e064c, 0xe547, 0x444c,{0xbb, 0x41, 0x8f, 0x2e, 0x5b, 0x12, 0x70, 0x0b}})
#define SB_WEB_TABBROWSER
An interface that represents the set of command buttons and context menu items available on a display...
nsresult OnBeforeTrackChange(sbIMediacoreEvent *aEvent)
nsCOMPtr< sbIDataRemote > mdrCurrentArtist
nsRefPtr< sbRemotePlayerDownloadCallback > mDownloadCallback
nsCOMPtr< sbIDataRemote > mdrPaused
nsresult CreateProperty(const nsAString &aPropertyType, const nsAString &aPropertyID, const nsAString &aDisplayName, const nsAString &aButtonLabel, PRInt32 aTimeType, PRBool aReadonly, PRBool aUserViewable, PRUint32 aNullSort)
_updateCookies aName
readonly attribute AString name
The name of the player.
var uri
Definition: FeedWriter.js:1135
countRef value
Definition: FeedWriter.js:1423
nsCOMPtr< sbIDataRemote > remote
const unsigned long BEFORE_VIEW_CHANGE
Sequencer view is about to change.
#define SB_LIB_NAME_MAIN
NS_IMPL_ISUPPORTS7(sbRemotePlayer, nsIClassInfo, nsISecurityCheckedComponent, sbIRemotePlayer, nsIDOMEventListener, nsISupportsWeakReference, sbIMediacoreEventListener, sbISecurityAggregator) NS_IMPL_CI_INTERFACE_GETTER6(sbRemotePlayer
static nsresult GetFilenameForSiteLibrary(const nsACString &aDomain, const nsACString &aPath, nsAString &_retval)
static nsresult GetJSScopeNameFromScope(const nsACString &aScopeName, nsAString &aJSScopeName)
let promptService
nsresult UnregisterCommands()
nsresult RegisterCommands(PRBool aUseDefaultCommands)
#define SB_EVENT_RAPI_PERMISSION_CHANGED
nsresult TakePlaybackControl(nsIURI *aURI)
static nsresult DispatchSecurityEvent(nsIDOMDocument *aDoc, sbIRemotePlayer *aPlayer, const nsAString &aClass, const nsAString &aType, const nsAString &aCategoryID, PRBool aHasAccess, PRBool aIsTrusted)
#define SB_MEDIACOREMANAGER_CONTRACTID
nsresult Initialize(sbRemotePlayer *aRemotePlayer)
static NS_METHOD Unregister(nsIComponentManager *aCompMgr, nsIFile *aPath, const char *aLoaderStr, const nsModuleComponentInfo *aInfo)
nsresult GetMainLibrary(sbILibrary **aMainLibrary)
Interface that defines a single item of media in the system.
#define RAPI_EVENT_TYPE_DOWNLOADCOMPLETE
sbRemoteNotificationManager * GetNotificationManager()
nsCOMPtr< sbIRemoteObserver > observer
restoreWindow aState
#define RAPI_EVENT_TYPE_VIEW
observe data
Definition: FeedWriter.js:1329
nsInterfaceHashtable< nsStringHashKey, sbIRemoteLibrary > mCachedLibraries
const unsigned long STREAM_END
End of stream.
nsCOMPtr< nsIURI > mSiteScopeURI
_getSelectedPageStyle s i
nsIDOMEventListener
An interface to control a media list from remote web pages.
#define LOG(args)
NS_IMETHODIMP OnEnumeratedItem(sbIMediaList *, sbIMediaItem *aItem, PRUint16 *_retval)
nsresult GetSiteScopeURL(nsAString &aURL)
Lightweight Observer style interface for use with sbIRemotePlayer::addListener.
NS_DECL_ISUPPORTS sbRemotePlayerEnumCallback(nsCOMArray< sbIMediaItem > &aArray)
var treeView
static const char * sPublicCategoryConversions[][2]
static nsresult SetPermission(nsIURI *aURI, const nsACString &aScopedName)
Set the permission to allow for a scoped name.