Bug 1818026 - stop loading page style actor stuff for every process all the time, r=mconley,emilio

Differential Revision: https://phabricator.services.mozilla.com/D170498
This commit is contained in:
Gijs Kruitbosch
2023-02-24 09:07:47 +00:00
parent 575dc308a6
commit 3e62d26641
7 changed files with 134 additions and 112 deletions

View File

@@ -6,28 +6,38 @@
var EXPORTED_SYMBOLS = ["PageStyleChild"];
class PageStyleChild extends JSWindowActorChild {
handleEvent(event) {
// On page show, tell the parent all of the stylesheets this document has.
if (event.type == "pageshow") {
// If we are in the topmost browsing context,
// delete the stylesheets from the previous page.
if (this.browsingContext.top === this.browsingContext) {
this.sendAsyncMessage("PageStyle:Clear");
}
let window = event.target.ownerGlobal;
window.requestIdleCallback(() => {
if (!window || window.closed) {
return;
}
let filteredStyleSheets = this._collectStyleSheets(window);
this.sendAsyncMessage("PageStyle:Add", {
filteredStyleSheets,
authorStyleDisabled: this.docShell.contentViewer.authorStyleDisabled,
preferredStyleSheetSet: this.document.preferredStyleSheetSet,
});
});
actorCreated() {
// C++ can create the actor and call us here once an "interesting" link
// element gets added to the DOM. If pageload hasn't finished yet, just
// wait for that by doing nothing; the actor registration event
// listeners will ensure we get the pageshow event.
// It is also possible we get created in response to the parent
// sending us a message - in that case, it's still worth doing the
// same things here:
if (!this.browsingContext || !this.browsingContext.associatedWindow) {
return;
}
let { document } = this.browsingContext.associatedWindow;
if (document.readyState != "complete") {
return;
}
// If we've already seen a pageshow, send stylesheets now:
this.#collectAndSendSheets();
}
handleEvent(event) {
if (event?.type != "pageshow") {
throw new Error("Unexpected event!");
}
// On page show, tell the parent all of the stylesheets this document
// has. If we are in the topmost browsing context, delete the stylesheets
// from the previous page.
if (this.browsingContext.top === this.browsingContext) {
this.sendAsyncMessage("PageStyle:Clear");
}
this.#collectAndSendSheets();
}
receiveMessage(msg) {
@@ -117,13 +127,28 @@ class PageStyleChild extends JSWindowActorChild {
}
}
#collectAndSendSheets() {
let window = this.browsingContext.associatedWindow;
window.requestIdleCallback(() => {
if (!window || window.closed) {
return;
}
let filteredStyleSheets = this.#collectStyleSheets(window);
this.sendAsyncMessage("PageStyle:Add", {
filteredStyleSheets,
authorStyleDisabled: this.docShell.contentViewer.authorStyleDisabled,
preferredStyleSheetSet: this.document.preferredStyleSheetSet,
});
});
}
/**
* Get the stylesheets that have a title (and thus can be switched) in this
* webpage.
*
* @param content The window object for the page.
*/
_collectStyleSheets(content) {
#collectStyleSheets(content) {
let result = [];
let document = content.document;

View File

@@ -6,27 +6,76 @@
var EXPORTED_SYMBOLS = ["PageStyleParent"];
class PageStyleParent extends JSWindowActorParent {
// This has the most recent information about the content stylesheets for
// that actor. It's populated via the PageStyle:Add and PageStyle:Clear
// messages from the content process. It has 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.
#styleSheetInfo = null;
receiveMessage(msg) {
// The top browser.
// Check if things are alive:
let browser = this.browsingContext.top.embedderElement;
if (!browser) {
return;
}
let permanentKey = browser.permanentKey;
let window = browser.ownerGlobal;
let styleMenu = window.gPageStyleMenu;
if (window.closed || !styleMenu) {
if (!browser || browser.ownerGlobal.closed) {
return;
}
// We always store information at the top of the frame tree.
let actor = this.browsingContext.top.currentWindowGlobal.getActor(
"PageStyle"
);
switch (msg.name) {
case "PageStyle:Add":
styleMenu.addBrowserStyleSheets(msg.data, permanentKey);
actor.addSheetInfo(msg.data);
break;
case "PageStyle:Clear":
styleMenu.clearBrowserStyleSheets(permanentKey);
if (actor == this) {
this.#styleSheetInfo = null;
}
break;
}
}
/**
* Add/append styleSheets to the _pageStyleSheets weakmap.
* @param newSheetData
* The stylesheet data, including new stylesheets to add,
* and the preferred stylesheet set for this document.
*/
addSheetInfo(newSheetData) {
let info = this.getSheetInfo();
info.filteredStyleSheets.push(...newSheetData.filteredStyleSheets);
info.preferredStyleSheetSet ||= newSheetData.preferredStyleSheetSet;
}
getSheetInfo() {
if (!this.#styleSheetInfo) {
this.#styleSheetInfo = {
filteredStyleSheets: [],
authorStyleDisabled: false,
preferredStyleSheetSet: true,
};
}
return this.#styleSheetInfo;
}
}

View File

@@ -6,71 +6,24 @@
/* eslint-env mozilla/browser-window */
var gPageStyleMenu = {
// This maps from a <browser> element (or, more specifically, a
// 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(),
/**
* Add/append styleSheets to the _pageStyleSheets weakmap.
* @param styleSheets
* The stylesheets to add, including the preferred
* stylesheet set for this document.
* @param permanentKey
* The permanent key of the browser that
* these stylesheets come from.
*/
addBrowserStyleSheets(styleSheets, permanentKey) {
let sheetData = this._pageStyleSheets.get(permanentKey);
if (!sheetData) {
this._pageStyleSheets.set(permanentKey, styleSheets);
return;
}
sheetData.filteredStyleSheets.push(...styleSheets.filteredStyleSheets);
sheetData.preferredStyleSheetSet =
sheetData.preferredStyleSheetSet || styleSheets.preferredStyleSheetSet;
},
clearBrowserStyleSheets(permanentKey) {
this._pageStyleSheets.delete(permanentKey);
},
_getStyleSheetInfo(browser) {
let data = this._pageStyleSheets.get(browser.permanentKey);
if (!data) {
return {
let actor = browser.browsingContext.currentWindowGlobal?.getActor(
"PageStyle"
);
let styleSheetInfo;
if (actor) {
styleSheetInfo = actor.getSheetInfo();
} else {
// Fallback if the actor is missing or we don't have a window global.
// It's unlikely things will work well but let's be optimistic,
// rather than throwing exceptions immediately.
styleSheetInfo = {
filteredStyleSheets: [],
authorStyleDisabled: false,
preferredStyleSheetSet: true,
};
}
return data;
return styleSheetInfo;
},
fillPopup(menuPopup) {
@@ -157,13 +110,10 @@ var gPageStyleMenu = {
* @param title The title of the stylesheet to switch to.
*/
switchStyleSheet(title) {
let { permanentKey } = gBrowser.selectedBrowser;
let sheetData = this._pageStyleSheets.get(permanentKey);
if (sheetData && sheetData.filteredStyleSheets) {
sheetData.authorStyleDisabled = false;
for (let sheet of sheetData.filteredStyleSheets) {
sheet.disabled = sheet.title !== title;
}
let sheetData = this._getStyleSheetInfo(gBrowser.selectedBrowser);
sheetData.authorStyleDisabled = false;
for (let sheet of sheetData.filteredStyleSheets) {
sheet.disabled = sheet.title !== title;
}
this._sendMessageToAll("PageStyle:Switch", { title });
},
@@ -172,11 +122,8 @@ var gPageStyleMenu = {
* Disable all stylesheets. Called with View > Page Style > No Style.
*/
disableStyle() {
let { permanentKey } = gBrowser.selectedBrowser;
let sheetData = this._pageStyleSheets.get(permanentKey);
if (sheetData) {
sheetData.authorStyleDisabled = true;
}
let sheetData = this._getStyleSheetInfo(gBrowser.selectedBrowser);
sheetData.authorStyleDisabled = true;
this._sendMessageToAll("PageStyle:Disable", {});
},
};

View File

@@ -34,7 +34,6 @@ const known_scripts = {
"resource:///actors/AboutReaderChild.sys.mjs",
"resource:///actors/BrowserTabChild.sys.mjs",
"resource:///actors/LinkHandlerChild.jsm",
"resource:///actors/PageStyleChild.jsm",
"resource:///actors/SearchSERPTelemetryChild.jsm",
"resource://gre/actors/ContentMetaChild.jsm",
"resource://gre/modules/Readerable.jsm",

View File

@@ -44,9 +44,6 @@ const known_scripts = {
// Logging related
"resource://gre/modules/Log.sys.mjs",
// Browser front-end
"resource:///actors/PageStyleChild.jsm",
// Telemetry
"resource://gre/modules/TelemetryControllerBase.sys.mjs", // bug 1470339
"resource://gre/modules/TelemetryControllerContent.sys.mjs", // bug 1470339

View File

@@ -646,13 +646,10 @@ let JSWINDOWACTORS = {
child: {
moduleURI: "resource:///actors/PageStyleChild.jsm",
events: {
pageshow: {},
pageshow: { createActor: false },
},
},
// Only matching web pages, as opposed to internal about:, chrome: or
// resource: pages. See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns
matches: ["*://*/*", "file:///*"],
messageManagerGroups: ["browsers"],
allFrames: true,
},

View File

@@ -48,6 +48,7 @@
#include "nsGkAtoms.h"
#include "nsIThreadInternal.h"
#include "nsINetworkPredictor.h"
#include "nsQueryActor.h"
#include "nsStringStream.h"
#include "mozilla/dom/MediaList.h"
#include "mozilla/dom/ShadowRoot.h"
@@ -1617,6 +1618,13 @@ void Loader::NotifyObservers(SheetLoadData& aData, nsresult aStatus) {
DecrementOngoingLoadCount();
}
}
if (!aData.mTitle.IsEmpty() && NS_SUCCEEDED(aStatus)) {
// Force creating the page style actor, if available. This will no-op
// if no actor with this name is registered (outside of desktop Firefox).
nsCOMPtr<nsISupports> pageStyleActor =
do_QueryActor("PageStyle", mDocument);
Unused << pageStyleActor;
}
if (aData.mMustNotify) {
if (nsCOMPtr<nsICSSLoaderObserver> observer = std::move(aData.mObserver)) {