Backed out changeset b11aa832c41a (bug 1453751) for Mochitest-15 failures in toolkit/components/extensions/test/mochitest/test_ext_webrequest_filter.html. CLOSED TREE

--HG--
rename : browser/base/content/test/favicons/browser_bug408415.js => browser/base/content/test/general/browser_bug408415.js
rename : browser/base/content/test/favicons/browser_bug550565.js => browser/base/content/test/general/browser_bug550565.js
rename : browser/base/content/test/favicons/browser_favicon_change.js => browser/base/content/test/general/browser_favicon_change.js
rename : browser/base/content/test/favicons/browser_favicon_change_not_in_document.js => browser/base/content/test/general/browser_favicon_change_not_in_document.js
rename : browser/base/content/test/favicons/browser_subframe_favicons_not_used.js => browser/base/content/test/general/browser_subframe_favicons_not_used.js
rename : browser/base/content/test/favicons/file_generic_favicon.ico => browser/base/content/test/general/file_bug970276_favicon1.ico
rename : browser/base/content/test/favicons/file_bug970276_popup1.html => browser/base/content/test/general/file_bug970276_popup1.html
rename : browser/base/content/test/favicons/file_bug970276_popup2.html => browser/base/content/test/general/file_bug970276_popup2.html
rename : browser/base/content/test/favicons/file_favicon_change.html => browser/base/content/test/general/file_favicon_change.html
rename : browser/base/content/test/favicons/file_favicon_change_not_in_document.html => browser/base/content/test/general/file_favicon_change_not_in_document.html
rename : browser/base/content/test/favicons/file_with_favicon.html => browser/base/content/test/general/file_with_favicon.html
This commit is contained in:
Brindusan Cristian 2018-06-28 23:15:49 +03:00
Родитель 12da58dd0d
Коммит 51f77cdfc4
57 изменённых файлов: 825 добавлений и 947 удалений

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

@ -268,6 +268,7 @@ pref("browser.aboutHomeSnippets.updateUrl", "https://snippets.cdn.mozilla.net/%S
pref("browser.enable_automatic_image_resizing", true);
pref("browser.chrome.site_icons", true);
pref("browser.chrome.favicons", true);
// browser.warnOnQuit == false will override all other possible prompts when quitting or restarting
pref("browser.warnOnQuit", true);
pref("browser.fullscreen.autohide", true);

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

@ -3740,8 +3740,8 @@ const DOMEventHandler = {
break;
case "Link:SetIcon":
this.setIconFromLink(aMsg.target, aMsg.data.originalURL, aMsg.data.canUseForTab,
aMsg.data.expiration, aMsg.data.iconURL);
this.setIcon(aMsg.target, aMsg.data.url, aMsg.data.loadingPrincipal,
aMsg.data.requestContextID, aMsg.data.canUseForTab);
break;
case "Link:AddSearch":
@ -3760,20 +3760,21 @@ const DOMEventHandler = {
return true;
},
setIconFromLink(aBrowser, aOriginalURL, aCanUseForTab, aExpiration, aIconURL) {
setIcon(aBrowser, aURL, aLoadingPrincipal, aRequestContextID = 0, aCanUseForTab = true) {
if (gBrowser.isFailedIcon(aURL))
return false;
let tab = gBrowser.getTabForBrowser(aBrowser);
if (!tab)
return false;
try {
PlacesUIUtils.loadFavicon(aBrowser, Services.scriptSecurityManager.getSystemPrincipal(),
makeURI(aOriginalURL), aExpiration, makeURI(aIconURL));
} catch (ex) {
Cu.reportError(ex);
let loadingPrincipal = aLoadingPrincipal ||
Services.scriptSecurityManager.getSystemPrincipal();
if (aURL) {
gBrowser.storeIcon(aBrowser, aURL, loadingPrincipal, aRequestContextID);
}
if (aCanUseForTab) {
gBrowser.setIcon(tab, aIconURL, aOriginalURL);
gBrowser.setIcon(tab, aURL, loadingPrincipal, aRequestContextID);
}
return true;
},

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

@ -315,7 +315,7 @@ var ClickEventHandler = {
};
ClickEventHandler.init();
new ContentLinkHandler(this);
ContentLinkHandler.init(this);
ContentMetaHandler.init(this);
var PluginContentStub = {

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

@ -762,38 +762,43 @@ window._gBrowser = {
}
},
setIcon(aTab, aIconURL = "", aOriginalURL = aIconURL) {
let makeString = (url) => url instanceof Ci.nsIURI ? url.spec : url;
aIconURL = makeString(aIconURL);
aOriginalURL = makeString(aOriginalURL);
let LOCAL_PROTOCOLS = [
"chrome:",
"about:",
"resource:",
"data:",
];
if (aIconURL && !LOCAL_PROTOCOLS.some(protocol => aIconURL.startsWith(protocol))) {
console.error(`Attempt to set a remote URL ${aIconURL} as a tab icon.`);
return;
storeIcon(aBrowser, aURI, aLoadingPrincipal, aRequestContextID) {
try {
if (!(aURI instanceof Ci.nsIURI)) {
aURI = makeURI(aURI);
}
PlacesUIUtils.loadFavicon(aBrowser, aLoadingPrincipal, aURI, aRequestContextID);
} catch (ex) {
Cu.reportError(ex);
}
},
setIcon(aTab, aURI, aLoadingPrincipal, aRequestContextID) {
let browser = this.getBrowserForTab(aTab);
browser.mIconURL = aIconURL;
if (aIconURL != aTab.getAttribute("image")) {
if (aIconURL) {
aTab.setAttribute("image", aIconURL);
browser.mIconURL = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
let loadingPrincipal = aLoadingPrincipal ||
Services.scriptSecurityManager.getSystemPrincipal();
let requestContextID = aRequestContextID || 0;
let sizedIconUrl = browser.mIconURL || "";
if (sizedIconUrl != aTab.getAttribute("image")) {
if (sizedIconUrl) {
if (!browser.mIconLoadingPrincipal ||
!browser.mIconLoadingPrincipal.equals(loadingPrincipal)) {
aTab.setAttribute("iconloadingprincipal",
this.serializationHelper.serializeToString(loadingPrincipal));
aTab.setAttribute("requestcontextid", requestContextID);
browser.mIconLoadingPrincipal = loadingPrincipal;
}
aTab.setAttribute("image", sizedIconUrl);
} else {
aTab.removeAttribute("iconloadingprincipal");
delete browser.mIconLoadingPrincipal;
aTab.removeAttribute("image");
}
this._tabAttrModified(aTab, ["image"]);
}
// The aOriginalURL argument is currently only used by tests.
this._callProgressListeners(browser, "onLinkIconAvailable", [aIconURL, aOriginalURL]);
this._callProgressListeners(browser, "onLinkIconAvailable", [browser.mIconURL]);
},
getIcon(aTab) {
@ -808,6 +813,51 @@ window._gBrowser = {
}
},
shouldLoadFavIcon(aURI) {
return (aURI &&
Services.prefs.getBoolPref("browser.chrome.site_icons") &&
Services.prefs.getBoolPref("browser.chrome.favicons") &&
("schemeIs" in aURI) && (aURI.schemeIs("http") || aURI.schemeIs("https")));
},
useDefaultIcon(aTab) {
let browser = this.getBrowserForTab(aTab);
let documentURI = browser.documentURI;
let requestContextID = browser.contentRequestContextID;
let loadingPrincipal = browser.contentPrincipal;
let icon = null;
if (browser.imageDocument) {
if (Services.prefs.getBoolPref("browser.chrome.site_icons")) {
let sz = Services.prefs.getIntPref("browser.chrome.image_icons.max_size");
if (browser.imageDocument.width <= sz &&
browser.imageDocument.height <= sz) {
// Don't try to store the icon in Places, regardless it would
// be skipped (see Bug 403651).
icon = browser.currentURI;
}
}
}
// Use documentURIObject in the check for shouldLoadFavIcon so that we
// do the right thing with about:-style error pages. Bug 453442
if (!icon && this.shouldLoadFavIcon(documentURI)) {
let url = documentURI.prePath + "/favicon.ico";
if (!this.isFailedIcon(url)) {
icon = url;
this.storeIcon(browser, icon, loadingPrincipal, requestContextID);
}
}
this.setIcon(aTab, icon, loadingPrincipal, requestContextID);
},
isFailedIcon(aURI) {
if (!(aURI instanceof Ci.nsIURI))
aURI = makeURI(aURI);
return PlacesUtils.favicons.isFailedFavicon(aURI);
},
getWindowTitleForBrowser(aBrowser) {
var newTitle = "";
var docElement = document.documentElement;
@ -3102,7 +3152,7 @@ window._gBrowser = {
// Workarounds for bug 458697
// Icon might have been set on DOMLinkAdded, don't override that.
if (!ourBrowser.mIconURL && otherBrowser.mIconURL)
this.setIcon(aOurTab, otherBrowser.mIconURL);
this.setIcon(aOurTab, otherBrowser.mIconURL, otherBrowser.contentPrincipal, otherBrowser.contentRequestContextID);
var isBusy = aOtherTab.hasAttribute("busy");
if (isBusy) {
aOurTab.setAttribute("busy", "true");
@ -4201,7 +4251,7 @@ window._gBrowser = {
}
tab.removeAttribute("soundplaying");
this.setIcon(tab, icon);
this.setIcon(tab, icon, browser.contentPrincipal, browser.contentRequestContextID);
});
this.addEventListener("oop-browser-buildid-mismatch", (event) => {
@ -4540,6 +4590,21 @@ class TabProgressListener {
} else if (isSuccessful) {
this.mBrowser.urlbarChangeTracker.finishedLoad();
}
// Ignore initial about:blank to prevent flickering.
if (!this.mBrowser.mIconURL && !ignoreBlank) {
// Don't switch to the default icon on about:home, about:newtab,
// about:privatebrowsing, or about:welcome since these pages get
// their favicon set in browser code to improve perceived performance.
let isNewTab = originalLocation &&
(originalLocation.spec == "about:newtab" ||
originalLocation.spec == "about:privatebrowsing" ||
originalLocation.spec == "about:home" ||
originalLocation.spec == "about:welcome");
if (!isNewTab) {
gBrowser.useDefaultIcon(this.mTab);
}
}
}
// For keyword URIs clear the user typed value since they will be changed into real URIs

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

@ -2,41 +2,21 @@
support-files =
head.js
discovery.html
file_rich_icon.html
file_mask_icon.html
moz.png
rich_moz_1.png
rich_moz_2.png
file_bug970276_favicon1.ico
file_generic_favicon.ico
file_with_favicon.html
prefs =
browser.chrome.guess_favicon=true
[browser_bug408415.js]
[browser_bug550565.js]
[browser_favicon_change.js]
support-files =
file_favicon_change.html
[browser_favicon_change_not_in_document.js]
support-files =
file_favicon_change_not_in_document.html
[browser_multiple_icons_in_short_timeframe.js]
skip-if = verify
[browser_rich_icons.js]
support-files =
file_rich_icon.html
file_mask_icon.html
[browser_icon_discovery.js]
[browser_preferred_icons.js]
support-files =
icon.svg
[browser_favicon_load.js]
support-files =
file_favicon.html
file_favicon.png
file_favicon.png^headers^
file_favicon_thirdParty.html
[browser_subframe_favicons_not_used.js]
support-files =
file_bug970276_popup1.html
file_bug970276_popup2.html
file_bug970276_favicon2.ico
[browser_multiple_icons_in_short_timeframe.js]
skip-if = verify
[browser_rich_icons.js]
skip-if = (verify && debug)
[browser_icon_discovery.js]
skip-if = verify
[browser_preferred_icons.js]
[browser_favicon_load.js]

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

@ -1,33 +0,0 @@
add_task(async function test() {
let testPath = getRootDirectory(gTestPath);
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" },
async function(tabBrowser) {
const URI = testPath + "file_with_favicon.html";
const expectedIcon = testPath + "file_generic_favicon.ico";
let faviconPromise = waitForLinkAvailable(tabBrowser);
BrowserTestUtils.loadURI(tabBrowser, URI);
let iconURI = await faviconPromise;
is(iconURI, expectedIcon, "Correct icon before pushState.");
faviconPromise = waitForLinkAvailable(tabBrowser);
await ContentTask.spawn(tabBrowser, null, function() {
content.location.href += "#foo";
});
TestUtils.executeSoon(() => {
faviconPromise.cancel();
});
try {
await faviconPromise;
ok(false, "Should not have seen a new icon load.");
} catch (e) {
ok(true, "Should have been able to cancel the promise.");
}
});
});

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

@ -1,33 +0,0 @@
add_task(async function test() {
let testPath = getRootDirectory(gTestPath);
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" },
async function(tabBrowser) {
const URI = testPath + "file_with_favicon.html";
const expectedIcon = testPath + "file_generic_favicon.ico";
let faviconPromise = waitForLinkAvailable(tabBrowser);
BrowserTestUtils.loadURI(tabBrowser, URI);
let iconURI = await faviconPromise;
is(iconURI, expectedIcon, "Correct icon before pushState.");
faviconPromise = waitForLinkAvailable(tabBrowser);
await ContentTask.spawn(tabBrowser, null, function() {
content.history.pushState("page2", "page2", "page2");
});
// We've navigated and shouldn't get a call to onLinkIconAvailable.
TestUtils.executeSoon(() => {
faviconPromise.cancel();
});
try {
await faviconPromise;
ok(false, "Should not have seen a new icon load.");
} catch (e) {
ok(true, "Should have been able to cancel the promise.");
}
});
});

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

@ -1,30 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_ROOT = "http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const TEST_URL = TEST_ROOT + "file_favicon_change.html";
add_task(async function() {
let extraTab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
let haveChanged = waitForFavicon(extraTab.linkedBrowser, TEST_ROOT + "file_bug970276_favicon1.ico");
extraTab.linkedBrowser.loadURI(TEST_URL);
await BrowserTestUtils.browserLoaded(extraTab.linkedBrowser);
await haveChanged;
haveChanged = waitForFavicon(extraTab.linkedBrowser, TEST_ROOT + "moz.png");
ContentTask.spawn(extraTab.linkedBrowser, null, function() {
let ev = new content.CustomEvent("PleaseChangeFavicon", {});
content.dispatchEvent(ev);
});
await haveChanged;
ok(true, "Saw all the icons we expected.");
gBrowser.removeTab(extraTab);
});

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

@ -70,6 +70,14 @@ FaviconObserver.prototype = {
return;
}
let loadingPrincipal = reqLoadInfo.loadingPrincipal;
if (loadingPrincipal.equals(systemPrincipal)) {
this._faviconReqXUL = true;
} else {
this._faviconReqPlaces = true;
}
let haveTailFlag = !!(cos.classFlags & Ci.nsIClassOfService.Tail);
info("classFlags=" + cos.classFlags);
is(haveTailFlag, this._tailingEnabled, "Should have correct cos flag.");
@ -77,10 +85,14 @@ FaviconObserver.prototype = {
ok(false, "Received unexpected topic: ", aTopic);
}
this._faviconLoaded.resolve();
if (this._faviconReqXUL && this._faviconReqPlaces) {
this._faviconLoaded.resolve();
}
},
reset(aPageURI, aFaviconURL, aTailingEnabled) {
this._faviconReqXUL = false;
this._faviconReqPlaces = false;
this._faviconURL = aFaviconURL;
this._faviconLoaded = PromiseUtils.defer();
this._tailingEnabled = aTailingEnabled;

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

@ -3,114 +3,94 @@
/* eslint-disable mozilla/no-arbitrary-setTimeout */
const ROOTURI = "http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const ICON = "moz.png";
const DATAURL = "data:image/x-icon;base64,AAABAAEAEBAAAAAAAABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAwMDAAMDcwADwyqYABAQEAAgICAAMDAwAERERABYWFgAcHBwAIiIiACkpKQBVVVUATU1NAEJCQgA5OTkAgHz/AFBQ/wCTANYA/+zMAMbW7wDW5+cAkKmtAAAAMwAAAGYAAACZAAAAzAAAMwAAADMzAAAzZgAAM5kAADPMAAAz/wAAZgAAAGYzAABmZgAAZpkAAGbMAABm/wAAmQAAAJkzAACZZgAAmZkAAJnMAACZ/wAAzAAAAMwzAADMZgAAzJkAAMzMAADM/wAA/2YAAP+ZAAD/zAAzAAAAMwAzADMAZgAzAJkAMwDMADMA/wAzMwAAMzMzADMzZgAzM5kAMzPMADMz/wAzZgAAM2YzADNmZgAzZpkAM2bMADNm/wAzmQAAM5kzADOZZgAzmZkAM5nMADOZ/wAzzAAAM8wzADPMZgAzzJkAM8zMADPM/wAz/zMAM/9mADP/mQAz/8wAM///AGYAAABmADMAZgBmAGYAmQBmAMwAZgD/AGYzAABmMzMAZjNmAGYzmQBmM8wAZjP/AGZmAABmZjMAZmZmAGZmmQBmZswAZpkAAGaZMwBmmWYAZpmZAGaZzABmmf8AZswAAGbMMwBmzJkAZszMAGbM/wBm/wAAZv8zAGb/mQBm/8wAzAD/AP8AzACZmQAAmTOZAJkAmQCZAMwAmQAAAJkzMwCZAGYAmTPMAJkA/wCZZgAAmWYzAJkzZgCZZpkAmWbMAJkz/wCZmTMAmZlmAJmZmQCZmcwAmZn/AJnMAACZzDMAZsxmAJnMmQCZzMwAmcz/AJn/AACZ/zMAmcxmAJn/mQCZ/8wAmf//AMwAAACZADMAzABmAMwAmQDMAMwAmTMAAMwzMwDMM2YAzDOZAMwzzADMM/8AzGYAAMxmMwCZZmYAzGaZAMxmzACZZv8AzJkAAMyZMwDMmWYAzJmZAMyZzADMmf8AzMwAAMzMMwDMzGYAzMyZAMzMzADMzP8AzP8AAMz/MwCZ/2YAzP+ZAMz/zADM//8AzAAzAP8AZgD/AJkAzDMAAP8zMwD/M2YA/zOZAP8zzAD/M/8A/2YAAP9mMwDMZmYA/2aZAP9mzADMZv8A/5kAAP+ZMwD/mWYA/5mZAP+ZzAD/mf8A/8wAAP/MMwD/zGYA/8yZAP/MzAD/zP8A//8zAMz/ZgD//5kA///MAGZm/wBm/2YAZv//AP9mZgD/Zv8A//9mACEApQBfX18Ad3d3AIaGhgCWlpYAy8vLALKysgDX19cA3d3dAOPj4wDq6uoA8fHxAPj4+ADw+/8ApKCgAICAgAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8ACgoKCgoKCgoKCgoKCgoKCgoKCgoHAQEMbQoKCgoKCgoAAAdDH/kgHRIAAAAAAAAAAADrHfn5ASQQAAAAAAAAAArsBx0B+fkgHesAAAAAAAD/Cgwf+fn5IA4dEus/IvcACgcMAfkg+QEB+SABHushbf8QHR/5HQH5+QEdHetEHx4K7B/5+QH5+fkdDBL5+SBE/wwdJfkf+fn5AR8g+fkfEArsCh/5+QEeJR/5+SAeBwAACgoe+SAlHwFAEhAfAAAAAPcKHh8eASYBHhAMAAAAAAAA9EMdIB8gHh0dBwAAAAAAAAAA7BAdQ+wHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AADwfwAAwH8AAMB/AAAAPwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAgAcAAIAPAADADwAA8D8AAP//AAA=";
add_task(async function() {
let url = "http://mochi.test:8888/browser/browser/base/content/test/favicons/discovery.html";
info("Test icons discovery");
// First we need to clear the failed favicons cache, since previous tests
// likely added this non-existing icon, and useDefaultIcon would skip it.
PlacesUtils.favicons.removeFailedFavicon(makeURI("http://mochi.test:8888/favicon.ico"));
await BrowserTestUtils.withNewTab(url, iconDiscovery);
});
let iconDiscoveryTests = [
{
text: "rel icon discovered",
icons: [{}]
}, {
text: "rel may contain additional rels separated by spaces",
icons: [{ rel: "abcdefg icon qwerty" }],
}, {
text: "rel is case insensitive",
icons: [{ rel: "ICON" }],
}, {
text: "rel shortcut-icon not discovered",
expectedIcon: ROOTURI + ICON,
icons: [ // We will prefer the later icon if detected
{ },
{ rel: "shortcut-icon", href: "nothere.png" },
],
}, {
text: "relative href works",
icons: [{ href: "moz.png" }],
}, {
text: "404'd icon is removed properly",
pass: false,
icons: [{ href: "notthere.png" }],
}, {
text: "data: URIs work",
icons: [{ href: DATAURL, type: "image/x-icon" }],
}, {
text: "type may have optional parameters (RFC2046)",
icons: [{ type: "image/png; charset=utf-8" }],
}, {
text: "apple-touch-icon discovered",
richIcon: true,
icons: [{ rel: "apple-touch-icon" }],
}, {
text: "apple-touch-icon-precomposed discovered",
richIcon: true,
icons: [{ rel: "apple-touch-icon-precomposed" }],
}, {
text: "fluid-icon discovered",
richIcon: true,
icons: [{ rel: "fluid-icon" }],
}, {
text: "unknown icon not discovered",
expectedIcon: ROOTURI + ICON,
richIcon: true,
icons: [ // We will prefer the larger icon if detected
{ rel: "apple-touch-icon", sizes: "32x32" },
{ rel: "unknown-icon", sizes: "128x128", href: "notthere.png" },
],
},
{ text: "rel icon discovered" },
{ rel: "abcdefg icon qwerty", text: "rel may contain additional rels separated by spaces" },
{ rel: "ICON", text: "rel is case insensitive" },
{ rel: "shortcut-icon", pass: false, text: "rel shortcut-icon not discovered" },
{ href: "moz.png", text: "relative href works" },
{ href: "notthere.png", text: "404'd icon is removed properly" },
{ href: "data:image/x-icon,%00", type: "image/x-icon", text: "data: URIs work" },
{ type: "image/png; charset=utf-8", text: "type may have optional parameters (RFC2046)" },
{ richIcon: true, rel: "apple-touch-icon", text: "apple-touch-icon discovered" },
{ richIcon: true, rel: "apple-touch-icon-precomposed", text: "apple-touch-icon-precomposed discovered" },
{ richIcon: true, rel: "fluid-icon", text: "fluid-icon discovered" },
{ richIcon: true, rel: "unknown-icon", pass: false, text: "unknown icon not discovered" }
];
add_task(async function() {
let url = ROOTURI + "discovery.html";
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
async function iconDiscovery() {
// Since the page doesn't have an icon, we should try using the root domain
// icon.
await BrowserTestUtils.waitForCondition(() => {
return gBrowser.getIcon() == "http://mochi.test:8888/favicon.ico";
}, "wait for default icon load to finish");
for (let testCase of iconDiscoveryTests) {
info(`Running test "${testCase.text}"`);
if (testCase.pass === undefined)
if (testCase.pass == undefined)
testCase.pass = true;
if (testCase.icons.length > 1 && !testCase.expectedIcon) {
ok(false, "Invalid test data, missing expectedIcon");
continue;
}
// Clear the current icon.
gBrowser.setIcon(gBrowser.selectedTab, null);
let expectedIcon = testCase.expectedIcon || testCase.icons[0].href || ICON;
expectedIcon = (new URL(expectedIcon, ROOTURI)).href;
let iconPromise = waitForFaviconMessage(!testCase.richIcon, expectedIcon);
await ContentTask.spawn(gBrowser.selectedBrowser, [testCase.icons, ROOTURI + ICON], ([icons, defaultIcon]) => {
let doc = content.document;
let head = doc.head;
for (let icon of icons) {
let link = doc.createElement("link");
link.rel = icon.rel || "icon";
link.href = icon.href || defaultIcon;
link.type = icon.type || "image/png";
if (icon.sizes) {
link.sizes = icon.sizes;
}
head.appendChild(link);
}
let promiseLinkAdded =
BrowserTestUtils.waitForContentEvent(gBrowser.selectedBrowser, "DOMLinkAdded",
false, null, true);
let promiseMessage = new Promise(resolve => {
let mm = window.messageManager;
mm.addMessageListener("Link:SetIcon", function listenForIcon(msg) {
mm.removeMessageListener("Link:SetIcon", listenForIcon);
resolve(msg.data);
});
});
try {
let { iconURL } = await iconPromise;
ok(testCase.pass, testCase.text);
is(iconURL, expectedIcon, "Should have seen the expected icon.");
} catch (e) {
ok(!testCase.pass, testCase.text);
await ContentTask.spawn(gBrowser.selectedBrowser, testCase, test => {
let doc = content.document;
let head = doc.getElementById("linkparent");
let link = doc.createElement("link");
link.rel = test.rel || "icon";
link.href = test.href || "http://mochi.test:8888/browser/browser/base/content/test/favicons/moz.png";
link.type = test.type || "image/png";
head.appendChild(link);
});
await promiseLinkAdded;
if (!testCase.richIcon) {
// Because there is debounce logic in ContentLinkHandler.jsm to reduce the
// favicon loads, we have to wait some time before checking that icon was
// stored properly.
try {
await BrowserTestUtils.waitForCondition(() => {
return gBrowser.getIcon() != null;
}, "wait for icon load to finish", 100, 20);
ok(testCase.pass, testCase.text);
} catch (ex) {
ok(!testCase.pass, testCase.text);
}
} else {
// Rich icons are not set as tab icons, so just check for the SetIcon message.
try {
let data = await Promise.race([promiseMessage,
new Promise((resolve, reject) => setTimeout(reject, 2000))]);
is(data.canUseForTab, false, "Rich icons cannot be used for tabs");
ok(testCase.pass, testCase.text);
} catch (ex) {
ok(!testCase.pass, testCase.text);
}
}
await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
let links = content.document.querySelectorAll("link");
for (let link of links) {
link.remove();
}
let head = content.document.getElementById("linkparent");
head.removeChild(head.getElementsByTagName("link")[0]);
});
}
BrowserTestUtils.removeTab(tab);
});
}

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

@ -5,25 +5,36 @@ add_task(async function() {
const ROOT = "http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const URL = ROOT + "discovery.html";
let iconPromise = waitForFaviconMessage(true, "http://mochi.test:8888/favicon.ico");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
let icon = await iconPromise;
// Because there is debounce logic in ContentLinkHandler.jsm to reduce the
// favicon loads, we have to wait some time before checking that icon was
// stored properly.
let promiseIcon = BrowserTestUtils.waitForCondition(
() => {
let tabIcon = gBrowser.getIcon();
info("Found icon " + tabIcon);
return tabIcon == ROOT + "two.png";
},
"wait for icon load to finish", 200, 25);
await ContentTask.spawn(gBrowser.selectedBrowser, ROOT, root => {
let doc = content.document;
let head = doc.head;
let head = doc.getElementById("linkparent");
let link = doc.createElement("link");
link.rel = "icon";
link.href = root + "rich_moz_1.png";
link.href = root + "one.png";
link.type = "image/png";
head.appendChild(link);
let link2 = link.cloneNode(false);
link2.href = root + "rich_moz_2.png";
link2.href = root + "two.png";
head.appendChild(link2);
});
icon = await waitForFaviconMessage();
Assert.equal(icon.iconURL, ROOT + "rich_moz_2.png", "The expected icon has been set");
await promiseIcon;
// The test must have at least one pass.
Assert.equal(gBrowser.getIcon(), ROOT + "two.png",
"The expected icon has been set");
BrowserTestUtils.removeTab(tab);
});

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

@ -3,15 +3,26 @@
const ROOT = "http://mochi.test:8888/browser/browser/base/content/test/favicons/";
async function waitIcon(url) {
let icon = await waitForFaviconMessage(true, url);
is(icon.iconURL, url, "Should have seen the right icon.");
function waitIcon(url) {
// Make sure we don't miss out on an icon if it was previously used in a test
PlacesUtils.favicons.removeFailedFavicon(makeURI(url));
// Because there is debounce logic in ContentLinkHandler.jsm to reduce the
// favicon loads, we have to wait some time before checking that icon was
// stored properly.
return BrowserTestUtils.waitForCondition(
() => {
let tabIcon = gBrowser.getIcon();
info("Found icon " + tabIcon);
return tabIcon == url;
},
"wait for icon load to finish", 200, 25);
}
function createLinks(linkInfos) {
return ContentTask.spawn(gBrowser.selectedBrowser, linkInfos, links => {
let doc = content.document;
let head = doc.head;
let head = doc.getElementById("linkparent");
for (let l of links) {
let link = doc.createElement("link");
link.rel = "icon";
@ -27,9 +38,7 @@ function createLinks(linkInfos) {
add_task(async function setup() {
const URL = ROOT + "discovery.html";
let iconPromise = waitIcon("http://mochi.test:8888/favicon.ico");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
await iconPromise;
registerCleanupFunction(async function() {
BrowserTestUtils.removeTab(tab);
});
@ -50,15 +59,17 @@ add_task(async function prefer_svg() {
},
]);
await promise;
// Must have at least one test.
Assert.ok(true, "The expected icon has been set");
});
add_task(async function prefer_sized() {
let promise = waitIcon(ROOT + "moz.png");
let promise = waitIcon(ROOT + "icon.png");
await createLinks([
{ href: ROOT + "icon.ico",
type: "image/x-icon"
},
{ href: ROOT + "moz.png",
{ href: ROOT + "icon.png",
type: "image/png",
size: 16 * Math.ceil(window.devicePixelRatio)
},
@ -67,10 +78,12 @@ add_task(async function prefer_sized() {
},
]);
await promise;
// Must have at least one test.
Assert.ok(true, "The expected icon has been set");
});
add_task(async function prefer_last_ico() {
let promise = waitIcon(ROOT + "file_generic_favicon.ico");
let promise = waitIcon(ROOT + "icon2.ico");
await createLinks([
{ href: ROOT + "icon.ico",
type: "image/x-icon"
@ -78,15 +91,17 @@ add_task(async function prefer_last_ico() {
{ href: ROOT + "icon.png",
type: "image/png",
},
{ href: ROOT + "file_generic_favicon.ico",
{ href: ROOT + "icon2.ico",
type: "image/x-icon"
},
]);
await promise;
// Must have at least one test.
Assert.ok(true, "The expected icon has been set");
});
add_task(async function fuzzy_ico() {
let promise = waitIcon(ROOT + "file_generic_favicon.ico");
let promise = waitIcon(ROOT + "microsoft.ico");
await createLinks([
{ href: ROOT + "icon.ico",
type: "image/x-icon"
@ -94,11 +109,13 @@ add_task(async function fuzzy_ico() {
{ href: ROOT + "icon.png",
type: "image/png",
},
{ href: ROOT + "file_generic_favicon.ico",
{ href: ROOT + "microsoft.ico",
type: "image/vnd.microsoft.icon"
},
]);
await promise;
// Must have at least one test.
Assert.ok(true, "The expected icon has been set");
});
add_task(async function guess_svg() {
@ -114,17 +131,21 @@ add_task(async function guess_svg() {
},
]);
await promise;
// Must have at least one test.
Assert.ok(true, "The expected icon has been set");
});
add_task(async function guess_ico() {
let promise = waitIcon(ROOT + "file_generic_favicon.ico");
let promise = waitIcon(ROOT + "icon.ico");
await createLinks([
{ href: ROOT + "file_generic_favicon.ico" },
{ href: ROOT + "icon.ico" },
{ href: ROOT + "icon.png",
type: "image/png",
},
]);
await promise;
// Must have at least one test.
Assert.ok(true, "The expected icon has been set");
});
add_task(async function guess_invalid() {
@ -140,11 +161,13 @@ add_task(async function guess_invalid() {
{ href: "about:icon" },
]);
await promise;
// Must have at least one test.
Assert.ok(true, "The expected icon has been set");
});
add_task(async function guess_bestSized() {
let preferredWidth = 16 * Math.ceil(window.devicePixelRatio);
let promise = waitIcon(ROOT + "moz.png");
let promise = waitIcon(ROOT + "icon3.png");
await createLinks([
{ href: ROOT + "icon.png",
type: "image/png",
@ -153,7 +176,7 @@ add_task(async function guess_bestSized() {
{ href: ROOT + "icon2.png",
type: "image/png",
},
{ href: ROOT + "moz.png",
{ href: ROOT + "icon3.png",
type: "image/png",
size: preferredWidth + 1
},
@ -163,4 +186,6 @@ add_task(async function guess_bestSized() {
},
]);
await promise;
// Must have at least one test.
Assert.ok(true, "The expected icon has been set");
});

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

@ -9,29 +9,61 @@ add_task(async function test_richIcons() {
const URL = ROOT + "file_rich_icon.html";
const EXPECTED_ICON = ROOT + "moz.png";
const EXPECTED_RICH_ICON = ROOT + "rich_moz_2.png";
// One regular icon and one rich icon. Note that ContentLinkHandler will
// choose the best rich icon if there are multiple candidates available
// in the page.
const EXPECTED_ICON_LOADS = 2;
let loadCount = 0;
let tabIconUri;
let richIconUri;
let tabPromises = Promise.all([
waitForFaviconMessage(true, EXPECTED_ICON),
waitForFaviconMessage(false, EXPECTED_RICH_ICON),
]);
const promiseMessage = new Promise(resolve => {
const mm = window.messageManager;
mm.addMessageListener("Link:SetIcon", function listenForSetIcon(msg) {
// Ignore the chrome favicon sets on the tab before the actual page load.
if (msg.data.url === "chrome://branding/content/icon32.png")
return;
if (!msg.data.canUseForTab)
richIconUri = msg.data.url;
if (++loadCount === EXPECTED_ICON_LOADS) {
mm.removeMessageListener("Link:SetIcon", listenForSetIcon);
resolve();
}
});
});
const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
let [tabIcon, richIcon] = await tabPromises;
await promiseMessage;
is(richIcon.iconURL, EXPECTED_RICH_ICON, "should choose the largest rich icon");
is(tabIcon.iconURL, EXPECTED_ICON, "should use the non-rich icon for the tab");
is(richIconUri, EXPECTED_RICH_ICON, "should choose the largest rich icon");
// Because there is debounce logic in ContentLinkHandler.jsm to reduce the
// favicon loads, we have to wait some time before checking that icon was
// stored properly.
await BrowserTestUtils.waitForCondition(() => {
tabIconUri = gBrowser.getIcon();
return tabIconUri != null;
}, "wait for icon load to finish", 100, 20);
is(tabIconUri, EXPECTED_ICON, "should use the non-rich icon for the tab");
BrowserTestUtils.removeTab(tab);
});
add_task(async function test_maskIcons() {
const URL = ROOT + "file_mask_icon.html";
// First we need to clear the failed favicons cache, since previous tests
// likely added this non-existing icon, and useDefaultIcon would skip it.
PlacesUtils.favicons.removeFailedFavicon(makeURI("http://mochi.test:8888/favicon.ico"));
const EXPECTED_ICON = "http://mochi.test:8888/favicon.ico";
let tabIconUri;
let promise = waitForFaviconMessage(true, EXPECTED_ICON);
const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
let tabIcon = await promise;
is(tabIcon.iconURL, EXPECTED_ICON, "should ignore the mask icons and load the root favicon");
await BrowserTestUtils.waitForCondition(() => {
tabIconUri = gBrowser.getIcon();
return tabIconUri != null;
}, "wait for icon load to finish", 100, 20);
is(tabIconUri, EXPECTED_ICON, "should ignore the mask icons and load the root favicon");
BrowserTestUtils.removeTab(tab);
});

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

@ -1,14 +0,0 @@
/* Make sure <link rel="..."> isn't respected in sub-frames. */
add_task(async function() {
const ROOT = "http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const URL = ROOT + "file_bug970276_popup1.html";
let promiseIcon = waitForFaviconMessage(true, ROOT + "file_bug970276_favicon1.ico");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
let icon = await promiseIcon;
Assert.equal(icon.iconURL, ROOT + "file_bug970276_favicon1.ico", "The expected icon has been set");
BrowserTestUtils.removeTab(tab);
});

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

@ -1,6 +1,6 @@
<!DOCTYPE HTML>
<html>
<head>
<head id="linkparent">
<title>Autodiscovery Test</title>
</head>
<body>

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

@ -3,90 +3,9 @@
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.defineModuleGetter(this, "BrowserTestUtils",
"resource://testing-common/BrowserTestUtils.jsm");
ChromeUtils.defineModuleGetter(this, "ContentTask",
"resource://testing-common/ContentTask.jsm");
ChromeUtils.defineModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
// Clear the network cache between every test to make sure we get a stable state
Services.cache2.clear();
function waitForFaviconMessage(isTabIcon = undefined, expectedURL = undefined) {
return new Promise((resolve, reject) => {
let listener = msg => {
// If requested filter out loads of the wrong kind of icon.
if (isTabIcon != undefined && isTabIcon != msg.data.canUseForTab) {
return;
}
if (expectedURL && msg.data.originalURL != expectedURL) {
return;
}
window.messageManager.removeMessageListener("Link:SetIcon", listener);
window.messageManager.removeMessageListener("Link:SetFailedIcon", listener);
if (msg.name == "Link:SetIcon") {
resolve({
iconURL: msg.data.originalURL,
dataURL: msg.data.iconURL,
canUseForTab: msg.data.canUseForTab,
});
} else {
reject({
iconURL: msg.data.originalURL,
canUseForTab: msg.data.canUseForTab,
});
}
};
window.messageManager.addMessageListener("Link:SetIcon", listener);
window.messageManager.addMessageListener("Link:SetFailedIcon", listener);
});
}
function waitForFavicon(browser, url) {
return new Promise(resolve => {
let listener = {
onLinkIconAvailable(b, dataURI, iconURI) {
if (b !== browser || iconURI != url) {
return;
}
gBrowser.removeTabsProgressListener(listener);
resolve();
}
};
gBrowser.addTabsProgressListener(listener);
});
}
function waitForLinkAvailable(browser) {
let resolve, reject;
let listener = {
onLinkIconAvailable(b, dataURI, iconURI) {
// Ignore icons for other browsers or empty icons.
if (browser !== b || !iconURI) {
return;
}
gBrowser.removeTabsProgressListener(listener);
resolve(iconURI);
}
};
let promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
gBrowser.addTabsProgressListener(listener);
});
promise.cancel = () => {
gBrowser.removeTabsProgressListener(listener);
reject();
};
return promise;
}

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

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<circle cx="8" cy="8" r="8" fill="#8d20ae" />
<circle cx="8" cy="8" r="7.5" stroke="#7b149a" stroke-width="1" fill="none" />
<path d="M11.309,10.995C10.061,10.995,9.2,9.5,8,9.5s-2.135,1.5-3.309,1.5c-1.541,0-2.678-1.455-2.7-3.948C1.983,5.5,2.446,5.005,4.446,5.005S7.031,5.822,8,5.822s1.555-.817,3.555-0.817S14.017,5.5,14.006,7.047C13.987,9.54,12.85,10.995,11.309,10.995ZM5.426,6.911a1.739,1.739,0,0,0-1.716.953A2.049,2.049,0,0,0,5.3,8.544c0.788,0,1.716-.288,1.716-0.544A1.428,1.428,0,0,0,5.426,6.911Zm5.148,0A1.429,1.429,0,0,0,8.981,8c0,0.257.928,0.544,1.716,0.544a2.049,2.049,0,0,0,1.593-.681A1.739,1.739,0,0,0,10.574,6.911Z" stroke="#670c83" stroke-width="2" fill="none" />
<path d="M11.309,10.995C10.061,10.995,9.2,9.5,8,9.5s-2.135,1.5-3.309,1.5c-1.541,0-2.678-1.455-2.7-3.948C1.983,5.5,2.446,5.005,4.446,5.005S7.031,5.822,8,5.822s1.555-.817,3.555-0.817S14.017,5.5,14.006,7.047C13.987,9.54,12.85,10.995,11.309,10.995ZM5.426,6.911a1.739,1.739,0,0,0-1.716.953A2.049,2.049,0,0,0,5.3,8.544c0.788,0,1.716-.288,1.716-0.544A1.428,1.428,0,0,0,5.426,6.911Zm5.148,0A1.429,1.429,0,0,0,8.981,8c0,0.257.928,0.544,1.716,0.544a2.049,2.049,0,0,0,1.593-.681A1.739,1.739,0,0,0,10.574,6.911Z" fill="#fff" />
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.5 KiB

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

@ -35,8 +35,16 @@ support-files =
download_page_2.txt
dummy_page.html
feed_tab.html
file_generic_favicon.ico
file_with_favicon.html
file_bug970276_popup1.html
file_bug970276_popup2.html
file_bug970276_favicon1.ico
file_bug970276_favicon2.ico
file_documentnavigation_frameset.html
file_double_close_tab.html
file_favicon_change.html
file_favicon_change_not_in_document.html
file_fullscreen-window-open.html
file_with_link_to_http.html
head.js
@ -97,6 +105,8 @@ skip-if = (verify && !debug && (os == 'win'))
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_bug406216.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_bug408415.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_bug413915.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_bug416661.js]
@ -157,6 +167,8 @@ skip-if = true # bug 1393813
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_bug537474.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_bug550565.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_bug555224.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_bug555767.js]
@ -294,6 +306,12 @@ skip-if = (verify && !debug && (os == 'linux'))
[browser_drag.js]
skip-if = true # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_favicon_change.js]
skip-if = verify
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_favicon_change_not_in_document.js]
skip-if = verify
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_findbarClose.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_focusonkeydown.js]
@ -407,6 +425,8 @@ support-files =
[browser_storagePressure_notification.js]
skip-if = verify
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_subframe_favicons_not_used.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_tab_close_dependent_window.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_tabDrop.js]

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

@ -0,0 +1,45 @@
add_task(async function test() {
let testPath = getRootDirectory(gTestPath);
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" },
async function(tabBrowser) {
const URI = testPath + "file_with_favicon.html";
const expectedIcon = testPath + "file_generic_favicon.ico";
let got_favicon = PromiseUtils.defer();
let listener = {
onLinkIconAvailable(browser, iconURI) {
if (got_favicon && iconURI && browser === tabBrowser) {
got_favicon.resolve(iconURI);
got_favicon = null;
}
}
};
gBrowser.addTabsProgressListener(listener);
BrowserTestUtils.loadURI(tabBrowser, URI);
let iconURI = await got_favicon.promise;
is(iconURI, expectedIcon, "Correct icon before pushState.");
got_favicon = PromiseUtils.defer();
got_favicon.promise.then(() => { ok(false, "shouldn't be called"); }, (e) => e);
await ContentTask.spawn(tabBrowser, null, function() {
content.location.href += "#foo";
});
// We've navigated and shouldn't get a call to onLinkIconAvailable.
TestUtils.executeSoon(() => {
got_favicon.reject(gBrowser.getIcon(gBrowser.getTabForBrowser(tabBrowser)));
});
try {
await got_favicon.promise;
} catch (e) {
iconURI = e;
}
is(iconURI, expectedIcon, "Correct icon after pushState.");
gBrowser.removeTabsProgressListener(listener);
});
});

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

@ -43,8 +43,9 @@ var progressListener = {
if (aBrowser == tab.linkedBrowser)
record("onStateChange");
},
onLinkIconAvailable: function onLinkIconAvailable(aBrowser) {
if (aBrowser == tab.linkedBrowser)
onLinkIconAvailable: function onLinkIconAvailable(aBrowser, aIconURL) {
if (aBrowser == tab.linkedBrowser &&
aIconURL == "about:logo")
record("onLinkIconAvailable");
}
};

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

@ -0,0 +1,44 @@
add_task(async function test() {
let testPath = getRootDirectory(gTestPath);
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" },
async function(tabBrowser) {
const URI = testPath + "file_with_favicon.html";
const expectedIcon = testPath + "file_generic_favicon.ico";
let got_favicon = PromiseUtils.defer();
let listener = {
onLinkIconAvailable(browser, iconURI) {
if (got_favicon && iconURI && browser === tabBrowser) {
got_favicon.resolve(iconURI);
got_favicon = null;
}
}
};
gBrowser.addTabsProgressListener(listener);
BrowserTestUtils.loadURI(tabBrowser, URI);
let iconURI = await got_favicon.promise;
is(iconURI, expectedIcon, "Correct icon before pushState.");
got_favicon = PromiseUtils.defer();
got_favicon.promise.then(() => { ok(false, "shouldn't be called"); }, (e) => e);
await ContentTask.spawn(tabBrowser, null, function() {
content.history.pushState("page2", "page2", "page2");
});
// We've navigated and shouldn't get a call to onLinkIconAvailable.
TestUtils.executeSoon(() => {
got_favicon.reject(gBrowser.getIcon(gBrowser.getTabForBrowser(tabBrowser)));
});
try {
await got_favicon.promise;
} catch (e) {
iconURI = e;
}
is(iconURI, expectedIcon, "Correct icon after pushState.");
gBrowser.removeTabsProgressListener(listener);
});
});

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

@ -0,0 +1,42 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_URL = "http://mochi.test:8888/browser/browser/base/content/test/general/file_favicon_change.html";
add_task(async function() {
let extraTab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
extraTab.linkedBrowser.loadURI(TEST_URL);
let tabLoaded = BrowserTestUtils.browserLoaded(extraTab.linkedBrowser);
let expectedFavicon = "http://example.org/one-icon";
let haveChanged = PromiseUtils.defer();
let observer = new MutationObserver(function(mutations) {
for (let mut of mutations) {
if (mut.attributeName != "image") {
continue;
}
let imageVal = extraTab.getAttribute("image").replace(/#.*$/, "");
// Ignore chrome favicons set on the tab before the actual page load.
if (!imageVal || !imageVal.startsWith("http://example.org/")) {
// The value gets removed because it doesn't load.
continue;
}
is(imageVal, expectedFavicon, "Favicon image should correspond to expected image.");
haveChanged.resolve();
}
});
observer.observe(extraTab, {attributes: true});
await tabLoaded;
await haveChanged.promise;
haveChanged = PromiseUtils.defer();
expectedFavicon = "http://example.org/other-icon";
ContentTask.spawn(extraTab.linkedBrowser, null, function() {
let ev = new content.CustomEvent("PleaseChangeFavicon", {});
content.dispatchEvent(ev);
});
await haveChanged.promise;
observer.disconnect();
gBrowser.removeTab(extraTab);
});

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

@ -1,7 +1,6 @@
"use strict";
const TEST_ROOT = "http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const TEST_URL = TEST_ROOT + "file_favicon_change_not_in_document.html";
const TEST_URL = "http://mochi.test:8888/browser/browser/base/content/test/general/file_favicon_change_not_in_document.html";
/*
* This test tests a link element won't fire DOMLinkChanged/DOMLinkAdded unless
@ -23,14 +22,19 @@ add_task(async function() {
const linkChangedhandler = event => domLinkChangedFired++;
BrowserTestUtils.addContentEventListener(gBrowser.selectedBrowser, "DOMLinkAdded", linkAddedHandler);
BrowserTestUtils.addContentEventListener(gBrowser.selectedBrowser, "DOMLinkChanged", linkChangedhandler);
let expectedFavicon = TEST_ROOT + "file_generic_favicon.ico";
let faviconPromise = waitForFavicon(extraTab.linkedBrowser, expectedFavicon);
extraTab.linkedBrowser.loadURI(TEST_URL);
await BrowserTestUtils.browserLoaded(extraTab.linkedBrowser);
let expectedFavicon = "http://example.org/yet-another-icon";
await promiseTabLoaded(extraTab);
await faviconPromise;
// Make sure the new added favicon link gets loaded.
try {
await BrowserTestUtils.waitForCondition(() => {
return gBrowser.getIcon(extraTab) === expectedFavicon;
}, "wait for favicon load to finish", 1000, 5);
ok(true, "Should load the added favicon");
} catch (e) {
ok(false, "Should've loaded the new added favicon.");
}
is(domLinkAddedFired, 2, "Should fire the correct number of DOMLinkAdded event.");
is(domLinkChangedFired, 0, "Should not fire any DOMLinkChanged event.");

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

@ -0,0 +1,32 @@
/* Make sure <link rel="..."> isn't respected in sub-frames. */
function test() {
waitForExplicitFinish();
let testPath = getRootDirectory(gTestPath);
let tab = BrowserTestUtils.addTab(gBrowser, testPath + "file_bug970276_popup1.html");
tab.linkedBrowser.addEventListener("load", function() {
let expectedIcon = testPath + "file_bug970276_favicon1.ico";
let icon;
// Because there is debounce logic in ContentLinkHandler.jsm to reduce the
// favicon loads, we have to wait some time before checking that icon was
// stored properly.
BrowserTestUtils.waitForCondition(() => {
icon = gBrowser.getIcon(tab);
return icon != null;
}, "wait for favicon load to finish", 100, 5)
.then(() => {
is(icon, expectedIcon, "Correct icon.");
})
.catch(() => {
ok(false, "Can't get the correct icon.");
})
.then(() => {
gBrowser.removeTab(tab);
finish();
});
}, {capture: true, once: true});
}

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

До

Ширина:  |  Высота:  |  Размер: 1.4 KiB

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

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

До

Ширина:  |  Высота:  |  Размер: 1.4 KiB

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

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

@ -1,13 +1,13 @@
<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rel="icon" href="file_bug970276_favicon1.ico" type="image/ico" id="i">
<link rel="icon" href="http://example.org/one-icon" type="image/ico" id="i">
</head>
<body>
<script>
window.addEventListener("PleaseChangeFavicon", function() {
var ico = document.getElementById("i");
ico.setAttribute("href", "moz.png");
ico.setAttribute("href", "http://example.org/other-icon");
});
</script>
</body></html>

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

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rel="icon" href="file_bug970276_favicon1.ico" type="image/ico" id="i">
<link rel="icon" href="http://example.org/one-icon" type="image/ico" id="i">
</head>
<body onload="onload()">
<script>
@ -9,9 +9,9 @@
var ico = document.createElement("link");
ico.setAttribute("rel", "icon");
ico.setAttribute("type", "image/ico");
ico.setAttribute("href", "file_bug970276_favicon1.ico");
ico.setAttribute("href", "http://example.org/other-icon");
setTimeout(function() {
ico.setAttribute("href", "file_generic_favicon.ico");
ico.setAttribute("href", "http://example.org/yet-another-icon");
document.getElementById("i").remove();
document.head.appendChild(ico);
}, 1000);

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

До

Ширина:  |  Высота:  |  Размер: 1.4 KiB

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

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

@ -186,6 +186,14 @@ add_task(async function navigate_around() {
min: 20,
max: 30,
},
"browser.chrome.favicons": {
min: 50,
max: 55,
},
"browser.chrome.site_icons": {
min: 50,
max: 55,
},
"toolkit.cosmeticAnimations.enabled": {
min: 45,
max: 55,

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

@ -26,8 +26,6 @@ const TEST_CACHE_PAGE = TEST_DIRECTORY + "file_favicon_cache.html";
const FAVICON_URI = TEST_DIRECTORY + "file_favicon.png";
const TEST_FAVICON_CACHE_URI = TEST_DIRECTORY + "file_favicon_cache.png";
const ICON_DATA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABH0lEQVRYw2P8////f4YBBEwMAwxGHcBCUMX/91DGOSj/BpT/DkpzQChGBSjfBErLQsVZhmoI/L8LpRdD6X1QietQGhYy7FB5aAgwmkLpBKi4BZTPMThDgBGjHIDF+f9mKD0fKvGBRKNdoF7sgPL1saaJwZgGDkJ9vpZMn8PAHqg5G9FyifBgD4H/W9HyOWrU/f+DIzHhkoeZxxgzZEIAVtJ9RxX+Q6DAxCmP3byhXxkxshAs5odqbcioAY3UC1CBLyTGOTqAmsfAOWRCwBvqxV0oIUB2OQAzDy3/D+a6wB7q8mCU2vD/nw94GziYIQOtDRn9oXz+IZMGBKGMbCjNh9Ii+v8HR4uIAUeLiEEbb9twELaIRlqrmHG0bzjiHQAA1LVfww8jwM4AAAAASUVORK5CYII=";
let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
let makeURI = ChromeUtils.import("resource://gre/modules/BrowserUtils.jsm", {}).BrowserUtils.makeURI;
@ -58,7 +56,10 @@ function clearAllPlacesFavicons() {
});
}
function observeFavicon(aFirstPartyDomain, aExpectedCookie, aPageURI) {
function observeFavicon(aFirstPartyDomain, aExpectedCookie, aPageURI, aOnlyXUL) {
let faviconReqXUL = false;
// If aOnlyXUL is true, we only care about the favicon request from XUL.
let faviconReqPlaces = aOnlyXUL === true;
let expectedPrincipal = Services.scriptSecurityManager
.createCodebasePrincipal(aPageURI, { firstPartyDomain: aFirstPartyDomain });
@ -88,10 +89,15 @@ function observeFavicon(aFirstPartyDomain, aExpectedCookie, aPageURI) {
is(reqLoadInfo.originAttributes.firstPartyDomain, aFirstPartyDomain,
"The loadInfo has correct first party domain");
ok(loadingPrincipal.equals(expectedPrincipal),
"The loadingPrincipal of favicon loads should be the content prinicpal");
ok(triggeringPrincipal.equals(expectedPrincipal),
"The triggeringPrincipal of favicon loads should be the content prinicpal");
if (loadingPrincipal.equals(systemPrincipal)) {
faviconReqXUL = true;
ok(triggeringPrincipal.equals(expectedPrincipal),
"The triggeringPrincipal of favicon loading from XUL should be the content principal.");
} else {
faviconReqPlaces = true;
ok(loadingPrincipal.equals(expectedPrincipal),
"The loadingPrincipal of favicon loading from Places should be the content prinicpal");
}
let faviconCookie = httpChannel.getRequestHeader("cookie");
@ -100,8 +106,10 @@ function observeFavicon(aFirstPartyDomain, aExpectedCookie, aPageURI) {
ok(false, "Received unexpected topic: ", aTopic);
}
Services.obs.removeObserver(observer, "http-on-modify-request");
resolve();
if (faviconReqXUL && faviconReqPlaces) {
Services.obs.removeObserver(observer, "http-on-modify-request");
resolve();
}
}
};
@ -207,12 +215,6 @@ async function generateCookies(aThirdParty) {
return cookies;
}
function assertIconIsData(item) {
let icon = item.getAttribute("image");
is(icon.substring(0, 5), "data:", "Expected the image element to be a data URI");
is(icon, ICON_DATA, "Expected to see the correct data.");
}
async function doTest(aTestPage, aExpectedCookies, aFaviconURL) {
let firstPageURI = makeURI(TEST_SITE_ONE + aTestPage);
let secondPageURI = makeURI(TEST_SITE_TWO + aTestPage);
@ -232,8 +234,6 @@ async function doTest(aTestPage, aExpectedCookies, aFaviconURL) {
// Waiting until favicon loaded.
await promiseFaviconLoaded;
assertIconIsData(tabInfo.tab);
BrowserTestUtils.removeTab(tabInfo.tab);
// FIXME: We need to wait for the next event tick here to avoid observing
// the previous tab info in the next step (bug 1446725).
@ -252,6 +252,8 @@ async function doTest(aTestPage, aExpectedCookies, aFaviconURL) {
}
async function doTestForAllTabsFavicon(aTestPage, aExpectedCookies, aIsThirdParty) {
let firstPageURI = makeURI(TEST_SITE_ONE + aTestPage);
let secondPageURI = makeURI(TEST_SITE_TWO + aTestPage);
let faviconURI = aIsThirdParty ? THIRD_PARTY_SITE + FAVICON_URI :
TEST_SITE_ONE + FAVICON_URI;
@ -268,16 +270,21 @@ async function doTestForAllTabsFavicon(aTestPage, aExpectedCookies, aIsThirdPart
// Waiting until the favicon loaded.
await promiseFaviconLoaded;
assertIconIsData(tabInfo.tab);
// We need to clear the image cache here for making sure the network request will
// be made for the favicon of allTabs menuitem.
clearAllImageCaches();
// Start to observe the allTabs favicon requests earlier in case we miss it.
let promiseObserveFavicon = observeFavicon(FIRST_PARTY_ONE, aExpectedCookies[0],
firstPageURI, true);
// Make the popup of allTabs showing up and trigger the loading of the favicon.
let allTabsView = document.getElementById("allTabsMenu-allTabsView");
let allTabsPopupShownPromise = BrowserTestUtils.waitForEvent(allTabsView, "ViewShown");
gTabsPanel.showAllTabsPanel();
await promiseObserveFavicon;
await allTabsPopupShownPromise;
assertIconIsData(gTabsPanel.allTabsViewTabs.lastChild.firstChild);
// Close the popup of allTabs and wait until it's done.
let allTabsPopupHiddenPromise = BrowserTestUtils.waitForEvent(allTabsView.panelMultiView, "PanelMultiViewHidden");
gTabsPanel.hideAllTabsPanel();
@ -298,15 +305,19 @@ async function doTestForAllTabsFavicon(aTestPage, aExpectedCookies, aIsThirdPart
// Wait until the favicon is fully loaded.
await promiseFaviconLoaded;
assertIconIsData(tabInfo.tab);
// Clear the image cache for the favicon of the second site.
clearAllImageCaches();
// Start to observe the allTabs favicon requests earlier in case we miss it.
promiseObserveFavicon = observeFavicon(FIRST_PARTY_TWO, aExpectedCookies[1],
secondPageURI, true);
// Make the popup of allTabs showing up again.
allTabsPopupShownPromise = BrowserTestUtils.waitForEvent(allTabsView, "ViewShown");
gTabsPanel.showAllTabsPanel();
await promiseObserveFavicon;
await allTabsPopupShownPromise;
assertIconIsData(gTabsPanel.allTabsViewTabs.lastChild.firstChild);
// Close the popup of allTabs and wait until it's done.
allTabsPopupHiddenPromise = BrowserTestUtils.waitForEvent(allTabsView.panelMultiView, "PanelMultiViewHidden");
gTabsPanel.hideAllTabsPanel();
@ -402,12 +413,17 @@ add_task(async function test_favicon_cache_firstParty() {
// Waiting until the favicon has been loaded and cached.
await promiseForFaviconLoaded;
// Here, we are going to observe the favicon response for the third tab which
// opens with the second first party.
// Open the tab again for checking the image cache is working correctly.
let tabInfoB = await openTab(TEST_SITE_ONE + TEST_CACHE_PAGE);
// Start to observe the favicon response, the second tab actually will not
// make any network request since the favicon will be loaded by the cache for
// both Places and XUL image. So here, we are going to observe the favicon
// response for the third tab which opens with the second first party.
let promiseForFaviconResponse = waitOnFaviconResponse(THIRD_PARTY_SITE + TEST_FAVICON_CACHE_URI);
// Open the tab for the second site.
let tabInfoB = await openTab(TEST_SITE_TWO + TEST_CACHE_PAGE);
let tabInfoC = await openTab(TEST_SITE_TWO + TEST_CACHE_PAGE);
// Wait for the favicon response. In this case, we suppose to catch the
// response for the third tab but not the second tab since it will not
@ -421,4 +437,5 @@ add_task(async function test_favicon_cache_firstParty() {
BrowserTestUtils.removeTab(tabInfoA.tab);
BrowserTestUtils.removeTab(tabInfoB.tab);
BrowserTestUtils.removeTab(tabInfoC.tab);
});

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

@ -56,8 +56,8 @@ function clearAllPlacesFavicons() {
});
}
function FaviconObserver(aUserContextId, aExpectedCookie, aPageURI, aFaviconURL) {
this.reset(aUserContextId, aExpectedCookie, aPageURI, aFaviconURL);
function FaviconObserver(aUserContextId, aExpectedCookie, aPageURI, aFaviconURL, aOnlyXUL) {
this.reset(aUserContextId, aExpectedCookie, aPageURI, aFaviconURL, aOnlyXUL);
}
FaviconObserver.prototype = {
@ -73,7 +73,8 @@ FaviconObserver.prototype = {
let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
let reqLoadInfo = httpChannel.loadInfo;
let loadingPrincipal, triggeringPrincipal;
let loadingPrincipal;
let triggeringPrincipal;
// Make sure this is a favicon request.
if (httpChannel.URI.spec !== this._faviconURL) {
@ -89,10 +90,15 @@ FaviconObserver.prototype = {
is(reqLoadInfo.originAttributes.userContextId, this._curUserContextId,
"The loadInfo has correct userContextId");
ok(loadingPrincipal.equals(this._expectedPrincipal),
"The loadingPrincipal of favicon loading from content should be the content prinicpal");
ok(triggeringPrincipal.equals(this._expectedPrincipal),
"The triggeringPrincipal of favicon loading from content should be the content prinicpal");
if (loadingPrincipal.equals(systemPrincipal)) {
this._faviconReqXUL = true;
ok(triggeringPrincipal.equals(this._expectedPrincipal),
"The triggeringPrincipal of favicon loading from XUL should be the content principal.");
} else {
this._faviconReqPlaces = true;
ok(loadingPrincipal.equals(this._expectedPrincipal),
"The loadingPrincipal of favicon loading from Places should be the content prinicpal");
}
let faviconCookie = httpChannel.getRequestHeader("cookie");
@ -101,14 +107,19 @@ FaviconObserver.prototype = {
ok(false, "Received unexpected topic: ", aTopic);
}
this._faviconLoaded.resolve();
if (this._faviconReqXUL && this._faviconReqPlaces) {
this._faviconLoaded.resolve();
}
},
reset(aUserContextId, aExpectedCookie, aPageURI, aFaviconURL) {
reset(aUserContextId, aExpectedCookie, aPageURI, aFaviconURL, aOnlyXUL) {
this._curUserContextId = aUserContextId;
this._expectedCookie = aExpectedCookie;
this._expectedPrincipal = Services.scriptSecurityManager
.createCodebasePrincipal(aPageURI, { userContextId: aUserContextId });
this._faviconReqXUL = false;
// If aOnlyXUL is true, we only care about the favicon request from XUL.
this._faviconReqPlaces = aOnlyXUL === true;
this._faviconURL = aFaviconURL;
this._faviconLoaded = new Promise.defer();
},
@ -198,17 +209,18 @@ async function doTest(aTestPage, aFaviconHost, aFaviconURL) {
BrowserTestUtils.removeTab(tabInfo.tab);
}
function assertIconIsData(item) {
is(item.getAttribute("image").substring(0, 5), "data:", "Expected the image element to be a data URI");
}
async function doTestForAllTabsFavicon(aTestPage, aFaviconHost, aFaviconURL) {
await generateCookies(aFaviconHost);
let cookies = await generateCookies(aFaviconHost);
let pageURI = makeURI(aTestPage);
// Set the 'overflow' attribute to make allTabs button available.
let tabBrowser = document.getElementById("tabbrowser-tabs");
tabBrowser.setAttribute("overflow", true);
// Create the observer object for observing request channels of the personal
// container.
let observer = new FaviconObserver(USER_CONTEXT_ID_PERSONAL, cookies[0], pageURI, aFaviconURL, true);
// Add the observer earlier in case we miss it.
let promiseWaitOnFaviconLoaded = waitOnFaviconLoaded(aFaviconURL);
@ -222,19 +234,25 @@ async function doTestForAllTabsFavicon(aTestPage, aFaviconHost, aFaviconURL) {
// be made for the favicon of allTabs menuitem.
clearAllImageCaches();
// Add the observer for listening favicon requests.
Services.obs.addObserver(observer, "http-on-modify-request");
// Make the popup of allTabs showing up and trigger the loading of the favicon.
let allTabsView = document.getElementById("allTabsMenu-allTabsView");
let allTabsPopupShownPromise = BrowserTestUtils.waitForEvent(allTabsView, "ViewShown");
gTabsPanel.showAllTabsPanel();
await observer.promise;
await allTabsPopupShownPromise;
assertIconIsData(gTabsPanel.allTabsViewTabs.lastChild.firstChild);
// Close the popup of allTabs and wait until it's done.
let allTabsPopupHiddenPromise = BrowserTestUtils.waitForEvent(allTabsView.panelMultiView, "PanelMultiViewHidden");
gTabsPanel.hideAllTabsPanel();
await allTabsPopupHiddenPromise;
// Remove the observer for not receiving the favicon requests for opening a tab
// since we want to focus on the favicon of allTabs menu here.
Services.obs.removeObserver(observer, "http-on-modify-request");
// Close the tab.
BrowserTestUtils.removeTab(tabInfo.tab);
// FIXME: We need to wait for the next event tick here to avoid observing
@ -249,18 +267,25 @@ async function doTestForAllTabsFavicon(aTestPage, aFaviconHost, aFaviconURL) {
// Clear the image cache again.
clearAllImageCaches();
// Reset the observer for observing requests for the work container.
observer.reset(USER_CONTEXT_ID_WORK, cookies[1], pageURI, aFaviconURL, true);
// Add the observer back for listening the favicon requests for allTabs menuitem.
Services.obs.addObserver(observer, "http-on-modify-request");
// Make the popup of allTabs showing up again.
allTabsPopupShownPromise = BrowserTestUtils.waitForEvent(allTabsView, "ViewShown");
gTabsPanel.showAllTabsPanel();
await observer.promise;
await allTabsPopupShownPromise;
assertIconIsData(gTabsPanel.allTabsViewTabs.lastChild.firstChild);
// Close the popup of allTabs and wait until it's done.
allTabsPopupHiddenPromise = BrowserTestUtils.waitForEvent(allTabsView.panelMultiView, "PanelMultiViewHidden");
gTabsPanel.hideAllTabsPanel();
await allTabsPopupHiddenPromise;
Services.obs.removeObserver(observer, "http-on-modify-request");
// Close the tab.
BrowserTestUtils.removeTab(tabInfo.tab);

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

@ -163,7 +163,7 @@ let InternalFaviconLoader = {
});
},
loadFavicon(browser, principal, uri, expiration, iconURI) {
loadFavicon(browser, principal, uri, requestContextID) {
this.ensureInitialized();
let win = browser.ownerGlobal;
if (!gFaviconLoadDataMap.has(win)) {
@ -186,15 +186,9 @@ let InternalFaviconLoader = {
? PlacesUtils.favicons.FAVICON_LOAD_PRIVATE
: PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE;
let callback = this._makeCompletionCallback(win, innerWindowID);
if (iconURI && iconURI.schemeIs("data")) {
expiration = PlacesUtils.toPRTime(expiration);
PlacesUtils.favicons.replaceFaviconDataFromDataURL(uri, iconURI.spec,
expiration, principal);
}
let request = PlacesUtils.favicons.setAndFetchFaviconForPage(currentURI, uri, false,
loadType, callback, principal);
loadType, callback, principal,
requestContextID);
// Now register the result so we can cancel it if/when necessary.
if (!request) {
@ -311,17 +305,15 @@ var PlacesUIUtils = {
/**
* set and fetch a favicon. Can only be used from the parent process.
* @param browser {Browser} The XUL browser element for which we're fetching a favicon.
* @param principal {Principal} The loading principal to use for the fetch.
* @param uri {URI} The URI to fetch.
* @param expiration {Number} An optional expiration time.
* @param iconURI {URI} An optional data: URI holding the icon's data.
* @param browser {Browser} The XUL browser element for which we're fetching a favicon.
* @param principal {Principal} The loading principal to use for the fetch.
* @param uri {URI} The URI to fetch.
*/
loadFavicon(browser, principal, uri, expiration = 0, iconURI = null) {
loadFavicon(browser, principal, uri, requestContextID) {
if (gInContentProcess) {
throw new Error("Can't track loads from within the child process!");
}
InternalFaviconLoader.loadFavicon(browser, principal, uri, expiration, iconURI);
InternalFaviconLoader.loadFavicon(browser, principal, uri, requestContextID);
},
/**

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

@ -2108,7 +2108,7 @@ var gMainPane = {
// they'll only visit URLs derived from that template (i.e. with %s
// in the template replaced by the URL of the content being handled).
if (/^https?$/.test(uri.scheme) && Services.prefs.getBoolPref("browser.chrome.site_icons"))
if (/^https?$/.test(uri.scheme) && Services.prefs.getBoolPref("browser.chrome.favicons"))
return uri.prePath + "/favicon.ico";
return "";

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

@ -44,6 +44,8 @@ function clearAllPlacesFavicons() {
}
function observeFavicon(aIsPrivate, aExpectedCookie, aPageURI) {
let faviconReqXUL = false;
let faviconReqPlaces = false;
let attr = {};
if (aIsPrivate) {
@ -68,6 +70,7 @@ function observeFavicon(aIsPrivate, aExpectedCookie, aPageURI) {
let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
let reqLoadInfo = httpChannel.loadInfo;
let loadingPrincipal = reqLoadInfo.loadingPrincipal;
let triggeringPrincipal = reqLoadInfo.triggeringPrincipal;
// Make sure this is a favicon request.
if (httpChannel.URI.spec !== FAVICON_URI) {
@ -81,8 +84,15 @@ function observeFavicon(aIsPrivate, aExpectedCookie, aPageURI) {
is(reqLoadInfo.originAttributes.privateBrowsingId, 0, "The loadInfo has correct privateBrowsingId");
}
ok(loadingPrincipal.equals(expectedPrincipal),
"The loadingPrincipal of favicon loading from Places should be the content prinicpal");
if (loadingPrincipal.equals(systemPrincipal)) {
faviconReqXUL = true;
ok(triggeringPrincipal.equals(expectedPrincipal),
"The triggeringPrincipal of favicon loading from XUL should be the content principal.");
} else {
faviconReqPlaces = true;
ok(loadingPrincipal.equals(expectedPrincipal),
"The loadingPrincipal of favicon loading from Places should be the content prinicpal");
}
let faviconCookie = httpChannel.getRequestHeader("cookie");
@ -91,8 +101,10 @@ function observeFavicon(aIsPrivate, aExpectedCookie, aPageURI) {
ok(false, "Received unexpected topic: ", aTopic);
}
resolve();
Services.obs.removeObserver(observer, "http-on-modify-request");
if (faviconReqXUL && faviconReqPlaces) {
resolve();
Services.obs.removeObserver(observer, "http-on-modify-request");
}
}
};

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

@ -25,8 +25,9 @@ add_task(async function test() {
return gBrowser.getIcon(tab) != null;
}, "wait for favicon load to finish", 100, 5);
// Check that the tab has an 'image' attribute.
// Check that the tab has 'image' and 'iconloadingprincipal' attributes.
ok(tab.hasAttribute("image"), "tab.image exists");
ok(tab.hasAttribute("iconloadingprincipal"), "tab.iconloadingprincipal exists");
tab.toggleMuteAudio();
// Check that the tab has a 'muted' attribute.
@ -35,8 +36,10 @@ add_task(async function test() {
// Make sure we do not persist 'image' and 'muted' attributes.
ss.persistTabAttribute("image");
ss.persistTabAttribute("muted");
ss.persistTabAttribute("iconloadingprincipal");
let {attributes} = JSON.parse(ss.getTabState(tab));
ok(!("image" in attributes), "'image' attribute not saved");
ok(!("iconloadingprincipal" in attributes), "'iconloadingprincipal' attribute not saved");
ok(!("muted" in attributes), "'muted' attribute not saved");
ok(!("custom" in attributes), "'custom' attribute not saved");

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

@ -39,6 +39,13 @@ add_task(async function test_label_and_icon() {
is(gBrowser.getIcon(tab), "chrome://browser/content/robot.ico", "icon is set");
is(tab.label, "Gort! Klaatu barada nikto!", "label is set");
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let serializedPrincipal = tab.getAttribute("iconloadingprincipal");
let iconLoadingPrincipal = serhelper.deserializeObject(serializedPrincipal)
.QueryInterface(Ci.nsIPrincipal);
is(iconLoadingPrincipal.origin, "about:robots", "correct loadingPrincipal used");
// Cleanup.
BrowserTestUtils.removeTab(tab);
});

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

@ -4,21 +4,13 @@
"use strict";
const EXPORTED_SYMBOLS = ["ContentLinkHandler"];
var EXPORTED_SYMBOLS = [ "ContentLinkHandler" ];
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGlobalGetters(this, ["Blob", "FileReader"]);
ChromeUtils.defineModuleGetter(this, "Feeds",
"resource:///modules/Feeds.jsm");
ChromeUtils.defineModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
ChromeUtils.defineModuleGetter(this, "DeferredTask",
"resource://gre/modules/DeferredTask.jsm");
ChromeUtils.defineModuleGetter(this, "PromiseUtils",
"resource://gre/modules/PromiseUtils.jsm");
const SIZES_TELEMETRY_ENUM = {
NO_SIZES: 0,
@ -29,148 +21,21 @@ const SIZES_TELEMETRY_ENUM = {
const FAVICON_PARSING_TIMEOUT = 100;
const FAVICON_RICH_ICON_MIN_WIDTH = 96;
const PREFERRED_WIDTH = 16;
// URL schemes that we don't want to load and convert to data URLs.
const LOCAL_FAVICON_SCHEMES = [
"chrome",
"about",
"resource",
"data",
];
const MAX_FAVICON_EXPIRATION = 7 * 24 * 60 * 60 * 1000;
const TYPE_ICO = "image/x-icon";
const TYPE_SVG = "image/svg+xml";
function promiseBlobAsDataURL(blob) {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.addEventListener("load", () => resolve(reader.result));
reader.addEventListener("error", reject);
reader.readAsDataURL(blob);
});
}
function promiseBlobAsOctets(blob) {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.addEventListener("load", () => {
resolve(Array.from(reader.result).map(c => c.charCodeAt(0)));
});
reader.addEventListener("error", reject);
reader.readAsBinaryString(blob);
});
}
class FaviconLoad {
constructor(iconInfo) {
this.buffers = [];
this.icon = iconInfo;
this.channel = NetUtil.newChannel({
uri: iconInfo.iconUri,
loadingNode: iconInfo.node,
loadingPrincipal: iconInfo.node.nodePrincipal,
triggeringPrincipal: iconInfo.node.nodePrincipal,
contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE_FAVICON,
securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
Ci.nsILoadInfo.SEC_ALLOW_CHROME |
Ci.nsILoadInfo.SEC_DISALLOW_SCRIPT,
});
this.channel.loadFlags |= Ci.nsIRequest.LOAD_BACKGROUND;
// Sometimes node is a document and sometimes it is an element. This is
// the easiest single way to get to the load group in both those cases.
this.channel.loadGroup = iconInfo.node.ownerGlobal.document.documentLoadGroup;
if (Services.prefs.getBoolPref("network.http.tailing.enabled", true) &&
this.channel instanceof Ci.nsIClassOfService) {
this.channel.addClassFlags(Ci.nsIClassOfService.Tail | Ci.nsIClassOfService.Throttleable);
}
}
load() {
this._deferred = PromiseUtils.defer();
try {
this.channel.asyncOpen2(this);
} catch (e) {
this._deferred.reject(e);
}
return this._deferred.promise;
}
cancel() {
this._deferred.reject(Components.Exception(`Favicon load from ${this.icon.iconUri.spec} was cancelled.`, Cr.NS_BINDING_ABORTED));
this.channel.cancel(Cr.NS_BINDING_ABORTED);
}
onStartRequest(request, context) {
}
onDataAvailable(request, context, inputStream, offset, count) {
let data = NetUtil.readInputStreamToString(inputStream, count);
this.buffers.push(Uint8Array.from(data, c => c.charCodeAt(0)));
}
async onStopRequest(request, context, statusCode) {
if (!Components.isSuccessCode(statusCode)) {
// If the load was cancelled the promise will have been rejected then.
if (statusCode != Cr.NS_BINDING_ABORTED) {
this._deferred.reject(Components.Exception(`Favicon at "${this.icon.iconUri.spec}" failed to load.`, statusCode));
}
return;
}
if (this.channel instanceof Ci.nsIHttpChannel) {
if (!this.channel.requestSucceeded) {
this._deferred.reject(Components.Exception(`Favicon at "${this.icon.iconUri.spec}" failed to load: ${this.channel.responseStatusText}.`, Cr.NS_ERROR_FAILURE));
return;
}
}
// Attempt to get an expiration time from the cache. If this fails, we'll
// use this default.
let expiration = Date.now() + MAX_FAVICON_EXPIRATION;
// This stuff isn't available after onStopRequest returns (so don't start
// any async operations before this!).
if (this.channel instanceof Ci.nsICacheInfoChannel) {
expiration = Math.min(this.channel.cacheTokenExpirationTime * 1000, expiration);
}
let type = this.channel.contentType;
let blob = new Blob(this.buffers, { type });
if (type != "image/svg+xml") {
let octets = await promiseBlobAsOctets(blob);
let sniffer = Cc["@mozilla.org/image/loader;1"].
createInstance(Ci.nsIContentSniffer);
try {
type = sniffer.getMIMETypeFromContent(this.channel, octets, octets.length);
} catch (e) {
this._deferred.reject(e);
return;
}
if (!type) {
this._deferred.reject(Components.Exception(`Favicon at "${this.icon.iconUri.spec}" did not match a known mimetype.`, Cr.NS_ERROR_FAILURE));
return;
}
blob = blob.slice(0, blob.size, type);
}
let dataURL = await promiseBlobAsDataURL(blob);
this._deferred.resolve({
expiration,
dataURL,
});
}
/*
* Create a nsITimer.
*
* @param {function} aCallback A timeout callback function.
* @param {Number} aDelay A timeout interval in millisecond.
* @return {nsITimer} A nsITimer object.
*/
function setTimeout(aCallback, aDelay) {
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(aCallback, aDelay, Ci.nsITimer.TYPE_ONE_SHOT);
return timer;
}
/*
@ -232,6 +97,25 @@ function getLinkIconURI(aLink) {
return uri;
}
/*
* Set the icon via sending the "Link:Seticon" message.
*
* @param {Object} aIconInfo The IconInfo object looks like {
* iconUri: icon URI,
* loadingPrincipal: icon loading principal
* }.
* @param {Object} aChromeGlobal A global chrome object.
*/
function setIconForLink(aIconInfo, aChromeGlobal) {
aChromeGlobal.sendAsyncMessage(
"Link:SetIcon",
{ url: aIconInfo.iconUri.spec,
loadingPrincipal: aIconInfo.loadingPrincipal,
requestContextID: aIconInfo.requestContextID,
canUseForTab: !aIconInfo.isRichIcon,
});
}
/**
* Guess a type for an icon based on its declared type or file extension.
*/
@ -257,21 +141,23 @@ function guessType(icon) {
}
/*
* Selects the best rich icon and tab icon from a list of IconInfo objects.
* Timeout callback function for loading favicon.
*
* @param {Document} document The document to select icons for.
* @param {Array} iconInfos A list of IconInfo objects.
* @param {integer} preferredWidth The preferred width for tab icons.
* @param {Map} aFaviconLoads A map of page URL and FaviconLoad object pairs,
* where the FaviconLoad object looks like {
* timer: a nsITimer object,
* iconInfos: an array of IconInfo objects
* }
* @param {String} aPageUrl A page URL string for this callback.
* @param {Object} aChromeGlobal A global chrome object.
*/
function selectIcons(document, iconInfos, preferredWidth) {
if (iconInfos.length == 0) {
return {
richIcon: null,
tabIcon: null,
};
}
function faviconTimeoutCallback(aFaviconLoads, aPageUrl, aChromeGlobal) {
let load = aFaviconLoads.get(aPageUrl);
if (!load)
return;
let preferredIcon;
let preferredWidth = 16 * Math.ceil(aChromeGlobal.content.devicePixelRatio);
let bestSizedIcon;
// Other links with the "icon" tag are the default icons
let defaultIcon;
@ -279,7 +165,7 @@ function selectIcons(document, iconInfos, preferredWidth) {
// dimension 96x96 or greater
let largestRichIcon;
for (let icon of iconInfos) {
for (let icon of load.iconInfos) {
if (!icon.isRichIcon) {
// First check for svg. If it's not available check for an icon with a
// size adapt to the current resolution. If both are not available, prefer
@ -317,200 +203,111 @@ function selectIcons(document, iconInfos, preferredWidth) {
// sized fit.
// This order allows smaller icon frames to eventually override rich icon
// frames.
let tabIcon = null;
if (largestRichIcon) {
setIconForLink(largestRichIcon, aChromeGlobal);
}
if (preferredIcon) {
tabIcon = preferredIcon;
setIconForLink(preferredIcon, aChromeGlobal);
} else if (bestSizedIcon) {
tabIcon = bestSizedIcon;
setIconForLink(bestSizedIcon, aChromeGlobal);
} else if (defaultIcon) {
tabIcon = defaultIcon;
setIconForLink(defaultIcon, aChromeGlobal);
}
return {
richIcon: largestRichIcon,
tabIcon
};
load.timer = null;
aFaviconLoads.delete(aPageUrl);
}
function makeFaviconFromLink(aLink, aIsRichIcon) {
/*
* Get request context ID of the link dom node's document.
*
* @param {DOMNode} aLink A link dom node.
* @return {Number} The request context ID.
* Return null when document's load group is not available.
*/
function getLinkRequestContextID(aLink) {
try {
return aLink.ownerDocument.documentLoadGroup.requestContextID;
} catch (e) {
return null;
}
}
/*
* Favicon link handler.
*
* @param {DOMNode} aLink A link dom node.
* @param {bool} aIsRichIcon A bool to indicate if the link is rich icon.
* @param {Object} aChromeGlobal A global chrome object.
* @param {Map} aFaviconLoads A map of page URL and FaviconLoad object pairs.
* @return {bool} Returns true if the link is successfully handled.
*/
function handleFaviconLink(aLink, aIsRichIcon, aChromeGlobal, aFaviconLoads) {
let pageUrl = aLink.ownerDocument.documentURI;
let iconUri = getLinkIconURI(aLink);
if (!iconUri)
return null;
return false;
// Extract the size type and width.
let width = extractIconSize(aLink.sizes);
return {
let iconInfo = {
iconUri,
width,
isRichIcon: aIsRichIcon,
type: aLink.type,
node: aLink,
loadingPrincipal: aLink.ownerDocument.nodePrincipal,
requestContextID: getLinkRequestContextID(aLink)
};
if (aFaviconLoads.has(pageUrl)) {
let load = aFaviconLoads.get(pageUrl);
load.iconInfos.push(iconInfo);
// Re-initialize the timer
load.timer.delay = FAVICON_PARSING_TIMEOUT;
} else {
let timer = setTimeout(() => faviconTimeoutCallback(aFaviconLoads, pageUrl, aChromeGlobal),
FAVICON_PARSING_TIMEOUT);
let load = { timer, iconInfos: [iconInfo] };
aFaviconLoads.set(pageUrl, load);
}
return true;
}
class IconLoader {
constructor(chromeGlobal) {
this.chromeGlobal = chromeGlobal;
}
async load(iconInfo) {
if (this._loader) {
this._loader.cancel();
}
if (LOCAL_FAVICON_SCHEMES.includes(iconInfo.iconUri.scheme)) {
this.chromeGlobal.sendAsyncMessage("Link:SetIcon", {
originalURL: iconInfo.iconUri.spec,
canUseForTab: !iconInfo.isRichIcon,
expiration: undefined,
iconURL: iconInfo.iconUri.spec,
});
return;
}
try {
this._loader = new FaviconLoad(iconInfo);
let { dataURL, expiration } = await this._loader.load();
this._loader = null;
this.chromeGlobal.sendAsyncMessage("Link:SetIcon", {
originalURL: iconInfo.iconUri.spec,
canUseForTab: !iconInfo.isRichIcon,
expiration,
iconURL: dataURL,
});
} catch (e) {
if (e.resultCode != Cr.NS_BINDING_ABORTED) {
Cu.reportError(e);
// Used mainly for tests currently.
this.chromeGlobal.sendAsyncMessage("Link:SetFailedIcon", {
originalURL: iconInfo.iconUri.spec,
canUseForTab: !iconInfo.isRichIcon,
});
var ContentLinkHandler = {
init(chromeGlobal) {
const faviconLoads = new Map();
chromeGlobal.addEventListener("DOMLinkAdded", event => {
this.onLinkEvent(event, chromeGlobal, faviconLoads);
});
chromeGlobal.addEventListener("DOMLinkChanged", event => {
this.onLinkEvent(event, chromeGlobal, faviconLoads);
});
chromeGlobal.addEventListener("unload", event => {
for (const [pageUrl, load] of faviconLoads) {
load.timer.cancel();
load.timer = null;
faviconLoads.delete(pageUrl);
}
}
}
});
},
cancel() {
if (!this._loader) {
onLinkEvent(event, chromeGlobal, faviconLoads) {
var link = event.originalTarget;
var rel = link.rel && link.rel.toLowerCase();
if (!link || !link.ownerDocument || !rel || !link.href)
return;
}
this._loader.cancel();
this._loader = null;
}
}
class ContentLinkHandler {
constructor(chromeGlobal) {
this.chromeGlobal = chromeGlobal;
this.iconInfos = [];
this.seenTabIcon = false;
chromeGlobal.addEventListener("DOMLinkAdded", this);
chromeGlobal.addEventListener("DOMLinkChanged", this);
chromeGlobal.addEventListener("pageshow", this);
chromeGlobal.addEventListener("pagehide", this);
// For every page we attempt to find a rich icon and a tab icon. These
// objects take care of the load process for each.
this.richIconLoader = new IconLoader(chromeGlobal);
this.tabIconLoader = new IconLoader(chromeGlobal);
this.iconTask = new DeferredTask(() => this.loadIcons(), FAVICON_PARSING_TIMEOUT);
}
loadIcons() {
let preferredWidth = PREFERRED_WIDTH * Math.ceil(this.chromeGlobal.content.devicePixelRatio);
let { richIcon, tabIcon } = selectIcons(this.chromeGlobal.content.document,
this.iconInfos, preferredWidth);
this.iconInfos = [];
if (richIcon) {
this.richIconLoader.load(richIcon);
}
if (tabIcon) {
this.tabIconLoader.load(tabIcon);
}
}
addIcon(iconInfo) {
if (!Services.prefs.getBoolPref("browser.chrome.site_icons", true)) {
return;
}
if (!iconInfo.isRichIcon) {
this.seenTabIcon = true;
}
this.iconInfos.push(iconInfo);
this.iconTask.arm();
}
onPageShow(event) {
if (event.target != this.chromeGlobal.content.document) {
return;
}
if (!this.seenTabIcon && Services.prefs.getBoolPref("browser.chrome.guess_favicon", true)) {
// Currently ImageDocuments will just load the default favicon, see bug
// 403651 for discussion.
// Inject the default icon. Use documentURIObject so that we do the right
// thing with about:-style error pages. See bug 453442
let baseURI = this.chromeGlobal.content.document.documentURIObject;
if (baseURI.schemeIs("http") || baseURI.schemeIs("https")) {
let iconUri = baseURI.mutate().setPathQueryRef("/favicon.ico").finalize();
this.addIcon({
iconUri,
width: -1,
isRichIcon: false,
type: TYPE_ICO,
node: this.chromeGlobal.content.document,
});
}
}
// We're likely done with icon parsing so load the pending icons now.
if (this.iconTask.isArmed) {
this.iconTask.disarm();
this.loadIcons();
}
}
onPageHide(event) {
if (event.target != this.chromeGlobal.content.document) {
return;
}
this.richIconLoader.cancel();
this.tabIconLoader.cancel();
this.iconTask.disarm();
this.iconInfos = [];
this.seenTabIcon = false;
}
onLinkEvent(event) {
let link = event.target;
// Ignore sub-frames (bugs 305472, 479408).
if (link.ownerGlobal != this.chromeGlobal.content) {
return;
}
let rel = link.rel && link.rel.toLowerCase();
if (!rel || !link.href)
let window = link.ownerGlobal;
if (window != window.top)
return;
// Note: following booleans only work for the current link, not for the
// whole content
let feedAdded = false;
let iconAdded = false;
let searchAdded = false;
let rels = {};
var feedAdded = false;
var iconAdded = false;
var searchAdded = false;
var rels = {};
for (let relString of rel.split(/\s+/))
rels[relString] = true;
@ -525,11 +322,10 @@ class ContentLinkHandler {
break;
if (Feeds.isValidFeed(link, link.ownerDocument.nodePrincipal, "feed" in rels)) {
this.chromeGlobal.sendAsyncMessage("Link:AddFeed", {
type: link.type,
href: link.href,
title: link.title,
});
chromeGlobal.sendAsyncMessage("Link:AddFeed",
{type: link.type,
href: link.href,
title: link.title});
feedAdded = true;
}
}
@ -540,50 +336,35 @@ class ContentLinkHandler {
case "apple-touch-icon":
case "apple-touch-icon-precomposed":
case "fluid-icon":
if (iconAdded || link.hasAttribute("mask")) { // Masked icons are not supported yet.
if (link.hasAttribute("mask") || // Masked icons are not supported yet.
iconAdded ||
!Services.prefs.getBoolPref("browser.chrome.site_icons")) {
break;
}
let iconInfo = makeFaviconFromLink(link, isRichIcon);
if (iconInfo) {
iconAdded = this.addIcon(iconInfo);
}
iconAdded = handleFaviconLink(link, isRichIcon, chromeGlobal, faviconLoads);
break;
case "search":
if (Services.policies && !Services.policies.isAllowed("installSearchEngine")) {
if (Services.policies &&
!Services.policies.isAllowed("installSearchEngine")) {
break;
}
if (!searchAdded && event.type == "DOMLinkAdded") {
let type = link.type && link.type.toLowerCase();
var type = link.type && link.type.toLowerCase();
type = type.replace(/^\s+|\s*(?:;.*)?$/g, "");
let re = /^(?:https?|ftp):/i;
if (type == "application/opensearchdescription+xml" && link.title &&
re.test(link.href)) {
let engine = { title: link.title, href: link.href };
this.chromeGlobal.sendAsyncMessage("Link:AddSearch", {
engine,
url: link.ownerDocument.documentURI,
});
chromeGlobal.sendAsyncMessage("Link:AddSearch",
{engine,
url: link.ownerDocument.documentURI});
searchAdded = true;
}
}
break;
}
}
}
handleEvent(event) {
switch (event.type) {
case "pageshow":
this.onPageShow(event);
break;
case "pagehide":
this.onPageHide(event);
break;
default:
this.onLinkEvent(event);
}
}
}
},
};

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

@ -7936,17 +7936,6 @@ nsIDocument::CanSavePresentation(nsIRequest *aNewRequest)
nsCOMPtr<nsIRequest> request = do_QueryInterface(elem);
if (request && request != aNewRequest && request != baseChannel) {
// Favicon loads don't need to block caching.
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
if (channel) {
nsCOMPtr<nsILoadInfo> li;
channel->GetLoadInfo(getter_AddRefs(li));
if (li) {
if (li->InternalContentPolicyType() == nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON) {
continue;
}
}
}
#ifdef DEBUG_PAGE_CACHE
nsAutoCString requestName, docSpec;
request->GetName(requestName);

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

@ -28,6 +28,11 @@
let expectedPrincipal = securityManager.createCodebasePrincipal(makeURI(LOADING_URI), {});
let systemPrincipal = Cc["@mozilla.org/systemprincipal;1"].createInstance();
// We expect 2 favicon loads, one from PlacesUIUtils.loadFavicon and one
// from XUL:image loads.
let requestXUL = false;
let requestPlaces = false;
function runTest() {
// Register our observer to intercept favicon requests.
let os = Cc["@mozilla.org/observer-service;1"].
@ -48,11 +53,29 @@
let triggeringPrincipal = httpChannel.loadInfo.triggeringPrincipal;
let loadingPrincipal = httpChannel.loadInfo.loadingPrincipal;
ok(loadingPrincipal.equals(expectedPrincipal), "Should be loading with the expected principal.");
ok(triggeringPrincipal.equals(expectedPrincipal), "Should be triggered with the expected principal.");
if (loadingPrincipal.equals(systemPrincipal)) {
// This is the favicon loading from XUL, which will have the system
// principal as its loading principal and have a content principal
// as its triggering principal.
ok(triggeringPrincipal.equals(expectedPrincipal),
"Correct triggeringPrincipal for favicon from XUL.");
requestXUL = true;
} else if (loadingPrincipal.equals(expectedPrincipal)) {
// This is the favicon loading from Places, which will have a
// content principal as its loading principal and triggering
// principal.
ok(triggeringPrincipal.equals(expectedPrincipal),
"Correct triggeringPrincipal for favicon from Places.");
requestPlaces = true;
} else {
ok(false, "An unexpected favicon request.")
}
os.removeObserver(this, "http-on-modify-request");
SimpleTest.finish();
// Cleanup after ourselves...
if (requestXUL && requestPlaces) {
os.removeObserver(this, "http-on-modify-request");
SimpleTest.finish();
}
}
}
os.addObserver(observer, "http-on-modify-request");

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

@ -5,7 +5,6 @@ skip-if = (verify && (os == 'linux' || os == 'mac'))
support-files =
damonbowling.jpg
damonbowling.jpg^headers^
file_favicon.html
[browser_permmgr_sync.js]
# The browser_permmgr_sync test tests e10s specific behavior, and runs code
# paths which would hit the debug only assertion in

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

@ -1,9 +1,9 @@
// Tests third party cookie blocking using a favicon loaded from a different
// domain. The cookie should be considered third party.
// tests third party cookie blocking using a favicon load directly from chrome.
// in this case, the docshell of the channel is chrome, not content; thus
// the cookie should be considered third party.
add_task(async function() {
const iconUrl = "http://example.org/browser/extensions/cookie/test/damonbowling.jpg";
const pageUrl = "http://example.com/browser/extensions/cookie/test/file_favicon.html";
await SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 1]]});
let promise = TestUtils.topicObserved("cookie-rejected", subject => {
@ -11,12 +11,13 @@ add_task(async function() {
return uri.spec == iconUrl;
});
// Kick off a page load that will load the favicon.
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/");
registerCleanupFunction(async function() {
BrowserTestUtils.removeTab(tab);
});
// Kick off a favicon load.
gBrowser.setIcon(tab, iconUrl);
await promise;
ok(true, "foreign favicon cookie was blocked");
});

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

@ -1,7 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<link rel="shortcut icon" href="http://example.org/browser/extensions/cookie/test/damonbowling.jpg">
</head>
</html>

Двоичные данные
testing/mochitest/favicon.ico

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.4 KiB

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

@ -49,7 +49,6 @@ TEST_HARNESS_FILES.testing.mochitest += [
'browser-test.js',
'chrome-harness.js',
'chunkifyTests.js',
'favicon.ico',
'gen_template.pl',
'harness.xul',
'leaks.py',

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

@ -15,7 +15,6 @@ user_pref("app.update.url.android", "");
// bug 1210465.
user_pref("apz.content_response_timeout", 60000);
user_pref("browser.EULA.override", true);
user_pref("browser.chrome.guess_favicon", false);
// Make sure we don't try to load snippets from the network.
user_pref("browser.aboutHomeSnippets.updateUrl", "nonexistent://test");
// Disable Bookmark backups by default.

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

@ -0,0 +1,5 @@
[icon-blocked.sub.html]
expected: TIMEOUT
[Test that spv event is fired]
expected: NOTRUN

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

@ -59,11 +59,6 @@ function background(events) {
let url = new URL(details.url);
let filename;
if (url.protocol == "data:") {
// See bug 1471387
if (details.originUrl == "about:newtab") {
return;
}
// pathname is everything after protocol.
filename = url.pathname;
} else {
@ -262,6 +257,10 @@ function background(events) {
browser.test.assertTrue(expectedEvent, `received ${name}`);
browser.test.assertEq(expected.type, details.type, "resource type is correct");
browser.test.assertEq(expected.origin || defaultOrigin, details.originUrl, "origin is correct");
// ignore origin test for generated background page
if (!details.originUrl || !details.originUrl.endsWith("_generated_background_page.html")) {
browser.test.assertEq(expected.origin || defaultOrigin, details.originUrl, "origin is correct");
}
if (name != "onBeforeRequest") {
// On events after onBeforeRequest, check the previous values.

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

@ -53,7 +53,6 @@ support-files =
file_redirect_data_uri.html
prefs =
security.mixed_content.upgrade_display_content=false
browser.chrome.guess_favicon=true
[test_ext_background_canvas.html]
[test_ext_background_page.html]

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

@ -30,10 +30,6 @@ add_task(async function setup() {
let imgTools = SpecialPowers.Cc["@mozilla.org/image/tools;1"].getService(SpecialPowers.Ci.imgITools);
let cache = imgTools.getImgCacheForDocument(document);
cache.clearCache(false);
function clearCache() {
ChromeUtils.import("resource://gre/modules/Services.jsm", {}).Services.cache2.clear();
}
SpecialPowers.loadChromeScript(clearCache);
await SpecialPowers.pushPrefEnv({
set: [["network.http.rcwn.enabled", false]],
@ -54,7 +50,6 @@ add_task(async function setup() {
// cancel: event in which we return cancel=true. cancelled message is sent.
// cached: expected fromCache value, default is false, checked in onCompletion
// headers: request or response headers to modify
// origin: The expected originUrl, a default origin can be passed for all files
add_task(async function test_webRequest_links() {
let expect = {
@ -273,24 +268,14 @@ add_task(async function test_webRequest_tabId() {
});
await tabExt.startup();
let linkUrl = `file_WebRequest_page3.html?trigger=a&nocache=${Math.random()}`;
let expect = {
"file_WebRequest_page3.html": {
type: "main_frame",
},
};
if (AppConstants.platform != "android") {
expect["favicon.ico"] = {
type: "image",
origin: SimpleTest.getTestFileURL(linkUrl),
cached: false,
};
}
extension.sendMessage("set-expected", {expect, origin: location.href});
await extension.awaitMessage("continue");
let a = addLink(linkUrl);
let a = addLink(`file_WebRequest_page3.html?trigger=a&nocache=${Math.random()}`);
a.click();
await extension.awaitMessage("done");
@ -313,14 +298,13 @@ add_task(async function test_webRequest_tabId_browser() {
tabId = tab.id;
}
let pageUrl = `${SimpleTest.getTestFileURL("file_sample.html")}?nocache=${Math.random()}`;
let tabExt = ExtensionTestUtils.loadExtension({
manifest: {
permissions: [
"tabs",
],
},
background: `(${background})('${pageUrl}')`,
background: `(${background})('${SimpleTest.getTestFileURL("file_sample.html")}?nocache=${Math.random()}')`,
});
let expect = {
@ -328,15 +312,6 @@ add_task(async function test_webRequest_tabId_browser() {
type: "main_frame",
},
};
if (AppConstants.platform != "android") {
expect["favicon.ico"] = {
type: "image",
origin: pageUrl,
cached: true,
};
}
// expecting origin == undefined
extension.sendMessage("set-expected", {expect});
await extension.awaitMessage("continue");

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

@ -20,7 +20,7 @@ let windowData, testWindow;
add_task(async function setup() {
let chromeScript = SpecialPowers.loadChromeScript(function() {
ChromeUtils.import("resource://gre/modules/Services.jsm", {}).Services.cache2.clear();
Services.cache2.clear();
});
chromeScript.destroy();
@ -78,13 +78,6 @@ add_task(async function test_webRequest_filter_window() {
},
};
if (AppConstants.platform != "android") {
expect["favicon.ico"] = {
type: "image",
origin: SimpleTest.getTestFileURL("file_image_bad.png"),
};
}
let extension = makeExtension(events);
await extension.startup();
extension.sendMessage("set-expected", {expect, origin: location.href});
@ -133,13 +126,6 @@ add_task(async function test_webRequest_filter_tab() {
},
};
if (AppConstants.platform != "android") {
expect["favicon.ico"] = {
type: "image",
origin: SimpleTest.getTestFileURL(img),
};
}
let extension = makeExtension(events);
await extension.startup();
extension.sendMessage("set-expected", {expect, origin: location.href});

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

@ -124,24 +124,9 @@ let expected = {
},
};
if (AppConstants.platform != "android") {
expected["favicon.ico"] = {
type: "image",
toplevel: true,
origin: "file_simple_xhr.html",
cached: false,
};
}
function checkDetails(details) {
// See bug 1471387
if (details.originUrl == "about:newtab") {
return;
}
let url = new URL(details.url);
let filename = url.pathname.split(url.protocol == "data:" ? "," : "/").pop();
ok(filename in expected, `Should be expecting a request for ${filename}`);
let expect = expected[filename];
is(expect.type, details.type, `${details.type} type matches`);
if (details.parentFrameId == -1) {
@ -192,10 +177,6 @@ add_task(async function test_webRequest_main_frame() {
let imgTools = SpecialPowers.Cc["@mozilla.org/image/tools;1"].getService(SpecialPowers.Ci.imgITools);
let cache = imgTools.getImgCacheForDocument(document);
cache.clearCache(false);
function clearCache() {
ChromeUtils.import("resource://gre/modules/Services.jsm", {}).Services.cache2.clear();
}
SpecialPowers.loadChromeScript(clearCache);
let extension = ExtensionTestUtils.loadExtension(extensionData);
await extension.startup();

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

@ -98,10 +98,6 @@ function background() {
browser.webRequest.onCompleted.addListener(
details => {
browser.test.log(`onCompleted ${details.requestId} ${details.url}`);
// See bug 1471387
if (details.url.endsWith("/favicon.ico") || details.originUrl == "about:newtab") {
return;
}
browser.test.sendMessage("done");
},
@ -109,10 +105,6 @@ function background() {
let onBeforeRequest = details => {
browser.test.log(`${name} ${details.requestId} ${details.url}`);
// See bug 1471387
if (details.url.endsWith("/favicon.ico") || details.originUrl == "about:newtab") {
return;
}
onUpload(details);
};

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

@ -2,7 +2,7 @@
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; img-src data: *; media-src *" />
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; img-src *; media-src *" />
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
<meta name="viewport" content="width=device-width; user-scalable=0" />
<link rel="stylesheet" href="chrome://global/skin/aboutReader.css" type="text/css"/>