Bug 1271345 Fix brower.download.download() on blob: urls r?kmag
Calling download() on a blob URL was failing in schema validation
since we weren't propagating the extension principal all the way
to the call to scriptSecurityManager.checkLoadURI...
MozReview-Commit-ID: JgEnQ6yxO4P
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -541,16 +541,20 @@ GlobalManager = {
let schemaApi = Management.generateAPIs(extension, context, Management.schemaApis, namespaces);
// Add in any extra API namespaces which do not have implementations
// outside of their schema file.
schemaApi.extensionTypes = {};
let schemaWrapper = {
+ get principal() {
+ return context.principal;
+ },
+
get cloneScope() {
return context.cloneScope;
},
callFunction(path, name, args) {
return findPathInObject(schemaApi, path)[name](...args);
},
--- a/toolkit/components/extensions/ext-downloads.js
+++ b/toolkit/components/extensions/ext-downloads.js
@@ -415,18 +415,23 @@ extensions.registerSchemaAPI("downloads"
function createTarget(downloadsDir) {
// TODO
// if (options.saveAs) { }
let target;
if (options.filename) {
target = OS.Path.join(downloadsDir, options.filename);
} else {
- let uri = NetUtil.newURI(options.url).QueryInterface(Ci.nsIURL);
- target = OS.Path.join(downloadsDir, uri.fileName);
+ let uri = NetUtil.newURI(options.url);
+
+ let filename;
+ if (uri instanceof Ci.nsIURL) {
+ filename = uri.fileName;
+ }
+ target = OS.Path.join(downloadsDir, filename || "download");
}
// This has a race, something else could come along and create
// the file between this test and them time the download code
// creates the target file. But we can't easily fix it without
// modifying DownloadCore so we live with it for now.
return OS.File.exists(target).then(exists => {
if (exists) {
--- a/toolkit/components/extensions/test/mochitest/test_chrome_ext_downloads_download.html
+++ b/toolkit/components/extensions/test/mochitest/test_chrome_ext_downloads_download.html
@@ -46,23 +46,39 @@ function setup() {
SimpleTest.registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.download.folderList");
Services.prefs.clearUserPref("browser.download.dir");
});
}
function backgroundScript() {
- browser.test.onMessage.addListener(function(msg) {
+ let blobUrl;
+ browser.test.onMessage.addListener((msg, ...args) => {
if (msg == "download.request") {
+ let options = args[0];
+
+ if (options.blobme) {
+ let blob = new Blob(options.blobme);
+ delete options.blobme;
+ blobUrl = options.url = window.URL.createObjectURL(blob);
+ }
+
// download() throws on bad arguments, we can remove the extra
// promise when bug 1250223 is fixed.
- return Promise.resolve().then(() => browser.downloads.download(arguments[1]))
- .then((id) => browser.test.sendMessage("download.done", {status: "success", id}))
- .catch(error => browser.test.sendMessage("download.done", {status: "error", errmsg: error.message}));
+ return Promise.resolve().then(() => browser.downloads.download(options))
+ .then(id => {
+ browser.test.sendMessage("download.done", {status: "success", id});
+ })
+ .catch(error => {
+ browser.test.sendMessage("download.done", {status: "error", errmsg: error.message});
+ });
+ } else if (msg == "killTheBlob") {
+ window.URL.revokeObjectURL(blobUrl);
+ blobUrl = null;
}
});
browser.test.sendMessage("ready");
}
// This function is a bit of a sledgehammer, it looks at every download
// the browser knows about and waits for all active downloads to complete.
@@ -195,16 +211,30 @@ add_task(function* test_downloads() {
yield download({
url: FILE_URL,
filename: OS.Path.join("foo", "..", "..", "file_download.txt"),
}).then(msg => {
is(msg.status, "error", "downloads.download() fails with back-references");
is(msg.errmsg, "filename must not contain back-references (..)", "error message for back-references is correct");
});
+ // Try to download a blob url
+ const BLOB_STRING = "Hello, world";
+ yield testDownload({
+ blobme: [BLOB_STRING],
+ filename: FILE_NAME,
+ }, FILE_NAME, BLOB_STRING.length, "blob url");
+ extension.sendMessage("killTheBlob");
+
+ // Try to download a blob url without a given filename
+ yield testDownload({
+ blobme: [BLOB_STRING],
+ }, "download", BLOB_STRING.length, "blob url with no filename");
+ extension.sendMessage("killTheBlob");
+
yield extension.unload();
});
// check for leftover files in the download directory
add_task(function* () {
let entries = downloadDir.directoryEntries;
while (entries.hasMoreElements()) {
let entry = entries.getNext().QueryInterface(Ci.nsIFile);