Bug 910036 - about:newtab shouldn't load thumbnails in background when hidden by preloader. r=gavin
This commit is contained in:
@@ -31,6 +31,15 @@ let gPage = {
|
||||
this._updateAttributes(enabled);
|
||||
},
|
||||
|
||||
/**
|
||||
* True if the page is allowed to capture thumbnails using the background
|
||||
* thumbnail service.
|
||||
*/
|
||||
get allowBackgroundCaptures() {
|
||||
return document.documentElement.getAttribute("allow-background-captures") ==
|
||||
"true";
|
||||
},
|
||||
|
||||
/**
|
||||
* Listens for notifications specific to this page.
|
||||
*/
|
||||
@@ -74,6 +83,20 @@ let gPage = {
|
||||
|
||||
this._initialized = true;
|
||||
|
||||
this._mutationObserver = new MutationObserver(() => {
|
||||
if (this.allowBackgroundCaptures) {
|
||||
for (let site of gGrid.sites) {
|
||||
if (site) {
|
||||
site.captureIfMissing();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
this._mutationObserver.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ["allow-background-captures"],
|
||||
});
|
||||
|
||||
gLinks.populateCache(function () {
|
||||
// Initialize and render the grid.
|
||||
gGrid.init();
|
||||
@@ -123,6 +146,7 @@ let gPage = {
|
||||
handleEvent: function Page_handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "unload":
|
||||
this._mutationObserver.disconnect();
|
||||
gAllPages.unregister(this);
|
||||
break;
|
||||
case "click":
|
||||
|
||||
31
browser/base/content/newtab/preloaderContent.js
Normal file
31
browser/base/content/newtab/preloaderContent.js
Normal file
@@ -0,0 +1,31 @@
|
||||
/* 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/. */
|
||||
|
||||
(function () { // bug 673569 workaround :(
|
||||
|
||||
const ALLOW_BG_CAPTURES_MSG = "BrowserNewTabPreloader:allowBackgroundCaptures";
|
||||
|
||||
addMessageListener(ALLOW_BG_CAPTURES_MSG, function onMsg(msg) {
|
||||
removeMessageListener(ALLOW_BG_CAPTURES_MSG, onMsg);
|
||||
|
||||
if (content.document.readyState == "complete") {
|
||||
setAllowBackgroundCaptures();
|
||||
return;
|
||||
}
|
||||
|
||||
// This is the case when preloading is disabled.
|
||||
addEventListener("load", function onLoad(event) {
|
||||
if (event.target == content.document) {
|
||||
removeEventListener("load", onLoad, true);
|
||||
setAllowBackgroundCaptures();
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
|
||||
function setAllowBackgroundCaptures() {
|
||||
content.document.documentElement.setAttribute("allow-background-captures",
|
||||
"true");
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -133,11 +133,20 @@ Site.prototype = {
|
||||
this._updateAttributes(true);
|
||||
// Capture the page if the thumbnail is missing, which will cause page.js
|
||||
// to be notified and call our refreshThumbnail() method.
|
||||
BackgroundPageThumbs.captureIfMissing(this.url);
|
||||
this.captureIfMissing();
|
||||
// but still display whatever thumbnail might be available now.
|
||||
this.refreshThumbnail();
|
||||
},
|
||||
|
||||
/**
|
||||
* Captures the site's thumbnail in the background, but only if there's no
|
||||
* existing thumbnail and the page allows background captures.
|
||||
*/
|
||||
captureIfMissing: function Site_captureIfMissing() {
|
||||
if (gPage.allowBackgroundCaptures)
|
||||
BackgroundPageThumbs.captureIfMissing(this.url);
|
||||
},
|
||||
|
||||
/**
|
||||
* Refreshes the thumbnail for the site.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[DEFAULT]
|
||||
support-files = head.js
|
||||
|
||||
[browser_newtab_background_captures.js]
|
||||
[browser_newtab_block.js]
|
||||
[browser_newtab_bug721442.js]
|
||||
[browser_newtab_bug722273.js]
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Verifies that hidden, pre-loaded newtabs don't allow background captures, and
|
||||
* when unhidden, do allow background captures.
|
||||
*/
|
||||
|
||||
const CAPTURE_PREF = "browser.pagethumbnails.capturing_disabled";
|
||||
|
||||
function runTests() {
|
||||
let imports = {};
|
||||
Cu.import("resource://gre/modules/PageThumbs.jsm", imports);
|
||||
Cu.import("resource:///modules/BrowserNewTabPreloader.jsm", imports);
|
||||
|
||||
// Disable captures.
|
||||
let originalDisabledState = Services.prefs.getBoolPref(CAPTURE_PREF);
|
||||
Services.prefs.setBoolPref(CAPTURE_PREF, true);
|
||||
|
||||
// Make sure the thumbnail doesn't exist yet.
|
||||
let siteName = "newtab_background_captures";
|
||||
let url = "http://example.com/#" + siteName;
|
||||
let path = imports.PageThumbsStorage.getFilePathForURL(url);
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
file.initWithPath(path);
|
||||
try {
|
||||
file.remove(false);
|
||||
}
|
||||
catch (err) {}
|
||||
|
||||
// Add a top site.
|
||||
yield setLinks(siteName);
|
||||
|
||||
// We need a handle to a hidden, pre-loaded newtab so we can verify that it
|
||||
// doesn't allow background captures. Add a newtab, which triggers creation
|
||||
// of a hidden newtab, and then keep calling BrowserNewTabPreloader.newTab
|
||||
// until it returns true, meaning that it swapped the passed-in tab's docshell
|
||||
// for the hidden newtab docshell.
|
||||
let tab = gWindow.gBrowser.addTab("about:blank");
|
||||
yield addNewTabPageTab();
|
||||
let swapWaitCount = 0;
|
||||
let swapped = imports.BrowserNewTabPreloader.newTab(tab);
|
||||
while (!swapped) {
|
||||
if (++swapWaitCount == 10) {
|
||||
ok(false, "Timed out waiting for newtab docshell swap.");
|
||||
return;
|
||||
}
|
||||
// Give the hidden newtab some time to finish loading.
|
||||
yield wait(2000);
|
||||
info("Checking newtab swap " + swapWaitCount);
|
||||
swapped = imports.BrowserNewTabPreloader.newTab(tab);
|
||||
}
|
||||
|
||||
// The tab's docshell is now the previously hidden newtab docshell.
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
isnot(doc.documentElement.getAttribute("allow-background-captures"), "true",
|
||||
"Pre-loaded docshell just synchronously swapped, so background " +
|
||||
"captures should not be allowed yet");
|
||||
|
||||
// Enable captures.
|
||||
Services.prefs.setBoolPref(CAPTURE_PREF, false);
|
||||
|
||||
// Now that the newtab is visible, its allow-background-captures attribute
|
||||
// should be set eventually.
|
||||
let allowBackgroundCaptures = false;
|
||||
let mutationObserver = new MutationObserver(() => {
|
||||
mutationObserver.disconnect();
|
||||
allowBackgroundCaptures = true;
|
||||
is(doc.documentElement.getAttribute("allow-background-captures"), "true",
|
||||
"allow-background-captures should now be true");
|
||||
info("Waiting for thumbnail to be created after observing " +
|
||||
"allow-background-captures change");
|
||||
});
|
||||
mutationObserver.observe(doc.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ["allow-background-captures"],
|
||||
});
|
||||
|
||||
// And the allow-background-captures change should trigger the thumbnail
|
||||
// capture.
|
||||
Services.obs.addObserver(function onCreate(subj, topic, data) {
|
||||
if (data != url)
|
||||
return;
|
||||
ok(allowBackgroundCaptures,
|
||||
"page-thumbnail:create should be observed after " +
|
||||
"allow-background-captures was set");
|
||||
Services.obs.removeObserver(onCreate, "page-thumbnail:create");
|
||||
// Test finished!
|
||||
Services.prefs.setBoolPref(CAPTURE_PREF, originalDisabledState);
|
||||
file.remove(false);
|
||||
TestRunner.next();
|
||||
}, "page-thumbnail:create", false);
|
||||
|
||||
info("Waiting for allow-background-captures change");
|
||||
yield true;
|
||||
}
|
||||
|
||||
function wait(ms) {
|
||||
setTimeout(TestRunner.next, ms);
|
||||
}
|
||||
@@ -64,6 +64,7 @@ browser.jar:
|
||||
content/browser/newtab/newTab.xul (content/newtab/newTab.xul)
|
||||
* content/browser/newtab/newTab.js (content/newtab/newTab.js)
|
||||
content/browser/newtab/newTab.css (content/newtab/newTab.css)
|
||||
content/browser/newtab/preloaderContent.js (content/newtab/preloaderContent.js)
|
||||
* content/browser/pageinfo/pageInfo.xul (content/pageinfo/pageInfo.xul)
|
||||
content/browser/pageinfo/pageInfo.js (content/pageinfo/pageInfo.js)
|
||||
content/browser/pageinfo/pageInfo.css (content/pageinfo/pageInfo.css)
|
||||
|
||||
@@ -35,6 +35,8 @@ const TOPIC_TIMER_CALLBACK = "timer-callback";
|
||||
const TOPIC_DELAYED_STARTUP = "browser-delayed-startup-finished";
|
||||
const TOPIC_XUL_WINDOW_CLOSED = "xul-window-destroyed";
|
||||
|
||||
const FRAME_SCRIPT_URL = "chrome://browser/content/newtab/preloaderContent.js";
|
||||
|
||||
function createTimer(obj, delay) {
|
||||
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.init(obj, delay, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
@@ -61,6 +63,7 @@ this.BrowserNewTabPreloader = {
|
||||
},
|
||||
|
||||
newTab: function Preloader_newTab(aTab) {
|
||||
let swapped = false;
|
||||
let win = aTab.ownerDocument.defaultView;
|
||||
if (win.gBrowser) {
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
@@ -69,11 +72,17 @@ this.BrowserNewTabPreloader = {
|
||||
let {width, height} = utils.getBoundsWithoutFlushing(win.gBrowser);
|
||||
let hiddenBrowser = HiddenBrowsers.get(width, height)
|
||||
if (hiddenBrowser) {
|
||||
return hiddenBrowser.swapWithNewTab(aTab);
|
||||
swapped = hiddenBrowser.swapWithNewTab(aTab);
|
||||
}
|
||||
|
||||
// aTab's browser is now visible and is therefore allowed to make
|
||||
// background captures.
|
||||
let msgMan = aTab.linkedBrowser.messageManager;
|
||||
msgMan.loadFrameScript(FRAME_SCRIPT_URL, false);
|
||||
msgMan.sendAsyncMessage("BrowserNewTabPreloader:allowBackgroundCaptures");
|
||||
}
|
||||
|
||||
return false;
|
||||
return swapped;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user