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 287323 689fd01b7b3ce084c1372cfd55869479dc128dbb
parent 287322 8843374b8ac7c8c823c3fad5e44a3295f02b6e20
child 287324 a37164c4c1bbec3a11efb47e5a4f92034c8843d5
push id934
push userraliiev@mozilla.com
push dateMon, 26 Oct 2015 12:58:05 +0000
treeherdermozilla-release@05704e35c1d0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm, bz
bugs1161831
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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]);