bug 1245606 - Implement chrome.downloads.getFileInfo r=kmag

MozReview-Commit-ID: 6dfpctduYtp

--HG--
extra : transplant_source : %F4%B1%1AD%92%A7%B0.%26%83%AB%D8%D5%11%A0%A4%24%A7%82T
This commit is contained in:
Mark Striemer 2016-04-15 16:08:16 -05:00
Родитель 6b09877efc
Коммит e34df7b9a1
3 изменённых файлов: 128 добавлений и 1 удалений

Просмотреть файл

@ -593,6 +593,67 @@ extensions.registerSchemaAPI("downloads", "downloads", (extension, context) => {
}); });
}, },
getFileIcon(downloadId, options) {
return DownloadMap.lazyInit().then(() => {
let size = options && options.size ? options.size : 32;
let download = DownloadMap.fromId(downloadId).download;
let pathPrefix = "";
let path;
if (download.succeeded) {
let file = FileUtils.File(download.target.path);
path = Services.io.newFileURI(file).spec;
} else {
path = OS.Path.basename(download.target.path);
pathPrefix = "//";
}
return new Promise((resolve, reject) => {
let chromeWebNav = Services.appShell.createWindowlessBrowser(true);
chromeWebNav
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.createAboutBlankContentViewer(Services.scriptSecurityManager.getSystemPrincipal());
let img = chromeWebNav.document.createElement("img");
img.width = size;
img.height = size;
let handleLoad;
let handleError;
const cleanup = () => {
img.removeEventListener("load", handleLoad);
img.removeEventListener("error", handleError);
chromeWebNav.close();
chromeWebNav = null;
};
handleLoad = () => {
let canvas = chromeWebNav.document.createElement("canvas");
canvas.width = size;
canvas.height = size;
let context = canvas.getContext("2d");
context.drawImage(img, 0, 0, size, size);
let dataURL = canvas.toDataURL("image/png");
cleanup();
resolve(dataURL);
};
handleError = (error) => {
Cu.reportError(error);
cleanup();
reject(new Error("An unexpected error occurred"));
};
img.addEventListener("load", handleLoad);
img.addEventListener("error", handleError);
img.src = `moz-icon:${pathPrefix}${path}?size=${size}`;
});
}).catch((error) => {
return Promise.reject({message: error.message});
});
},
// When we do setShelfEnabled(), check for additional "downloads.shelf" permission. // When we do setShelfEnabled(), check for additional "downloads.shelf" permission.
// i.e.: // i.e.:
// setShelfEnabled(enabled) { // setShelfEnabled(enabled) {

Просмотреть файл

@ -520,7 +520,7 @@
{ {
"name": "getFileIcon", "name": "getFileIcon",
"type": "function", "type": "function",
"unsupported": true, "async": "callback",
"description": "Retrieve an icon for the specified download. For new downloads, file icons are available after the <a href='#event-onCreated'>onCreated</a> event has been received. The image returned by this function while a download is in progress may be different from the image returned after the download is complete. Icon retrieval is done by querying the underlying operating system or toolkit depending on the platform. The icon that is returned will therefore depend on a number of factors including state of the download, platform, registered file types and visual theme. If a file icon cannot be determined, <a href='extension.html#property-lastError'>chrome.extension.lastError</a> will contain an error message.", "description": "Retrieve an icon for the specified download. For new downloads, file icons are available after the <a href='#event-onCreated'>onCreated</a> event has been received. The image returned by this function while a download is in progress may be different from the image returned after the download is complete. Icon retrieval is done by querying the underlying operating system or toolkit depending on the platform. The icon that is returned will therefore depend on a number of factors including state of the download, platform, registered file types and visual theme. If a file icon cannot be determined, <a href='extension.html#property-lastError'>chrome.extension.lastError</a> will contain an error message.",
"parameters": [ "parameters": [
{ {
@ -535,6 +535,8 @@
"size": { "size": {
"description": "The size of the icon. The returned icon will be square with dimensions size * size pixels. The default size for the icon is 32x32 pixels.", "description": "The size of the icon. The returned icon will be square with dimensions size * size pixels. The default size for the icon is 32x32 pixels.",
"optional": true, "optional": true,
"minimum": 1,
"maximum": 127,
"type": "integer" "type": "integer"
} }
}, },

Просмотреть файл

@ -742,6 +742,70 @@ add_task(function* test_erase() {
is(msg.result.length, 0, "search found 0 downloads"); is(msg.result.length, 0, "search found 0 downloads");
}); });
function loadImage(img, data) {
return new Promise((resolve) => {
let handle = () => {
img.removeEventListener("load", handle);
resolve();
};
img.addEventListener("load", handle);
img.src = data;
});
}
add_task(function* test_getFileIcon() {
let img = document.createElement("img");
let msg = yield runInExtension("download", {url: TXT_URL});
is(msg.status, "success", "download() succeeded");
const id = msg.result;
msg = yield runInExtension("getFileIcon", id);
is(msg.status, "success", "getFileIcon() succeeded");
yield loadImage(img, msg.result);
is(img.height, 32, "returns an icon with the right height");
is(img.width, 32, "returns an icon with the right width");
msg = yield runInExtension("waitForEvents", [
{type: "onCreated", data: {id, url: TXT_URL}},
{type: "onChanged"},
]);
is(msg.status, "success", "got events");
msg = yield runInExtension("getFileIcon", id);
is(msg.status, "success", "getFileIcon() succeeded");
yield loadImage(img, msg.result);
is(img.height, 32, "returns an icon with the right height after download");
is(img.width, 32, "returns an icon with the right width after download");
msg = yield runInExtension("getFileIcon", id + 100);
is(msg.status, "error", "getFileIcon() failed");
ok(msg.errmsg.includes("Invalid download id"), "download id is invalid");
msg = yield runInExtension("getFileIcon", id, {size: 127});
is(msg.status, "success", "getFileIcon() succeeded");
yield loadImage(img, msg.result);
is(img.height, 127, "returns an icon with the right custom height");
is(img.width, 127, "returns an icon with the right custom width");
msg = yield runInExtension("getFileIcon", id, {size: 1});
is(msg.status, "success", "getFileIcon() succeeded");
yield loadImage(img, msg.result);
is(img.height, 1, "returns an icon with the right custom height");
is(img.width, 1, "returns an icon with the right custom width");
msg = yield runInExtension("getFileIcon", id, {size: "foo"});
is(msg.status, "error", "getFileIcon() fails");
ok(msg.errmsg.includes("Error processing size"), "size is not a number");
msg = yield runInExtension("getFileIcon", id, {size: 0});
is(msg.status, "error", "getFileIcon() fails");
ok(msg.errmsg.includes("Error processing size"), "size is too small");
msg = yield runInExtension("getFileIcon", id, {size: 128});
is(msg.status, "error", "getFileIcon() fails");
ok(msg.errmsg.includes("Error processing size"), "size is too big");
});
add_task(function* cleanup() { add_task(function* cleanup() {
yield extension.unload(); yield extension.unload();
}); });