Bug 1141041 - Stop using CPOWs for the Page Style menu. r=Gijs

Instead of using a CPOW to synchronously grab the stylesheet information
from the currently loaded tab, each tab now sends up the stylesheet
information once they've finished loading for the parent to cache.

Unfortunately, the cache will not be invalidated if the stylesheets on
a page are dynamically altered with script.

--HG--
extra : commitid : 2hUmENX2xHY
extra : rebase_source : c6464f56ebcc2444bd8974b1d81f3fe96660f3ea
This commit is contained in:
Mike Conley 2015-10-02 10:03:51 -04:00
parent 8954b74bea
commit 218c8bb1c0
2 changed files with 80 additions and 34 deletions

View File

@ -5858,38 +5858,79 @@ function UpdateCurrentCharset(target) {
}
var gPageStyleMenu = {
// This maps from a <browser> element (or, more specifically, a
// browser's permanentKey) to a CPOW that gives synchronous access
// to the list of style sheets in a content window. The use of the
// permanentKey is to avoid issues with docshell swapping.
_pageStyleSyncHandlers: new WeakMap(),
// browser's permanentKey) to an Object that contains the most recent
// information about the browser content's stylesheets. That Object
// is populated via the PageStyle:StyleSheets message from the content
// process. The Object should have the following structure:
//
// filteredStyleSheets (Array):
// An Array of objects with a filtered list representing all stylesheets
// that the current page offers. Each object has the following members:
//
// title (String):
// The title of the stylesheet
//
// disabled (bool):
// Whether or not the stylesheet is currently applied
//
// href (String):
// The URL of the stylesheet. Stylesheets loaded via a data URL will
// have this property set to null.
//
// authorStyleDisabled (bool):
// Whether or not the user currently has "No Style" selected for
// the current page.
//
// preferredStyleSheetSet (bool):
// Whether or not the user currently has the "Default" style selected
// for the current page.
//
_pageStyleSheets: new WeakMap(),
init: function() {
let mm = window.messageManager;
mm.addMessageListener("PageStyle:SetSyncHandler", (msg) => {
this._pageStyleSyncHandlers.set(msg.target.permanentKey, msg.objects.syncHandler);
mm.addMessageListener("PageStyle:StyleSheets", (msg) => {
this._pageStyleSheets.set(msg.target.permanentKey, msg.data);
});
},
getAllStyleSheets: function () {
let handler = this._pageStyleSyncHandlers.get(gBrowser.selectedBrowser.permanentKey);
try {
return handler.getAllStyleSheets();
} catch (ex) {
// In case the child died or timed out.
/**
* Returns an array of Objects representing stylesheets in a
* browser. Note that the pageshow event needs to fire in content
* before this information will be available.
*
* @param browser (optional)
* The <xul:browser> to search for stylesheets. If omitted, this
* defaults to the currently selected tab's browser.
* @returns Array
* An Array of Objects representing stylesheets in the browser.
* See the documentation for gPageStyleMenu for a description
* of the Object structure.
*/
getBrowserStyleSheets: function (browser) {
if (!browser) {
browser = gBrowser.selectedBrowser;
}
let data = this._pageStyleSheets.get(browser.permanentKey);
if (!data) {
return [];
}
return data.filteredStyleSheets;
},
_getStyleSheetInfo: function (browser) {
let handler = this._pageStyleSyncHandlers.get(gBrowser.selectedBrowser.permanentKey);
try {
return handler.getStyleSheetInfo();
} catch (ex) {
// In case the child died or timed out.
return {styleSheets: [], authorStyleDisabled: false, preferredStyleSheetSet: true};
let data = this._pageStyleSheets.get(browser.permanentKey);
if (!data) {
return {
filteredStyleSheets: [],
authorStyleDisabled: false,
preferredStyleSheetSet: true
};
}
return data;
},
fillPopup: function (menuPopup) {
@ -5900,7 +5941,7 @@ var gPageStyleMenu = {
while (sep.nextSibling)
menuPopup.removeChild(sep.nextSibling);
let styleSheets = styleSheetInfo.styleSheets;
let styleSheets = styleSheetInfo.filteredStyleSheets;
var currentStyleSheets = {};
var styleDisabled = styleSheetInfo.authorStyleDisabled;
var haveAltSheets = false;
@ -5948,7 +5989,6 @@ var gPageStyleMenu = {
};
/* Legacy global page-style functions */
var getAllStyleSheets = gPageStyleMenu.getAllStyleSheets.bind(gPageStyleMenu);
var stylesheetFillPopup = gPageStyleMenu.fillPopup.bind(gPageStyleMenu);
function stylesheetSwitchAll(contentWindow, title) {
// We ignore the contentWindow param. Add-ons don't appear to use

View File

@ -432,27 +432,23 @@ var PageStyleHandler = {
init: function() {
addMessageListener("PageStyle:Switch", this);
addMessageListener("PageStyle:Disable", this);
// Send a CPOW to the parent so that it can synchronously request
// the list of style sheets.
sendSyncMessage("PageStyle:SetSyncHandler", {}, {syncHandler: this});
addEventListener("pageshow", () => this.sendStyleSheetInfo());
},
get markupDocumentViewer() {
return docShell.contentViewer;
},
// Called synchronously via CPOW from the parent.
getStyleSheetInfo: function() {
let styleSheets = this._filterStyleSheets(this.getAllStyleSheets());
return {
styleSheets: styleSheets,
sendStyleSheetInfo: function() {
let filteredStyleSheets = this._filterStyleSheets(this.getAllStyleSheets());
sendAsyncMessage("PageStyle:StyleSheets", {
filteredStyleSheets: filteredStyleSheets,
authorStyleDisabled: this.markupDocumentViewer.authorStyleDisabled,
preferredStyleSheetSet: content.document.preferredStyleSheetSet
};
});
},
// Called synchronously via CPOW from the parent.
getAllStyleSheets: function(frameset = content) {
let selfSheets = Array.slice(frameset.document.styleSheets);
let subSheets = Array.map(frameset.frames, frame => this.getAllStyleSheets(frame));
@ -470,6 +466,8 @@ var PageStyleHandler = {
this.markupDocumentViewer.authorStyleDisabled = true;
break;
}
this.sendStyleSheetInfo();
},
_stylesheetSwitchAll: function (frameset, title) {
@ -515,8 +513,16 @@ var PageStyleHandler = {
}
}
result.push({title: currentStyleSheet.title,
disabled: currentStyleSheet.disabled});
// We won't send data URIs all of the way up to the parent, as these
// can be arbitrarily large.
let URI = Services.io.newURI(currentStyleSheet.href, null, null);
let sentURI = URI.scheme == "data" ? null : URI.spec;
result.push({
title: currentStyleSheet.title,
disabled: currentStyleSheet.disabled,
href: sentURI,
});
}
return result;