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
--- 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>