Bug 1221148 - Allow passing blob:// URIs to mozIJSSubScriptLoader; r=smaug draft
authorAlex Gaynor <agaynor@mozilla.com>
Wed, 07 Jun 2017 11:00:24 -0400
changeset 596598 56dfe91ac9fbeb0bd48dc8a2f87ed6038e7521cc
parent 596561 d39cd452b52bf82fa4a717172a62d62ab9e5366f
child 634006 124cfea1b0286d1566b874ef291f616b826d727b
push id64690
push userbmo:agaynor@mozilla.com
push dateMon, 19 Jun 2017 14:10:45 +0000
reviewerssmaug
bugs1221148
milestone56.0a1
Bug 1221148 - Allow passing blob:// URIs to mozIJSSubScriptLoader; r=smaug This is useful for legacy addons as we increasingly lockdown filesystem access in content processes. MozReview-Commit-ID: AZbsSFpbIvt
js/xpconnect/idl/mozIJSSubScriptLoader.idl
js/xpconnect/loader/mozJSSubScriptLoader.cpp
js/xpconnect/tests/chrome/test_chrometoSource.xul
--- a/js/xpconnect/idl/mozIJSSubScriptLoader.idl
+++ b/js/xpconnect/idl/mozIJSSubScriptLoader.idl
@@ -13,33 +13,33 @@ interface nsIObserver;
 [scriptable, uuid(19533e7b-f321-4ef1-bc59-6e812dc2a733)]
 interface mozIJSSubScriptLoader : nsISupports
 {
     /**
      * This method should only be called from JS!
      * In JS, the signature looks like:
      * rv loadSubScript (url [, obj] [, charset]);
      * @param url the url of the sub-script, it MUST be either a file:,
-     *            resource:, or chrome: url, and MUST be local.
+     *            resource:, blob:, or chrome: url, and MUST be local.
      * @param obj an optional object to evaluate the script onto, it
      *            defaults to the global object of the caller.
      * @param charset optionally specifies the character encoding of
      *                the file. If absent, the file is interpreted
      *                as ASCII.
      * @retval rv the value returned by the sub-script
      */
     [implicit_jscontext]
     jsval loadSubScript(in AString url, [optional] in jsval obj, [optional] in AString charset);
 
     /**
      * This method should only be called from JS!
      * In JS, the signature looks like:
      * rv = loadSubScript (url, optionsObject)
      * @param url the url of the sub-script, it MUST be either a file:,
-     *            resource:, or chrome: url, and MUST be local.
+     *            resource:, blob:, or chrome: url, and MUST be local.
      * @param optionsObject an object with parameters. Valid parameters are:
      *                      - charset: specifying the character encoding of the file (default: ASCII)
      *                      - target:  an object to evaluate onto (default: global object of the caller)
      *                      - ignoreCache: if set to true, will bypass the cache for reading the file.
      *                      - async: if set to true, the script will be loaded
      *                        asynchronously, and a Promise is returned which
      *                        resolves to its result when execution is complete.
      *                      - wantReturnValue: If true, the script will return
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -615,20 +615,16 @@ mozJSSubScriptLoader::DoLoadSubScriptWit
     JS::AutoFilename filename;
     if (!JS::DescribeScriptedCaller(cx, &filename)) {
         // No scripted frame means we don't know who's calling, bail.
         return NS_ERROR_FAILURE;
     }
 
     JSAutoCompartment ac(cx, targetObj);
 
-    // Suppress caching if we're compiling as content.
-    bool ignoreCache = options.ignoreCache || principal != mSystemPrincipal;
-    StartupCache* cache = ignoreCache ? nullptr : StartupCache::GetSingleton();
-
     nsCOMPtr<nsIIOService> serv = do_GetService(NS_IOSERVICE_CONTRACTID);
     if (!serv) {
         ReportError(cx, NS_LITERAL_CSTRING(LOAD_ERROR_NOSERVICE));
         return NS_OK;
     }
 
     const nsCString& asciiUrl = NS_LossyConvertUTF16toASCII(url);
     PROFILER_LABEL_DYNAMIC("mozJSSubScriptLoader", "LoadSubScript",
@@ -650,17 +646,18 @@ mozJSSubScriptLoader::DoLoadSubScriptWit
     }
 
     rv = uri->GetScheme(scheme);
     if (NS_FAILED(rv)) {
         ReportError(cx, LOAD_ERROR_NOSCHEME, uri);
         return NS_OK;
     }
 
-    if (!scheme.EqualsLiteral("chrome") && !scheme.EqualsLiteral("app")) {
+    if (!scheme.EqualsLiteral("chrome") && !scheme.EqualsLiteral("app") &&
+        !scheme.EqualsLiteral("blob")) {
         // This might be a URI to a local file, though!
         nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(uri);
         nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(innerURI);
         if (!fileURL) {
             ReportError(cx, LOAD_ERROR_URI_NOT_LOCAL, uri);
             return NS_OK;
         }
 
@@ -668,16 +665,22 @@ mozJSSubScriptLoader::DoLoadSubScriptWit
         // calling script, and " -> ". See bug 418356.
         nsAutoCString tmp(filename.get());
         tmp.AppendLiteral(" -> ");
         tmp.Append(uriStr);
 
         uriStr = tmp;
     }
 
+    // Suppress caching if we're compiling as content or if we're loading a
+    // blob: URI.
+    bool ignoreCache = options.ignoreCache || principal != mSystemPrincipal ||
+                       scheme.EqualsLiteral("blob");
+    StartupCache* cache = ignoreCache ? nullptr : StartupCache::GetSingleton();
+
     JSVersion version = JS_GetVersion(cx);
     nsAutoCString cachePath;
     cachePath.AppendPrintf("jssubloader/%d", version);
     PathifyURI(uri, cachePath);
 
     RootedScript script(cx);
     if (!options.ignoreCache) {
         if (!options.wantReturnValue)
--- a/js/xpconnect/tests/chrome/test_chrometoSource.xul
+++ b/js/xpconnect/tests/chrome/test_chrometoSource.xul
@@ -53,10 +53,18 @@ Services.scriptloader.loadSubScript(reso
 src = ns.f.toSource();
 isnot(src.indexOf("return 42;"), -1, "encoded subscript should have correct source");
 
 ns = {};
 Services.scriptloader.loadSubScriptWithOptions(resolvedBase + "utf8_subscript.js",
                                                {target: ns, charset: "UTF-8", ignoreCache: true});
 src = ns.f.toSource();
 isnot(src.indexOf("return 42;"), -1, "encoded subscript should have correct source");
+
+ns = {};
+let b = new Blob([
+  "var Exported = 17;"
+]);
+var blobUrl = URL.createObjectURL(b);
+Services.scriptloader.loadSubScript(blobUrl, ns);
+is(ns.Exported, 17, "subscript from a blob URL should work");
   ]]></script>
 </window>