Bug 1161831 - Associate extension URIs with the appropriate addon ID. r=billm,sr=bz
authorBobby Holley <bobbyholley@gmail.com>
Mon, 20 Jul 2015 14:46:58 -0700
changeset 280066 689fd01b7b3ce084c1372cfd55869479dc128dbb
parent 280065 8843374b8ac7c8c823c3fad5e44a3295f02b6e20
child 280067 a37164c4c1bbec3a11efb47e5a4f92034c8843d5
push id3697
push userusarracini@mozilla.com
push dateWed, 22 Jul 2015 14:58:08 +0000
reviewersbillm, bz
bugs1161831
milestone42.0a1
Bug 1161831 - Associate extension URIs with the appropriate addon ID. r=billm,sr=bz
caps/nsIAddonPolicyService.idl
caps/nsScriptSecurityManager.cpp
caps/nsScriptSecurityManager.h
toolkit/components/utils/simpleServices.js
--- a/caps/nsIAddonPolicyService.idl
+++ b/caps/nsIAddonPolicyService.idl
@@ -6,22 +6,27 @@
 
 #include "nsISupports.idl"
 #include "nsIURI.idl"
 
 /**
  * This interface allows the security manager to query custom per-addon security
  * policy.
  */
-[scriptable,uuid(3ec203f8-2bd0-4f4c-8f99-f9f056221231)]
+[scriptable,uuid(8a034ef9-9d14-4c5d-8319-06c1ab574baa)]
 interface nsIAddonPolicyService : nsISupports
 {
   /**
    * Returns true if unprivileged code associated with the given addon may load
    * data from |aURI|.
    */
   boolean addonMayLoadURI(in AString aAddonId, in nsIURI aURI);
 
   /**
    * Returns true if a given extension:// URI is web-accessible.
    */
   boolean extensionURILoadableByAnyone(in nsIURI aURI);
+
+  /**
+   * Maps an extension URI to the ID of the addon it belongs to.
+   */
+  AString extensionURIToAddonId(in nsIURI aURI);
 };
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -355,16 +355,30 @@ nsScriptSecurityManager::GetChannelResul
                 triggeringPrincipal.forget(aPrincipal);
                 return NS_OK;
             }
         }
     }
     return GetChannelURIPrincipal(aChannel, aPrincipal);
 }
 
+nsresult
+nsScriptSecurityManager::MaybeSetAddonIdFromURI(OriginAttributes& aAttrs, nsIURI* aURI)
+{
+  nsAutoCString scheme;
+  nsresult rv = aURI->GetScheme(scheme);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (scheme.EqualsLiteral("moz-extension") && GetAddonPolicyService()) {
+    rv = GetAddonPolicyService()->ExtensionURIToAddonId(aURI, aAttrs.mAddonId);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return NS_OK;
+}
+
 /* The principal of the URI that this channel is loading. This is never
  * affected by things like sandboxed loads, or loads where we forcefully
  * inherit the principal.  Think of this as the principal of the server
  * which this channel is loading from.  Most callers should use
  * GetChannelResultPrincipal instead of GetChannelURIPrincipal.  Only
  * call GetChannelURIPrincipal if you are sure that you want the
  * principal that matches the uri, even in cases when the load is
  * sandboxed or when the load could be a blob or data uri (i.e even when
@@ -386,16 +400,18 @@ nsScriptSecurityManager::GetChannelURIPr
     nsCOMPtr<nsILoadContext> loadContext;
     NS_QueryNotificationCallbacks(aChannel, loadContext);
 
     if (loadContext) {
         return GetLoadContextCodebasePrincipal(uri, loadContext, aPrincipal);
     }
 
     OriginAttributes attrs(UNKNOWN_APP_ID, false);
+    rv = MaybeSetAddonIdFromURI(attrs, uri);
+    NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
     prin.forget(aPrincipal);
     return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal* aPrincipal,
                                            bool* aIsSystem)
@@ -1092,28 +1108,32 @@ nsScriptSecurityManager::
   GetLoadContextCodebasePrincipal(nsIURI* aURI,
                                   nsILoadContext* aLoadContext,
                                   nsIPrincipal** aPrincipal)
 {
   // XXXbholley - Make this more general in bug 1165466.
   OriginAttributes attrs;
   aLoadContext->GetAppId(&attrs.mAppId);
   aLoadContext->GetIsInBrowserElement(&attrs.mInBrowser);
+  nsresult rv = MaybeSetAddonIdFromURI(attrs, aURI);
+  NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
   prin.forget(aPrincipal);
   return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::GetDocShellCodebasePrincipal(nsIURI* aURI,
                                                       nsIDocShell* aDocShell,
                                                       nsIPrincipal** aPrincipal)
 {
   // XXXbholley - Make this more general in bug 1165466.
   OriginAttributes attrs(aDocShell->GetAppId(), aDocShell->GetIsInBrowserElement());
+  nsresult rv = MaybeSetAddonIdFromURI(attrs, aURI);
+  NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
   prin.forget(aPrincipal);
   return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
 }
 
 // static
 nsIPrincipal*
 nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj)
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -115,16 +115,19 @@ private:
     InitPrefs();
 
     inline void
     ScriptSecurityPrefChanged();
 
     inline void
     AddSitesToFileURIWhitelist(const nsCString& aSiteList);
 
+    // If aURI is a moz-extension:// URI, set mAddonId to the associated addon.
+    nsresult MaybeSetAddonIdFromURI(mozilla::OriginAttributes& aAttrs, nsIURI* aURI);
+
     nsCOMPtr<nsIPrincipal> mSystemPrincipal;
     bool mPrefInitialized;
     bool mIsJavaScriptEnabled;
     nsTArray<nsCOMPtr<nsIURI>> mFileURIWhitelist;
 
     // This machinery controls new-style domain policies. The old-style
     // policy machinery will be removed soon.
     nsCOMPtr<nsIDomainPolicy> mDomainPolicy;
--- a/toolkit/components/utils/simpleServices.js
+++ b/toolkit/components/utils/simpleServices.js
@@ -77,16 +77,33 @@ AddonPolicyService.prototype = {
       throw new TypeError("non-extension URI passed");
     }
 
     let cb = this.extensionURILoadCallback;
     return cb ? cb(aURI) : false;
   },
 
   /*
+   * Maps an extension URI to an addon ID.
+   *
+   * @see nsIAddonPolicyService.extensionURIToAddonId
+   */
+  extensionURIToAddonId(aURI) {
+    if (aURI.scheme != "moz-extension") {
+      throw new TypeError("non-extension URI passed");
+    }
+
+    let cb = this.extensionURIToAddonIdCallback;
+    if (!cb) {
+      throw new Error("no callback set to map extension URIs to addon Ids");
+    }
+    return cb(aURI);
+  },
+
+  /*
    * Sets the callbacks used in addonMayLoadURI above. Not accessible over
    * XPCOM - callers should use .wrappedJSObject on the service to call it
    * directly.
    */
   setAddonLoadURICallback(aAddonId, aCallback) {
     this.mayLoadURICallbacks[aAddonId] = aCallback;
   },
 
@@ -94,12 +111,23 @@ AddonPolicyService.prototype = {
    * Sets the callback used in extensionURILoadableByAnyone above. Not
    * accessible over XPCOM - callers should use .wrappedJSObject on the
    * service to call it directly.
    */
   setExtensionURILoadCallback(aCallback) {
     var old = this.extensionURILoadCallback;
     this.extensionURILoadCallback = aCallback;
     return old;
+  },
+
+  /*
+   * Sets the callback used in extensionURIToAddonId above. Not accessible over
+   * XPCOM - callers should use .wrappedJSObject on the service to call it
+   * directly.
+   */
+  setExtensionURIToAddonIdCallback(aCallback) {
+    var old = this.extensionURIToAddonIdCallback;
+    this.extensionURIToAddonIdCallback = aCallback;
+    return old;
   }
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RemoteTagServiceService, AddonPolicyService]);