sbSecurityMixin.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 "sbSecurityMixin.h"
28 #include <sbClassInfoUtils.h>
29 #include <sbMemoryUtils.h>
31 
32 #include <nsIConsoleService.h>
33 #include <nsIPermissionManager.h>
34 #include <nsIPrefBranch.h>
35 #include <nsIScriptSecurityManager.h>
36 #include <nsServiceManagerUtils.h>
37 #include <nsStringGlue.h>
38 #include <prlog.h>
39 #include <plstr.h>
40 
41 #include "sbRemotePlayer.h"
42 
43 #define PERM_TYPE_PLAYBACK_CONTROL "rapi.playback_control"
44 #define PERM_TYPE_PLAYBACK_READ "rapi.playback_read"
45 #define PERM_TYPE_LIBRARY_READ "rapi.library_read"
46 #define PERM_TYPE_LIBRARY_WRITE "rapi.library_write"
47 
48 #define PREF_PLAYBACK_CONTROL "playback_control_disable"
49 #define PREF_PLAYBACK_READ "playback_read_disable"
50 #define PREF_LIBRARY_READ "library_read_disable"
51 #define PREF_LIBRARY_WRITE "library_write_disable"
52 /*
53  * To log this module, set the following environment variable:
54  * NSPR_LOG_MODULES=sbSecurityMixin:5
55  */
56 #ifdef PR_LOGGING
57 static PRLogModuleInfo* gLibraryLog = nsnull;
58 #endif
59 
60 #undef LOG
61 #define LOG(args) PR_LOG(gLibraryLog, PR_LOG_WARN, args)
62 
63 static const char* sNotificationNone = "none";
64 static const char* sNotificationHat = "hat";
65 static const char* sNotificationAlert = "alert";
66 static const char* sNotificationStatus = "status";
67 
68 
69 struct Scope {
70  const char* name;
71  const char* blocked_notification;
72  const char* allowed_notification;
73 };
74 
75 // Note: If you change the catagory names here then please change them in
76 // sbRemotePlayer.cpp in the sPublicCatagoryConversions array as well
77 static const Scope sScopes[] = {
78  { "playback_control", sNotificationHat, sNotificationNone, },
79  { "playback_read", sNotificationHat, sNotificationNone, },
80  { "library_read", sNotificationHat, sNotificationNone, },
81  { "library_write", sNotificationAlert, sNotificationStatus, },
82 };
83 
84 static NS_DEFINE_CID( kSecurityMixinCID, SONGBIRD_SECURITYMIXIN_CID );
85 
90 
94 
95 SB_IMPL_CLASSINFO( sbSecurityMixin,
98  nsIProgrammingLanguage::CPLUSPLUS,
99  0,
100  kSecurityMixinCID );
101 
102 sbSecurityMixin::sbSecurityMixin()
103 : mOuter(nsnull),
104  mInterfacesCount(0),
105  mPrivileged(PR_FALSE)
106 {
107 #ifdef PR_LOGGING
108  if (!gLibraryLog) {
109  gLibraryLog = PR_NewLogModule( "sbSecurityMixin" );
110  }
111 #endif
112 }
113 
115 {
116  if (mInterfacesCount) {
117  for (PRUint32 index = 0; index < mInterfacesCount; ++index)
118  NS_Free( mInterfaces[index] );
119  NS_Free(mInterfaces);
120  }
121 }
122 
123 // ---------------------------------------------------------------------------
124 //
125 // sbISecurityMixin
126 //
127 // ---------------------------------------------------------------------------
128 
129 NS_IMETHODIMP
131  const nsIID **aInterfacesArray, PRUint32 aInterfacesArrayLength,
132  const char **aMethodsArray, PRUint32 aMethodsArrayLength,
133  const char **aRPropsArray, PRUint32 aRPropsArrayLength,
134  const char **aWPropsArray, PRUint32 aWPropsArrayLength,
135  PRBool aPrivileged)
136 {
137  NS_ENSURE_ARG_POINTER(aOuter);
138 
139  mOuter = aOuter; // no refcount
140 
141  // do interfaces last so we know when to free the allocation there
142  if ( NS_FAILED( CopyStrArray( aMethodsArrayLength, aMethodsArray, &mMethods ) ) ||
143  NS_FAILED( CopyStrArray( aRPropsArrayLength, aRPropsArray, &mRProperties ) ) ||
144  NS_FAILED( CopyStrArray( aWPropsArrayLength, aWPropsArray, &mWProperties ) ) ||
145  NS_FAILED( CopyIIDArray( aInterfacesArrayLength,
146  aInterfacesArray,
147  &mInterfaces)) )
148  return NS_ERROR_OUT_OF_MEMORY;
149 
150  // set this only if we've succeeded
151  mInterfacesCount = aInterfacesArrayLength;
152  mPrivileged = aPrivileged;
153 
154  return NS_OK;
155 }
156 
157 // ---------------------------------------------------------------------------
158 //
159 // nsISecurityCheckedComponent (nsISCC)
160 //
161 // ---------------------------------------------------------------------------
162 
163 NS_IMETHODIMP
164 sbSecurityMixin::CanCreateWrapper(const nsIID *aIID, char **_retval)
165 {
166  LOG(("sbSecurityMixin::CanCreateWrapper()"));
167  NS_ENSURE_ARG_POINTER(aIID);
168  NS_ENSURE_ARG_POINTER(_retval);
169 
170  if (!mOuter) {
171  LOG(("sbSecurityMixin::CanCreateWrapper() - ERROR, no outer"));
172  *_retval = nsnull;
173  return NS_ERROR_FAILURE;
174  }
175 
176  // Make sure the interface requested is one of the approved interfaces
177  PRBool canCreate = PR_FALSE;
178  for ( PRUint32 index = 0; index < mInterfacesCount; index++ ) {
179  const nsIID* ifaceIID = mInterfaces[index];
180  if ( aIID->Equals(*ifaceIID) ) {
181  canCreate = PR_TRUE;
182  break;
183  }
184  }
185  if (!canCreate) {
186  LOG(( "sbSecurityMixin::CanCreateWrapper() - DENIED, bad interface" ));
187  *_retval = nsnull;
188  return NS_ERROR_FAILURE;
189  }
190 
191  // XXXredfive - if the interface is approved, create the wrapper; any actions
192  // on the object will be passed through security for further checking
193  *_retval = SB_CloneAllAccess();
194  return NS_OK;
195 
196 #if 0
197  // Get the codebase of the current page
198  nsCOMPtr<nsIURI> codebase;
199  GetCodebase( getter_AddRefs(codebase) );
200 
201  // bz mentioned in an email that if we don't have a codebase we can infer
202  // that the code didn't come from a http: load. He also mentions that if
203  // they move to a lattice of principals this may not hold true.
204  // for his full message see
205  // http://groups.google.com/group/mozilla.dev.security/msg/fc48e8d0c795a638
206  if (!codebase) {
207  // When the commands object gets called by the sb-commands bindings we
208  // wind up here, no codebase because the call is coming from internal code.
209  *_retval = SB_CloneAllAccess();
210  return NS_OK;
211  }
212 
213  // Do this directly opposed to how it is done in CanCallMethod et al. because
214  // if ANY of these are allowed we need to let the object get created since
215  // we don't know at this point what the request on the object is actually
216  // going to be.
220  LOG(("sbSecurityMixin::CanCreateWrapper - Permission GRANTED!!!"));
221  *_retval = SB_CloneAllAccess();
222  } else {
223  LOG(("sbSecurityMixin::CanCreateWrapper - Permission DENIED (looser)!!!"));
224  *_retval = nsnull;
225  return NS_ERROR_FAILURE;
226  }
227 
228  return NS_OK;
229 #endif
230 }
231 
232 NS_IMETHODIMP
233 sbSecurityMixin::CanCallMethod(const nsIID *aIID,
234  const PRUnichar *aMethodName,
235  char **_retval)
236 {
237  // For some reasone we always get the IID for canCallMethod,
238  // so this works (see CanGetProperty)
239  NS_ENSURE_ARG_POINTER(aIID);
240  NS_ENSURE_ARG_POINTER(aMethodName);
241  NS_ENSURE_ARG_POINTER(_retval);
242 
243  LOG(( "sbSecurityMixin::CanCallMethod(%s)",
244  NS_LossyConvertUTF16toASCII(aMethodName).get() ));
245 
246  nsAutoString method;
247  nsDependentString inMethodName(aMethodName);
248 
249  GetScopedName( mMethods, inMethodName, method );
250  if ( method.IsEmpty() ) {
251  LOG(( "sbSecurityMixin::CanCallMethod(%s) - DENIED, unapproved method",
252  NS_LossyConvertUTF16toASCII(aMethodName).get() ));
253  *_retval = nsnull;
254  return NS_ERROR_FAILURE;
255  }
256 
257  if ( GetPermissionForScopedName(method) ) {
258  LOG(("sbSecurityMixin::CanCallMethod - Permission GRANTED!!!"));
259  *_retval = SB_CloneAllAccess();
260  } else {
261  LOG(("sbSecurityMixin::CanCallMethod - Permission DENIED (looser)!!!"));
262  *_retval = nsnull;
263  return NS_ERROR_FAILURE;
264  }
265  return NS_OK;
266 }
267 
268 NS_IMETHODIMP
269 sbSecurityMixin::CanGetProperty(const nsIID *aIID,
270  const PRUnichar *aPropertyID,
271  char **_retval)
272 {
273  // Because of the peculiarities of XPConnect, XPCWrappedNatives,
274  // XPCNativeWrappers (they're different), XPCWrappedJS and the nsISCC
275  // patterns we get 2 calls for each getproperty and one has an IID and one
276  // doesn't. So we can't verify IID here. Good thing we don't actually need
277  // it. XXXredfive - file a bug!!!
278  //NS_ENSURE_ARG_POINTER(aIID);
279  NS_ENSURE_ARG_POINTER(aPropertyID);
280  NS_ENSURE_ARG_POINTER(_retval);
281 
282  LOG(( "sbSecurityMixin::CanGetProperty(%s)",
283  NS_LossyConvertUTF16toASCII(aPropertyID).get() ));
284 
285  nsAutoString prop;
286  nsDependentString inPropertyID(aPropertyID);
287 
288  GetScopedName( mRProperties, inPropertyID, prop );
289  if ( prop.IsEmpty() ) {
290  LOG(( "sbSecurityMixin::CanGetProperty(%s) - DENIED, unapproved property",
291  NS_LossyConvertUTF16toASCII(aPropertyID).get() ));
292  *_retval = nsnull;
293  return NS_ERROR_FAILURE;
294  }
295 
296  if ( GetPermissionForScopedName(prop) ) {
297  LOG(("sbSecurityMixin::CanGetProperty - Permission GRANTED!!!"));
298  *_retval = SB_CloneAllAccess();
299  } else {
300  LOG(("sbSecurityMixin::CanGetProperty - Permission DENIED (looser)!!!"));
301  *_retval = nsnull;
302  return NS_ERROR_FAILURE;
303  }
304  return NS_OK;
305 }
306 
307 NS_IMETHODIMP
308 sbSecurityMixin::CanSetProperty(const nsIID *aIID,
309  const PRUnichar *aPropertyID,
310  char **_retval)
311 {
312  // Because of the peculiarities of XPConnect, XPCWrappedNatives,
313  // XPCNativeWrappers (they're different), XPCWrappedJS and the nsISCC
314  // patterns we get 2 calls for each SetProperty and one has an IID and one
315  // doesn't. So we can't verify IID here. Good thing we don't actually need
316  // it. XXXredfive - file a bug!!!
317  //NS_ENSURE_ARG_POINTER(aIID);
318  NS_ENSURE_ARG_POINTER(aPropertyID);
319  NS_ENSURE_ARG_POINTER(_retval);
320 
321  LOG(( "sbSecurityMixin::CanSetProperty(%s)",
322  NS_LossyConvertUTF16toASCII(aPropertyID).get() ));
323 
324  nsAutoString prop;
325  nsDependentString inPropertyID(aPropertyID);
326 
327  GetScopedName( mWProperties, inPropertyID, prop );
328  if (prop.IsEmpty()) {
329  LOG(( "sbSecurityMixin::CanSetProperty(%s) - DENIED, unapproved property",
330  NS_LossyConvertUTF16toASCII(aPropertyID).get() ));
331  *_retval = nsnull;
332  return NS_ERROR_FAILURE;
333  }
334 
335  if ( GetPermissionForScopedName(prop) ) {
336  LOG(("sbSecurityMixin::CanSetProperty - Permission GRANTED!!!"));
337  *_retval = SB_CloneAllAccess();
338  } else {
339  LOG(("sbSecurityMixin::CanSetProperty - Permission DENIED (looser)!!!"));
340  *_retval = nsnull;
341  return NS_ERROR_FAILURE;
342  }
343  return NS_OK;
344 }
345 
346 // ---------------------------------------------------------------------------
347 //
348 // nsISCC helper functions
349 //
350 // ---------------------------------------------------------------------------
351 
352 NS_IMETHODIMP
353 sbSecurityMixin::GetCodebase(nsIURI **aCodebase) {
354  NS_ENSURE_ARG_POINTER(aCodebase);
355 
356  // Get the current domain.
357  nsresult rv;
358  nsCOMPtr<nsIScriptSecurityManager> secman( do_GetService( NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv ) );
359  NS_ENSURE_SUCCESS( rv, rv );
360  nsCOMPtr<nsIPrincipal> principal;
361  secman->GetSubjectPrincipal( getter_AddRefs(principal) );
362 
363  if (!principal) {
364  LOG(("sbSecurityMixin::GetCodebase -- Error: No Subject Principal."));
365  *aCodebase = nsnull;
366  return NS_OK;
367  }
368  LOG(("sbSecurityMixin::GetCodebase -- Have Subject Principal."));
369 
370 #ifdef PR_LOGGING
371  nsCOMPtr<nsIPrincipal> systemPrincipal;
372  secman->GetSystemPrincipal( getter_AddRefs(systemPrincipal) );
373 
374  if (principal == systemPrincipal) {
375  LOG(("sbSecurityMixin::GetCodebase -- System Principal."));
376  } else {
377  LOG(("sbSecurityMixin::GetCodebase -- Not System Principal."));
378  }
379 #endif
380 
381  nsCOMPtr<nsIURI> codebase;
382  principal->GetDomain( getter_AddRefs(codebase) );
383 
384  if (!codebase) {
385  LOG(("sbSecurityMixin::GetCodebase -- no codebase from domain, getting it from URI."));
386  principal->GetURI( getter_AddRefs(codebase) );
387  }
388 
389  *aCodebase = codebase;
390  NS_IF_ADDREF(*aCodebase);
391  return NS_OK;
392 }
393 
394 PRBool
395 sbSecurityMixin::GetScopedName(nsTArray<nsCString> &aStringArray,
396  const nsAString &aMethodName,
397  nsAString &aScopedName)
398 {
399  LOG(( "sbSecurityMixin::GetScopedName()"));
400  PRBool approved = PR_FALSE;
401  nsAutoString method;
402 
403  nsCOMPtr<nsIStringEnumerator> methods = new sbTArrayStringEnumerator(&aStringArray);
404  NS_ENSURE_TRUE( methods, PR_FALSE );
405 
406  while ( NS_SUCCEEDED( methods->GetNext(method) ) ) {
407  LOG(( " -- checking method: %s", NS_ConvertUTF16toUTF8(method).get() ));
408  if ( StringEndsWith( method, aMethodName ) ) {
409  aScopedName = method;
410  approved = PR_TRUE;
411  break;
412  }
413  }
414  return approved;
415 }
416 
417 PRBool
418 sbSecurityMixin::GetPermissionForScopedName(const nsAString &aScopedName,
419  PRBool disableNotificationCheck)
420 {
421  LOG(( "sbSecurityMixin::GetPermissionForScopedName()"));
422 
423  // If this instance was set to be privileged, skip the check
424  if (mPrivileged) {
425  return PR_TRUE;
426  }
427 
428  PRBool allowed = PR_FALSE;
429 
430  nsCOMPtr<nsIURI> codebase;
431  GetCodebase( getter_AddRefs(codebase) );
432 
433  if ( StringBeginsWith( aScopedName, NS_LITERAL_STRING("internal:") ) ) {
434  if (!codebase) {
435  // internal stuff always allowed, should never be called from insecure code.
436  allowed = PR_TRUE;
437  } else {
438  // I think this is always a bad thing. It should represent calling of
439  // methods flagged as internal only being called by insecure code (not
440  // using system principal)
441  NS_WARNING("sbSecurityMixin::GetPermissionForScopedName() -- AHHH!!! Asked for internal with codebase");
442  return PR_FALSE;
443  }
444  }
445 
446  // without a codebase we're either calling internal stuff or wrong.
447  if (!codebase)
448  return allowed;
449 
450  // look up information about the scope
451  const struct Scope* scope = GetScopeForScopedName( aScopedName );
452 
453  if (scope) {
454  // if the current scope is in the table then use the values in the table
455  // to get permission
456  allowed = GetPermission( codebase, scope );
457  }
458  else if ( StringBeginsWith( aScopedName, NS_LITERAL_STRING("site:") ) ) {
459  // site library methods are always cleared
460  allowed = PR_TRUE;
461  }
462  else if ( StringBeginsWith( aScopedName, NS_LITERAL_STRING("helper:") ) ) {
463  // helper classes always allowed
464  allowed = PR_TRUE;
465  }
466  else if ( StringBeginsWith( aScopedName, NS_LITERAL_STRING("classinfo:") ) ) {
467  // class info stuff always allowed - this might need to move above the codebase check.
468  allowed = PR_TRUE;
469  }
470 
471  // if we found additional info about the scope, work out if there's a
472  // notification to fire
473  if ( scope && !disableNotificationCheck ) {
474  const char* notification =
475  allowed ? scope->allowed_notification : scope->blocked_notification;
476  LOG(( "sbSecurityMixin::GetPermissionsForScopedName() notification=%s",
477  notification ));
478 
479  if ( strcmp(notification, sNotificationAlert) == 0 ) {
480  LOG(( "sbSecurityMixin::GetPermissionsForScopedName() - ALERT" ));
481  // Launch a prompt asking the user if they want to do this action.
482 
483  allowed =
485  NS_LITERAL_STRING("rapi.media_add.request.title"),
486  NS_LITERAL_STRING("rapi.media_add.request.message"),
487  scope->name );
488 
489  }
490  else if ( strcmp(notification, sNotificationStatus) == 0 ) {
491  LOG(( "sbSecurityMixin::GetPermissionsForScopedName() - STATUS" ));
492  }
493  else if ( strcmp(notification, sNotificationHat) == 0 ) {
494  LOG(( "sbSecurityMixin::GetPermissionsForScopedName() - HAT" ));
495  // notification is not "none"
496 
497  // we want to fire a notification, but does the user want a notification?
498 
499  // get the prefs service
500  nsresult rv;
501  nsCOMPtr<nsIPrefBranch> prefService =
502  do_GetService( "@mozilla.org/preferences-service;1", &rv );
503  NS_ENSURE_SUCCESS( rv, allowed );
504 
505  PRBool notify;
506  // look up the pref
507  nsCString prefKey("songbird.rapi.");
508  prefKey.Append(scope->name);
509  prefKey.AppendLiteral("_notify");
510  rv = prefService->GetBoolPref( prefKey.get(), &notify );
511  NS_ENSURE_SUCCESS( rv, allowed );
512 
513  LOG(( "sbSecurityMixin::GetPermissionsForScopedName() pref value: %s",
514  notify?"true":"false" ));
515 
516  // if the pref is true we should notify
517  if (notify) {
518  DispatchNotificationEvent(notification, scope, allowed);
519  }
520  }
521  }
522 
523  return allowed;
524 }
525 
526 const struct Scope*
527 sbSecurityMixin::GetScopeForScopedName(const nsAString &aScopedName) {
528  for (unsigned i=0; i<NS_ARRAY_LENGTH(sScopes); i++) {
529  NS_ConvertUTF8toUTF16 prefix( sScopes[i].name );
530  prefix.AppendLiteral(":");
531  if( StringBeginsWith( aScopedName, prefix ) ) {
532  return &sScopes[i];
533  }
534  }
535  return NULL;
536 }
537 
538 PRBool
539 sbSecurityMixin::GetPermission(nsIURI *aURI, const struct Scope *aScope )
540 {
541  NS_ENSURE_TRUE( aURI, PR_FALSE );
542  NS_ENSURE_TRUE( aScope, PR_FALSE );
543  NS_ENSURE_TRUE( aScope->name, PR_FALSE );
544 
545 #ifdef PR_LOGGING
546  if (aURI) {
547  nsCAutoString spec;
548  aURI->GetSpec(spec);
549  LOG(( "sbSecurityMixin::GetPermission( %s, %s)", spec.get(), aScope->name ));
550  }
551 #endif
552 
553  nsresult rv;
554  nsCOMPtr<nsIPrefBranch> prefService =
555  do_GetService( "@mozilla.org/preferences-service;1", &rv );
556  NS_ENSURE_SUCCESS( rv, PR_FALSE );
557 
558  // build the pref key to check
559  PRBool prefBlocked = PR_TRUE;
560  nsCString prefKey("songbird.rapi.");
561  prefKey.Append(aScope->name);
562  prefKey.AppendLiteral("_disable");
563 
564  // get the pref value
565  LOG(( "sbSecurityMixin::GetPermission() - asking for pref: %s", prefKey.get() ));
566  rv = prefService->GetBoolPref( prefKey.get(), &prefBlocked );
567  NS_ENSURE_SUCCESS( rv, PR_FALSE );
568 
569  // get the permission for the domain
570  nsCString permission_name("rapi.");
571  permission_name.Append(aScope->name);
572  nsCOMPtr<nsIPermissionManager> permMgr( do_GetService( NS_PERMISSIONMANAGER_CONTRACTID, &rv ) );
573  NS_ENSURE_SUCCESS( rv, PR_FALSE );
574  PRUint32 perms = nsIPermissionManager::UNKNOWN_ACTION;
575  rv = permMgr->TestPermission( aURI, permission_name.get(), &perms );
576  NS_ENSURE_SUCCESS( rv, PR_FALSE );
577 
578  // check to see if the action is allowed for the domain
579  if (prefBlocked) {
580  LOG(( "sbSecurityMixin::GetPermission() - action is blocked" ));
581  // action is blocked, see if domain is cleared explicitly
582  if ( perms == nsIPermissionManager::ALLOW_ACTION ) {
583  LOG(("sbSecurityMixin::GetPermission - Permission GRANTED!!!"));
584  return PR_TRUE;
585  }
586  } else {
587  LOG(( "sbSecurityMixin::GetPermission() - action not blocked" ));
588  // action not blocked, make sure domain isn't blocked explicitly
589  if ( perms != nsIPermissionManager::DENY_ACTION ) {
590  LOG(("sbSecurityMixin::GetPermission - Permission GRANTED!!!"));
591  return PR_TRUE;
592  }
593  }
594 
595  // Negative Ghostrider, pattern is full.
596  LOG(("sbSecurityMixin::GetPermission - Permission DENIED (looooooser)!!!"));
597  return PR_FALSE;
598 }
599 
600 nsresult
601 sbSecurityMixin::SetPermission(nsIURI *aURI, const nsACString &aScopedName)
602 {
603  NS_ENSURE_ARG(aURI);
604  NS_ENSURE_TRUE( !aScopedName.IsEmpty(), NS_ERROR_INVALID_ARG );
605 
606  nsresult rv;
607  nsCString permission_name("rapi.");
608  permission_name.Append(aScopedName);
609  nsCOMPtr<nsIPermissionManager> permMgr =
610  do_GetService( NS_PERMISSIONMANAGER_CONTRACTID, &rv );
611  NS_ENSURE_SUCCESS( rv, rv );
612 
613  rv = permMgr->Add( aURI,
614  permission_name.BeginReading(),
615  nsIPermissionManager::ALLOW_ACTION );
616  NS_ENSURE_SUCCESS( rv, rv );
617 
618  return NS_OK;
619 }
620 
621 
622 nsresult
623 sbSecurityMixin::DispatchNotificationEvent(const char* aNotificationType,
624  const Scope* aScope,
625  PRBool aHasAccess)
626 {
627  // NOTE: This method only /tries/ to dispatch the notification event.
628  // If there's no notification document then it fails mostly silently.
629  // This is intentional since there might be cases where this mixin is
630  // used when no notification document is available.
631 
632  NS_ENSURE_ARG_POINTER(aNotificationType);
633  NS_ENSURE_ARG_POINTER(aScope);
634 
635  // TODO: we need to add the notification type to the event eventually
636  // get it? event eventually...
637 
638  LOG(( "sbSecurityMixin::DispatchNotificationEvent(%s)", aNotificationType ));
639 
640  // see if we've got a document to dispatch events to
641  if ( mNotificationDocument ) {
642  LOG(( "sbSecurityMixin::DispatchNotificationEvent - dispatching event" ));
643 
644  nsCOMPtr<sbIRemotePlayer> remotePlayer;
645  nsresult rv = mOuter->GetRemotePlayer(getter_AddRefs(remotePlayer));
646 
647  // objects that do not return a remote player do not want to trigger notifications because
648  // they are owned by other objects that supercede them in the security hierarchy.
649  if(NS_SUCCEEDED(rv)) {
650 
652  remotePlayer,
655  NS_ConvertASCIItoUTF16(aScope->name),
656  aHasAccess,
657  PR_TRUE );
658 
659  }
660 
661  } else {
662  LOG(( "sbSecurityMixin::DispatchNotificationEvent - not dispatching event" ));
663  NS_WARNING( "sbSecurityMixin::DispatchNotificationEvent didn't have a notification document to dispatch to" );
664  }
665 
666  return NS_OK;
667 }
668 
669 NS_IMETHODIMP
670 sbSecurityMixin::GetNotificationDocument(nsIDOMDocument **aNotificationDocument)
671 {
672  NS_ENSURE_ARG_POINTER(aNotificationDocument);
673 
674  NS_IF_ADDREF(*aNotificationDocument = mNotificationDocument);
675 
676  return NS_OK;
677 }
678 NS_IMETHODIMP sbSecurityMixin::SetNotificationDocument(nsIDOMDocument * aNotificationDocument)
679 {
680  NS_ENSURE_ARG_POINTER(aNotificationDocument);
681 
682  mNotificationDocument = aNotificationDocument;
683  return NS_OK;
684 }
685 
686 
687 // ---------------------------------------------------------------------------
688 //
689 // Helper Functions
690 //
691 // ---------------------------------------------------------------------------
692 
693 nsresult
694 sbSecurityMixin::CopyStrArray(PRUint32 aCount, const char **aSourceArray, nsTArray<nsCString> *aDestArray )
695 {
696  NS_ENSURE_ARG_POINTER(aSourceArray);
697  NS_ENSURE_ARG_POINTER(aDestArray);
698 
699  for ( PRUint32 index = 0; index < aCount; index++ ) {
700  if ( !aDestArray->AppendElement(aSourceArray[index]))
701  return NS_ERROR_OUT_OF_MEMORY;
702  }
703  return NS_OK;
704 }
705 
706 nsresult
707 sbSecurityMixin::CopyIIDArray(PRUint32 aCount, const nsIID **aSourceArray, nsIID ***aDestArray)
708 {
709  NS_ENSURE_ARG_POINTER(aSourceArray);
710  NS_ENSURE_ARG_POINTER(aDestArray);
711 
712  *aDestArray = 0;
713 
714  nsIID **iids = static_cast<nsIID**>( NS_Alloc( aCount * sizeof(nsIID*) ) );
715  if (!iids) {
716  return NS_ERROR_OUT_OF_MEMORY;
717  }
718 
719  for (PRUint32 index = 0; index < aCount; ++index) {
720  iids[index] = static_cast<nsIID*>( SB_CloneMemory( aSourceArray[index], sizeof(nsIID) ) );
721 
722  if (!iids[index]) {
723  for (PRUint32 alloc_index = 0; alloc_index < index; ++alloc_index)
724  NS_Free( iids[alloc_index] );
725  NS_Free(iids);
726  return NS_ERROR_OUT_OF_MEMORY;
727  }
728  }
729 
730  *aDestArray = iids;
731  return NS_OK;
732 }
733 
734 inline char* SB_CloneAllAccess()
735 {
736  return ToNewCString( NS_LITERAL_CSTRING("AllAccess") );
737 }
738 
739 NS_IMETHODIMP
740 sbSecurityMixin::GetPermissionForScopedNameWrapper( const nsAString& aRemotePermCategory,
741  PRBool *_retval )
742 {
743  // We need to prevent the notification from appearing when calling
744  *_retval = GetPermissionForScopedName( aRemotePermCategory, PR_TRUE );
745  return NS_OK;
746 }
static const char * sNotificationNone
#define SONGBIRD_SECURITYMIXIN_CLASSNAME
sbISecurityMixin SB_IMPL_CLASSINFO(sbSecurityMixin,"@songbirdnest.com/remoteapi/security-mixin;1","Songbird Remote Security Mixin", nsIProgrammingLanguage::CPLUSPLUS, 0, kSecurityMixinCID)
void * SB_CloneMemory(const void *ptr, PRSize size)
Clone a block of contiguous memory.
const char * allowed_notification
static PRBool GetUserApprovalForHost(nsIURI *aURI, const nsAString &aTitleKey, const nsAString &aMessageKey, const char *aScopedName=nsnull)
#define RAPI_EVENT_TYPE
return NS_OK
#define PERM_TYPE_PLAYBACK_CONTROL
nsTArray< nsCString > mMethods
nsTArray< nsCString > mWProperties
static const char * sNotificationStatus
#define PREF_LIBRARY_READ
#define PERM_TYPE_PLAYBACK_READ
virtual ~sbSecurityMixin()
#define SONGBIRD_SECURITYMIXIN_CONTRACTID
PRBool GetScopedName(nsTArray< nsCString > &aStringArray, const nsAString &aMethodName, nsAString &aScopedName)
#define RAPI_EVENT_CLASS
var scope
nsTArray< nsCString > mRProperties
const char * name
PRUint32 mInterfacesCount
NS_IMPL_ISUPPORTS3(sbSecurityMixin, nsIClassInfo, nsISecurityCheckedComponent, sbISecurityMixin) NS_IMPL_CI_INTERFACE_GETTER2(sbSecurityMixin
An interface for setting up nsISecurityCheckedComponent security checks.
static NS_DEFINE_CID(kSecurityMixinCID,{0xaaae98ec, 0x386e, 0x405e,{0xb1, 0x09, 0xcf, 0x1a, 0x87, 0x2e, 0xf6, 0xdd}})
TimerLoop prototype notify
static const char * sNotificationAlert
A marker interface for objects that aggregate the security mixin.
nsresult CopyIIDArray(PRUint32 aCount, const nsIID **aSourceArray, nsIID ***aDestArray)
#define PREF_PLAYBACK_READ
function Init()
#define PERM_TYPE_LIBRARY_READ
const char * blocked_notification
const struct Scope * GetScopeForScopedName(const nsAString &aScopedName)
static const Scope sScopes[]
nsresult DispatchNotificationEvent(const char *aNotificationType, const Scope *aScope, PRBool aHasAccess)
static nsresult DispatchSecurityEvent(nsIDOMDocument *aDoc, sbIRemotePlayer *aPlayer, const nsAString &aClass, const nsAString &aType, const nsAString &aCategoryID, PRBool aHasAccess, PRBool aIsTrusted)
sbISecurityAggregator * mOuter
restoreHistoryPrecursor aCount
nsCOMPtr< nsIDOMDocument > mNotificationDocument
NS_IMPL_CI_INTERFACE_GETTER2(sbDataRemoteWrapper, sbIDataRemote, nsIClassInfo) sbDataRemoteWrapper
nsISecurityCheckedComponent
#define PREF_PLAYBACK_CONTROL
nsresult CopyStrArray(PRUint32 aCount, const char **aSourceArray, nsTArray< nsCString > *aDestArray)
var secman
Definition: FeedWriter.js:1161
char * SB_CloneAllAccess()
PRBool GetPermission(nsIURI *aURI, const struct Scope *aScope)
_getSelectedPageStyle s i
#define LOG(args)
#define SONGBIRD_SECURITYMIXIN_CID
static const char * sNotificationHat
PRBool GetPermissionForScopedName(const nsAString &aScopedName, PRBool disableNotificationCheck=PR_FALSE)
static nsresult SetPermission(nsIURI *aURI, const nsACString &aScopedName)
Set the permission to allow for a scoped name.