зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1294199: Part 2 - Fix rendering of SDK panels in private browsing windows. r=gabor
MozReview-Commit-ID: 6nCyoHUHyZb --HG-- extra : rebase_source : ac27225296a5b93494c3cf67618f04c4f81cc17a
This commit is contained in:
Родитель
afd82f6743
Коммит
bad6103170
|
@ -9,6 +9,7 @@ module.metadata = {
|
|||
};
|
||||
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const { Services } = require("resource://gre/modules/Services.jsm");
|
||||
const { setTimeout } = require("../timers");
|
||||
const { platform } = require("../system");
|
||||
const { getMostRecentBrowserWindow, getOwnerBrowserWindow,
|
||||
|
@ -186,6 +187,13 @@ function display(panel, options, anchor) {
|
|||
panel.setAttribute("flip", "both");
|
||||
}
|
||||
|
||||
panel.viewFrame = document.importNode(panel.backgroundFrame, false);
|
||||
panel.appendChild(panel.viewFrame);
|
||||
|
||||
let {privateBrowsingId} = getDocShell(panel.viewFrame).getOriginAttributes();
|
||||
let principal = Services.scriptSecurityManager.createNullPrincipal({privateBrowsingId});
|
||||
getDocShell(panel.viewFrame).createAboutBlankContentViewer(principal);
|
||||
|
||||
// Resize the iframe instead of using panel.sizeTo
|
||||
// because sizeTo doesn't work with arrow panels
|
||||
panel.firstChild.style.width = width + "px";
|
||||
|
@ -252,12 +260,10 @@ function make(document, options) {
|
|||
document = document || getMostRecentBrowserWindow().document;
|
||||
let panel = document.createElementNS(XUL_NS, "panel");
|
||||
panel.setAttribute("type", "arrow");
|
||||
panel.setAttribute("sdkscriptenabled", "" + options.allowJavascript);
|
||||
panel.setAttribute("sdkscriptenabled", options.allowJavascript);
|
||||
|
||||
// Note that panel is a parent of `viewFrame` who's `docShell` will be
|
||||
// configured at creation time. If `panel` and there for `viewFrame` won't
|
||||
// have an owner document attempt to access `docShell` will throw. There
|
||||
// for we attach panel to a document.
|
||||
// The panel needs to be attached to a browser window in order for us
|
||||
// to copy browser styles to the content document when it loads.
|
||||
attach(panel, document);
|
||||
|
||||
let frameOptions = {
|
||||
|
@ -269,34 +275,29 @@ function make(document, options) {
|
|||
// history and in consequence do not dispatch "inner-window-destroyed"
|
||||
// notifications.
|
||||
browser: false,
|
||||
// Note that use of this URL let's use swap frame loaders earlier
|
||||
// than if we used default "about:blank".
|
||||
uri: "data:text/plain;charset=utf-8,"
|
||||
};
|
||||
|
||||
let backgroundFrame = createFrame(addonWindow, frameOptions);
|
||||
setupPanelFrame(backgroundFrame);
|
||||
|
||||
let viewFrame = createFrame(panel, frameOptions);
|
||||
setupPanelFrame(viewFrame);
|
||||
getDocShell(backgroundFrame).inheritPrivateBrowsingId = false;
|
||||
|
||||
function onDisplayChange({type, target}) {
|
||||
// Events from child element like <select /> may propagate (dropdowns are
|
||||
// popups too), in which case frame loader shouldn't be swapped.
|
||||
// See Bug 886329
|
||||
if (target !== this) return;
|
||||
function onPopupShowing({type, target}) {
|
||||
if (target === this) {
|
||||
let attrs = getDocShell(backgroundFrame).getOriginAttributes();
|
||||
getDocShell(panel.viewFrame).setOriginAttributes(attrs);
|
||||
|
||||
try {
|
||||
swapFrameLoaders(backgroundFrame, viewFrame);
|
||||
// We need to re-set this because... swapFrameLoaders. Or something.
|
||||
let shouldEnableScript = panel.getAttribute("sdkscriptenabled") == "true";
|
||||
getDocShell(backgroundFrame).allowJavascript = shouldEnableScript;
|
||||
getDocShell(viewFrame).allowJavascript = shouldEnableScript;
|
||||
swapFrameLoaders(backgroundFrame, panel.viewFrame);
|
||||
}
|
||||
catch(error) {
|
||||
console.exception(error);
|
||||
}
|
||||
|
||||
function onPopupHiding({type, target}) {
|
||||
if (target === this) {
|
||||
swapFrameLoaders(backgroundFrame, panel.viewFrame);
|
||||
|
||||
panel.viewFrame.remove();
|
||||
panel.viewFrame = null;
|
||||
}
|
||||
events.emit(type, { subject: panel });
|
||||
}
|
||||
|
||||
function onContentReady({target, type}) {
|
||||
|
@ -316,14 +317,15 @@ function make(document, options) {
|
|||
events.emit(type, { subject: panel });
|
||||
}
|
||||
|
||||
function onPanelStateChange({type}) {
|
||||
events.emit(type, { subject: panel })
|
||||
function onPanelStateChange({target, type}) {
|
||||
if (target === this)
|
||||
events.emit(type, { subject: panel })
|
||||
}
|
||||
|
||||
panel.addEventListener("popupshowing", onDisplayChange, false);
|
||||
panel.addEventListener("popuphiding", onDisplayChange, false);
|
||||
panel.addEventListener("popupshown", onPanelStateChange, false);
|
||||
panel.addEventListener("popuphidden", onPanelStateChange, false);
|
||||
panel.addEventListener("popupshowing", onPopupShowing);
|
||||
panel.addEventListener("popuphiding", onPopupHiding);
|
||||
for (let event of ["popupshowing", "popuphiding", "popupshown", "popuphidden"])
|
||||
panel.addEventListener(event, onPanelStateChange);
|
||||
|
||||
panel.addEventListener("click", onPanelClick, false);
|
||||
|
||||
|
@ -339,9 +341,8 @@ function make(document, options) {
|
|||
|
||||
events.on("document-element-inserted", onContentChange);
|
||||
|
||||
|
||||
panel.backgroundFrame = backgroundFrame;
|
||||
panel.viewFrame = viewFrame;
|
||||
panel.viewFrame = null;
|
||||
|
||||
// Store event listener on the panel instance so that it won't be GC-ed
|
||||
// while panel is alive.
|
||||
|
@ -368,9 +369,7 @@ exports.detach = detach;
|
|||
|
||||
function dispose(panel) {
|
||||
panel.backgroundFrame.remove();
|
||||
panel.viewFrame.remove();
|
||||
panel.backgroundFrame = null;
|
||||
panel.viewFrame = null;
|
||||
events.off("document-element-inserted", panel.onContentChange);
|
||||
panel.onContentChange = null;
|
||||
detach(panel);
|
||||
|
@ -392,11 +391,7 @@ function style(panel) {
|
|||
let contentDocument = getContentDocument(panel);
|
||||
let window = document.defaultView;
|
||||
let node = document.getAnonymousElementByAttribute(panel, "class",
|
||||
"panel-arrowcontent") ||
|
||||
// Before bug 764755, anonymous content was different:
|
||||
// TODO: Remove this when targeting FF16+
|
||||
document.getAnonymousElementByAttribute(panel, "class",
|
||||
"panel-inner-arrowcontent");
|
||||
"panel-arrowcontent");
|
||||
|
||||
let { color, fontFamily, fontSize, fontWeight } = window.getComputedStyle(node);
|
||||
|
||||
|
@ -424,10 +419,7 @@ function style(panel) {
|
|||
}
|
||||
exports.style = style;
|
||||
|
||||
var getContentFrame = panel =>
|
||||
(isOpen(panel) || isOpening(panel)) ?
|
||||
panel.firstChild :
|
||||
panel.backgroundFrame
|
||||
var getContentFrame = panel => panel.viewFrame || panel.backgroundFrame;
|
||||
exports.getContentFrame = getContentFrame;
|
||||
|
||||
function getContentDocument(panel) {
|
||||
|
@ -436,7 +428,10 @@ function getContentDocument(panel) {
|
|||
exports.getContentDocument = getContentDocument;
|
||||
|
||||
function setURL(panel, url) {
|
||||
getContentFrame(panel).setAttribute("src", url ? data.url(url) : url);
|
||||
let frame = getContentFrame(panel);
|
||||
let webNav = getDocShell(frame).QueryInterface(Ci.nsIWebNavigation);
|
||||
|
||||
webNav.loadURI(url ? data.url(url) : "about:blank", 0, null, null, null);
|
||||
}
|
||||
|
||||
exports.setURL = setURL;
|
||||
|
|
|
@ -7,6 +7,8 @@ const { open, focus, close } = require('sdk/window/helpers');
|
|||
const { isPrivate } = require('sdk/private-browsing');
|
||||
const { defer } = require('sdk/core/promise');
|
||||
const { browserWindows: windows } = require('sdk/windows');
|
||||
const { getInnerId, getMostRecentBrowserWindow } = require('sdk/window/utils');
|
||||
const { getActiveView } = require('sdk/view/core');
|
||||
|
||||
const BROWSER = 'chrome://browser/content/browser.xul';
|
||||
|
||||
|
@ -17,7 +19,7 @@ exports.testRequirePanel = function(assert) {
|
|||
|
||||
exports.testShowPanelInPrivateWindow = function(assert, done) {
|
||||
let panel = require('sdk/panel').Panel({
|
||||
contentURL: "data:text/html;charset=utf-8,"
|
||||
contentURL: "data:text/html;charset=utf-8,I'm a leaf on the wind"
|
||||
});
|
||||
|
||||
assert.ok(windows.length > 0, 'there is at least one open window');
|
||||
|
@ -25,7 +27,50 @@ exports.testShowPanelInPrivateWindow = function(assert, done) {
|
|||
assert.equal(isPrivate(window), false, 'open window is private');
|
||||
}
|
||||
|
||||
testShowPanel(assert, panel).
|
||||
let panelView = getActiveView(panel);
|
||||
let expectedWindowId = getInnerId(panelView.backgroundFrame.contentWindow);
|
||||
|
||||
function checkPanelFrame() {
|
||||
let iframe = panelView.firstChild;
|
||||
|
||||
assert.equal(panelView.viewFrame, iframe, 'panel has the correct viewFrame value');
|
||||
|
||||
let windowId = getInnerId(iframe.contentWindow);
|
||||
|
||||
assert.equal(windowId, expectedWindowId, 'panel has the correct window visible');
|
||||
|
||||
assert.equal(iframe.contentDocument.body.textContent,
|
||||
"I'm a leaf on the wind",
|
||||
'the panel has the expected content');
|
||||
}
|
||||
|
||||
function testPanel(window) {
|
||||
let { promise, resolve } = defer();
|
||||
|
||||
assert.ok(!panel.isShowing, 'the panel is not showing [1]');
|
||||
|
||||
panel.once('show', function() {
|
||||
assert.ok(panel.isShowing, 'the panel is showing');
|
||||
|
||||
checkPanelFrame();
|
||||
|
||||
panel.once('hide', function() {
|
||||
assert.ok(!panel.isShowing, 'the panel is not showing [2]');
|
||||
|
||||
resolve(window);
|
||||
});
|
||||
|
||||
panel.hide();
|
||||
});
|
||||
|
||||
panel.show();
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
let initialWindow = getMostRecentBrowserWindow();
|
||||
|
||||
testPanel(initialWindow).
|
||||
then(makeEmptyPrivateBrowserWindow).
|
||||
then(focus).
|
||||
then(function(window) {
|
||||
|
@ -33,28 +78,10 @@ exports.testShowPanelInPrivateWindow = function(assert, done) {
|
|||
assert.pass('private window was focused');
|
||||
return window;
|
||||
}).
|
||||
then(function(window) {
|
||||
let { promise, resolve } = defer();
|
||||
|
||||
assert.ok(!panel.isShowing, 'the panel is not showing [1]');
|
||||
|
||||
panel.once('show', function() {
|
||||
assert.ok(panel.isShowing, 'the panel is showing');
|
||||
|
||||
panel.once('hide', function() {
|
||||
assert.ok(!panel.isShowing, 'the panel is not showing [2]');
|
||||
|
||||
resolve(window);
|
||||
});
|
||||
|
||||
panel.hide();
|
||||
});
|
||||
|
||||
panel.show();
|
||||
|
||||
return promise;
|
||||
}).
|
||||
then(testPanel).
|
||||
then(close).
|
||||
then(() => focus(initialWindow)).
|
||||
then(testPanel).
|
||||
then(done).
|
||||
then(null, assert.fail);
|
||||
};
|
||||
|
@ -70,32 +97,3 @@ function makeEmptyPrivateBrowserWindow(options) {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testShowPanel(assert, panel) {
|
||||
let { promise, resolve } = defer();
|
||||
let shown = false;
|
||||
|
||||
assert.ok(!panel.isShowing, 'the panel is not showing [1]');
|
||||
|
||||
panel.once('hide', function() {
|
||||
assert.ok(!panel.isShowing, 'the panel is not showing [2]');
|
||||
assert.ok(shown, 'the panel was shown')
|
||||
|
||||
resolve(null);
|
||||
});
|
||||
|
||||
panel.once('show', function() {
|
||||
shown = true;
|
||||
|
||||
assert.ok(panel.isShowing, 'the panel is showing');
|
||||
|
||||
panel.hide();
|
||||
});
|
||||
|
||||
panel.show();
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
//Test disabled because of bug 911071
|
||||
module.exports = {}
|
||||
|
|
Загрузка…
Ссылка в новой задаче