зеркало из https://github.com/mozilla/gecko-dev.git
Bug 361923 - Can't use remote search engine icons larger than 10KB. r=florian
MozReview-Commit-ID: D0lmhAwabb3 --HG-- extra : rebase_source : 403b76132df74af3aeddc1ad4a00d85ea03d929f
This commit is contained in:
Родитель
708f0175c1
Коммит
0296cb4328
|
@ -31,6 +31,13 @@ XPCOMUtils.defineLazyServiceGetters(this, {
|
|||
gChromeReg: ["@mozilla.org/chrome/chrome-registry;1", "nsIChromeRegistry"],
|
||||
});
|
||||
|
||||
const ArrayBufferInputStream = Components.Constructor(
|
||||
"@mozilla.org/io/arraybuffer-input-stream;1",
|
||||
"nsIArrayBufferInputStream", "setData");
|
||||
const BinaryInputStream = Components.Constructor(
|
||||
"@mozilla.org/binaryinputstream;1",
|
||||
"nsIBinaryInputStream", "setInputStream");
|
||||
|
||||
Cu.importGlobalProperties(["XMLHttpRequest"]);
|
||||
|
||||
// A text encoder to UTF8, used whenever we commit the cache to disk.
|
||||
|
@ -98,7 +105,7 @@ const NEW_LINES = /(\r\n|\r|\n)/;
|
|||
|
||||
// Set an arbitrary cap on the maximum icon size. Without this, large icons can
|
||||
// cause big delays when loading them at startup.
|
||||
const MAX_ICON_SIZE = 10000;
|
||||
const MAX_ICON_SIZE = 20000;
|
||||
|
||||
// Default charset to use for sending search parameters. ISO-8859-1 is used to
|
||||
// match previous nsInternetSearchService behavior as a URL parameter. Label
|
||||
|
@ -306,11 +313,11 @@ loadListener.prototype = {
|
|||
if (requestFailed || this._countRead == 0) {
|
||||
LOG("loadListener: request failed!");
|
||||
// send null so the callback can deal with the failure
|
||||
this._callback(null, this._engine);
|
||||
} else
|
||||
this._callback(this._bytes, this._engine);
|
||||
this._bytes = null;
|
||||
}
|
||||
this._callback(this._bytes, this._engine);
|
||||
this._channel = null;
|
||||
this._engine = null;
|
||||
this._engine = null;
|
||||
},
|
||||
|
||||
// nsIStreamListener
|
||||
|
@ -341,6 +348,29 @@ loadListener.prototype = {
|
|||
onStatus(aRequest, aContext, aStatus, aStatusArg) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tries to rescale an icon to a given size.
|
||||
*
|
||||
* @param aByteArray Byte array containing the icon payload.
|
||||
* @param aContentType Mime type of the payload.
|
||||
* @param [optional] aSize desired icon size.
|
||||
* @throws if the icon cannot be rescaled or the rescaled icon is too big.
|
||||
*/
|
||||
function rescaleIcon(aByteArray, aContentType, aSize = 32) {
|
||||
if (aContentType == "image/svg+xml")
|
||||
throw new Error("Cannot rescale SVG image");
|
||||
let buffer = Uint8Array.from(aByteArray).buffer;
|
||||
let imgTools = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools);
|
||||
let input = new ArrayBufferInputStream(buffer, 0, buffer.byteLength);
|
||||
let container = imgTools.decodeImage(input, aContentType);
|
||||
let stream = imgTools.encodeScaledImage(container, "image/png", aSize, aSize);
|
||||
let size = stream.available();
|
||||
if (size > MAX_ICON_SIZE)
|
||||
throw new Error("Icon is too big");
|
||||
let bis = new BinaryInputStream(stream);
|
||||
return [bis.readByteArray(size), "image/png"];
|
||||
}
|
||||
|
||||
function isPartnerBuild() {
|
||||
try {
|
||||
let distroID = Services.prefs.getCharPref("distribution.id");
|
||||
|
@ -1740,15 +1770,26 @@ Engine.prototype = {
|
|||
if (aEngine._hasPreferredIcon && !aIsPreferred)
|
||||
return;
|
||||
|
||||
if (!aByteArray || aByteArray.length > MAX_ICON_SIZE) {
|
||||
LOG("iconLoadCallback: load failed, or the icon was too large!");
|
||||
if (!aByteArray) {
|
||||
LOG("iconLoadCallback: load failed");
|
||||
return;
|
||||
}
|
||||
|
||||
let type = chan.contentType;
|
||||
if (!type.startsWith("image/"))
|
||||
type = "image/x-icon";
|
||||
let dataURL = "data:" + type + ";base64," +
|
||||
let contentType = chan.contentType;
|
||||
if (aByteArray.length > MAX_ICON_SIZE) {
|
||||
try {
|
||||
LOG("iconLoadCallback: rescaling icon");
|
||||
[aByteArray, contentType] = rescaleIcon(aByteArray, contentType);
|
||||
} catch (ex) {
|
||||
LOG("iconLoadCallback: got exception: " + ex);
|
||||
Cu.reportError("Unable to set an icon for the search engine because: " + ex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!contentType.startsWith("image/"))
|
||||
contentType = "image/x-icon";
|
||||
let dataURL = "data:" + contentType + ";base64," +
|
||||
btoa(String.fromCharCode.apply(null, aByteArray));
|
||||
|
||||
aEngine._iconURI = makeURI(dataURL);
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 55 KiB |
|
@ -10,6 +10,8 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://testing-common/AppInfo.jsm");
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TestUtils",
|
||||
"resource://testing-common/TestUtils.jsm");
|
||||
|
||||
const BROWSER_SEARCH_PREF = "browser.search.";
|
||||
const NS_APP_SEARCH_DIR = "SrchPlugns";
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function test_big_icon() {
|
||||
let srv = useHttpServer();
|
||||
srv.registerContentType("ico", "image/x-icon");
|
||||
await asyncInit();
|
||||
|
||||
let promiseChanged = TestUtils.topicObserved("browser-search-engine-modified",
|
||||
(engine, verb) => verb == "engine-changed" && engine.name == "BigIcon" && engine.iconURI);
|
||||
|
||||
let iconUrl = gDataUrl + "big_icon.ico";
|
||||
await addTestEngines([
|
||||
{ name: "BigIcon",
|
||||
details: [iconUrl, "", "Big icon", "GET",
|
||||
"http://test_big_icon/search?q={searchTerms}"] },
|
||||
]);
|
||||
|
||||
await promiseAfterCache();
|
||||
|
||||
let [engine] = await promiseChanged;
|
||||
Assert.ok(engine.iconURI.spec.startsWith("data:image/png"),
|
||||
"The icon is saved as a PNG data url");
|
||||
});
|
|
@ -3,6 +3,7 @@ head = head_search.js
|
|||
firefox-appdir = browser
|
||||
skip-if = toolkit == 'android'
|
||||
support-files =
|
||||
data/big_icon.ico
|
||||
data/chrome.manifest
|
||||
data/engine.xml
|
||||
data/engine2.xml
|
||||
|
@ -32,6 +33,7 @@ support-files =
|
|||
|
||||
[test_nocache.js]
|
||||
[test_645970.js]
|
||||
[test_big_icon.js]
|
||||
[test_bug930456.js]
|
||||
[test_bug930456_child.js]
|
||||
[test_engine_set_alias.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче