Merge autoland to mozilla-central. a=merge

This commit is contained in:
Marian-Vasile Laza 2022-04-19 14:44:58 -07:00
Родитель 0ecc093828 c582dbf6d7
Коммит 5a948a4c8d
132 изменённых файлов: 4603 добавлений и 6081 удалений

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

@ -150,6 +150,11 @@ add_task(async function test_preferences_page() {
openPreferences("search");
let popupEvent = await openHistoryMenu(true);
// Wait for the session data to be flushed before continuing the test
await new Promise(resolve =>
SessionStore.getSessionHistory(gBrowser.selectedTab, resolve)
);
is(popupEvent.target.children.length, 2, "Correct number of history items");
let popupHiddenPromise = BrowserTestUtils.waitForEvent(

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

@ -75,12 +75,11 @@ this.LoginBreaches = {
// they were changed. It's important to note here that we are NOT considering the
// username and password of that login.
for (const login of logins) {
const loginURI = Services.io.newURI(login.origin);
let loginHost;
try {
// nsIURI.host can throw if the URI scheme doesn't have a host.
loginHost = loginURI.host;
} catch (ex) {
loginHost = Services.io.newURI(login.origin).host;
} catch {
continue;
}
for (const breach of breaches) {

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

@ -54,10 +54,10 @@
<div class="overlay">
<div class="container" role="dialog" aria-labelledby="title" aria-describedby="message">
<button class="dismiss-button ghost-button" data-l10n-id="confirmation-dialog-dismiss-button">
<img class="dismiss-icon" src="chrome://global/skin/icons/close.svg"/>
<img class="dismiss-icon" src="chrome://global/skin/icons/close.svg" draggable="false"/>
</button>
<div class="content">
<img class="warning-icon" src="chrome://global/skin/icons/warning.svg"/>
<img class="warning-icon" src="chrome://global/skin/icons/warning.svg" draggable="false"/>
<h1 class="title" id="title"></h1>
<p class="message" id="message"></p>
</div>
@ -119,7 +119,7 @@
<link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/import-error-dialog.css">
<generic-dialog>
<span slot="dialog-title" data-l10n-id="about-logins-import-dialog-error-title"></span>
<img slot="dialog-icon" part="dialog-icon" class="warning-icon" src="chrome://global/skin/icons/warning.svg"/>
<img slot="dialog-icon" part="dialog-icon" class="warning-icon" src="chrome://global/skin/icons/warning.svg"/ draggable="false">
<div slot="content" class="content">
<span class="error-title" data-l10n-id="about-logins-import-dialog-error-unable-to-read-title"></span>
<span class="error-description" data-l10n-id="about-logins-import-dialog-error-unable-to-read-description"></span>

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

@ -61,6 +61,13 @@ const TEST_BREACHES = [
},
];
const CRASHING_URI_LOGIN = LoginTestUtils.testData.formLogin({
origin: "chrome://grwatcher",
formActionOrigin: "https://www.example.com",
username: "username",
password: "password",
timePasswordChanged: new Date("2018-12-15").getTime(),
});
const NOT_BREACHED_LOGIN = LoginTestUtils.testData.formLogin({
origin: "https://www.example.com",
formActionOrigin: "https://www.example.com",
@ -107,7 +114,6 @@ const LOGIN_WITH_NON_STANDARD_URI = LoginTestUtils.testData.formLogin({
add_task(async function test_notBreachedLogin() {
Services.logins.addLogin(NOT_BREACHED_LOGIN);
const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
[NOT_BREACHED_LOGIN],
TEST_BREACHES
@ -137,6 +143,25 @@ add_task(async function test_breachedLogin() {
);
});
add_task(async function test_breachedLoginAfterCrashingUriLogin() {
Services.logins.addLogin(CRASHING_URI_LOGIN);
const breachesByLoginGUID = await LoginBreaches.getPotentialBreachesByLoginGUID(
[CRASHING_URI_LOGIN, BREACHED_LOGIN],
TEST_BREACHES
);
Assert.strictEqual(
breachesByLoginGUID.size,
1,
"Should be 1 breached login: " + BREACHED_LOGIN.origin
);
Assert.strictEqual(
breachesByLoginGUID.get(BREACHED_LOGIN.guid).breachAlertURL,
"https://monitor.firefox.com/breach-details/Breached?utm_source=firefox-desktop&utm_medium=referral&utm_campaign=about-logins&utm_content=about-logins",
"Breach alert link should be equal to the breachAlertURL"
);
});
add_task(async function test_notBreachedSubdomain() {
Services.logins.addLogin(NOT_BREACHED_SUBDOMAIN_LOGIN);

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

@ -4,10 +4,8 @@
"use strict";
ChromeUtils.defineModuleGetter(
this,
"Ajv",
"resource://testing-common/ajv-6.12.6.js"
const { JsonSchema } = ChromeUtils.import(
"resource://gre/modules/JsonSchema.jsm"
);
const { TelemetryArchive } = ChromeUtils.import(
@ -312,13 +310,12 @@ add_task(async function testMockSchema() {
throw new Error(`Failed to load ${schemaName}`);
}
const ajv = new Ajv({ allErrors: true });
const validate = ajv.compile(schema);
const validator = new JsonSchema.Validator(schema, { shortCircuit: false });
for (const entry of values) {
const valid = validate(entry);
if (!valid) {
throw new Error(JSON.stringify(validate.errors));
const result = validator.validate(entry);
if (!result.valid) {
throw new Error(JSON.stringify(result.errors));
}
}
}

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

@ -439,13 +439,11 @@ class TestFirefoxRefresh(MarionetteTestCase):
let resolve = arguments[arguments.length - 1]
let mm = gBrowser.selectedBrowser.messageManager;
let {TabStateFlusher} = Cu.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
window.addEventListener("SSWindowStateReady", function testSSPostReset() {
window.removeEventListener("SSWindowStateReady", testSSPostReset, false);
Promise.all(gBrowser.browsers.map(b => TabStateFlusher.flush(b))).then(function() {
resolve([... gBrowser.browsers].map(b => b.currentURI && b.currentURI.spec));
});
}, false);
window.addEventListener("SSWindowStateReady", function() {
window.addEventListener("SSTabRestored", function() {
resolve(Array.from(gBrowser.browsers, b => b.currentURI?.spec));
}, { capture: false, once: true });
}, { capture: false, once: true });
let fs = function() {
if (content.document.readyState === "complete") {

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

@ -149,6 +149,9 @@ add_task(async function test_bookmark_contextmenu_contents() {
return contextMenu;
}, optionItems);
let tab;
let contextMenuOnContent;
await checkContextMenu(async function() {
info("Check context menu after opening context menu on content");
const toolbarBookmark = await PlacesUtils.bookmarks.insert({
@ -158,13 +161,8 @@ add_task(async function test_bookmark_contextmenu_contents() {
});
info("Open context menu on about:config");
const tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:config"
);
const contextMenuOnContent = document.getElementById(
"contentAreaContextMenu"
);
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:config");
contextMenuOnContent = document.getElementById("contentAreaContextMenu");
const popupShownPromiseOnContent = BrowserTestUtils.waitForEvent(
contextMenuOnContent,
"popupshown"
@ -189,10 +187,15 @@ add_task(async function test_bookmark_contextmenu_contents() {
});
await popupShownPromise;
BrowserTestUtils.removeTab(tab);
return contextMenu;
}, optionItems);
// We need to do a thorough cleanup to avoid leaking the window of
// 'about:config'.
const tabClosed = BrowserTestUtils.waitForTabClosing(tab);
contextMenuOnContent.hidePopup();
BrowserTestUtils.removeTab(tab);
await tabClosed;
});
add_task(async function test_empty_contextmenu_contents() {

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

@ -1376,8 +1376,11 @@ var SessionStoreInternal = {
this.onTabStateUpdate(browser.permanentKey, browser.ownerGlobal, data);
// SHIP code will call this when it receives "browser-shutdown-tabstate-updated"
if (data.isFinal) {
this.onFinalTabStateUpdateComplete(browser);
if (!Services.appinfo.sessionHistoryInParent) {
this.onFinalTabStateUpdateComplete(browser);
}
} else if (data.flushID) {
// This is an update kicked off by an async flush request. Notify the
// TabStateFlusher so that it can finish the request and notify its

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

@ -139,77 +139,6 @@ var TabStateCacheInternal = {
}
},
/**
* Helper function used by update (see below). To be fission compatible
* we need to be able to update scroll and formdata per entry in the
* cache. This is done by looking up the desired position and applying
* the update for that node only.
*
* @param data (object)
* The cached data where we want to update the changes.
* @param path (object)
* The path to the node to update specified by a list of indices
* to follow from the root downwards.
* @param includeChildren (booelan)
* Determines if the children of the changed node should be kept
* or not.
* @param change (object)
* Object containing the optional formdata and optional scroll
* position to be updated as well as information if the node
* should keep the data for its children.
*/
updatePartialWindowStateChange(data, path, includeChildren, change) {
if (!path.length) {
for (let key of Object.keys(change)) {
let children = includeChildren ? data[key]?.children : null;
if (!Object.keys(change[key]).length) {
data[key] = null;
} else {
data[key] = change[key];
}
if (children) {
data[key] = { ...data[key], children };
}
}
return data;
}
let index = path.pop();
let scroll = data?.scroll?.children?.[index];
let formdata = data?.formdata?.children?.[index];
change = this.updatePartialWindowStateChange(
{ scroll, formdata },
path,
includeChildren,
change
);
for (let key of Object.keys(change)) {
let value = change[key];
let children = data[key]?.children;
if (children) {
if (value) {
children[index] = value;
} else {
delete children[index];
}
if (!children.some(e => e)) {
data[key] = null;
}
} else if (value) {
children = new Array(index + 1);
children[index] = value;
data[key] = { ...data[key], children };
}
}
return data;
},
/**
* Updates cached data for a given |tab| or associated |browser|.
*
@ -233,22 +162,6 @@ var TabStateCacheInternal = {
continue;
}
if (key == "windowstatechange") {
let { path, hasChildren, ...change } = newData.windowstatechange;
this.updatePartialWindowStateChange(data, path, hasChildren, change);
for (key of Object.keys(change)) {
let value = data[key];
if (value === null) {
delete data[key];
} else {
data[key] = value;
}
}
continue;
}
let value = newData[key];
if (value === null) {
delete data[key];

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

@ -92,6 +92,10 @@ async function test_restore_text_data_subframes(aURL) {
}
);
Assert.equal(out2Val, "", "id prefixes can't be faked");
// Bug 588077
// XXX(farre): disabling this, because it started passing more heavily on Windows.
/*
let in1ValFrame0_1 = await SpecialPowers.spawn(
content.frames[0],
[],
@ -101,8 +105,8 @@ async function test_restore_text_data_subframes(aURL) {
});
}
);
// Bug 588077
todo_is(in1ValFrame0_1, "", "id prefixes aren't mixed up");
*/
let in1ValFrame1_0 = await SpecialPowers.spawn(
content.frames[1],

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

@ -1,7 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
async function test() {
let assertNumberOfTabs = function(num, msg) {
is(gBrowser.tabs.length, num, msg);
};
@ -18,38 +18,26 @@ function test() {
// setup
let tab = BrowserTestUtils.addTab(gBrowser, "about:mozilla");
whenTabIsLoaded(tab, function() {
// hide the newly created tab
assertNumberOfVisibleTabs(2, "there are two visible tabs");
gBrowser.showOnlyTheseTabs([gBrowser.tabs[0]]);
assertNumberOfVisibleTabs(1, "there is one visible tab");
ok(tab.hidden, "newly created tab is now hidden");
await promiseBrowserLoaded(tab.linkedBrowser);
// close and restore hidden tab
promiseRemoveTabAndSessionState(tab).then(() => {
tab = ss.undoCloseTab(window, 0);
// hide the newly created tab
assertNumberOfVisibleTabs(2, "there are two visible tabs");
gBrowser.showOnlyTheseTabs([gBrowser.tabs[0]]);
assertNumberOfVisibleTabs(1, "there is one visible tab");
ok(tab.hidden, "newly created tab is now hidden");
// check that everything was restored correctly, clean up and finish
whenTabIsLoaded(tab, function() {
is(
tab.linkedBrowser.currentURI.spec,
"about:mozilla",
"restored tab has correct url"
);
// close and restore hidden tab
await promiseRemoveTabAndSessionState(tab);
tab = ss.undoCloseTab(window, 0);
gBrowser.removeTab(tab);
finish();
});
});
});
}
function whenTabIsLoaded(tab, callback) {
tab.linkedBrowser.addEventListener(
"load",
function() {
callback();
},
{ capture: true, once: true }
// check that everything was restored correctly, clean up and finish
await promiseBrowserLoaded(tab.linkedBrowser);
is(
tab.linkedBrowser.currentURI.spec,
"about:mozilla",
"restored tab has correct url"
);
gBrowser.removeTab(tab);
finish();
}

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

@ -22,12 +22,16 @@ add_task(async function() {
// Change the "multiple" attribute of the <select> element and select some
// options.
await SpecialPowers.spawn(tab.linkedBrowser, [VALUES], values => {
content.document.querySelector("select").multiple = true;
for (let v of values) {
content.document.querySelector(`option[value="${v}"]`).selected = true;
}
});
await setPropertyOfFormField(tab.linkedBrowser, "select", "multiple", true);
for (let v of VALUES) {
await setPropertyOfFormField(
tab.linkedBrowser,
`option[value="${v}"]`,
"selected",
true
);
}
// Remove the tab.
await promiseRemoveTabAndSessionState(tab);

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

@ -211,7 +211,7 @@ toolbarseparator + .panel-subview-body,
#wrapper-edit-controls:is([place="palette"],[place="menu-panel"]) > #edit-controls,
#wrapper-zoom-controls:is([place="palette"],[place="menu-panel"]) > #zoom-controls,
.toolbaritem-combined-buttons:is([cui-areatype="menu-panel"], [overflowedItem=true]) {
:is(panelview, #widget-overflow-fixed-list) .toolbaritem-combined-buttons {
margin: var(--arrowpanel-menuitem-margin);
}
@ -385,7 +385,10 @@ panelview[id^=PanelUI-webext-] {
min-width: calc(var(--menu-panel-width) + 32px);
}
.toolbaritem-combined-buttons:is([cui-areatype="menu-panel"], [overflowedItem=true]) > toolbarbutton > .toolbarbutton-icon {
.toolbaritem-combined-buttons:is(
:not([cui-areatype="toolbar"]),
[overflowedItem=true]
) > toolbarbutton > .toolbarbutton-icon {
min-width: 0;
min-height: 0;
margin: 0;
@ -1225,8 +1228,10 @@ panelview .toolbarbutton-1 {
panelview .toolbarbutton-1,
toolbarbutton.subviewbutton,
.widget-overflow-list .toolbarbutton-1,
.toolbaritem-combined-buttons[cui-areatype="menu-panel"] > toolbarbutton,
.toolbaritem-combined-buttons[overflowedItem=true] > toolbarbutton
.toolbaritem-combined-buttons:is(
:not([cui-areatype="toolbar"]),
[overflowedItem=true]
) > toolbarbutton
):focus-visible {
outline: var(--focus-outline);
outline-offset: var(--focus-outline-inset);
@ -1237,8 +1242,10 @@ panelview .toolbarbutton-1 {
panelview .toolbarbutton-1,
toolbarbutton.subviewbutton,
.widget-overflow-list .toolbarbutton-1,
.toolbaritem-combined-buttons[cui-areatype="menu-panel"] > toolbarbutton,
.toolbaritem-combined-buttons[overflowedItem=true] > toolbarbutton
.toolbaritem-combined-buttons:is(
:not([cui-areatype="toolbar"]),
[overflowedItem=true]
) > toolbarbutton
):not([disabled]):hover {
color: inherit;
background-color: var(--panel-item-hover-bgcolor);
@ -1249,8 +1256,10 @@ panelview .toolbarbutton-1 {
panelview .toolbarbutton-1,
toolbarbutton.subviewbutton,
.widget-overflow-list .toolbarbutton-1,
.toolbaritem-combined-buttons[cui-areatype="menu-panel"] > toolbarbutton,
.toolbaritem-combined-buttons[overflowedItem=true] > toolbarbutton
.toolbaritem-combined-buttons:is(
:not([cui-areatype="toolbar"]),
[overflowedItem=true]
) > toolbarbutton
):not([disabled]):hover:active {
color: inherit;
background-color: var(--panel-item-active-bgcolor);
@ -1389,7 +1398,10 @@ toolbarpaletteitem[place="palette"] > #search-container {
max-height: 37px;
}
.toolbaritem-combined-buttons:is([cui-areatype="menu-panel"], [overflowedItem=true]) > toolbarbutton {
.toolbaritem-combined-buttons:is(
:not([cui-areatype="toolbar"]),
[overflowedItem=true]
) > toolbarbutton {
border: 0;
margin: 0;
-moz-box-flex: 1;
@ -1407,7 +1419,10 @@ toolbarpaletteitem[place="menu-panel"] > toolbaritem {
display: none;
}
.toolbaritem-combined-buttons:is([cui-areatype="menu-panel"], [overflowedItem=true]) > toolbarbutton:not(.toolbarbutton-1)[disabled] {
.toolbaritem-combined-buttons:is(
:not([cui-areatype="toolbar"]),
[overflowedItem=true]
) > toolbarbutton:not(.toolbarbutton-1)[disabled] {
opacity: 0.4;
/* Override toolbarbutton.css which sets the color to GrayText */
color: inherit;
@ -1418,7 +1433,10 @@ toolbarpaletteitem[place="menu-panel"] > toolbaritem {
min-width: calc(5ch + var(--toolbarbutton-inner-padding) * 2);
}
.toolbaritem-combined-buttons:is([cui-areatype="menu-panel"], [overflowedItem=true]) > separator {
.toolbaritem-combined-buttons:is(
:not([cui-areatype="toolbar"]),
[overflowedItem=true]
) > separator {
appearance: none;
-moz-box-align: stretch;
margin: .5em 0;
@ -1430,7 +1448,10 @@ toolbarpaletteitem[place="menu-panel"] > toolbaritem {
transition-timing-function: ease;
}
.toolbaritem-combined-buttons:is([cui-areatype="menu-panel"], [overflowedItem=true]):hover > separator {
.toolbaritem-combined-buttons:is(
:not([cui-areatype="toolbar"]),
[overflowedItem=true]
):hover > separator {
margin: 0;
}

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

@ -1406,11 +1406,10 @@ const windowGlobalTargetPrototype = {
* DebuggerProgressListener.
*/
_windowReady(window, { isFrameSwitching, isBFCache } = {}) {
const isTopLevel = window == this.window;
if (this.ignoreSubFrames && !this.isTopLevel) {
if (this.ignoreSubFrames) {
return;
}
const isTopLevel = window == this.window;
// We just reset iframe list on WillNavigate, so we now list all existing
// frames when we load a new document in the original window
@ -1440,11 +1439,10 @@ const windowGlobalTargetPrototype = {
window,
{ id = null, isFrozen = false, isFrameSwitching = false }
) {
const isTopLevel = window == this.window;
if (this.ignoreSubFrames && !this.isTopLevel) {
if (this.ignoreSubFrames) {
return;
}
const isTopLevel = window == this.window;
// If this follows WindowGlobal lifecycle, this target will be destroyed, alongside its top level document.
// Only notify about in-process iframes.
@ -1474,11 +1472,10 @@ const windowGlobalTargetPrototype = {
isFrameSwitching = false,
navigationStart,
}) {
let isTopLevel = window == this.window;
if (this.ignoreSubFrames && !this.isTopLevel) {
if (this.ignoreSubFrames) {
return;
}
let isTopLevel = window == this.window;
let reset = false;
if (window == this._originalWindow && !isFrameSwitching) {
@ -1533,11 +1530,10 @@ const windowGlobalTargetPrototype = {
* targeted window global.
*/
_navigate(window, isFrameSwitching = false) {
const isTopLevel = window == this.window;
if (this.ignoreSubFrames && !this.isTopLevel) {
if (this.ignoreSubFrames) {
return;
}
const isTopLevel = window == this.window;
// navigate event needs to be dispatched synchronously,
// by calling the listeners in the order or registration.

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

@ -7,6 +7,8 @@
"use strict";
const EventEmitter = require("devtools/shared/event-emitter");
const { Ci } = require("chrome");
const ChromeUtils = require("ChromeUtils");
/**
* About "navigationStart - ${WILL_NAVIGATE_TIME_SHIFT}ms":
@ -54,11 +56,32 @@ exports.DocumentEventsListener = DocumentEventsListener;
DocumentEventsListener.prototype = {
listen() {
// Listen to will-navigate and do not emit a fake one as we only care about upcoming navigation
this.targetActor.on("will-navigate", this.onWillNavigate);
// When EFT is enabled, the Target Actor won't dispatch any will-navigate/window-ready event
// Instead listen to WebProgressListener interface directly, so that we can later drop the whole
// DebuggerProgressListener interface in favor of this class.
// Also, do not wait for "load" event as it can be blocked in case of error during the load
// or when calling window.stop(). We still want to emit "dom-complete" in these scenarios.
if (this.targetActor.ignoreSubFrames) {
// Ignore listening to anything if the page is already fully loaded.
// This can be the case when opening DevTools against an already loaded page
// or when doing bfcache navigations.
if (this.targetActor.window.document.readyState != "complete") {
this.webProgress = this.targetActor.docShell
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
this.webProgress.addProgressListener(
this,
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW |
Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT
);
}
} else {
// Listen to will-navigate and do not emit a fake one as we only care about upcoming navigation
this.targetActor.on("will-navigate", this.onWillNavigate);
// Listen to window-ready and then fake one in order to notify about dom-loading for the existing document
this.targetActor.on("window-ready", this.onWindowReady);
// Listen to window-ready and then fake one in order to notify about dom-loading for the existing document
this.targetActor.on("window-ready", this.onWindowReady);
}
// The target actor already emitted a window-ready for the top document when instantiating.
// So fake one for the top document right away.
this.onWindowReady({
@ -101,20 +124,26 @@ DocumentEventsListener.prototype = {
const { readyState } = window.document;
if (readyState != "interactive" && readyState != "complete") {
window.addEventListener(
"DOMContentLoaded",
e => this.onContentLoaded(e, isFrameSwitching),
{
once: true,
}
);
// When EFT is enabled, we track this event via the WebProgressListener interface.
if (!this.targetActor.ignoreSubFrames) {
window.addEventListener(
"DOMContentLoaded",
e => this.onContentLoaded(e, isFrameSwitching),
{
once: true,
}
);
}
} else {
this.onContentLoaded({ target: window.document }, isFrameSwitching);
}
if (readyState != "complete") {
window.addEventListener("load", e => this.onLoad(e, isFrameSwitching), {
once: true,
});
// When EFT is enabled, we track the load event via the WebProgressListener interface.
if (!this.targetActor.ignoreSubFrames) {
window.addEventListener("load", e => this.onLoad(e, isFrameSwitching), {
once: true,
});
}
} else {
this.onLoad({ target: window.document }, isFrameSwitching);
}
@ -148,6 +177,29 @@ DocumentEventsListener.prototype = {
});
},
onStateChange(progress, request, flag, status) {
progress.QueryInterface(Ci.nsIDocShell);
// Ignore destroyed, or progress for same-process iframes
if (progress.isBeingDestroyed() || progress != this.webProgress) {
return;
}
const isStop = flag & Ci.nsIWebProgressListener.STATE_STOP;
const isDocument = flag & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
const isWindow = flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
const window = progress.DOMWindow;
if (isDocument && isStop) {
const time = window.performance.timing.domInteractive;
this.emit("dom-interactive", { time });
} else if (isWindow && isStop) {
const time = window.performance.timing.domComplete;
this.emit("dom-complete", {
time,
hasNativeConsoleAPI: this.hasNativeConsoleAPI(window),
});
}
},
/**
* Tells if the window.console object is native or overwritten by script in
* the page.
@ -179,5 +231,17 @@ DocumentEventsListener.prototype = {
this.destroyed = true;
this.targetActor.off("will-navigate", this.onWillNavigate);
this.targetActor.off("window-ready", this.onWindowReady);
if (this.webProgress) {
this.webProgress.removeProgressListener(
this,
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW |
Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT
);
}
},
QueryInterface: ChromeUtils.generateQI([
"nsIWebProgressListener",
"nsISupportsWeakReference",
]),
};

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

@ -11,6 +11,7 @@ add_task(async function() {
await testDomCompleteWithOverloadedConsole();
await testIframeNavigation();
await testBfCacheNavigation();
await testDomCompleteWithWindowStop();
// Enable server side target switching for next test
// as the regression it tracks only occurs with server side target switching enabled
@ -540,6 +541,47 @@ async function testDomCompleteWithOverloadedConsole() {
await client.close();
}
async function testDomCompleteWithWindowStop() {
info("Test dom-complete with a page calling window.stop()");
const tab = await addTab("data:text/html,foo");
const {
commands,
client,
resourceCommand,
targetCommand,
} = await initResourceCommand(tab);
info("Check that all DOCUMENT_EVENTS are fired for the already loaded page");
let documentEvents = [];
await resourceCommand.watchResources([resourceCommand.TYPES.DOCUMENT_EVENT], {
onAvailable: resources => documentEvents.push(...resources),
});
is(documentEvents.length, 3, "Existing document events are fired");
documentEvents = [];
const html = `<!DOCTYPE html><html>
<head>
<title>stopped page</title>
<script>window.stop();</script>
</head>
<body>Page content that shouldn't be displayed</body>
</html>`;
const secondLocation = "data:text/html," + encodeURIComponent(html);
const targetBeforeNavigation = commands.targetCommand.targetFront;
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, secondLocation);
info(
"Wait for will-navigate, dom-loading, dom-interactive and dom-complete events"
);
await waitFor(() => documentEvents.length === 4);
assertEvents({ commands, targetBeforeNavigation, documentEvents });
targetCommand.destroy();
await client.close();
}
async function assertPromises(
commands,
targetBeforeNavigation,

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

@ -36,11 +36,12 @@
#include "mozilla/dom/MediaDevices.h"
#include "mozilla/dom/PopupBlocker.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/SessionStoreChild.h"
#include "mozilla/dom/SessionStorageManager.h"
#include "mozilla/dom/SessionStoreDataCollector.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/UserActivationIPCUtils.h"
#include "mozilla/dom/WindowBinding.h"
#include "mozilla/dom/WindowContext.h"
#include "mozilla/dom/WindowGlobalChild.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/dom/WindowProxyHolder.h"
@ -2277,44 +2278,6 @@ void BrowsingContext::IncrementHistoryEntryCountForBrowsingContext() {
Unused << SetHistoryEntryCount(GetHistoryEntryCount() + 1);
}
void BrowsingContext::FlushSessionStore() {
nsTArray<RefPtr<BrowserChild>> nestedBrowserChilds;
PreOrderWalk([&](BrowsingContext* aContext) {
BrowserChild* browserChild = BrowserChild::GetFrom(aContext->GetDocShell());
if (browserChild && browserChild->GetBrowsingContext() == aContext) {
nestedBrowserChilds.AppendElement(browserChild);
}
if (aContext->CreatedDynamically()) {
return WalkFlag::Skip;
}
WindowContext* windowContext = aContext->GetCurrentWindowContext();
if (!windowContext) {
return WalkFlag::Skip;
}
WindowGlobalChild* windowChild = windowContext->GetWindowGlobalChild();
if (!windowChild) {
return WalkFlag::Next;
}
RefPtr<SessionStoreDataCollector> collector =
windowChild->GetSessionStoreDataCollector();
if (!collector) {
return WalkFlag::Next;
}
collector->Flush();
return WalkFlag::Next;
});
for (auto& child : nestedBrowserChilds) {
child->UpdateSessionStore();
}
}
std::tuple<bool, bool> BrowsingContext::CanFocusCheck(CallerType aCallerType) {
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (!fm) {
@ -2635,6 +2598,20 @@ nsresult BrowsingContext::ResetGVAutoplayRequestStatus() {
return txn.Commit(this);
}
void BrowsingContext::DidSet(FieldIndex<IDX_SessionStoreEpoch>,
uint32_t aOldValue) {
if (!mCurrentWindowContext) {
return;
}
SessionStoreChild* sessionStoreChild =
SessionStoreChild::From(mCurrentWindowContext->GetWindowGlobalChild());
if (!sessionStoreChild) {
return;
}
sessionStoreChild->SetEpoch(GetSessionStoreEpoch());
}
void BrowsingContext::DidSet(FieldIndex<IDX_GVAudibleAutoplayRequestStatus>) {
MOZ_ASSERT(IsTop(),
"Should only set GVAudibleAutoplayRequestStatus in the top-level "
@ -3407,6 +3384,17 @@ void BrowsingContext::AddDeprioritizedLoadRunner(nsIRunnable* aRunner) {
EventQueuePriority::Idle);
}
bool BrowsingContext::IsDynamic() const {
const BrowsingContext* current = this;
do {
if (current->CreatedDynamically()) {
return true;
}
} while ((current = current->GetParent()));
return false;
}
bool BrowsingContext::GetOffsetPath(nsTArray<uint32_t>& aPath) const {
for (const BrowsingContext* current = this; current && current->GetParent();
current = current->GetParent()) {

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

@ -784,6 +784,10 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
bool CreatedDynamically() const { return mCreatedDynamically; }
// Returns true if this browsing context, or any ancestor to this browsing
// context was created dynamically. See also `CreatedDynamically`.
bool IsDynamic() const;
int32_t ChildOffset() const { return mChildOffset; }
bool GetOffsetPath(nsTArray<uint32_t>& aPath) const;
@ -889,8 +893,6 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
return GetPrefersColorSchemeOverride();
}
void FlushSessionStore();
bool IsInBFCache() const;
bool AllowJavascript() const { return GetAllowJavascript(); }
@ -1002,6 +1004,8 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
return IsTop() && !aSource;
}
void DidSet(FieldIndex<IDX_SessionStoreEpoch>, uint32_t aOldValue);
using CanSetResult = syncedcontext::CanSetResult;
// Ensure that opener is in the same BrowsingContextGroup.

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

@ -2367,7 +2367,7 @@ void CanonicalBrowsingContext::UpdateSessionStoreSessionStorage(
using DataPromise = BackgroundSessionStorageManager::DataPromise;
BackgroundSessionStorageManager::GetData(
this, StaticPrefs::browser_sessionstore_dom_storage_limit(),
/* aCancelSessionStoreTiemr = */ true)
/* aClearSessionStoreTimer = */ true)
->Then(GetCurrentSerialEventTarget(), __func__,
[self = RefPtr{this}, aDone, epoch = GetSessionStoreEpoch()](
const DataPromise::ResolveOrRejectValue& valueList) {

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

@ -55,6 +55,8 @@ class MediaController;
struct LoadingSessionHistoryInfo;
class SSCacheCopy;
class WindowGlobalParent;
class SessionStoreFormData;
class SessionStoreScrollData;
// CanonicalBrowsingContext is a BrowsingContext living in the parent
// process, with whatever extra data that a BrowsingContext in the
@ -524,6 +526,17 @@ class CanonicalBrowsingContext final : public BrowsingContext {
RefPtr<FeaturePolicy> mContainerFeaturePolicy;
friend class BrowserSessionStore;
WeakPtr<SessionStoreFormData>& GetSessionStoreFormDataRef() {
return mFormdata;
}
WeakPtr<SessionStoreScrollData>& GetSessionStoreScrollDataRef() {
return mScroll;
}
WeakPtr<SessionStoreFormData> mFormdata;
WeakPtr<SessionStoreScrollData> mScroll;
RefPtr<RestoreState> mRestoreState;
// If this is a top level context, this is true if our browser ID is marked as

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

@ -78,7 +78,7 @@
#include "mozilla/dom/SessionHistoryEntry.h"
#include "mozilla/dom/SessionStorageManager.h"
#include "mozilla/dom/SessionStoreChangeListener.h"
#include "mozilla/dom/SessionStoreDataCollector.h"
#include "mozilla/dom/SessionStoreChild.h"
#include "mozilla/dom/SessionStoreUtils.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/ToJSValue.h"
@ -1325,7 +1325,10 @@ void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
// performance.navigation.type is 2.
// Traditionally this type change has been done to the top level page
// only.
inner->GetPerformance()->GetDOMTiming()->NotifyRestoreStart();
Performance* performance = inner->GetPerformance();
if (performance) {
performance->GetDOMTiming()->NotifyRestoreStart();
}
}
}
@ -5813,7 +5816,12 @@ nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
if (IsForceReloadType(mLoadType)) {
SessionStoreUtils::ResetSessionStore(mBrowsingContext);
if (WindowContext* windowContext =
mBrowsingContext->GetCurrentWindowContext()) {
SessionStoreChild::From(windowContext->GetWindowGlobalChild())
->SendResetSessionStore(
mBrowsingContext, mBrowsingContext->GetSessionStoreEpoch());
}
}
}
}
@ -6554,13 +6562,13 @@ nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
return NS_OK;
}
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
if (Document* document = GetDocument()) {
if (WindowGlobalChild* windowChild = document->GetWindowGlobalChild()) {
RefPtr<SessionStoreDataCollector> collector =
SessionStoreDataCollector::CollectSessionStoreData(windowChild);
collector->RecordInputChange();
collector->RecordScrollChange();
}
if (WindowContext* windowContext =
mBrowsingContext->GetCurrentWindowContext()) {
// TODO(farre): File bug: From a user perspective this would probably be
// just fine to run off the change listener timer. Turns out that a flush
// is needed. Several tests depend on this behaviour. Could potentially be
// an optimization for later. See Bug 1756995.
SessionStoreChangeListener::FlushAllSessionStoreData(windowContext);
}
}
@ -7755,7 +7763,10 @@ nsresult nsDocShell::RestoreFromHistory() {
// Now that we have found the inner window of the page restored
// from the history, we have to make sure that
// performance.navigation.type is 2.
privWinInner->GetPerformance()->GetDOMTiming()->NotifyRestoreStart();
Performance* performance = privWinInner->GetPerformance();
if (performance) {
performance->GetDOMTiming()->NotifyRestoreStart();
}
// Restore the refresh URI list. The refresh timers will be restarted
// when EndPageLoad() is called.
@ -11175,27 +11186,35 @@ bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
return onLocationChangeNeeded;
}
void nsDocShell::CollectWireframe() {
if (mozilla::SessionHistoryInParent() &&
bool nsDocShell::CollectWireframe() {
const bool collectWireFrame =
mozilla::SessionHistoryInParent() &&
StaticPrefs::browser_history_collectWireframes() &&
mBrowsingContext->IsTopContent() && mActiveEntry) {
RefPtr<Document> doc = mContentViewer->GetDocument();
Nullable<Wireframe> wireframe;
doc->GetWireframeWithoutFlushing(false, wireframe);
if (!wireframe.IsNull()) {
if (XRE_IsParentProcess()) {
SessionHistoryEntry* entry =
mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
if (entry) {
entry->SetWireframe(Some(wireframe.Value()));
}
} else {
mozilla::Unused
<< ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe(
mBrowsingContext, wireframe.Value());
}
}
mBrowsingContext->IsTopContent() && mActiveEntry;
if (!collectWireFrame) {
return false;
}
RefPtr<Document> doc = mContentViewer->GetDocument();
Nullable<Wireframe> wireframe;
doc->GetWireframeWithoutFlushing(false, wireframe);
if (wireframe.IsNull()) {
return false;
}
if (XRE_IsParentProcess()) {
SessionHistoryEntry* entry =
mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
if (entry) {
entry->SetWireframe(Some(wireframe.Value()));
}
} else {
mozilla::Unused
<< ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe(
mBrowsingContext, wireframe.Value());
}
return true;
}
//*****************************************************************************

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

@ -742,8 +742,8 @@ class nsDocShell final : public nsDocLoader,
public:
// If wireframe collection is enabled, will attempt to gather the
// wireframe for the document and stash it inside of the active history
// entry.
void CollectWireframe();
// entry. Returns true if wireframes were collected.
bool CollectWireframe();
// Helper method that is called when a new document (including any
// sub-documents - ie. frames) has been completely loaded.

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

@ -54,9 +54,12 @@ static nsSize GetContentRectSize(const nsIFrame& aFrame) {
nsMargin padding =
aFrame.GetUsedPadding().ApplySkipSides(aFrame.GetSkipSides());
scrollPort.Deflate(padding);
MOZ_ASSERT(!aFrame.PresContext()->UseOverlayScrollbars() ||
scrollPort.Size() ==
aFrame.GetContentRectRelativeToSelf().Size());
// This can break in some edge cases like when layout overflows sizes or
// what not.
NS_ASSERTION(
!aFrame.PresContext()->UseOverlayScrollbars() ||
scrollPort.Size() == aFrame.GetContentRectRelativeToSelf().Size(),
"Wrong scrollport?");
return scrollPort.Size();
}
return aFrame.GetContentRectRelativeToSelf().Size();

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

@ -86,15 +86,17 @@
#include "mozilla/ScopeExit.h"
#include "mozilla/StaticPrefs_fission.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/ChromeMessageSender.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/FrameCrashedEvent.h"
#include "mozilla/dom/FrameLoaderBinding.h"
#include "mozilla/dom/InProcessChild.h"
#include "mozilla/dom/MozFrameLoaderOwnerBinding.h"
#include "mozilla/dom/PBrowser.h"
#include "mozilla/dom/SessionHistoryEntry.h"
#include "mozilla/dom/SessionStoreChangeListener.h"
#include "mozilla/dom/SessionStoreListener.h"
#include "mozilla/dom/SessionStoreChild.h"
#include "mozilla/dom/SessionStoreParent.h"
#include "mozilla/dom/SessionStoreUtils.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/dom/XULFrameElement.h"
@ -164,8 +166,7 @@ using PrintPreviewResolver = std::function<void(const PrintPreviewResultInfo&)>;
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsFrameLoader, mPendingBrowsingContext,
mMessageManager, mChildMessageManager,
mRemoteBrowser,
mSessionStoreChangeListener)
mRemoteBrowser, mSessionStoreChild)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
@ -2041,14 +2042,9 @@ void nsFrameLoader::DestroyDocShell() {
mChildMessageManager->FireUnloadEvent();
}
if (mSessionStoreListener) {
mSessionStoreListener->RemoveListeners();
mSessionStoreListener = nullptr;
}
if (mSessionStoreChangeListener) {
mSessionStoreChangeListener->Stop();
mSessionStoreChangeListener = nullptr;
if (mSessionStoreChild) {
mSessionStoreChild->Stop();
mSessionStoreChild = nullptr;
}
// Destroy the docshell.
@ -2141,22 +2137,22 @@ void nsFrameLoader::SetOwnerContent(Element* aContent) {
#endif
}
if (mSessionStoreListener && mOwnerContent) {
if (mSessionStoreChild && mOwnerContent) {
// mOwnerContent will only be null when the frame loader is being destroyed,
// so the session store listener will be destroyed along with it.
// XXX(farre): This probably needs to update the cache. See bug 1698497.
mSessionStoreListener->SetOwnerContent(mOwnerContent);
mSessionStoreChild->SetOwnerContent(mOwnerContent);
}
if (RefPtr<BrowsingContext> browsingContext = GetExtantBrowsingContext()) {
browsingContext->SetEmbedderElement(mOwnerContent);
}
if (mSessionStoreChangeListener) {
if (mSessionStoreChild) {
// UpdateEventTargets will requery its browser contexts for event
// targets, so this call needs to happen after the call to
// SetEmbedderElement above.
mSessionStoreChangeListener->UpdateEventTargets();
mSessionStoreChild->UpdateEventTargets();
}
AutoJSAPI jsapi;
@ -3101,15 +3097,11 @@ nsresult nsFrameLoader::EnsureMessageManager() {
GetDocShell(), mOwnerContent, mMessageManager);
NS_ENSURE_TRUE(mChildMessageManager, NS_ERROR_UNEXPECTED);
// Set up a TabListener for sessionStore
// Set up session store
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
if (XRE_IsParentProcess()) {
mSessionStoreListener = new TabListener(GetDocShell(), mOwnerContent);
rv = mSessionStoreListener->Init();
NS_ENSURE_SUCCESS(rv, rv);
mSessionStoreChangeListener =
SessionStoreChangeListener::Create(GetExtantBrowsingContext());
if (XRE_IsParentProcess() && mIsTopLevelContent) {
mSessionStoreChild = SessionStoreChild::GetOrCreate(
GetExtantBrowsingContext(), mOwnerContent);
}
}
}
@ -3237,6 +3229,21 @@ void nsFrameLoader::RequestUpdatePosition(ErrorResult& aRv) {
}
}
SessionStoreParent* nsFrameLoader::GetSessionStoreParent() {
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
if (mSessionStoreChild) {
return static_cast<SessionStoreParent*>(
InProcessChild::ParentActorFor(mSessionStoreChild));
}
if (BrowserParent* browserParent = GetBrowserParent()) {
return static_cast<SessionStoreParent*>(
SingleManagedOrNull(browserParent->ManagedPSessionStoreParent()));
}
return nullptr;
}
already_AddRefed<Promise> nsFrameLoader::RequestTabStateFlush(
ErrorResult& aRv) {
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
@ -3247,42 +3254,24 @@ already_AddRefed<Promise> nsFrameLoader::RequestTabStateFlush(
}
RefPtr<Promise> promise = Promise::Create(ownerDoc->GetOwnerGlobal(), aRv);
if (aRv.Failed()) {
return nullptr;
}
RefPtr<BrowsingContext> context = GetExtantBrowsingContext();
if (!context) {
BrowsingContext* browsingContext = GetExtantBrowsingContext();
if (!browsingContext) {
promise->MaybeResolveWithUndefined();
return promise.forget();
}
if (mSessionStoreListener) {
context->FlushSessionStore();
mSessionStoreListener->ForceFlushFromParent();
context->Canonical()->UpdateSessionStoreSessionStorage(
[promise]() { promise->MaybeResolveWithUndefined(); });
SessionStoreParent* sessionStoreParent = GetSessionStoreParent();
if (!sessionStoreParent) {
promise->MaybeResolveWithUndefined();
return promise.forget();
}
using FlushPromise = ContentParent::FlushTabStatePromise;
nsTArray<RefPtr<FlushPromise>> flushPromises;
context->Group()->EachParent([&](ContentParent* aParent) {
if (aParent->CanSend()) {
flushPromises.AppendElement(aParent->SendFlushTabState(context));
}
});
RefPtr<FlushPromise::AllPromiseType> flushPromise =
FlushPromise::All(GetCurrentSerialEventTarget(), flushPromises);
context->Canonical()->UpdateSessionStoreSessionStorage([flushPromise,
promise]() {
flushPromise->Then(GetCurrentSerialEventTarget(), __func__,
[promise]() { promise->MaybeResolveWithUndefined(); });
});
sessionStoreParent->FlushAllSessionStoreChildren(
[promise]() { promise->MaybeResolveWithUndefined(); });
return promise.forget();
}
@ -3297,10 +3286,8 @@ void nsFrameLoader::RequestFinalTabStateFlush() {
RefPtr<WindowGlobalParent> wgp = canonical->GetCurrentWindowGlobal();
RefPtr<Element> embedder = context->GetEmbedderElement();
if (mSessionStoreListener) {
context->FlushSessionStore();
mSessionStoreListener->ForceFlushFromParent();
RefPtr<SessionStoreParent> sessionStoreParent = GetSessionStoreParent();
if (!sessionStoreParent) {
canonical->ClearPermanentKey();
if (wgp) {
wgp->NotifySessionStoreUpdatesComplete(embedder);
@ -3309,24 +3296,15 @@ void nsFrameLoader::RequestFinalTabStateFlush() {
return;
}
using FlushPromise = ContentParent::FlushTabStatePromise;
nsTArray<RefPtr<FlushPromise>> flushPromises;
context->Group()->EachParent([&](ContentParent* aParent) {
if (aParent->CanSend()) {
flushPromises.AppendElement(aParent->SendFlushTabState(context));
}
});
FlushPromise::All(GetCurrentSerialEventTarget(), flushPromises)
->Then(GetCurrentSerialEventTarget(), __func__,
[canonical = RefPtr{canonical}, wgp, embedder]() {
if (canonical) {
canonical->ClearPermanentKey();
}
if (wgp) {
wgp->NotifySessionStoreUpdatesComplete(embedder);
}
});
sessionStoreParent->FinalFlushAllSessionStoreChildren(
[canonical, wgp, embedder]() {
if (canonical) {
canonical->ClearPermanentKey();
}
if (wgp) {
wgp->NotifySessionStoreUpdatesComplete(embedder);
}
});
}
void nsFrameLoader::RequestEpochUpdate(uint32_t aEpoch) {
@ -3335,21 +3313,11 @@ void nsFrameLoader::RequestEpochUpdate(uint32_t aEpoch) {
BrowsingContext* top = context->Top();
Unused << top->SetSessionStoreEpoch(aEpoch);
}
if (mSessionStoreListener) {
mSessionStoreListener->SetEpoch(aEpoch);
return;
}
// If remote browsing (e10s), handle this with the BrowserParent.
if (auto* browserParent = GetBrowserParent()) {
Unused << browserParent->SendUpdateEpoch(aEpoch);
}
}
void nsFrameLoader::RequestSHistoryUpdate() {
if (mSessionStoreListener) {
mSessionStoreListener->UpdateSHistoryChanges();
if (mSessionStoreChild) {
mSessionStoreChild->UpdateSHistoryChanges();
return;
}

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

@ -63,7 +63,6 @@ class ChromeMessageSender;
class ContentParent;
class Document;
class Element;
class TabListener;
class InProcessBrowserChildMessageManager;
class MessageSender;
class ProcessMessageManager;
@ -73,7 +72,8 @@ class BrowserBridgeChild;
class RemoteBrowser;
struct RemotenessOptions;
struct NavigationIsolationOptions;
class SessionStoreChangeListener;
class SessionStoreChild;
class SessionStoreParent;
namespace ipc {
class StructuredCloneData;
@ -411,6 +411,12 @@ class nsFrameLoader final : public nsStubMutationObserver,
void FireErrorEvent();
mozilla::dom::SessionStoreChild* GetSessionStoreChild() {
return mSessionStoreChild;
}
mozilla::dom::SessionStoreParent* GetSessionStoreParent();
private:
nsFrameLoader(mozilla::dom::Element* aOwner,
mozilla::dom::BrowsingContext* aBrowsingContext, bool aIsRemote,
@ -520,9 +526,10 @@ class nsFrameLoader final : public nsStubMutationObserver,
// Holds the last known size of the frame.
mozilla::ScreenIntSize mLazySize;
RefPtr<mozilla::dom::TabListener> mSessionStoreListener;
RefPtr<mozilla::dom::SessionStoreChangeListener> mSessionStoreChangeListener;
// Actor for collecting session store data from content children. This will be
// cleared and set to null eagerly when taking down the frameloader to break
// refcounted cycles early.
RefPtr<mozilla::dom::SessionStoreChild> mSessionStoreChild;
nsCString mRemoteType;

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

@ -0,0 +1,47 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
// object contains either a CollectedFileListValue or a CollectedNonMultipleSelectValue or Sequence<DOMString>
typedef (DOMString or boolean or object) FormDataValue;
[ChromeOnly, Exposed=Window]
interface SessionStoreFormData {
[Cached, Pure]
readonly attribute ByteString? url;
[Cached, Pure]
readonly attribute record<DOMString, FormDataValue>? id;
[Cached, Pure]
readonly attribute record<DOMString, FormDataValue>? xpath;
[Cached, Pure]
readonly attribute DOMString? innerHTML;
[Cached, Frozen, Pure]
readonly attribute sequence<SessionStoreFormData?>? children;
object toJSON();
};
[ChromeOnly, Exposed=Window]
interface SessionStoreScrollData {
[Cached, Pure]
readonly attribute ByteString? scroll;
[Cached, Pure]
readonly attribute sequence<SessionStoreScrollData?>? children;
object toJSON();
};
[GenerateConversionToJS]
dictionary UpdateSessionStoreData {
// This is docshell caps, but on-disk format uses the disallow property name.
ByteString? disallow;
boolean isPrivate;
SessionStoreFormData? formdata;
SessionStoreScrollData? scroll;
};

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

@ -167,28 +167,3 @@ dictionary InputElementData {
sequence<DOMString> strVal;
sequence<boolean> boolVal;
};
[GenerateConversionToJS]
dictionary UpdateSessionStoreData {
ByteString docShellCaps;
boolean isPrivate;
};
[GenerateConversionToJS]
dictionary SessionStoreWindowStateChange {
SessionStoreFormData formdata;
SessionStoreScroll scroll;
boolean hasChildren;
required sequence<unsigned long> path;
};
dictionary SessionStoreFormData {
ByteString url;
record<DOMString, CollectedFormDataValue> id;
record<DOMString, CollectedFormDataValue> xpath;
DOMString innerHTML;
};
dictionary SessionStoreScroll {
ByteString scroll;
};

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

@ -37,6 +37,7 @@ PREPROCESSED_WEBIDL_FILES = [
]
WEBIDL_FILES = [
"BrowserSessionStore.webidl",
"BrowsingContext.webidl",
"ChannelWrapper.webidl",
"ClonedErrorHolder.webidl",

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

@ -362,7 +362,9 @@ GetStructuredCloneReadInfoFromBlob(const uint8_t* aBlobData,
&uncompressedLength)),
Err(NS_ERROR_FILE_CORRUPTED));
AutoTArray<uint8_t, 512> uncompressed;
// `data` (JSStructuredCloneData) currently uses 4k buffer internally.
// For performance reasons, it's better to align `uncompressed` with that.
AutoTArray<uint8_t, 4096> uncompressed;
QM_TRY(OkIf(uncompressed.SetLength(uncompressedLength, fallible)),
Err(NS_ERROR_OUT_OF_MEMORY));

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

@ -69,10 +69,8 @@
#include "mozilla/dom/PBrowser.h"
#include "mozilla/dom/PaymentRequestChild.h"
#include "mozilla/dom/PointerEventHandler.h"
#include "mozilla/dom/SessionStoreChangeListener.h"
#include "mozilla/dom/SessionStoreDataCollector.h"
#include "mozilla/dom/SessionStoreListener.h"
#include "mozilla/dom/SessionStoreUtils.h"
#include "mozilla/dom/SessionStoreChild.h"
#include "mozilla/dom/WindowGlobalChild.h"
#include "mozilla/dom/WindowProxyHolder.h"
#include "mozilla/gfx/CrossProcessPaint.h"
@ -522,12 +520,7 @@ nsresult BrowserChild::Init(mozIDOMWindowProxy* aParent,
mIPCOpen = true;
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
mSessionStoreListener = new TabListener(docShell, nullptr);
rv = mSessionStoreListener->Init();
NS_ENSURE_SUCCESS(rv, rv);
mSessionStoreChangeListener =
SessionStoreChangeListener::Create(mBrowsingContext);
mSessionStoreChild = SessionStoreChild::GetOrCreate(mBrowsingContext);
}
// We've all set up, make sure our visibility state is consistent. This is
@ -545,8 +538,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowserChild)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusFilter)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebNav)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStoreListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStoreChangeListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStoreChild)
NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -555,8 +547,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowserChild)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusFilter)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebNav)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStoreListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStoreChangeListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStoreChild)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(BrowserChild)
@ -849,14 +840,9 @@ void BrowserChild::DestroyWindow() {
mCoalescedTouchMoveEventFlusher = nullptr;
}
if (mSessionStoreListener) {
mSessionStoreListener->RemoveListeners();
mSessionStoreListener = nullptr;
}
if (mSessionStoreChangeListener) {
mSessionStoreChangeListener->Stop();
mSessionStoreChangeListener = nullptr;
if (mSessionStoreChild) {
mSessionStoreChild->Stop();
mSessionStoreChild = nullptr;
}
// In case we don't have chance to process all entries, clean all data in
@ -2060,16 +2046,9 @@ mozilla::ipc::IPCResult BrowserChild::RecvNativeSynthesisResponse(
return IPC_OK();
}
mozilla::ipc::IPCResult BrowserChild::RecvUpdateEpoch(const uint32_t& aEpoch) {
if (mSessionStoreListener) {
mSessionStoreListener->SetEpoch(aEpoch);
}
return IPC_OK();
}
mozilla::ipc::IPCResult BrowserChild::RecvUpdateSHistory() {
if (mSessionStoreListener) {
mSessionStoreListener->UpdateSHistoryChanges();
if (mSessionStoreChild) {
mSessionStoreChild->UpdateSHistoryChanges();
}
return IPC_OK();
}
@ -3809,26 +3788,10 @@ nsresult BrowserChild::PrepareProgressListenerData(
return PrepareRequestData(aRequest, aRequestData);
}
bool BrowserChild::UpdateSessionStore() {
if (!mSessionStoreListener) {
return false;
void BrowserChild::UpdateSessionStore() {
if (mSessionStoreChild) {
mSessionStoreChild->UpdateSessionStore();
}
RefPtr<ContentSessionStore> store = mSessionStoreListener->GetSessionStore();
Maybe<nsCString> docShellCaps;
if (store->IsDocCapChanged()) {
docShellCaps.emplace(store->GetDocShellCaps());
}
Maybe<bool> privatedMode;
if (store->IsPrivateChanged()) {
privatedMode.emplace(store->GetPrivateModeEnabled());
}
Unused << SendSessionStoreUpdate(docShellCaps, privatedMode,
store->GetAndClearSHistoryChanged(),
mSessionStoreListener->GetEpoch());
return true;
}
#ifdef XP_WIN

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

@ -86,9 +86,7 @@ class TabGroup;
class ClonedMessageData;
class CoalescedMouseData;
class CoalescedWheelData;
class ContentSessionStore;
class SessionStoreChangeListener;
class TabListener;
class SessionStoreChild;
class RequestData;
class WebProgressData;
@ -396,8 +394,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
aApzResponse);
}
mozilla::ipc::IPCResult RecvUpdateEpoch(const uint32_t& aEpoch);
mozilla::ipc::IPCResult RecvUpdateSHistory();
mozilla::ipc::IPCResult RecvNativeSynthesisResponse(
@ -673,7 +669,11 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
mCancelContentJSEpoch = aEpoch;
}
bool UpdateSessionStore();
void UpdateSessionStore();
mozilla::dom::SessionStoreChild* GetSessionStoreChild() {
return mSessionStoreChild;
}
#ifdef XP_WIN
// Check if the window this BrowserChild is associated with supports
@ -892,8 +892,7 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
RefPtr<CoalescedTouchMoveFlusher> mCoalescedTouchMoveEventFlusher;
RefPtr<layers::IAPZCTreeManager> mApzcTreeManager;
RefPtr<TabListener> mSessionStoreListener;
RefPtr<SessionStoreChangeListener> mSessionStoreChangeListener;
RefPtr<SessionStoreChild> mSessionStoreChild;
// The most recently seen layer observer epoch in RecvSetDocShellIsActive.
layers::LayersObserverEpoch mLayersObserverEpoch;

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

@ -16,6 +16,7 @@
#endif
#include "mozilla/Components.h"
#include "mozilla/dom/BrowserHost.h"
#include "mozilla/dom/BrowserSessionStore.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/CancelContentJSOptionsBinding.h"
#include "mozilla/dom/ChromeMessageSender.h"
@ -32,8 +33,7 @@
#include "mozilla/dom/RemoteDragStartData.h"
#include "mozilla/dom/RemoteWebProgressRequest.h"
#include "mozilla/dom/SessionHistoryEntry.h"
#include "mozilla/dom/SessionStoreUtils.h"
#include "mozilla/dom/SessionStoreUtilsBinding.h"
#include "mozilla/dom/SessionStoreParent.h"
#include "mozilla/dom/UserActivation.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/gfx/2D.h"
@ -53,6 +53,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/PresShell.h"
#include "mozilla/ProcessHangMonitor.h"
#include "mozilla/RefPtr.h"
#include "mozilla/StaticPrefs_accessibility.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/TextEventDispatcher.h"
@ -128,7 +129,6 @@
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/ProfilerLabels.h"
#include "MMPrinter.h"
#include "SessionStoreFunctions.h"
#include "mozilla/dom/CrashReport.h"
#include "nsISecureBrowserUI.h"
#include "nsIXULRuntime.h"
@ -1372,6 +1372,17 @@ IPCResult BrowserParent::RecvIndexedDBPermissionRequest(
return IPC_OK();
}
already_AddRefed<PSessionStoreParent>
BrowserParent::AllocPSessionStoreParent() {
RefPtr<BrowserSessionStore> sessionStore =
BrowserSessionStore::GetOrCreate(mBrowsingContext->Top());
if (!sessionStore) {
return nullptr;
}
return do_AddRef(new SessionStoreParent(mBrowsingContext, sessionStore));
}
IPCResult BrowserParent::RecvNewWindowGlobal(
ManagedEndpoint<PWindowGlobalParent>&& aEndpoint,
const WindowGlobalInit& aInit) {
@ -3008,41 +3019,6 @@ BrowserParent::BrowsingContextForWebProgress(
return browsingContext.forget();
}
mozilla::ipc::IPCResult BrowserParent::RecvSessionStoreUpdate(
const Maybe<nsCString>& aDocShellCaps, const Maybe<bool>& aPrivatedMode,
const bool aNeedCollectSHistory, const uint32_t& aEpoch) {
UpdateSessionStoreData data;
if (aDocShellCaps.isSome()) {
data.mDocShellCaps.Construct() = aDocShellCaps.value();
}
if (aPrivatedMode.isSome()) {
data.mIsPrivate.Construct() = aPrivatedMode.value();
}
nsCOMPtr<nsISessionStoreFunctions> funcs = do_ImportModule(
"resource://gre/modules/SessionStoreFunctions.jsm", fallible);
nsCOMPtr<nsIXPConnectWrappedJS> wrapped = do_QueryInterface(funcs);
NS_ENSURE_TRUE(wrapped, IPC_OK());
AutoJSAPI jsapi;
if (!jsapi.Init(wrapped->GetJSObjectGlobal())) {
return IPC_OK();
}
JS::Rooted<JS::Value> update(jsapi.cx());
if (!ToJSValue(jsapi.cx(), data, &update)) {
return IPC_OK();
}
JS::RootedValue key(jsapi.cx(),
mBrowsingContext->Canonical()->Top()->PermanentKey());
Unused << funcs->UpdateSessionStore(mFrameElement, mBrowsingContext, key,
aEpoch, aNeedCollectSHistory, update);
return IPC_OK();
}
mozilla::ipc::IPCResult BrowserParent::RecvIntrinsicSizeOrRatioChanged(
const Maybe<IntrinsicSize>& aIntrinsicSize,
const Maybe<AspectRatio>& aIntrinsicRatio) {

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

@ -317,10 +317,6 @@ class BrowserParent final : public PBrowserParent,
already_AddRefed<CanonicalBrowsingContext> BrowsingContextForWebProgress(
const WebProgressData& aWebProgressData);
mozilla::ipc::IPCResult RecvSessionStoreUpdate(
const Maybe<nsCString>& aDocShellCaps, const Maybe<bool>& aPrivatedMode,
const bool aNeedCollectSHistory, const uint32_t& aEpoch);
mozilla::ipc::IPCResult RecvIntrinsicSizeOrRatioChanged(
const Maybe<IntrinsicSize>& aIntrinsicSize,
const Maybe<AspectRatio>& aIntrinsicRatio);
@ -445,6 +441,8 @@ class BrowserParent final : public PBrowserParent,
const IAccessibleHolder& aDocCOMProxy) override;
#endif
already_AddRefed<PSessionStoreParent> AllocPSessionStoreParent();
mozilla::ipc::IPCResult RecvNewWindowGlobal(
ManagedEndpoint<PWindowGlobalParent>&& aEndpoint,
const WindowGlobalInit& aInit);

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

@ -4524,25 +4524,6 @@ mozilla::ipc::IPCResult ContentChild::RecvInitNextGenLocalStorageEnabled(
}
}
mozilla::ipc::IPCResult ContentChild::RecvFlushTabState(
const MaybeDiscarded<BrowsingContext>& aContext,
FlushTabStateResolver&& aResolver) {
if (aContext.IsNullOrDiscarded()) {
aResolver(false);
return IPC_OK();
}
if (auto* docShell = nsDocShell::Cast(aContext->GetDocShell())) {
docShell->CollectWireframe();
}
aContext->FlushSessionStore();
aResolver(true);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvGoBack(
const MaybeDiscarded<BrowsingContext>& aContext,
const Maybe<int32_t>& aCancelContentJSEpoch, bool aRequireUserInteraction,

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

@ -812,10 +812,6 @@ class ContentChild final : public PContentChild,
const MaybeDiscarded<BrowsingContext>& aStartingAt,
DispatchBeforeUnloadToSubtreeResolver&& aResolver);
mozilla::ipc::IPCResult RecvFlushTabState(
const MaybeDiscarded<BrowsingContext>& aContext,
FlushTabStateResolver&& aResolver);
mozilla::ipc::IPCResult RecvDecoderSupportedMimeTypes(
nsTArray<nsCString>&& aSupportedTypes);

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

@ -17,6 +17,7 @@ include protocol PParentToChildStream;
include protocol PFileDescriptorSet;
include protocol PRemoteLazyInputStream;
include protocol PPaymentRequest;
include protocol PSessionStore;
include protocol PWindowGlobal;
include protocol PBrowserBridge;
include protocol PVsync;
@ -190,6 +191,7 @@ struct PrintPreviewResultInfo
manages PFilePicker;
manages PPaymentRequest;
manages PSessionStore;
manages PWindowGlobal;
manages PBrowserBridge;
manages PVsync;
@ -575,9 +577,6 @@ parent:
async NavigationFinished();
async SessionStoreUpdate(nsCString? aDocShellCaps, bool? aPrivatedMode,
bool aNeedCollectSHistory, uint32_t aEpoch);
async IntrinsicSizeOrRatioChanged(IntrinsicSize? aIntrinsicSize,
AspectRatio? aIntrinsicRatio);
@ -595,7 +594,6 @@ parent:
child:
async NativeSynthesisResponse(uint64_t aObserverId, nsCString aResponse);
async UpdateEpoch(uint32_t aEpoch);
async UpdateSHistory();
async CloneDocumentTreeIntoSelf(MaybeDiscardedBrowsingContext aBc, PrintData aPrintData) returns(bool aSuccess);
async UpdateRemotePrintSettings(PrintData aPrintData);
@ -1016,6 +1014,9 @@ parent:
/** Fetches the visited status for an array of URIs (Android-only). */
async QueryVisitedState(nsIURI[] aURIs);
/** Create a session store for a browser child. */
async PSessionStore();
/**
* Construct a new WindowGlobal for an existing global in the content process
*/

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

@ -1027,9 +1027,6 @@ child:
// Update the cached list of codec supported in the given process.
async UpdateMediaCodecsSupported(RemoteDecodeIn aLocation, MediaCodecsSupported aSupported);
async FlushTabState(MaybeDiscardedBrowsingContext aBrowsingContext)
returns(bool aHadContext);
// Send the list of the supported mimetypes in the given process. GeckoView-specific
async DecoderSupportedMimeTypes(nsCString[] supportedTypes);

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

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PExtensions;
include protocol PSessionStore;
include protocol PWindowGlobal;
include DOMTypes;
@ -23,6 +24,7 @@ namespace dom {
async protocol PInProcess
{
manages PExtensions;
manages PSessionStore;
manages PWindowGlobal;
};

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

@ -180,11 +180,6 @@ parent:
async RequestRestoreTabContent();
async UpdateSessionStore(FormData? aFormData, nsPoint? aScrollPosition,
uint32_t aEpoch);
async ResetSessionStore(uint32_t aEpoch);
// Add the flags in aOnFlags to the current BFCache status and remove the
// flags in aOffFlags from the current BFCache status. See the BFCacheStatus
// enum for the valid flags.

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

@ -18,7 +18,6 @@
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/SecurityPolicyViolationEvent.h"
#include "mozilla/dom/SessionStoreRestoreData.h"
#include "mozilla/dom/SessionStoreDataCollector.h"
#include "mozilla/dom/WindowGlobalActorsBinding.h"
#include "mozilla/dom/WindowContext.h"
#include "mozilla/dom/InProcessChild.h"
@ -327,11 +326,6 @@ void WindowGlobalChild::Destroy() {
if (!browserChild || !browserChild->IsDestroyed()) {
SendDestroy();
}
if (mSessionStoreDataCollector) {
mSessionStoreDataCollector->Cancel();
mSessionStoreDataCollector = nullptr;
}
}
mozilla::ipc::IPCResult WindowGlobalChild::RecvMakeFrameLocal(
@ -703,20 +697,9 @@ nsISupports* WindowGlobalChild::GetParentObject() {
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
}
void WindowGlobalChild::SetSessionStoreDataCollector(
SessionStoreDataCollector* aCollector) {
mSessionStoreDataCollector = aCollector;
}
SessionStoreDataCollector* WindowGlobalChild::GetSessionStoreDataCollector()
const {
return mSessionStoreDataCollector;
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_WEAK_PTR(WindowGlobalChild, mWindowGlobal,
mContainerFeaturePolicy,
mWindowContext,
mSessionStoreDataCollector)
mWindowContext)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WindowGlobalChild)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY

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

@ -28,7 +28,6 @@ class WindowGlobalParent;
class JSWindowActorChild;
class JSActorMessageMeta;
class BrowserChild;
class SessionStoreDataCollector;
/**
* Actor for a single nsGlobalWindowInner. This actor is used to communicate
@ -133,9 +132,6 @@ class WindowGlobalChild final : public WindowGlobalActor,
return mContainerFeaturePolicy;
}
void SetSessionStoreDataCollector(SessionStoreDataCollector* aCollector);
SessionStoreDataCollector* GetSessionStoreDataCollector() const;
void UnblockBFCacheFor(BFCacheStatus aStatus);
void BlockBFCacheFor(BFCacheStatus aStatus);
@ -205,7 +201,6 @@ class WindowGlobalChild final : public WindowGlobalActor,
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
RefPtr<dom::FeaturePolicy> mContainerFeaturePolicy;
nsCOMPtr<nsIURI> mDocumentURI;
RefPtr<SessionStoreDataCollector> mSessionStoreDataCollector;
int64_t mBeforeUnloadListeners = 0;
};

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

@ -26,9 +26,6 @@
#include "mozilla/dom/ChromeUtils.h"
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/dom/ipc/StructuredCloneData.h"
#include "mozilla/dom/sessionstore/SessionStoreTypes.h"
#include "mozilla/dom/SessionStoreUtils.h"
#include "mozilla/dom/SessionStoreUtilsBinding.h"
#include "mozilla/Components.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/ServoCSSParser.h"
@ -535,16 +532,6 @@ const nsACString& WindowGlobalParent::GetRemoteType() {
return NOT_REMOTE_TYPE;
}
static nsCString PointToString(const nsPoint& aPoint) {
int scrollX = nsPresContext::AppUnitsToIntCSSPixels(aPoint.x);
int scrollY = nsPresContext::AppUnitsToIntCSSPixels(aPoint.y);
if ((scrollX != 0) || (scrollY != 0)) {
return nsPrintfCString("%d,%d", scrollX, scrollY);
}
return ""_ns;
}
void WindowGlobalParent::NotifyContentBlockingEvent(
uint32_t aEvent, nsIRequest* aRequest, bool aBlocked,
const nsACString& aTrackingOrigin,
@ -1166,44 +1153,6 @@ void WindowGlobalParent::FinishAccumulatingPageUseCounters() {
mPageUseCounters = nullptr;
}
static void GetFormData(JSContext* aCx, const sessionstore::FormData& aFormData,
nsIURI* aDocumentURI, SessionStoreFormData& aUpdate) {
if (!aFormData.hasData()) {
return;
}
bool parseSessionData = false;
if (aDocumentURI) {
nsCString& url = aUpdate.mUrl.Construct();
aDocumentURI->GetSpecIgnoringRef(url);
// We want to avoid saving data for about:sessionrestore as a string.
// Since it's stored in the form as stringified JSON, stringifying
// further causes an explosion of escape characters. cf. bug 467409
parseSessionData =
url == "about:sessionrestore"_ns || url == "about:welcomeback"_ns;
}
if (!aFormData.innerHTML().IsEmpty()) {
aUpdate.mInnerHTML.Construct(aFormData.innerHTML());
}
if (!aFormData.id().IsEmpty()) {
auto& id = aUpdate.mId.Construct();
if (NS_FAILED(SessionStoreUtils::ConstructFormDataValues(
aCx, aFormData.id(), id.Entries(), parseSessionData))) {
return;
}
}
if (!aFormData.xpath().IsEmpty()) {
auto& xpath = aUpdate.mXpath.Construct();
if (NS_FAILED(SessionStoreUtils::ConstructFormDataValues(
aCx, aFormData.xpath(), xpath.Entries()))) {
return;
}
}
}
Element* WindowGlobalParent::GetRootOwnerElement() {
WindowGlobalParent* top = TopWindowContext();
if (!top) {
@ -1221,104 +1170,6 @@ Element* WindowGlobalParent::GetRootOwnerElement() {
return nullptr;
}
nsresult WindowGlobalParent::WriteFormDataAndScrollToSessionStore(
const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
uint32_t aEpoch) {
if (!aFormData && !aScrollPosition) {
return NS_OK;
}
RefPtr<CanonicalBrowsingContext> context = BrowsingContext();
if (!context) {
return NS_OK;
}
nsCOMPtr<nsISessionStoreFunctions> funcs = do_ImportModule(
"resource://gre/modules/SessionStoreFunctions.jsm", fallible);
if (!funcs) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIXPConnectWrappedJS> wrapped = do_QueryInterface(funcs);
AutoJSAPI jsapi;
if (!jsapi.Init(wrapped->GetJSObjectGlobal())) {
return NS_ERROR_FAILURE;
}
RootedDictionary<SessionStoreWindowStateChange> windowState(jsapi.cx());
if (aFormData) {
GetFormData(jsapi.cx(), *aFormData, mDocumentURI,
windowState.mFormdata.Construct());
}
if (aScrollPosition) {
auto& update = windowState.mScroll.Construct();
if (*aScrollPosition != nsPoint(0, 0)) {
update.mScroll.Construct() = PointToString(*aScrollPosition);
}
}
nsTArray<uint32_t> path;
if (!context->GetOffsetPath(path)) {
return NS_OK;
}
windowState.mPath = std::move(path);
windowState.mHasChildren.Construct() = !context->Children().IsEmpty();
JS::RootedValue update(jsapi.cx());
if (!ToJSValue(jsapi.cx(), windowState, &update)) {
return NS_ERROR_FAILURE;
}
JS::RootedValue key(jsapi.cx(), context->Top()->PermanentKey());
return funcs->UpdateSessionStoreForWindow(GetRootOwnerElement(), context, key,
aEpoch, update);
}
nsresult WindowGlobalParent::ResetSessionStore(uint32_t aEpoch) {
RefPtr<CanonicalBrowsingContext> context = BrowsingContext();
if (!context) {
return NS_OK;
}
nsCOMPtr<nsISessionStoreFunctions> funcs = do_ImportModule(
"resource://gre/modules/SessionStoreFunctions.jsm", fallible);
if (!funcs) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIXPConnectWrappedJS> wrapped = do_QueryInterface(funcs);
AutoJSAPI jsapi;
if (!jsapi.Init(wrapped->GetJSObjectGlobal())) {
return NS_ERROR_FAILURE;
}
RootedDictionary<SessionStoreWindowStateChange> windowState(jsapi.cx());
nsTArray<uint32_t> path;
if (!context->GetOffsetPath(path)) {
return NS_OK;
}
windowState.mPath = std::move(path);
windowState.mHasChildren.Construct() = false;
windowState.mFormdata.Construct();
windowState.mScroll.Construct();
JS::RootedValue update(jsapi.cx());
if (!ToJSValue(jsapi.cx(), windowState, &update)) {
return NS_ERROR_FAILURE;
}
JS::RootedValue key(jsapi.cx(), context->Top()->PermanentKey());
return funcs->UpdateSessionStoreForWindow(GetRootOwnerElement(), context, key,
aEpoch, update);
}
void WindowGlobalParent::NotifySessionStoreUpdatesComplete(Element* aEmbedder) {
if (!aEmbedder) {
aEmbedder = GetRootOwnerElement();
@ -1331,27 +1182,6 @@ void WindowGlobalParent::NotifySessionStoreUpdatesComplete(Element* aEmbedder) {
}
}
mozilla::ipc::IPCResult WindowGlobalParent::RecvUpdateSessionStore(
const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
uint32_t aEpoch) {
if (NS_FAILED(WriteFormDataAndScrollToSessionStore(aFormData, aScrollPosition,
aEpoch))) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Failed to update session store entry."));
}
return IPC_OK();
}
mozilla::ipc::IPCResult WindowGlobalParent::RecvResetSessionStore(
uint32_t aEpoch) {
if (NS_FAILED(ResetSessionStore(aEpoch))) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Failed to reset session store entry."));
}
return IPC_OK();
}
mozilla::ipc::IPCResult WindowGlobalParent::RecvRequestRestoreTabContent() {
CanonicalBrowsingContext* bc = BrowsingContext();
if (bc && bc->AncestorsAreCurrent()) {

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

@ -80,7 +80,7 @@ class WindowGlobalParent final : public WindowContext,
WindowGlobalParent* TopWindowContext() {
return static_cast<WindowGlobalParent*>(WindowContext::TopWindowContext());
}
CanonicalBrowsingContext* GetBrowsingContext() {
CanonicalBrowsingContext* GetBrowsingContext() const {
return CanonicalBrowsingContext::Cast(WindowContext::GetBrowsingContext());
}
@ -214,10 +214,6 @@ class WindowGlobalParent final : public WindowContext,
const nsACString& GetRemoteType() override;
nsresult WriteFormDataAndScrollToSessionStore(
const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
uint32_t aEpoch);
void NotifySessionStoreUpdatesComplete(Element* aEmbedder);
Maybe<uint64_t> GetSingleChannelId() { return mSingleChannelId; }
@ -288,12 +284,6 @@ class WindowGlobalParent final : public WindowContext,
mozilla::ipc::IPCResult RecvRequestRestoreTabContent();
mozilla::ipc::IPCResult RecvUpdateSessionStore(
const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
uint32_t aEpoch);
mozilla::ipc::IPCResult RecvResetSessionStore(uint32_t aEpoch);
mozilla::ipc::IPCResult RecvUpdateBFCacheStatus(const uint32_t& aOnFlags,
const uint32_t& aOffFlags);
@ -320,8 +310,6 @@ class WindowGlobalParent final : public WindowContext,
bool ShouldTrackSiteOriginTelemetry();
void FinishAccumulatingPageUseCounters();
nsresult ResetSessionStore(uint32_t aEpoch);
// Returns failure if the new storage principal cannot be validated
// against the current document principle.
nsresult SetDocumentStoragePrincipal(

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

@ -132,11 +132,13 @@ static HRESULT GetDirectWriteFaceName(IDWriteFont* aFont,
return S_OK;
}
void gfxDWriteFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) {
void gfxDWriteFontFamily::FindStyleVariationsLocked(
FontInfoData* aFontInfoData) {
HRESULT hr;
if (mHasStyles) {
return;
}
mHasStyles = true;
gfxPlatformFontList* fp = gfxPlatformFontList::PlatformFontList();
@ -188,7 +190,7 @@ void gfxDWriteFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) {
fe->SetupVariationRanges();
AddFontEntry(fe);
AddFontEntryLocked(fe);
// postscript/fullname if needed
nsAutoCString psname, fullname;
@ -1839,7 +1841,7 @@ void gfxDWriteFontList::GetFontsFromCollection(
// if this fails/doesn't exist, we'll have used name index 0,
// so that's the one we'll want to skip here
names->FindLocaleName(L"en-us", &englishIdx, &exists);
AutoTArray<nsCString, 4> otherFamilyNames;
for (nameIndex = 0; nameIndex < nameCount; nameIndex++) {
UINT32 nameLen;
AutoTArray<WCHAR, 32> localizedName;
@ -1866,9 +1868,12 @@ void gfxDWriteFontList::GetFontsFromCollection(
NS_ConvertUTF16toUTF8 locName(localizedName.Elements());
if (!familyName.Equals(locName)) {
AddOtherFamilyName(fam, locName);
otherFamilyNames.AppendElement(locName);
}
}
if (!otherFamilyNames.IsEmpty()) {
AddOtherFamilyNames(fam, otherFamilyNames);
}
}
// at this point, all family names have been read in
@ -2010,7 +2015,7 @@ void gfxDWriteFontList::GetDirectWriteSubstitutes() {
}
}
bool gfxDWriteFontList::FindAndAddFamilies(
bool gfxDWriteFontList::FindAndAddFamiliesLocked(
nsPresContext* aPresContext, StyleGenericFontFamily aGeneric,
const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
FindFamiliesFlags aFlags, gfxFontStyle* aStyle, nsAtom* aLanguage,
@ -2037,7 +2042,7 @@ bool gfxDWriteFontList::FindAndAddFamilies(
return false;
}
return gfxPlatformFontList::FindAndAddFamilies(
return gfxPlatformFontList::FindAndAddFamiliesLocked(
aPresContext, aGeneric, keyName, aOutput, aFlags, aStyle, aLanguage,
aDevToCssSize);
}
@ -2046,6 +2051,8 @@ void gfxDWriteFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
FontListSizes* aSizes) const {
gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
AutoLock lock(mLock);
// We are a singleton, so include the font loader singleton's memory.
MOZ_ASSERT(static_cast<const gfxPlatformFontList*>(this) ==
gfxPlatformFontList::PlatformFontList());

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

@ -63,7 +63,7 @@ class gfxDWriteFontFamily final : public gfxFontFamily {
mForceGDIClassic(false) {}
virtual ~gfxDWriteFontFamily();
void FindStyleVariations(FontInfoData* aFontInfoData = nullptr) final;
void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr) final;
void LocalizedName(nsACString& aLocalizedName) final;
@ -194,7 +194,7 @@ class gfxDWriteFontEntry final : public gfxFontEntry {
hb_blob_t* GetFontTable(uint32_t aTableTag) override;
nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr);
nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr) override;
bool IsCJKFont();
@ -387,7 +387,8 @@ class gfxDWriteFontList final : public gfxPlatformFontList {
const mozilla::fontlist::Family* aFamily) override;
void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily,
bool aNeedFullnamePostscriptNames) override;
bool aNeedFullnamePostscriptNames)
REQUIRES(mLock) override;
bool ReadFaceNames(mozilla::fontlist::Family* aFamily,
mozilla::fontlist::Face* aFace, nsCString& aPSName,
@ -414,7 +415,7 @@ class gfxDWriteFontList final : public gfxPlatformFontList {
IDWriteGdiInterop* GetGDIInterop() { return mGDIInterop; }
bool UseGDIFontTableAccess() const;
bool FindAndAddFamilies(
bool FindAndAddFamiliesLocked(
nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric,
const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr,

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

@ -618,6 +618,7 @@ void FT2FontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
*/
void FT2FontFamily::AddFacesToFontList(nsTArray<FontListEntry>* aFontList) {
AutoReadLock lock(mLock);
for (int i = 0, n = mAvailableFonts.Length(); i < n; ++i) {
const FT2FontEntry* fe =
static_cast<const FT2FontEntry*>(mAvailableFonts[i].get());
@ -1168,7 +1169,9 @@ void gfxFT2FontList::AppendFacesFromFontFile(const nsCString& aFileName,
CollectFunc unshared =
[](const FontListEntry& aFLE, const nsCString& aPSName,
const nsCString& aFullName, StandardFile aStdFile) {
PlatformFontList()->AppendFaceFromFontListEntry(aFLE, aStdFile);
auto* pfl = PlatformFontList();
pfl->mLock.AssertCurrentThreadIn();
pfl->AppendFaceFromFontListEntry(aFLE, aStdFile);
};
CollectFunc shared = [](const FontListEntry& aFLE, const nsCString& aPSName,
const nsCString& aFullName, StandardFile aStdFile) {
@ -1339,7 +1342,9 @@ void gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive,
CollectFunc unshared =
[](const FontListEntry& aFLE, const nsCString& aPSName,
const nsCString& aFullName, StandardFile aStdFile) {
PlatformFontList()->AppendFaceFromFontListEntry(aFLE, aStdFile);
auto* pfl = PlatformFontList();
pfl->mLock.AssertCurrentThreadIn();
pfl->AppendFaceFromFontListEntry(aFLE, aStdFile);
};
CollectFunc shared = [](const FontListEntry& aFLE,
const nsCString& aPSName,
@ -1382,17 +1387,15 @@ void gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive,
// Called on each family after all fonts are added to the list;
// if aSortFaces is true this will sort faces to give priority to "standard"
// font files.
static void FinalizeFamilyMemberList(nsCStringHashKey::KeyType aKey,
const RefPtr<gfxFontFamily>& aFamily,
bool aSortFaces) {
gfxFontFamily* family = aFamily.get();
void FT2FontFamily::FinalizeMemberList(bool aSortFaces) {
AutoWriteLock lock(mLock);
family->SetHasStyles(true);
SetHasStyles(true);
if (aSortFaces) {
family->SortAvailableFonts();
SortAvailableFonts();
}
family->CheckForSimpleFamily();
CheckForSimpleFamily();
}
void gfxFT2FontList::FindFonts() {
@ -1640,6 +1643,7 @@ void gfxFT2FontList::AppendFaceFromFontListEntry(const FontListEntry& aFLE,
}
void gfxFT2FontList::ReadSystemFontList(dom::SystemFontList* aList) {
AutoLock lock(mLock);
for (const auto& entry : mFontFamilies) {
auto family = static_cast<FT2FontFamily*>(entry.GetData().get());
family->AddFacesToFontList(&aList->entries());
@ -1669,9 +1673,8 @@ nsresult gfxFT2FontList::InitFontListForPlatform() {
// Finalize the families by sorting faces into standard order
// and marking "simple" families.
for (const auto& entry : mFontFamilies) {
nsCStringHashKey::KeyType key = entry.GetKey();
const RefPtr<gfxFontFamily>& family = entry.GetData();
FinalizeFamilyMemberList(key, family, /* aSortFaces */ true);
auto* family = static_cast<FT2FontFamily*>(entry.GetData().get());
family->FinalizeMemberList(/* aSortFaces */ true);
}
return NS_OK;
@ -1689,9 +1692,8 @@ nsresult gfxFT2FontList::InitFontListForPlatform() {
// We don't need to sort faces (because they were already sorted by the
// chrome process, so we just maintain the existing order)
for (const auto& entry : mFontFamilies) {
nsCStringHashKey::KeyType key = entry.GetKey();
const RefPtr<gfxFontFamily>& family = entry.GetData();
FinalizeFamilyMemberList(key, family, /* aSortFaces */ false);
auto* family = static_cast<FT2FontFamily*>(entry.GetData().get());
family->FinalizeMemberList(/* aSortFaces */ false);
}
LOG(("got font list from chrome process: %" PRIdPTR " faces in %" PRIu32
@ -1747,10 +1749,13 @@ gfxFontEntry* gfxFT2FontList::LookupLocalFont(nsPresContext* aPresContext,
WeightRange aWeightForEntry,
StretchRange aStretchForEntry,
SlantStyleRange aStyleForEntry) {
AutoLock lock(mLock);
if (SharedFontList()) {
return LookupInSharedFaceNameList(aPresContext, aFontName, aWeightForEntry,
aStretchForEntry, aStyleForEntry);
}
// walk over list of names
FT2FontEntry* fontEntry = nullptr;
FontVisibility level =

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

@ -128,6 +128,8 @@ class FT2FontFamily final : public gfxFontFamily {
// Append this family's faces to the IPC fontlist
void AddFacesToFontList(nsTArray<FontListEntry>* aFontList);
void FinalizeMemberList(bool aSortFaces);
};
class gfxFT2FontList final : public gfxPlatformFontList {
@ -172,23 +174,26 @@ class gfxFT2FontList final : public gfxPlatformFontList {
typedef enum { kUnknown, kStandard } StandardFile;
// initialize font lists
nsresult InitFontListForPlatform() override;
nsresult InitFontListForPlatform() REQUIRES(mLock) override;
void AppendFaceFromFontListEntry(const FontListEntry& aFLE,
StandardFile aStdFile);
StandardFile aStdFile) REQUIRES(mLock);
void AppendFacesFromBlob(const nsCString& aFileName, StandardFile aStdFile,
hb_blob_t* aBlob, FontNameCache* aCache,
uint32_t aTimestamp, uint32_t aFilesize);
uint32_t aTimestamp, uint32_t aFilesize)
REQUIRES(mLock);
void AppendFacesFromFontFile(const nsCString& aFileName,
FontNameCache* aCache, StandardFile aStdFile);
FontNameCache* aCache, StandardFile aStdFile)
REQUIRES(mLock);
void AppendFacesFromOmnijarEntry(nsZipArchive* aReader,
const nsCString& aEntryName,
FontNameCache* aCache, bool aJarChanged);
FontNameCache* aCache, bool aJarChanged)
REQUIRES(mLock);
void InitSharedFontListForPlatform() override;
void InitSharedFontListForPlatform() REQUIRES(mLock) override;
void CollectInitData(const FontListEntry& aFLE, const nsCString& aPSName,
const nsCString& aFullName, StandardFile aStdFile);
@ -212,21 +217,23 @@ class gfxFT2FontList final : public gfxPlatformFontList {
bool AppendFacesFromCachedFaceList(CollectFunc aCollectFace,
const nsCString& aFileName,
const nsCString& aFaceList,
StandardFile aStdFile);
StandardFile aStdFile) REQUIRES(mLock);
void AddFaceToList(const nsCString& aEntryName, uint32_t aIndex,
StandardFile aStdFile, hb_face_t* aFace,
nsCString& aFaceList);
nsCString& aFaceList) REQUIRES(mLock);
void FindFonts();
void FindFonts() REQUIRES(mLock);
void FindFontsInOmnijar(FontNameCache* aCache);
void FindFontsInOmnijar(FontNameCache* aCache) REQUIRES(mLock);
void FindFontsInDir(const nsCString& aDir, FontNameCache* aFNC);
void FindFontsInDir(const nsCString& aDir, FontNameCache* aFNC)
REQUIRES(mLock);
FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext,
const gfxFontStyle* aStyle,
nsAtom* aLanguage = nullptr) override;
nsAtom* aLanguage = nullptr)
REQUIRES(mLock) override;
nsTHashSet<nsCString> mSkipSpaceLookupCheckFamilies;

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

@ -1015,7 +1015,8 @@ nsresult gfxFontconfigFontEntry::CopyFontTable(uint32_t aTableTag,
return gfxFT2FontEntryBase::CopyFaceTable(GetFTFace(), aTableTag, aBuffer);
}
void gfxFontconfigFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) {
void gfxFontconfigFontFamily::FindStyleVariationsLocked(
FontInfoData* aFontInfoData) {
if (mHasStyles) {
return;
}
@ -1039,7 +1040,7 @@ void gfxFontconfigFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) {
fontEntry->SetupVariationRanges();
}
AddFontEntry(fontEntry);
AddFontEntryLocked(fontEntry);
if (fontEntry->IsNormalStyle()) {
numRegularFaces++;
@ -1226,6 +1227,7 @@ bool gfxFontconfigFontFamily::SupportsLangGroup(nsAtom* aLangGroup) const {
// will contain the font entries, each of which holds a reference to its
// pattern. We only check the first pattern in each list, because support
// for langs is considered to be consistent across all faces in a family.
AutoReadLock lock(mLock);
FcPattern* fontPattern;
if (mFontPatterns.Length()) {
fontPattern = mFontPatterns[0];
@ -1248,6 +1250,7 @@ gfxFontconfigFontFamily::~gfxFontconfigFontFamily() {
template <typename Func>
void gfxFontconfigFontFamily::AddFacesToFontList(Func aAddPatternFunc) {
AutoReadLock lock(mLock);
if (HasStyles()) {
for (auto& fe : mAvailableFonts) {
if (!fe) {
@ -1431,14 +1434,17 @@ void gfxFcPlatformFontList::AddPatternToFontList(
// will usually not match
FcChar8* otherName;
int n = (cIndex == 0 ? 1 : 0);
AutoTArray<nsCString, 4> otherFamilyNames;
while (FcPatternGetString(aFont, FC_FAMILY, n, &otherName) == FcResultMatch) {
nsAutoCString otherFamilyName(ToCharPtr(otherName));
AddOtherFamilyName(aFontFamily, otherFamilyName);
otherFamilyNames.AppendElement(nsCString(ToCharPtr(otherName)));
n++;
if (n == int(cIndex)) {
n++; // skip over canonical name
}
}
if (!otherFamilyNames.IsEmpty()) {
AddOtherFamilyNames(aFontFamily, otherFamilyNames);
}
const bool singleName = n == 1;
@ -1576,6 +1582,8 @@ nsresult gfxFcPlatformFontList::InitFontListForPlatform() {
}
void gfxFcPlatformFontList::ReadSystemFontList(dom::SystemFontList* retValue) {
AutoLock lock(mLock);
// Fontconfig versions below 2.9 drop the FC_FILE element in FcNameUnparse
// (see https://bugs.freedesktop.org/show_bug.cgi?id=26718), so when using
// an older version, we manually append it to the unparsed pattern.
@ -2039,6 +2047,8 @@ gfxFontEntry* gfxFcPlatformFontList::LookupLocalFont(
nsPresContext* aPresContext, const nsACString& aFontName,
WeightRange aWeightForEntry, StretchRange aStretchForEntry,
SlantStyleRange aStyleForEntry) {
AutoLock lock(mLock);
nsAutoCString keyName(aFontName);
ToLowerCase(keyName);
@ -2071,7 +2081,7 @@ gfxFontEntry* gfxFcPlatformFontList::MakePlatformFont(
std::move(face));
}
bool gfxFcPlatformFontList::FindAndAddFamilies(
bool gfxFcPlatformFontList::FindAndAddFamiliesLocked(
nsPresContext* aPresContext, StyleGenericFontFamily aGeneric,
const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
FindFamiliesFlags aFlags, gfxFontStyle* aStyle, nsAtom* aLanguage,
@ -2184,7 +2194,7 @@ bool gfxFcPlatformFontList::FindAndAddFamilies(
if (terminator && FcStrCmp(substName, terminator) == 0) {
break;
}
gfxPlatformFontList::FindAndAddFamilies(
gfxPlatformFontList::FindAndAddFamiliesLocked(
aPresContext, aGeneric, nsDependentCString(ToCharPtr(substName)),
&cachedFamilies, aFlags, aStyle, aLanguage);
}
@ -2340,6 +2350,7 @@ void gfxFcPlatformFontList::AddGenericFonts(
}
}
AutoLock lock(mLock);
PrefFontList* prefFonts =
FindGenericFamilies(aPresContext, genericToLookup, aLanguage);
NS_ASSERTION(prefFonts, "null generic font list");
@ -2349,9 +2360,9 @@ void gfxFcPlatformFontList::AddGenericFonts(
}
}
void gfxFcPlatformFontList::ClearLangGroupPrefFonts() {
ClearGenericMappings();
gfxPlatformFontList::ClearLangGroupPrefFonts();
void gfxFcPlatformFontList::ClearLangGroupPrefFontsLocked() {
ClearGenericMappingsLocked();
gfxPlatformFontList::ClearLangGroupPrefFontsLocked();
mAlwaysUseFontconfigGenerics = PrefFontListsUseOnlyGenerics();
}
@ -2411,9 +2422,10 @@ gfxPlatformFontList::PrefFontList* gfxFcPlatformFontList::FindGenericFamilies(
FcPatternGetString(font, FC_FAMILY, 0, &mappedGeneric);
if (mappedGeneric) {
mLock.AssertCurrentThreadIn();
nsAutoCString mappedGenericName(ToCharPtr(mappedGeneric));
AutoTArray<FamilyAndGeneric, 1> genericFamilies;
if (gfxPlatformFontList::FindAndAddFamilies(
if (gfxPlatformFontList::FindAndAddFamiliesLocked(
aPresContext, StyleGenericFontFamily::None,
mappedGenericName, &genericFamilies,
FindFamiliesFlags(0))) {

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

@ -175,7 +175,8 @@ class gfxFontconfigFontFamily final : public gfxFontFamily {
template <typename Func>
void AddFacesToFontList(Func aAddPatternFunc);
void FindStyleVariations(FontInfoData* aFontInfoData = nullptr) override;
void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr)
REQUIRES(mLock) override;
// Families are constructed initially with just references to patterns.
// When necessary, these are enumerated within FindStyleVariations.
@ -244,8 +245,8 @@ class gfxFcPlatformFontList final : public gfxPlatformFontList {
}
// initialize font lists
nsresult InitFontListForPlatform() override;
void InitSharedFontListForPlatform() override;
nsresult InitFontListForPlatform() REQUIRES(mLock) override;
void InitSharedFontListForPlatform() REQUIRES(mLock) override;
void GetFontList(nsAtom* aLangGroup, const nsACString& aGenericFamily,
nsTArray<nsString>& aListOfFonts) override;
@ -269,11 +270,12 @@ class gfxFcPlatformFontList final : public gfxPlatformFontList {
const uint8_t* aFontData,
uint32_t aLength) override;
bool FindAndAddFamilies(
bool FindAndAddFamiliesLocked(
nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric,
const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr,
nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0) override;
nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0)
REQUIRES(mLock) override;
bool GetStandardFamilyName(const nsCString& aFontName,
nsACString& aFamilyName) override;
@ -285,10 +287,16 @@ class gfxFcPlatformFontList final : public gfxPlatformFontList {
mozilla::StyleGenericFontFamily, nsAtom* aLanguage,
nsTArray<FamilyAndGeneric>& aFamilyList) override;
void ClearLangGroupPrefFonts() override;
void ClearLangGroupPrefFontsLocked() REQUIRES(mLock) override;
// clear out cached generic-lang ==> family-list mappings
void ClearGenericMappings() { mGenericMappings.Clear(); }
void ClearGenericMappings() {
AutoLock lock(mLock);
ClearGenericMappingsLocked();
}
void ClearGenericMappingsLocked() REQUIRES(mLock) {
mGenericMappings.Clear();
}
// map lang group ==> lang string
// When aForFontEnumerationThread is true, this method will avoid using
@ -310,28 +318,29 @@ class gfxFcPlatformFontList final : public gfxPlatformFontList {
// Add all the font families found in a font set.
// aAppFonts indicates whether this is the system or application fontset.
void AddFontSetFamilies(FcFontSet* aFontSet, const SandboxPolicy* aPolicy,
bool aAppFonts);
bool aAppFonts) REQUIRES(mLock);
// Helper for above, to add a single font pattern.
void AddPatternToFontList(FcPattern* aFont, FcChar8*& aLastFamilyName,
nsACString& aFamilyName,
RefPtr<gfxFontconfigFontFamily>& aFontFamily,
bool aAppFonts);
bool aAppFonts) REQUIRES(mLock);
// figure out which families fontconfig maps a generic to
// (aGeneric assumed already lowercase)
PrefFontList* FindGenericFamilies(nsPresContext* aPresContext,
const nsCString& aGeneric,
nsAtom* aLanguage);
nsAtom* aLanguage) REQUIRES(mLock);
// are all pref font settings set to use fontconfig generics?
bool PrefFontListsUseOnlyGenerics();
bool PrefFontListsUseOnlyGenerics() REQUIRES(mLock);
static void CheckFontUpdates(nsITimer* aTimer, void* aThis);
FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext,
const gfxFontStyle* aStyle,
nsAtom* aLanguage = nullptr) override;
nsAtom* aLanguage = nullptr)
REQUIRES(mLock) override;
enum class DistroID : int8_t {
Unknown = 0,

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

@ -234,7 +234,7 @@ bool gfxFontCache::HashEntry::KeyEquals(const KeyTypePointer aKey) const {
gfxFont* gfxFontCache::Lookup(const gfxFontEntry* aFontEntry,
const gfxFontStyle* aStyle,
const gfxCharacterMap* aUnicodeRangeMap) {
AutoReadLock lock(mCacheLock);
MutexAutoLock lock(mMutex);
Key key(aFontEntry, aStyle, aUnicodeRangeMap);
HashEntry* entry = mFonts.GetEntry(key);
@ -247,7 +247,7 @@ gfxFont* gfxFontCache::Lookup(const gfxFontEntry* aFontEntry,
void gfxFontCache::AddNew(gfxFont* aFont) {
gfxFont* oldFont;
{
AutoWriteLock lock(mCacheLock);
MutexAutoLock lock(mMutex);
Key key(aFont->GetFontEntry(), aFont->GetStyle(),
aFont->GetUnicodeRangeMap());
@ -287,7 +287,7 @@ void gfxFontCache::NotifyReleased(gfxFont* aFont) {
void gfxFontCache::NotifyExpiredLocked(gfxFont* aFont, const AutoLock& aLock) {
aFont->ClearCachedWords();
RemoveObjectLocked(aFont, aLock);
DestroyFont(aFont);
DestroyFontLocked(aFont);
}
void gfxFontCache::NotifyExpired(gfxFont* aFont) {
@ -296,14 +296,29 @@ void gfxFontCache::NotifyExpired(gfxFont* aFont) {
DestroyFont(aFont);
}
void gfxFontCache::DestroyFont(gfxFont* aFont) {
AutoWriteLock lock(mCacheLock);
void gfxFontCache::DestroyFontLocked(gfxFont* aFont) {
Key key(aFont->GetFontEntry(), aFont->GetStyle(),
aFont->GetUnicodeRangeMap());
HashEntry* entry = mFonts.GetEntry(key);
if (entry && entry->mFont == aFont) {
mFonts.RemoveEntry(entry);
}
NS_ASSERTION(aFont->GetRefCount() == 0,
"Destroying with non-zero ref count!");
MutexAutoUnlock unlock(mMutex);
delete aFont;
}
void gfxFontCache::DestroyFont(gfxFont* aFont) {
{
MutexAutoLock lock(mMutex);
Key key(aFont->GetFontEntry(), aFont->GetStyle(),
aFont->GetUnicodeRangeMap());
HashEntry* entry = mFonts.GetEntry(key);
if (entry && entry->mFont == aFont) {
mFonts.RemoveEntry(entry);
}
}
NS_ASSERTION(aFont->GetRefCount() == 0,
"Destroying with non-zero ref count!");
delete aFont;
@ -319,7 +334,7 @@ void gfxFontCache::WordCacheExpirationTimerCallback(nsITimer* aTimer,
void gfxFontCache::AgeCachedWords() {
bool allEmpty = true;
{
AutoReadLock lock(mCacheLock);
MutexAutoLock lock(mMutex);
for (const auto& entry : mFonts) {
allEmpty = entry.mFont->AgeCachedWords() && allEmpty;
}
@ -331,7 +346,7 @@ void gfxFontCache::AgeCachedWords() {
void gfxFontCache::FlushShapedWordCaches() {
{
AutoReadLock lock(mCacheLock);
MutexAutoLock lock(mMutex);
for (const auto& entry : mFonts) {
entry.mFont->ClearCachedWords();
}
@ -340,7 +355,7 @@ void gfxFontCache::FlushShapedWordCaches() {
}
void gfxFontCache::NotifyGlyphsChanged() {
AutoReadLock lock(mCacheLock);
MutexAutoLock lock(mMutex);
for (const auto& entry : mFonts) {
entry.mFont->NotifyGlyphsChanged();
}
@ -350,7 +365,7 @@ void gfxFontCache::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
FontCacheSizes* aSizes) const {
// TODO: add the overhead of the expiration tracker (generation arrays)
AutoReadLock lock(mCacheLock);
MutexAutoLock lock(*const_cast<Mutex*>(&mMutex));
aSizes->mFontInstances += mFonts.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (const auto& entry : mFonts) {
entry.mFont->AddSizeOfExcludingThis(aMallocSizeOf, aSizes);

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

@ -348,7 +348,7 @@ class gfxFontCache final
// into the expiration queues and removed.
void Flush() {
{
mozilla::AutoWriteLock lock(mCacheLock);
mozilla::MutexAutoLock lock(mMutex);
mFonts.Clear();
}
AgeAllGenerations();
@ -361,7 +361,7 @@ class gfxFontCache final
void RunWordCacheExpirationTimer() {
if (!mTimerRunning) {
mozilla::AutoWriteLock lock(mCacheLock);
mozilla::MutexAutoLock lock(mMutex);
if (!mTimerRunning && mWordCacheExpirationTimer) {
mWordCacheExpirationTimer->InitWithNamedFuncCallback(
WordCacheExpirationTimerCallback, this,
@ -373,7 +373,7 @@ class gfxFontCache final
}
void PauseWordCacheExpirationTimer() {
if (mTimerRunning) {
mozilla::AutoWriteLock lock(mCacheLock);
mozilla::MutexAutoLock lock(mMutex);
if (mTimerRunning && mWordCacheExpirationTimer) {
mWordCacheExpirationTimer->Cancel();
mTimerRunning = false;
@ -396,13 +396,7 @@ class gfxFontCache final
RemoveObjectLocked(aFont, lock);
}
mozilla::RWLock& GetCacheLock() { return mCacheLock; }
protected:
// Guards the global font hashtable, separately from the expiration-tracker
// records.
mutable mozilla::RWLock mCacheLock = mozilla::RWLock("fontCacheLock");
class MemoryReporter final : public nsIMemoryReporter {
~MemoryReporter() = default;
@ -427,10 +421,12 @@ class gfxFontCache final
// This gets called when the timeout has expired on a zero-refcount
// font; we just delete it.
void NotifyExpiredLocked(gfxFont* aFont, const AutoLock&) override;
void NotifyExpiredLocked(gfxFont* aFont, const AutoLock&)
REQUIRES(mMutex) override;
void NotifyExpired(gfxFont* aFont);
void DestroyFont(gfxFont* aFont);
void DestroyFontLocked(gfxFont* aFont) REQUIRES(mMutex);
static gfxFontCache* gGlobalCache;
@ -469,11 +465,11 @@ class gfxFontCache final
gfxFont* MOZ_UNSAFE_REF("tracking for deferred deletion") mFont;
};
nsTHashtable<HashEntry> mFonts GUARDED_BY(mCacheLock);
nsTHashtable<HashEntry> mFonts GUARDED_BY(mMutex);
static void WordCacheExpirationTimerCallback(nsITimer* aTimer, void* aCache);
nsCOMPtr<nsITimer> mWordCacheExpirationTimer GUARDED_BY(mCacheLock);
nsCOMPtr<nsITimer> mWordCacheExpirationTimer GUARDED_BY(mMutex);
std::atomic<bool> mTimerRunning = false;
};

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

@ -56,9 +56,8 @@ using namespace mozilla::unicode;
using mozilla::services::GetObserverService;
void gfxCharacterMap::NotifyReleased() {
gfxPlatformFontList* fontlist = gfxPlatformFontList::PlatformFontList();
if (mShared) {
fontlist->RemoveCmap(this);
gfxPlatformFontList::PlatformFontList()->RemoveCmap(this);
}
delete this;
}
@ -1541,12 +1540,14 @@ class FontEntryStandardFaceComparator {
};
void gfxFontFamily::SortAvailableFonts() {
MOZ_ASSERT(mLock.LockedForWritingByCurrentThread());
mAvailableFonts.Sort(FontEntryStandardFaceComparator());
}
bool gfxFontFamily::HasOtherFamilyNames() {
// need to read in other family names to determine this
if (!mOtherFamilyNamesInitialized) {
AutoWriteLock lock(mLock);
ReadOtherFamilyNames(
gfxPlatformFontList::PlatformFontList()); // sets mHasOtherFamilyNames
}
@ -1588,9 +1589,12 @@ void gfxFontFamily::FindAllFontsForStyle(
const gfxFontStyle& aFontStyle, nsTArray<gfxFontEntry*>& aFontEntryList,
bool aIgnoreSizeTolerance) {
if (!mHasStyles) {
FindStyleVariations(); // collect faces for the family, if not already done
FindStyleVariations(); // collect faces for the family, if not already
// done
}
AutoReadLock lock(mLock);
NS_ASSERTION(mAvailableFonts.Length() > 0, "font family with no faces!");
NS_ASSERTION(aFontEntryList.IsEmpty(), "non-empty fontlist passed in");
@ -1696,6 +1700,7 @@ void gfxFontFamily::FindAllFontsForStyle(
}
void gfxFontFamily::CheckForSimpleFamily() {
MOZ_ASSERT(mLock.LockedForWritingByCurrentThread());
// already checked this family
if (mIsSimpleFamily) {
return;
@ -1749,6 +1754,8 @@ void gfxFontFamily::CheckForSimpleFamily() {
#ifdef DEBUG
bool gfxFontFamily::ContainsFace(gfxFontEntry* aFontEntry) {
AutoReadLock lock(mLock);
uint32_t i, numFonts = mAvailableFonts.Length();
for (i = 0; i < numFonts; i++) {
if (mAvailableFonts[i] == aFontEntry) {
@ -1773,10 +1780,15 @@ void gfxFontFamily::LocalizedName(nsACString& aLocalizedName) {
}
void gfxFontFamily::FindFontForChar(GlobalFontMatch* aMatchData) {
if (mFamilyCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) {
// none of the faces in the family support the required char,
// so bail out immediately
return;
gfxPlatformFontList::PlatformFontList()->mLock.AssertCurrentThreadIn();
{
AutoReadLock lock(mLock);
if (mFamilyCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) {
// none of the faces in the family support the required char,
// so bail out immediately
return;
}
}
nsCString charAndName;
@ -1866,6 +1878,7 @@ void gfxFontFamily::SearchAllFontsForChar(GlobalFontMatch* aMatchData) {
if (!mFamilyCharacterMapInitialized) {
ReadAllCMAPs();
}
AutoReadLock lock(mLock);
if (!mFamilyCharacterMap.test(aMatchData->mCh)) {
return;
}
@ -1914,20 +1927,27 @@ bool gfxFontFamily::ReadOtherFamilyNamesForFace(
gfxFontUtils::ReadOtherFamilyNamesForFace(mName, nameData, dataLength,
otherFamilyNames, useFullName);
uint32_t n = otherFamilyNames.Length();
for (uint32_t i = 0; i < n; i++) {
aPlatformFontList->AddOtherFamilyName(this, otherFamilyNames[i]);
if (!otherFamilyNames.IsEmpty()) {
aPlatformFontList->AddOtherFamilyNames(this, otherFamilyNames);
}
return n != 0;
return !otherFamilyNames.IsEmpty();
}
void gfxFontFamily::ReadOtherFamilyNames(
gfxPlatformFontList* aPlatformFontList) {
if (mOtherFamilyNamesInitialized) return;
if (mOtherFamilyNamesInitialized) {
return;
}
AutoWriteLock lock(mLock);
if (mOtherFamilyNamesInitialized) {
return;
}
mOtherFamilyNamesInitialized = true;
FindStyleVariations();
FindStyleVariationsLocked();
// read in other family names for the first face in the list
uint32_t i, numFonts = mAvailableFonts.Length();
@ -1950,7 +1970,9 @@ void gfxFontFamily::ReadOtherFamilyNames(
// read in other names for the first face in the list with the assumption
// that if extra names don't exist in that face then they don't exist in
// other faces for the same font
if (!mHasOtherFamilyNames) return;
if (!mHasOtherFamilyNames) {
return;
}
// read in names for all faces, needed to catch cases where fonts have
// family names for individual weights (e.g. Hiragino Kaku Gothic Pro W6)
@ -2012,6 +2034,8 @@ bool gfxFontFamily::CheckForLegacyFamilyNames(gfxPlatformFontList* aFontList) {
// we already did this, so there's nothing more to add
return false;
}
aFontList->mLock.AssertCurrentThreadIn();
AutoWriteLock lock(mLock);
mCheckedForLegacyFamilyNames = true;
bool added = false;
const uint32_t kNAME = TRUETYPE_TAG('n', 'a', 'm', 'e');
@ -2041,22 +2065,23 @@ bool gfxFontFamily::CheckForLegacyFamilyNames(gfxPlatformFontList* aFontList) {
void gfxFontFamily::ReadFaceNames(gfxPlatformFontList* aPlatformFontList,
bool aNeedFullnamePostscriptNames,
FontInfoData* aFontInfoData) {
aPlatformFontList->mLock.AssertCurrentThreadIn();
// if all needed names have already been read, skip
if (mOtherFamilyNamesInitialized &&
(mFaceNamesInitialized || !aNeedFullnamePostscriptNames)) {
return;
}
AutoWriteLock lock(mLock);
bool asyncFontLoaderDisabled = false;
if (!mOtherFamilyNamesInitialized && aFontInfoData &&
aFontInfoData->mLoadOtherNames && !asyncFontLoaderDisabled) {
const auto* otherFamilyNames = aFontInfoData->GetOtherFamilyNames(mName);
if (otherFamilyNames) {
uint32_t i, n = otherFamilyNames->Length();
for (i = 0; i < n; i++) {
aPlatformFontList->AddOtherFamilyName(this, (*otherFamilyNames)[i]);
}
if (otherFamilyNames && otherFamilyNames->Length()) {
aPlatformFontList->AddOtherFamilyNames(this, *otherFamilyNames);
}
mOtherFamilyNamesInitialized = true;
}
@ -2067,7 +2092,7 @@ void gfxFontFamily::ReadFaceNames(gfxPlatformFontList* aPlatformFontList,
return;
}
FindStyleVariations(aFontInfoData);
FindStyleVariationsLocked(aFontInfoData);
// check again, as style enumeration code may have loaded names
if (mOtherFamilyNamesInitialized &&
@ -2091,10 +2116,10 @@ void gfxFontFamily::ReadFaceNames(gfxPlatformFontList* aPlatformFontList,
aFontInfoData && aFontInfoData->mLoadFaceNames) {
aFontInfoData->GetFaceNames(fe->Name(), fullname, psname);
if (!fullname.IsEmpty()) {
aPlatformFontList->AddFullname(fe, fullname);
aPlatformFontList->AddFullnameLocked(fe, fullname);
}
if (!psname.IsEmpty()) {
aPlatformFontList->AddPostscriptName(fe, psname);
aPlatformFontList->AddPostscriptNameLocked(fe, psname);
}
foundFaceNames = true;
@ -2113,12 +2138,12 @@ void gfxFontFamily::ReadFaceNames(gfxPlatformFontList* aPlatformFontList,
if (aNeedFullnamePostscriptNames && !foundFaceNames) {
if (gfxFontUtils::ReadCanonicalName(nameTable, gfxFontUtils::NAME_ID_FULL,
fullname) == NS_OK) {
aPlatformFontList->AddFullname(fe, fullname);
aPlatformFontList->AddFullnameLocked(fe, fullname);
}
if (gfxFontUtils::ReadCanonicalName(
nameTable, gfxFontUtils::NAME_ID_POSTSCRIPT, psname) == NS_OK) {
aPlatformFontList->AddPostscriptName(fe, psname);
aPlatformFontList->AddPostscriptNameLocked(fe, psname);
}
}
@ -2147,16 +2172,20 @@ void gfxFontFamily::ReadFaceNames(gfxPlatformFontList* aPlatformFontList,
gfxFontEntry* gfxFontFamily::FindFont(const nsACString& aPostscriptName) {
// find the font using a simple linear search
AutoReadLock lock(mLock);
uint32_t numFonts = mAvailableFonts.Length();
for (uint32_t i = 0; i < numFonts; i++) {
gfxFontEntry* fe = mAvailableFonts[i].get();
if (fe && fe->Name() == aPostscriptName) return fe;
if (fe && fe->Name() == aPostscriptName) {
return fe;
}
}
return nullptr;
}
void gfxFontFamily::ReadAllCMAPs(FontInfoData* aFontInfoData) {
FindStyleVariations(aFontInfoData);
AutoWriteLock lock(mLock);
FindStyleVariationsLocked(aFontInfoData);
uint32_t i, numFonts = mAvailableFonts.Length();
for (i = 0; i < numFonts; i++) {
@ -2174,6 +2203,7 @@ void gfxFontFamily::ReadAllCMAPs(FontInfoData* aFontInfoData) {
void gfxFontFamily::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
FontListSizes* aSizes) const {
AutoReadLock lock(mLock);
aSizes->mFontListSize += mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
aSizes->mCharMapsSize +=
mFamilyCharacterMap.SizeOfExcludingThis(aMallocSizeOf);

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

@ -790,10 +790,8 @@ class gfxFontEntry {
};
using FontTableCache = nsTHashtable<FontTableHashEntry>;
mozilla::Atomic<FontTableCache*> mFontTableCache GUARDED_BY(mLock);
FontTableCache* GetFontTableCache() const NO_THREAD_SAFETY_ANALYSIS {
return mFontTableCache;
}
mozilla::Atomic<FontTableCache*> mFontTableCache;
FontTableCache* GetFontTableCache() const { return mFontTableCache; }
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxFontEntry::RangeFlags)
@ -851,17 +849,12 @@ class gfxFontFamily {
gfxFontFamily(const nsACString& aName, FontVisibility aVisibility)
: mName(aName),
mLock("gfxFontFamily lock"),
mVisibility(aVisibility),
mOtherFamilyNamesInitialized(false),
mHasOtherFamilyNames(false),
mFaceNamesInitialized(false),
mHasStyles(false),
mIsSimpleFamily(false),
mIsBadUnderlineFamily(false),
mFamilyCharacterMapInitialized(false),
mSkipDefaultFeatureSpaceCheck(false),
mCheckForFallbackFaces(false),
mCheckedForLegacyFamilyNames(false) {}
mCheckForFallbackFaces(false) {}
const nsCString& Name() const { return mName; }
@ -874,11 +867,20 @@ class gfxFontFamily {
// faces in a large family into separate "styled families" because of
// GDI's 4-faces-per-family limitation). If found, the styled family
// name will be added to the font list's "other family names" table.
// Note that the caller must already hold the gfxPlatformFontList lock.
bool CheckForLegacyFamilyNames(gfxPlatformFontList* aFontList);
nsTArray<RefPtr<gfxFontEntry>>& GetFontList() { return mAvailableFonts; }
nsTArray<RefPtr<gfxFontEntry>>& GetFontList() {
mozilla::AutoReadLock lock(mLock);
return mAvailableFonts;
}
void AddFontEntry(RefPtr<gfxFontEntry> aFontEntry) {
mozilla::AutoWriteLock lock(mLock);
AddFontEntryLocked(aFontEntry);
}
void AddFontEntryLocked(RefPtr<gfxFontEntry> aFontEntry) REQUIRES(mLock) {
// bug 589682 - set the IgnoreGDEF flag on entries for Italic faces
// of Times New Roman, because of buggy table in those fonts
if (aFontEntry->IsItalic() && !aFontEntry->IsUserFont() &&
@ -916,8 +918,10 @@ class gfxFontFamily {
nsTArray<gfxFontEntry*>& aFontEntryList,
bool aIgnoreSizeTolerance = false);
// checks for a matching font within the family
// used as part of the font fallback process
// Checks for a matching font within the family; used as part of the font
// fallback process.
// Note that when this is called, the caller must already be holding the
// gfxPlatformFontList lock.
void FindFontForChar(GlobalFontMatch* aMatchData);
// checks all fonts for a matching font within the family
@ -929,36 +933,51 @@ class gfxFontFamily {
// set when other family names have been read in
void SetOtherFamilyNamesInitialized() { mOtherFamilyNamesInitialized = true; }
// read in other localized family names, fullnames and Postscript names
// for all faces and append to lookup tables
// Read in other localized family names, fullnames and Postscript names
// for all faces and append to lookup tables.
// Note that when this is called, the caller must already be holding the
// gfxPlatformFontList lock.
virtual void ReadFaceNames(gfxPlatformFontList* aPlatformFontList,
bool aNeedFullnamePostscriptNames,
FontInfoData* aFontInfoData = nullptr);
// find faces belonging to this family (platform implementations override
// this; should be made pure virtual once all subclasses have been updated)
virtual void FindStyleVariations(FontInfoData* aFontInfoData = nullptr) {}
// Find faces belonging to this family (platform implementations override).
// This is a no-op in cases where the family is explicitly populated by other
// means, rather than being asked to find its faces via system API.
virtual void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr)
REQUIRES(mLock){};
void FindStyleVariations(FontInfoData* aFontInfoData = nullptr) {
if (mHasStyles) {
return;
}
mozilla::AutoWriteLock lock(mLock);
FindStyleVariationsLocked(aFontInfoData);
}
// search for a specific face using the Postscript name
gfxFontEntry* FindFont(const nsACString& aPostscriptName);
// read in cmaps for all the faces
// Read in cmaps for all the faces.
// Note that when this is called, the caller must already be holding the
// gfxPlatformFontList lock.
void ReadAllCMAPs(FontInfoData* aFontInfoData = nullptr);
bool TestCharacterMap(uint32_t aCh) {
if (!mFamilyCharacterMapInitialized) {
ReadAllCMAPs();
}
mozilla::AutoReadLock lock(mLock);
return mFamilyCharacterMap.test(aCh);
}
void ResetCharacterMap() {
void ResetCharacterMap() REQUIRES(mLock) {
mFamilyCharacterMap.reset();
mFamilyCharacterMapInitialized = false;
}
// mark this family as being in the "bad" underline offset blocklist
void SetBadUnderlineFamily() {
mozilla::AutoWriteLock lock(mLock);
mIsBadUnderlineFamily = true;
if (mHasStyles) {
SetBadUnderlineFonts();
@ -971,12 +990,12 @@ class gfxFontFamily {
bool CheckForFallbackFaces() const { return mCheckForFallbackFaces; }
// sort available fonts to put preferred (standard) faces towards the end
void SortAvailableFonts();
void SortAvailableFonts() REQUIRES(mLock);
// check whether the family fits into the simple 4-face model,
// so we can use simplified style-matching;
// if so set the mIsSimpleFamily flag (defaults to False before we've checked)
void CheckForSimpleFamily();
void CheckForSimpleFamily() REQUIRES(mLock);
// For memory reporter
virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
@ -1019,31 +1038,33 @@ class gfxFontFamily {
bool useFullName = false);
// set whether this font family is in "bad" underline offset blocklist.
void SetBadUnderlineFonts() {
uint32_t i, numFonts = mAvailableFonts.Length();
for (i = 0; i < numFonts; i++) {
if (mAvailableFonts[i]) {
mAvailableFonts[i]->mIsBadUnderlineFont = true;
void SetBadUnderlineFonts() REQUIRES(mLock) {
for (auto& f : mAvailableFonts) {
if (f) {
f->mIsBadUnderlineFont = true;
}
}
}
nsCString mName;
nsTArray<RefPtr<gfxFontEntry>> mAvailableFonts;
gfxSparseBitSet mFamilyCharacterMap;
nsTArray<RefPtr<gfxFontEntry>> mAvailableFonts GUARDED_BY(mLock);
gfxSparseBitSet mFamilyCharacterMap GUARDED_BY(mLock);
mutable mozilla::RWLock mLock;
FontVisibility mVisibility;
bool mOtherFamilyNamesInitialized : 1;
bool mHasOtherFamilyNames : 1;
bool mFaceNamesInitialized : 1;
bool mHasStyles : 1;
bool mIsSimpleFamily : 1;
mozilla::Atomic<bool> mOtherFamilyNamesInitialized;
mozilla::Atomic<bool> mFaceNamesInitialized;
mozilla::Atomic<bool> mHasStyles;
mozilla::Atomic<bool> mFamilyCharacterMapInitialized;
mozilla::Atomic<bool> mCheckedForLegacyFamilyNames;
mozilla::Atomic<bool> mHasOtherFamilyNames;
bool mIsSimpleFamily : 1 GUARDED_BY(mLock);
bool mIsBadUnderlineFamily : 1;
bool mFamilyCharacterMapInitialized : 1;
bool mSkipDefaultFeatureSpaceCheck : 1;
bool mCheckForFallbackFaces : 1; // check other faces for character
bool mCheckedForLegacyFamilyNames : 1;
enum {
// for "simple" families, the faces are stored in mAvailableFonts

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

@ -143,14 +143,24 @@ void gfxFontInfoLoader::StartLoader(uint32_t aDelay) {
return;
}
NS_ASSERTION(!mFontInfo, "fontinfo should be null when starting font loader");
// sanity check
if (mState != stateInitial && mState != stateTimerOff &&
mState != stateTimerOnDelay) {
CancelLoader();
}
// Create mFontInfo when we're initially called to set up the delay, rather
// than when called by the DelayedStartCallback, because on the initial call
// we know we'll be holding the gfxPlatformFontList lock.
if (!mFontInfo) {
mFontInfo = CreateFontInfoData();
if (!mFontInfo) {
// The platform doesn't want anything loaded, so just bail out.
mState = stateTimerOff;
return;
}
}
AddShutdownObserver();
// Caller asked for a delay? ==> start async thread after a delay
@ -195,13 +205,6 @@ void gfxFontInfoLoader::StartLoader(uint32_t aDelay) {
"Bug 1508626 - Initializing font loader after shutdown but "
"before observer");
mFontInfo = CreateFontInfoData();
if (!mFontInfo) {
// The platform doesn't want anything loaded, so just bail out.
mState = stateTimerOff;
return;
}
// initialize
InitLoader();

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

@ -119,7 +119,9 @@ GDIFontEntry::GDIFontEntry(const nsACString& aFaceName,
mStyleRange = aStyle;
mWeightRange = aWeight;
mStretchRange = aStretch;
if (IsType1()) mForceGDI = true;
if (IsType1()) {
mForceGDI = true;
}
mIsDataUserFont = aUserFontData != nullptr;
InitLogFont(aFaceName, aFontType);
@ -372,10 +374,8 @@ GDIFontEntry* GDIFontEntry::CreateFontEntry(const nsACString& aName,
gfxUserFontData* aUserFontData) {
// jtdfix - need to set charset, unicode ranges, pitch/family
GDIFontEntry* fe = new GDIFontEntry(aName, aFontType, aStyle, aWeight,
aStretch, aUserFontData);
return fe;
return new GDIFontEntry(aName, aFontType, aStyle, aWeight, aStretch,
aUserFontData);
}
void GDIFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
@ -454,9 +454,12 @@ int CALLBACK GDIFontFamily::FamilyAddStylesProc(
SlantStyleRange(italicStyle),
WeightRange(FontWeight(int32_t(logFont.lfWeight))),
StretchRange(FontStretch::Normal()), nullptr);
if (!fe) return 1;
if (!fe) {
return 1;
}
ff->AddFontEntry(fe);
MOZ_ASSERT(ff->mLock.LockedForWritingByCurrentThread());
ff->AddFontEntryLocked(fe);
if (nmetrics->ntmFontSig.fsUsb[0] != 0x00000000 &&
nmetrics->ntmFontSig.fsUsb[1] != 0x00000000 &&
@ -482,8 +485,10 @@ int CALLBACK GDIFontFamily::FamilyAddStylesProc(
return 1;
}
void GDIFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) {
if (mHasStyles) return;
void GDIFontFamily::FindStyleVariationsLocked(FontInfoData* aFontInfoData) {
if (mHasStyles) {
return;
}
mHasStyles = true;
HDC hdc = GetDC(nullptr);
@ -838,13 +843,11 @@ gfxFontEntry* gfxGDIFontList::MakePlatformFont(const nsACString& aFontName,
return fe;
}
bool gfxGDIFontList::FindAndAddFamilies(nsPresContext* aPresContext,
StyleGenericFontFamily aGeneric,
const nsACString& aFamily,
nsTArray<FamilyAndGeneric>* aOutput,
FindFamiliesFlags aFlags,
gfxFontStyle* aStyle, nsAtom* aLanguage,
gfxFloat aDevToCssSize) {
bool gfxGDIFontList::FindAndAddFamiliesLocked(
nsPresContext* aPresContext, StyleGenericFontFamily aGeneric,
const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
FindFamiliesFlags aFlags, gfxFontStyle* aStyle, nsAtom* aLanguage,
gfxFloat aDevToCssSize) {
NS_ConvertUTF8toUTF16 key16(aFamily);
BuildKeyNameFromFontName(key16);
NS_ConvertUTF16toUTF8 keyName(key16);
@ -861,7 +864,7 @@ bool gfxGDIFontList::FindAndAddFamilies(nsPresContext* aPresContext,
return false;
}
return gfxPlatformFontList::FindAndAddFamilies(
return gfxPlatformFontList::FindAndAddFamiliesLocked(
aPresContext, aGeneric, aFamily, aOutput, aFlags, aStyle, aLanguage,
aDevToCssSize);
}
@ -897,6 +900,9 @@ FontFamily gfxGDIFontList::GetDefaultFontForPlatform(
void gfxGDIFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
FontListSizes* aSizes) const {
gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
AutoLock lock(mLock);
aSizes->mFontListSize +=
SizeOfFontFamilyTableExcludingThis(mFontSubstitutes, aMallocSizeOf);
aSizes->mFontListSize +=

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

@ -193,7 +193,8 @@ class GDIFontFamily final : public gfxFontFamily {
mWindowsPitch(0),
mCharset() {}
virtual void FindStyleVariations(FontInfoData* aFontInfoData = nullptr);
void FindStyleVariationsLocked(
FontInfoData* aFontInfoData = nullptr) override;
bool FilterForFontList(nsAtom* aLangGroup,
const nsACString& aGeneric) const final {
@ -304,7 +305,7 @@ class gfxGDIFontList final : public gfxPlatformFontList {
gfxFontFamily* CreateFontFamily(const nsACString& aName,
FontVisibility aVisibility) const override;
bool FindAndAddFamilies(
bool FindAndAddFamiliesLocked(
nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric,
const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr,

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

@ -140,11 +140,12 @@ class gfxMacPlatformFontList final : public gfxPlatformFontList {
const uint8_t* aFontData,
uint32_t aLength) override;
bool FindAndAddFamilies(
bool FindAndAddFamiliesLocked(
nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric,
const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr,
nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0) override;
nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0)
REQUIRES(mLock) override;
// lookup the system font for a particular system font type and set
// the name and style characteristics
@ -163,7 +164,8 @@ class gfxMacPlatformFontList final : public gfxPlatformFontList {
protected:
FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext,
const gfxFontStyle* aStyle,
nsAtom* aLanguage = nullptr) override;
nsAtom* aLanguage = nullptr)
REQUIRES(mLock) override;
private:
friend class gfxPlatformMac;
@ -172,22 +174,23 @@ class gfxMacPlatformFontList final : public gfxPlatformFontList {
virtual ~gfxMacPlatformFontList();
// initialize font lists
nsresult InitFontListForPlatform() override;
void InitSharedFontListForPlatform() override;
nsresult InitFontListForPlatform() REQUIRES(mLock) override;
void InitSharedFontListForPlatform() REQUIRES(mLock) override;
// handle commonly used fonts for which the name table should be loaded at
// startup
void PreloadNamesList();
void PreloadNamesList() REQUIRES(mLock);
// special case font faces treated as font families (set via prefs)
void InitSingleFaceList();
void InitAliasesForSingleFaceList();
void InitSingleFaceList() REQUIRES(mLock);
void InitAliasesForSingleFaceList() REQUIRES(mLock);
// initialize system fonts
void InitSystemFontNames();
void InitSystemFontNames() REQUIRES(mLock);
// helper function to lookup in both hidden system fonts and normal fonts
gfxFontFamily* FindSystemFontFamily(const nsACString& aFamily);
gfxFontFamily* FindSystemFontFamily(const nsACString& aFamily)
REQUIRES(mLock);
FontVisibility GetVisibilityForFamily(const nsACString& aName) const;
@ -201,7 +204,8 @@ class gfxMacPlatformFontList final : public gfxPlatformFontList {
const uint32_t aCh,
Script aRunScript,
const gfxFontStyle* aMatchStyle,
FontFamily& aMatchedFamily) override;
FontFamily& aMatchedFamily)
REQUIRES(mLock) override;
bool UsesSystemFallback() override { return true; }
@ -212,9 +216,10 @@ class gfxMacPlatformFontList final : public gfxPlatformFontList {
// file is included in .cpp files, so we can't use objective C classes here.
// But CFStringRef and NSString* are the same thing anyway (they're
// toll-free bridged).
void AddFamily(CFStringRef aFamily);
void AddFamily(CFStringRef aFamily) REQUIRES(mLock);
void AddFamily(const nsACString& aFamilyName, FontVisibility aVisibility);
void AddFamily(const nsACString& aFamilyName, FontVisibility aVisibility)
REQUIRES(mLock);
gfxFontEntry* CreateFontEntry(
mozilla::fontlist::Face* aFace,
@ -226,7 +231,8 @@ class gfxMacPlatformFontList final : public gfxPlatformFontList {
bool aLoadCmaps) const override;
void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily,
bool aNeedFullnamePostscriptNames) override;
bool aNeedFullnamePostscriptNames)
REQUIRES(mLock) override;
enum { kATSGenerationInitial = -1 };

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

@ -583,14 +583,14 @@ void MacOSFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
class gfxMacFontFamily final : public gfxFontFamily {
public:
gfxMacFontFamily(const nsACString& aName, FontVisibility aVisibility, double aSizeHint)
gfxMacFontFamily(const nsACString& aName, FontVisibility aVisibility, double aSizeHint = 0.0)
: gfxFontFamily(aName, aVisibility), mSizeHint(aSizeHint) {}
virtual ~gfxMacFontFamily() = default;
virtual void LocalizedName(nsACString& aLocalizedName);
void LocalizedName(nsACString& aLocalizedName) override;
virtual void FindStyleVariations(FontInfoData* aFontInfoData = nullptr);
void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr) REQUIRES(mLock) override;
protected:
double mSizeHint;
@ -634,7 +634,7 @@ static inline int GetWeightOverride(const nsAString& aPSName) {
return Preferences::GetInt(prefName.get(), 0);
}
void gfxMacFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) {
void gfxMacFontFamily::FindStyleVariationsLocked(FontInfoData* aFontInfoData) {
if (mHasStyles) {
return;
}
@ -735,7 +735,7 @@ void gfxMacFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) {
}
// insert into font entry array of family
AddFontEntry(fontEntry);
AddFontEntryLocked(fontEntry);
}
SortAvailableFonts();
@ -760,16 +760,20 @@ class gfxSingleFaceMacFontFamily final : public gfxFontFamily {
virtual ~gfxSingleFaceMacFontFamily() = default;
virtual void LocalizedName(nsACString& aLocalizedName);
void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr) REQUIRES(mLock) override{};
virtual void ReadOtherFamilyNames(gfxPlatformFontList* aPlatformFontList);
void LocalizedName(nsACString& aLocalizedName) override;
virtual bool IsSingleFaceFamily() const { return true; }
void ReadOtherFamilyNames(gfxPlatformFontList* aPlatformFontList) override;
bool IsSingleFaceFamily() const override { return true; }
};
void gfxSingleFaceMacFontFamily::LocalizedName(nsACString& aLocalizedName) {
nsAutoreleasePool localPool;
AutoReadLock lock(mLock);
if (!HasOtherFamilyNames()) {
aLocalizedName = mName;
return;
@ -797,6 +801,7 @@ void gfxSingleFaceMacFontFamily::ReadOtherFamilyNames(gfxPlatformFontList* aPlat
return;
}
AutoWriteLock lock(mLock);
gfxFontEntry* fe = mAvailableFonts[0];
if (!fe) {
return;
@ -888,7 +893,8 @@ void gfxMacPlatformFontList::AddFamily(CFStringRef aFamily) {
AddFamily(nameUtf8, GetVisibilityForFamily(nameUtf8));
}
void gfxMacPlatformFontList::ReadSystemFontList(dom::SystemFontList* aList) {
void gfxMacPlatformFontList::ReadSystemFontList(dom::SystemFontList* aList)
NO_THREAD_SAFETY_ANALYSIS {
// Note: We rely on the records for mSystemTextFontFamilyName and
// mSystemDisplayFontFamilyName (if present) being *before* the main
// font list, so that those names are known in the content process
@ -1203,7 +1209,7 @@ static NSString* GetRealFamilyName(NSFont* aFont) {
// so we expect the system font to be a variable-weight face rather than requiring
// a number of discrete faces of different weights.
static gfxFontFamily* CreateFamilyForSystemFont(NSFont* aFont, const nsACString& aFamilyName) {
gfxFontFamily* familyEntry = new gfxFontFamily(aFamilyName, FontVisibility::Unknown);
gfxFontFamily* familyEntry = new gfxMacFontFamily(aFamilyName, FontVisibility::Unknown);
NSString* psNameNS = [[aFont fontDescriptor] postscriptName];
nsAutoString nameUTF16;
@ -1366,7 +1372,7 @@ gfxFontEntry* gfxMacPlatformFontList::PlatformGlobalFontFallback(nsPresContext*
if (family) {
fontlist::Face* face = family->FindFaceForStyle(SharedFontList(), *aMatchStyle);
if (face) {
fontEntry = GetOrCreateFontEntry(face, family);
fontEntry = GetOrCreateFontEntryLocked(face, family);
}
if (fontEntry) {
if (fontEntry->HasCharacter(aCh)) {
@ -1437,6 +1443,8 @@ gfxFontEntry* gfxMacPlatformFontList::LookupLocalFont(nsPresContext* aPresContex
return nullptr;
}
AutoLock lock(mLock);
nsAutoreleasePool localPool;
NSString* faceName = GetNSStringForString(NS_ConvertUTF8toUTF16(aFontName));
@ -1521,12 +1529,10 @@ gfxFontEntry* gfxMacPlatformFontList::MakePlatformFont(const nsACString& aFontNa
// WebCore/platform/graphics/mac/FontCacheMac.mm
static const char kSystemFont_system[] = "-apple-system";
bool gfxMacPlatformFontList::FindAndAddFamilies(nsPresContext* aPresContext,
StyleGenericFontFamily aGeneric,
const nsACString& aFamily,
nsTArray<FamilyAndGeneric>* aOutput,
FindFamiliesFlags aFlags, gfxFontStyle* aStyle,
nsAtom* aLanguage, gfxFloat aDevToCssSize) {
bool gfxMacPlatformFontList::FindAndAddFamiliesLocked(
nsPresContext* aPresContext, StyleGenericFontFamily aGeneric, const nsACString& aFamily,
nsTArray<FamilyAndGeneric>* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle,
nsAtom* aLanguage, gfxFloat aDevToCssSize) {
if (aFamily.EqualsLiteral(kSystemFont_system)) {
// Search for special system font name, -apple-system. This is not done via
// the shared fontlist on Catalina or later, because the hidden system font
@ -1539,9 +1545,9 @@ bool gfxMacPlatformFontList::FindAndAddFamilies(nsPresContext* aPresContext,
: mSystemTextFontFamilyName;
if (SharedFontList() && !nsCocoaFeatures::OnCatalinaOrLater()) {
FindFamiliesFlags flags = aFlags | FindFamiliesFlags::eSearchHiddenFamilies;
return gfxPlatformFontList::FindAndAddFamilies(aPresContext, aGeneric, systemFontFamilyName,
aOutput, flags, aStyle, aLanguage,
aDevToCssSize);
return gfxPlatformFontList::FindAndAddFamiliesLocked(aPresContext, aGeneric,
systemFontFamilyName, aOutput, flags,
aStyle, aLanguage, aDevToCssSize);
} else {
if (auto* fam = FindSystemFontFamily(systemFontFamilyName)) {
aOutput->AppendElement(fam);
@ -1551,8 +1557,8 @@ bool gfxMacPlatformFontList::FindAndAddFamilies(nsPresContext* aPresContext,
return false;
}
return gfxPlatformFontList::FindAndAddFamilies(aPresContext, aGeneric, aFamily, aOutput, aFlags,
aStyle, aLanguage, aDevToCssSize);
return gfxPlatformFontList::FindAndAddFamiliesLocked(aPresContext, aGeneric, aFamily, aOutput,
aFlags, aStyle, aLanguage, aDevToCssSize);
}
void gfxMacPlatformFontList::LookupSystemFont(LookAndFeel::FontID aSystemFontID,
@ -1730,6 +1736,7 @@ already_AddRefed<FontInfoData> gfxMacPlatformFontList::CreateFontInfoData() {
bool loadCmaps =
!UsesSystemFallback() || gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
mLock.AssertCurrentThreadIn();
RefPtr<MacFontInfo> fi = new MacFontInfo(true, NeedFullnamePostscriptNames(), loadCmaps);
return fi.forget();
}

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

@ -264,7 +264,7 @@ bool gfxPlatformFontList::Initialize(gfxPlatformFontList* aList) {
}
gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
: mFontFamiliesMutex("gfxPlatformFontList::mFontFamiliesMutex"),
: mLock("gfxPlatformFontList lock"),
mFontFamilies(64),
mOtherFamilyNames(16),
mSharedCmaps(8) {
@ -305,7 +305,7 @@ gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
gfxPlatformFontList::~gfxPlatformFontList() {
mSharedCmaps.Clear();
ClearLangGroupPrefFonts();
ClearLangGroupPrefFontsLocked();
NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer");
@ -375,6 +375,7 @@ void gfxPlatformFontList::ApplyWhitelist() {
void gfxPlatformFontList::ApplyWhitelist(
nsTArray<fontlist::Family::InitData>& aFamilies) {
mLock.AssertCurrentThreadIn();
mFontFamilyWhitelistActive = !mEnabledFontsList.IsEmpty();
if (!mFontFamilyWhitelistActive) {
return;
@ -435,6 +436,7 @@ void gfxPlatformFontList::CheckFamilyList(const char* aList[], size_t aCount) {
bool gfxPlatformFontList::AddWithLegacyFamilyName(const nsACString& aLegacyName,
gfxFontEntry* aFontEntry,
FontVisibility aVisibility) {
mLock.AssertCurrentThreadIn();
bool added = false;
nsAutoCString key;
ToLowerCase(aLegacyName, key);
@ -455,7 +457,14 @@ bool gfxPlatformFontList::AddWithLegacyFamilyName(const nsACString& aLegacyName,
}
bool gfxPlatformFontList::InitFontList() {
MutexAutoLock lock(mFontFamiliesMutex);
// If the startup font-list-init thread is still running, we need to wait
// for it to finish before trying to reinitialize here.
if (sInitFontListThread && !IsInitFontListThread()) {
PR_JoinThread(sInitFontListThread);
sInitFontListThread = nullptr;
}
AutoLock lock(mLock);
if (LOG_FONTINIT_ENABLED()) {
LOG_FONTINIT(("(fontinit) system fontlist initialization\n"));
@ -507,7 +516,7 @@ bool gfxPlatformFontList::InitFontList() {
mExtraNames->mPostscriptNames.Clear();
}
mFaceNameListsInitialized = false;
ClearLangGroupPrefFonts();
ClearLangGroupPrefFontsLocked();
CancelLoader();
// Clear cached family records that will no longer be valid.
@ -576,14 +585,15 @@ bool gfxPlatformFontList::InitFontList() {
// Set up mDefaultFontEntry as a "last resort" default that we can use
// to avoid crashing if the font list is otherwise unusable.
gfxFontStyle defStyle;
FontFamily fam = GetDefaultFont(nullptr, &defStyle);
FontFamily fam = GetDefaultFontLocked(nullptr, &defStyle);
gfxFontEntry* fe;
if (fam.mIsShared) {
auto face = fam.mShared->FindFaceForStyle(SharedFontList(), defStyle);
mDefaultFontEntry =
face ? GetOrCreateFontEntry(face, fam.mShared) : nullptr;
fe = face ? GetOrCreateFontEntryLocked(face, fam.mShared) : nullptr;
} else {
mDefaultFontEntry = fam.mUnshared->FindFontForStyle(defStyle);
fe = fam.mUnshared->FindFontForStyle(defStyle);
}
mDefaultFontEntry = fe;
return true;
}
@ -610,6 +620,7 @@ void gfxPlatformFontList::InitializeCodepointsWithNoFonts() {
void gfxPlatformFontList::FontListChanged() {
MOZ_ASSERT(!XRE_IsParentProcess());
AutoLock lock(mLock);
InitializeCodepointsWithNoFonts();
if (SharedFontList()) {
// If we're using a shared local face-name list, this may have changed
@ -641,8 +652,10 @@ class InitOtherFamilyNamesForStylo : public mozilla::Runnable {
if (!list) {
return NS_OK;
}
bool initialized = false;
dom::ContentChild::GetSingleton()->SendInitOtherFamilyNames(
list->GetGeneration(), mDefer, &pfl->mOtherFamilyNamesInitialized);
list->GetGeneration(), mDefer, &initialized);
pfl->mOtherFamilyNamesInitialized.compareExchange(false, initialized);
return NS_OK;
}
@ -660,9 +673,11 @@ bool gfxPlatformFontList::InitOtherFamilyNames(
if (SharedFontList() && !XRE_IsParentProcess()) {
if (NS_IsMainThread()) {
bool initialized;
dom::ContentChild::GetSingleton()->SendInitOtherFamilyNames(
SharedFontList()->GetGeneration(), aDeferOtherFamilyNamesLoading,
&mOtherFamilyNamesInitialized);
&initialized);
mOtherFamilyNamesInitialized.compareExchange(false, initialized);
} else {
NS_DispatchToMainThread(
new InitOtherFamilyNamesForStylo(aDeferOtherFamilyNamesLoading));
@ -836,6 +851,7 @@ void gfxPlatformFontList::UpdateFontList(bool aFullRebuild) {
MOZ_ASSERT(NS_IsMainThread());
if (aFullRebuild) {
InitFontList();
AutoLock lock(mLock);
RebuildLocalFonts();
} else {
// The font list isn't being fully rebuilt, we're just being notified that
@ -843,6 +859,7 @@ void gfxPlatformFontList::UpdateFontList(bool aFullRebuild) {
// done. We only care about this if we have previously encountered a
// fallback that required cmaps that were not yet available, and so we
// asked for the async cmap loader to run.
AutoLock lock(mLock);
if (mStartedLoadingCmapsFrom != 0xffffffffu) {
InitializeCodepointsWithNoFonts();
mStartedLoadingCmapsFrom = 0xffffffffu;
@ -864,6 +881,8 @@ bool gfxPlatformFontList::IsVisibleToCSS(const fontlist::Family& aFamily,
void gfxPlatformFontList::GetFontList(nsAtom* aLangGroup,
const nsACString& aGenericFamily,
nsTArray<nsString>& aListOfFonts) {
AutoLock lock(mLock);
if (SharedFontList()) {
fontlist::FontList* list = SharedFontList();
const fontlist::Family* families = list->Families();
@ -882,7 +901,6 @@ void gfxPlatformFontList::GetFontList(nsAtom* aLangGroup,
return;
}
MutexAutoLock lock(mFontFamiliesMutex);
for (const RefPtr<gfxFontFamily>& family : mFontFamilies.Values()) {
if (!IsVisibleToCSS(*family, FontVisibility::User)) {
continue;
@ -900,6 +918,7 @@ void gfxPlatformFontList::GetFontList(nsAtom* aLangGroup,
void gfxPlatformFontList::GetFontFamilyList(
nsTArray<RefPtr<gfxFontFamily>>& aFamilyArray) {
AutoLock lock(mLock);
MOZ_ASSERT(aFamilyArray.IsEmpty());
// This doesn't use ToArray, because the caller passes an AutoTArray.
aFamilyArray.SetCapacity(mFontFamilies.Count());
@ -912,6 +931,7 @@ gfxFont* gfxPlatformFontList::SystemFindFontForChar(
nsPresContext* aPresContext, uint32_t aCh, uint32_t aNextCh,
Script aRunScript, eFontPresentation aPresentation,
const gfxFontStyle* aStyle, FontVisibility* aVisibility) {
AutoLock lock(mLock);
FontVisibility level =
aPresContext ? aPresContext->GetFontVisibility() : FontVisibility::User;
MOZ_ASSERT(!mCodepointsWithNoFonts[level].test(aCh),
@ -928,7 +948,7 @@ gfxFont* gfxPlatformFontList::SystemFindFontForChar(
fontlist::Face* face =
fallbackFamily.mShared->FindFaceForStyle(SharedFontList(), *aStyle);
if (face) {
fontEntry = GetOrCreateFontEntry(face, fallbackFamily.mShared);
fontEntry = GetOrCreateFontEntryLocked(face, fallbackFamily.mShared);
*aVisibility = fallbackFamily.mShared->Visibility();
}
} else if (!fallbackFamily.mIsShared && fallbackFamily.mUnshared) {
@ -1357,9 +1377,11 @@ class LoadCmapsRunnable : public CancelableRunnable {
RefPtr<CancelableRunnable> task = this;
NS_DispatchToMainThreadQueue(task.forget(), EventQueuePriority::Idle);
} else {
pfl->Lock();
pfl->CancelLoadCmapsTask();
pfl->InitializeCodepointsWithNoFonts();
dom::ContentParent::NotifyUpdatedFonts(false);
pfl->Unlock();
}
return NS_OK;
}
@ -1416,7 +1438,7 @@ gfxFontFamily* gfxPlatformFontList::CheckFamily(gfxFontFamily* aFamily) {
}
if (aFamily && aFamily->GetFontList().Length() == 0) {
// failed to load any faces for this family, so discard it
// Failed to load any faces for this family, so discard it.
nsAutoCString key;
GenerateFontListKey(aFamily->Name(), key);
mFontFamilies.Remove(key);
@ -1426,7 +1448,7 @@ gfxFontFamily* gfxPlatformFontList::CheckFamily(gfxFontFamily* aFamily) {
return aFamily;
}
bool gfxPlatformFontList::FindAndAddFamilies(
bool gfxPlatformFontList::FindAndAddFamiliesLocked(
nsPresContext* aPresContext, StyleGenericFontFamily aGeneric,
const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
FindFamiliesFlags aFlags, gfxFontStyle* aStyle, nsAtom* aLanguage,
@ -1437,6 +1459,7 @@ bool gfxPlatformFontList::FindAndAddFamilies(
bool allowHidden = bool(aFlags & FindFamiliesFlags::eSearchHiddenFamilies);
FontVisibility visibilityLevel =
aPresContext ? aPresContext->GetFontVisibility() : FontVisibility::User;
if (SharedFontList()) {
fontlist::Family* family = SharedFontList()->FindFamily(key);
// If not found, and other family names have not yet been initialized,
@ -1471,12 +1494,7 @@ bool gfxPlatformFontList::FindAndAddFamilies(
}
if (!family && !mOtherFamilyNamesInitialized &&
!(aFlags & FindFamiliesFlags::eNoAddToNamesMissedWhenSearching)) {
// localized family names load timed out, add name to list of
// names to check after localized names are loaded
if (!mOtherNamesMissed) {
mOtherNamesMissed = MakeUnique<nsTHashSet<nsCString>>(2);
}
mOtherNamesMissed->Insert(key);
AddToMissedNames(key);
}
}
// Check whether the family we found is actually allowed to be looked up,
@ -1539,10 +1557,7 @@ bool gfxPlatformFontList::FindAndAddFamilies(
!(aFlags & FindFamiliesFlags::eNoAddToNamesMissedWhenSearching)) {
// localized family names load timed out, add name to list of
// names to check after localized names are loaded
if (!mOtherNamesMissed) {
mOtherNamesMissed = MakeUnique<nsTHashSet<nsCString>>(2);
}
mOtherNamesMissed->Insert(key);
AddToMissedNames(key);
}
if (familyEntry) {
if (isBlockedByVisibilityLevel(familyEntry)) {
@ -1594,6 +1609,13 @@ bool gfxPlatformFontList::FindAndAddFamilies(
return false;
}
void gfxPlatformFontList::AddToMissedNames(const nsCString& aKey) {
if (!mOtherNamesMissed) {
mOtherNamesMissed = MakeUnique<nsTHashSet<nsCString>>(2);
}
mOtherNamesMissed->Insert(aKey);
}
fontlist::Family* gfxPlatformFontList::FindSharedFamily(
nsPresContext* aPresContext, const nsACString& aFamily,
FindFamiliesFlags aFlags, gfxFontStyle* aStyle, nsAtom* aLanguage,
@ -1602,8 +1624,9 @@ fontlist::Family* gfxPlatformFontList::FindSharedFamily(
return nullptr;
}
AutoTArray<FamilyAndGeneric, 1> families;
if (!FindAndAddFamilies(aPresContext, StyleGenericFontFamily::None, aFamily,
&families, aFlags, aStyle, aLanguage, aDevToCss) ||
if (!FindAndAddFamiliesLocked(aPresContext, StyleGenericFontFamily::None,
aFamily, &families, aFlags, aStyle, aLanguage,
aDevToCss) ||
!families[0].mFamily.mIsShared) {
return nullptr;
}
@ -1707,6 +1730,7 @@ gfxFontEntry* gfxPlatformFontList::FindFontForFamily(
const gfxFontStyle* aStyle) {
nsAutoCString key;
GenerateFontListKey(aFamily, key);
FontFamily family = FindFamily(aPresContext, key);
if (family.IsNull()) {
return nullptr;
@ -1716,12 +1740,12 @@ gfxFontEntry* gfxPlatformFontList::FindFontForFamily(
if (!face) {
return nullptr;
}
return GetOrCreateFontEntry(face, family.mShared);
return GetOrCreateFontEntryLocked(face, family.mShared);
}
return family.mUnshared->FindFontForStyle(*aStyle);
}
gfxFontEntry* gfxPlatformFontList::GetOrCreateFontEntry(
gfxFontEntry* gfxPlatformFontList::GetOrCreateFontEntryLocked(
fontlist::Face* aFace, const fontlist::Family* aFamily) {
return mFontEntries
.LookupOrInsertWith(aFace,
@ -1729,25 +1753,28 @@ gfxFontEntry* gfxPlatformFontList::GetOrCreateFontEntry(
.get();
}
void gfxPlatformFontList::AddOtherFamilyName(
gfxFontFamily* aFamilyEntry, const nsCString& aOtherFamilyName) {
nsAutoCString key;
GenerateFontListKey(aOtherFamilyName, key);
void gfxPlatformFontList::AddOtherFamilyNames(
gfxFontFamily* aFamilyEntry, const nsTArray<nsCString>& aOtherFamilyNames) {
AutoLock lock(mLock);
mOtherFamilyNames.LookupOrInsertWith(key, [&] {
LOG_FONTLIST(
("(fontlist-otherfamily) canonical family: %s, "
"other family: %s\n",
aFamilyEntry->Name().get(), aOtherFamilyName.get()));
if (mBadUnderlineFamilyNames.ContainsSorted(key)) {
aFamilyEntry->SetBadUnderlineFamily();
}
return RefPtr{aFamilyEntry};
});
for (const auto& name : aOtherFamilyNames) {
nsAutoCString key;
GenerateFontListKey(name, key);
mOtherFamilyNames.LookupOrInsertWith(key, [&] {
LOG_FONTLIST(
("(fontlist-otherfamily) canonical family: %s, other family: %s\n",
aFamilyEntry->Name().get(), name.get()));
if (mBadUnderlineFamilyNames.ContainsSorted(key)) {
aFamilyEntry->SetBadUnderlineFamily();
}
return RefPtr{aFamilyEntry};
});
}
}
void gfxPlatformFontList::AddFullname(gfxFontEntry* aFontEntry,
const nsCString& aFullname) {
void gfxPlatformFontList::AddFullnameLocked(gfxFontEntry* aFontEntry,
const nsCString& aFullname) {
mExtraNames->mFullnames.LookupOrInsertWith(aFullname, [&] {
LOG_FONTLIST(("(fontlist-fullname) name: %s, fullname: %s\n",
aFontEntry->Name().get(), aFullname.get()));
@ -1755,8 +1782,8 @@ void gfxPlatformFontList::AddFullname(gfxFontEntry* aFontEntry,
});
}
void gfxPlatformFontList::AddPostscriptName(gfxFontEntry* aFontEntry,
const nsCString& aPostscriptName) {
void gfxPlatformFontList::AddPostscriptNameLocked(
gfxFontEntry* aFontEntry, const nsCString& aPostscriptName) {
mExtraNames->mPostscriptNames.LookupOrInsertWith(aPostscriptName, [&] {
LOG_FONTLIST(("(fontlist-postscript) name: %s, psname: %s\n",
aFontEntry->Name().get(), aPostscriptName.get()));
@ -1766,6 +1793,7 @@ void gfxPlatformFontList::AddPostscriptName(gfxFontEntry* aFontEntry,
bool gfxPlatformFontList::GetStandardFamilyName(const nsCString& aFontName,
nsACString& aFamilyName) {
AutoLock lock(mLock);
FontFamily family = FindFamily(nullptr, aFontName);
if (family.IsNull()) {
return false;
@ -1794,6 +1822,8 @@ FamilyAndGeneric gfxPlatformFontList::GetDefaultFontFamily(
return FamilyAndGeneric();
}
AutoLock lock(mLock);
nsAutoCString value;
AutoTArray<nsCString, 4> names;
if (mFontPrefs->LookupNameList(PrefName(aGenericFamily, aLangGroup), value)) {
@ -1819,7 +1849,7 @@ ShmemCharMapHashEntry::ShmemCharMapHashEntry(const gfxSparseBitSet* aCharMap)
SharedBitSet::Create(mCharMap.ToPtr(mList), len, *aCharMap);
}
fontlist::Pointer gfxPlatformFontList::GetShmemCharMap(
fontlist::Pointer gfxPlatformFontList::GetShmemCharMapLocked(
const gfxSparseBitSet* aCmap) {
auto* entry = mShmemCharMaps.GetEntry(aCmap);
if (!entry) {
@ -1828,22 +1858,18 @@ fontlist::Pointer gfxPlatformFontList::GetShmemCharMap(
return entry->GetCharMap();
}
// lookup cmap in the shared cmap set, adding if not already present
gfxCharacterMap* gfxPlatformFontList::FindCharMap(gfxCharacterMap* aCmap) {
AutoLock lock(mLock);
aCmap->CalcHash();
gfxCharacterMap* cmap = AddCmap(aCmap);
gfxCharacterMap* cmap = mSharedCmaps.PutEntry(aCmap)->GetKey();
cmap->mShared = true;
return cmap;
}
// add a cmap to the shared cmap set
gfxCharacterMap* gfxPlatformFontList::AddCmap(const gfxCharacterMap* aCharMap) {
CharMapHashKey* found =
mSharedCmaps.PutEntry(const_cast<gfxCharacterMap*>(aCharMap));
return found->GetKey();
}
// remove the cmap from the shared cmap set
void gfxPlatformFontList::RemoveCmap(const gfxCharacterMap* aCharMap) {
AutoLock lock(mLock);
// skip lookups during teardown
if (mSharedCmaps.Count() == 0) {
return;
@ -1939,8 +1965,9 @@ void gfxPlatformFontList::GetFontFamiliesFromGenericFamilies(
// lookup and add platform fonts uniquely
for (const nsCString& genericFamily : aGenericNameFamilies) {
AutoTArray<FamilyAndGeneric, 10> families;
FindAndAddFamilies(aPresContext, aGenericType, genericFamily, &families,
FindFamiliesFlags(0), nullptr, aLangGroup);
FindAndAddFamiliesLocked(aPresContext, aGenericType, genericFamily,
&families, FindFamiliesFlags(0), nullptr,
aLangGroup);
for (const FamilyAndGeneric& f : families) {
if (!aGenericFamilies->Contains(f.mFamily)) {
aGenericFamilies->AppendElement(f.mFamily);
@ -1949,7 +1976,8 @@ void gfxPlatformFontList::GetFontFamiliesFromGenericFamilies(
}
}
gfxPlatformFontList::PrefFontList* gfxPlatformFontList::GetPrefFontsLangGroup(
gfxPlatformFontList::PrefFontList*
gfxPlatformFontList::GetPrefFontsLangGroupLocked(
nsPresContext* aPresContext, StyleGenericFontFamily aGenericType,
eFontPrefLang aPrefLang) {
if (aGenericType == StyleGenericFontFamily::MozEmoji ||
@ -1977,6 +2005,8 @@ gfxPlatformFontList::PrefFontList* gfxPlatformFontList::GetPrefFontsLangGroup(
void gfxPlatformFontList::AddGenericFonts(
nsPresContext* aPresContext, StyleGenericFontFamily aGenericType,
nsAtom* aLanguage, nsTArray<FamilyAndGeneric>& aFamilyList) {
AutoLock lock(mLock);
// map lang ==> langGroup
nsAtom* langGroup = GetLangGroup(aLanguage);
@ -1985,7 +2015,7 @@ void gfxPlatformFontList::AddGenericFonts(
// lookup pref fonts
PrefFontList* prefFonts =
GetPrefFontsLangGroup(aPresContext, aGenericType, prefLang);
GetPrefFontsLangGroupLocked(aPresContext, aGenericType, prefLang);
if (!prefFonts->IsEmpty()) {
aFamilyList.SetCapacity(aFamilyList.Length() + prefFonts->Length());
@ -2181,6 +2211,7 @@ bool gfxPlatformFontList::IsLangCJK(eFontPrefLang aLang) {
void gfxPlatformFontList::GetLangPrefs(eFontPrefLang aPrefLangs[],
uint32_t& aLen, eFontPrefLang aCharLang,
eFontPrefLang aPageLang) {
AutoLock lock(mLock);
if (IsLangCJK(aCharLang)) {
AppendCJKPrefLangs(aPrefLangs, aLen, aCharLang, aPageLang);
} else {
@ -2351,6 +2382,8 @@ StyleGenericFontFamily gfxPlatformFontList::GetDefaultGeneric(
return StyleGenericFontFamily::MozEmoji;
}
AutoLock lock(mLock);
// initialize lang group pref font defaults (i.e. serif/sans-serif)
if (MOZ_UNLIKELY(mDefaultGenericsLangGroup.IsEmpty())) {
mDefaultGenericsLangGroup.AppendElements(ArrayLength(gPrefLangNames));
@ -2375,6 +2408,12 @@ StyleGenericFontFamily gfxPlatformFontList::GetDefaultGeneric(
FontFamily gfxPlatformFontList::GetDefaultFont(nsPresContext* aPresContext,
const gfxFontStyle* aStyle) {
AutoLock lock(mLock);
return GetDefaultFontLocked(aPresContext, aStyle);
}
FontFamily gfxPlatformFontList::GetDefaultFontLocked(
nsPresContext* aPresContext, const gfxFontStyle* aStyle) {
FontFamily family = GetDefaultFontForPlatform(aPresContext, aStyle);
if (!family.IsNull()) {
return family;
@ -2461,6 +2500,7 @@ void gfxPlatformFontList::InitLoader() {
20 // max time for one pass through RunLoader = 20ms
bool gfxPlatformFontList::LoadFontInfo() {
AutoLock lock(mLock);
TimeStamp start = TimeStamp::Now();
uint32_t i, endIndex = mNumFamilies;
fontlist::FontList* list = SharedFontList();
@ -2528,6 +2568,8 @@ bool gfxPlatformFontList::LoadFontInfo() {
}
void gfxPlatformFontList::CleanupLoader() {
AutoLock lock(mLock);
mFontFamiliesToLoad.Clear();
mNumFamilies = 0;
bool rebuilt = false, forceReflow = false;
@ -2535,7 +2577,10 @@ void gfxPlatformFontList::CleanupLoader() {
// if had missed face names that are now available, force reflow all
if (mFaceNamesMissed) {
rebuilt = std::any_of(mFaceNamesMissed->cbegin(), mFaceNamesMissed->cend(),
[&](const auto& key) { return FindFaceName(key); });
[&](const auto& key) {
mLock.AssertCurrentThreadIn();
return FindFaceName(key);
});
if (rebuilt) {
RebuildLocalFonts();
}
@ -2547,6 +2592,7 @@ void gfxPlatformFontList::CleanupLoader() {
forceReflow = std::any_of(
mOtherNamesMissed->cbegin(), mOtherNamesMissed->cend(),
[&](const auto& key) {
mLock.AssertCurrentThreadIn();
return FindUnsharedFamily(
nullptr, key,
(FindFamiliesFlags::eForceOtherFamilyNamesLoading |
@ -2580,8 +2626,11 @@ void gfxPlatformFontList::GetPrefsAndStartLoader() {
StartLoader(delay);
} else {
NS_DispatchToMainThread(NS_NewRunnableFunction(
"StartLoader callback",
[delay, fontList = this] { fontList->StartLoader(delay); }));
"StartLoader callback", [delay, fontList = this] {
fontList->Lock();
fontList->StartLoader(delay);
fontList->Unlock();
}));
}
}
@ -2594,7 +2643,7 @@ void gfxPlatformFontList::RebuildLocalFonts(bool aForgetLocalFaces) {
}
}
void gfxPlatformFontList::ClearLangGroupPrefFonts() {
void gfxPlatformFontList::ClearLangGroupPrefFontsLocked() {
for (uint32_t i = eFontPrefLang_First;
i < eFontPrefLang_First + eFontPrefLang_Count; i++) {
auto& prefFontsLangGroup = mLangGroupPrefFonts[i];
@ -2642,6 +2691,8 @@ size_t gfxPlatformFontList::SizeOfFontEntryTableExcludingThis(
void gfxPlatformFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
FontListSizes* aSizes) const {
AutoLock lock(mLock);
aSizes->mFontListSize +=
mFontFamilies.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (const auto& entry : mFontFamilies) {
@ -2717,6 +2768,8 @@ void gfxPlatformFontList::InitOtherFamilyNamesInternal(
return;
}
AutoLock lock(mLock);
if (aDeferOtherFamilyNamesLoading) {
TimeStamp start = TimeStamp::Now();
bool timedOut = false;

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

@ -24,8 +24,8 @@
#include "mozilla/EnumeratedArray.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Mutex.h"
#include "mozilla/RangedArray.h"
#include "mozilla/RecursiveMutex.h"
#include "nsLanguageAtomService.h"
#include "base/shared_memory.h"
@ -164,6 +164,8 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
typedef mozilla::WeightRange WeightRange;
typedef mozilla::intl::Script Script;
using AutoLock = mozilla::RecursiveMutexAutoLock;
// Class used to hold cached copies of the font-name prefs, so that they can
// be accessed from non-main-thread callers who are not allowed to touch the
// Preferences service.
@ -265,7 +267,11 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// but not completely invalidated.
void UpdateFontList(bool aFullRebuild = true);
virtual void ClearLangGroupPrefFonts();
void ClearLangGroupPrefFonts() {
AutoLock lock(mLock);
ClearLangGroupPrefFontsLocked();
}
virtual void ClearLangGroupPrefFontsLocked() REQUIRES(mLock);
void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily>>& aFamilyArray);
@ -307,15 +313,25 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// Find family(ies) matching aFamily and append to the aOutput array
// (there may be multiple results in the case of fontconfig aliases, etc).
// Return true if any match was found and appended, false if none.
virtual bool FindAndAddFamilies(
bool FindAndAddFamilies(
nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric,
const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr,
nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0);
nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0) {
AutoLock lock(mLock);
return FindAndAddFamiliesLocked(aPresContext, aGeneric, aFamily, aOutput,
aFlags, aStyle, aLanguage, aDevToCssSize);
}
virtual bool FindAndAddFamiliesLocked(
nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric,
const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr,
nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0)
REQUIRES(mLock);
gfxFontEntry* FindFontForFamily(nsPresContext* aPresContext,
const nsACString& aFamily,
const gfxFontStyle* aStyle);
const gfxFontStyle* aStyle) REQUIRES(mLock);
mozilla::fontlist::FontList* SharedFontList() const {
return mSharedFontList.get();
@ -371,13 +387,24 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// name lookup table methods
void AddOtherFamilyName(gfxFontFamily* aFamilyEntry,
const nsCString& aOtherFamilyName);
void AddOtherFamilyNames(gfxFontFamily* aFamilyEntry,
const nsTArray<nsCString>& aOtherFamilyNames);
void AddFullname(gfxFontEntry* aFontEntry, const nsCString& aFullname);
void AddFullname(gfxFontEntry* aFontEntry, const nsCString& aFullname) {
AutoLock lock(mLock);
AddFullnameLocked(aFontEntry, aFullname);
}
void AddFullnameLocked(gfxFontEntry* aFontEntry, const nsCString& aFullname)
REQUIRES(mLock);
void AddPostscriptName(gfxFontEntry* aFontEntry,
const nsCString& aPostscriptName);
const nsCString& aPostscriptName) {
AutoLock lock(mLock);
AddPostscriptNameLocked(aFontEntry, aPostscriptName);
}
void AddPostscriptNameLocked(gfxFontEntry* aFontEntry,
const nsCString& aPostscriptName)
REQUIRES(mLock);
bool NeedFullnamePostscriptNames() { return mExtraNames != nullptr; }
@ -400,10 +427,15 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// get the system default font family
FontFamily GetDefaultFont(nsPresContext* aPresContext,
const gfxFontStyle* aStyle);
FontFamily GetDefaultFontLocked(nsPresContext* aPresContext,
const gfxFontStyle* aStyle) REQUIRES(mLock);
// get the "ultimate" default font, for use if the font list is otherwise
// unusable (e.g. in the middle of being updated)
gfxFontEntry* GetDefaultFontEntry() { return mDefaultFontEntry.get(); }
gfxFontEntry* GetDefaultFontEntry() {
AutoLock lock(mLock);
return mDefaultFontEntry.get();
}
/**
* Look up a font by name on the host platform.
@ -456,24 +488,28 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
FontListSizes* aSizes) const;
mozilla::fontlist::Pointer GetShmemCharMap(const gfxSparseBitSet* aCmap);
mozilla::fontlist::Pointer GetShmemCharMap(const gfxSparseBitSet* aCmap) {
AutoLock lock(mLock);
return GetShmemCharMapLocked(aCmap);
}
mozilla::fontlist::Pointer GetShmemCharMapLocked(const gfxSparseBitSet* aCmap)
REQUIRES(mLock);
// search for existing cmap that matches the input
// return the input if no match is found
// Search for existing cmap that matches the input; return the input if no
// match is found.
gfxCharacterMap* FindCharMap(gfxCharacterMap* aCmap);
// add a cmap to the shared cmap set
gfxCharacterMap* AddCmap(const gfxCharacterMap* aCharMap);
// remove the cmap from the shared cmap set
// Remove the cmap from the shared cmap set.
void RemoveCmap(const gfxCharacterMap* aCharMap);
// keep track of userfont sets to notify when global fontlist changes occur
// Keep track of userfont sets to notify when global fontlist changes occur.
void AddUserFontSet(gfxUserFontSet* aUserFontSet) {
AutoLock lock(mLock);
mUserFontSetList.Insert(aUserFontSet);
}
void RemoveUserFontSet(gfxUserFontSet* aUserFontSet) {
AutoLock lock(mLock);
mUserFontSetList.Remove(aUserFontSet);
}
@ -496,15 +532,32 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
* make one, and adds it to the cache.
*/
gfxFontEntry* GetOrCreateFontEntry(mozilla::fontlist::Face* aFace,
const mozilla::fontlist::Family* aFamily);
const mozilla::fontlist::Family* aFamily) {
AutoLock lock(mLock);
return GetOrCreateFontEntryLocked(aFace, aFamily);
}
gfxFontEntry* GetOrCreateFontEntryLocked(
mozilla::fontlist::Face* aFace, const mozilla::fontlist::Family* aFamily)
REQUIRES(mLock);
const FontPrefs* GetFontPrefs() const { return mFontPrefs.get(); }
const FontPrefs* GetFontPrefs() const REQUIRES(mLock) {
return mFontPrefs.get();
}
bool EmojiPrefHasUserValue() const { return mFontPrefs->EmojiHasUserValue(); }
bool EmojiPrefHasUserValue() const {
AutoLock lock(mLock);
return mFontPrefs->EmojiHasUserValue();
}
PrefFontList* GetPrefFontsLangGroup(
nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType,
eFontPrefLang aPrefLang);
eFontPrefLang aPrefLang) {
AutoLock lock(mLock);
return GetPrefFontsLangGroupLocked(aPresContext, aGenericType, aPrefLang);
}
PrefFontList* GetPrefFontsLangGroupLocked(
nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType,
eFontPrefLang aPrefLang) REQUIRES(mLock);
// in some situations, need to make decisions about ambiguous characters, may
// need to look at multiple pref langs
@ -555,6 +608,7 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
mozilla::StyleGenericFontFamily aGenericType);
bool SkipFontFallbackForChar(FontVisibility aVisibility, uint32_t aCh) const {
AutoLock lock(mLock);
return mCodepointsWithNoFonts[aVisibility].test(aCh);
}
@ -566,7 +620,7 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
FontVisibility aVisibility) const;
// (Re-)initialize the set of codepoints that we know cannot be rendered.
void InitializeCodepointsWithNoFonts();
void InitializeCodepointsWithNoFonts() REQUIRES(mLock);
// If using the shared font list, returns a generation count that is
// incremented if/when the platform list is reinitialized (e.g. because
@ -581,6 +635,13 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
return PR_GetCurrentThread() == sInitFontListThread;
}
void Lock() CAPABILITY_ACQUIRE(mLock) { mLock.Lock(); }
void Unlock() CAPABILITY_RELEASE(mLock) { mLock.Unlock(); }
// This is only public because some external callers want to be able to
// assert about the locked status.
mutable mozilla::RecursiveMutex mLock;
protected:
friend class mozilla::fontlist::FontList;
friend class InitOtherFamilyNamesForStylo;
@ -680,20 +741,20 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
nsPresContext* aPresContext, const nsACString& aFamily,
FindFamiliesFlags aFlags = FindFamiliesFlags(0),
gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr,
gfxFloat aDevToCssSize = 1.0);
gfxFloat aDevToCssSize = 1.0) REQUIRES(mLock);
gfxFontFamily* FindUnsharedFamily(
nsPresContext* aPresContext, const nsACString& aFamily,
FindFamiliesFlags aFlags = FindFamiliesFlags(0),
gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr,
gfxFloat aDevToCssSize = 1.0) {
gfxFloat aDevToCssSize = 1.0) REQUIRES(mLock) {
if (SharedFontList()) {
return nullptr;
}
AutoTArray<FamilyAndGeneric, 1> families;
if (FindAndAddFamilies(aPresContext, mozilla::StyleGenericFontFamily::None,
aFamily, &families, aFlags, aStyle, aLanguage,
aDevToCssSize)) {
if (FindAndAddFamiliesLocked(
aPresContext, mozilla::StyleGenericFontFamily::None, aFamily,
&families, aFlags, aStyle, aLanguage, aDevToCssSize)) {
return families[0].mFamily.mUnshared;
}
return nullptr;
@ -703,7 +764,7 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
FindFamiliesFlags aFlags = FindFamiliesFlags(0),
gfxFontStyle* aStyle = nullptr,
nsAtom* aLanguage = nullptr,
gfxFloat aDevToCssSize = 1.0) {
gfxFloat aDevToCssSize = 1.0) REQUIRES(mLock) {
if (SharedFontList()) {
return FontFamily(FindSharedFamily(aPresContext, aFamily, aFlags, aStyle,
aLanguage, aDevToCssSize));
@ -714,7 +775,8 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// Lookup family name in global family list without substitutions or
// localized family name lookup. Used for common font fallback families.
gfxFontFamily* FindFamilyByCanonicalName(const nsACString& aFamily) {
gfxFontFamily* FindFamilyByCanonicalName(const nsACString& aFamily)
REQUIRES(mLock) {
nsAutoCString key;
gfxFontFamily* familyEntry;
GenerateFontListKey(aFamily, key);
@ -729,14 +791,15 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
uint32_t aNextCh, Script aRunScript,
eFontPresentation aPresentation,
const gfxFontStyle* aMatchStyle,
FontFamily& aMatchedFamily);
FontFamily& aMatchedFamily) REQUIRES(mLock);
// Search fonts system-wide for a given character, null if not found.
gfxFont* GlobalFontFallback(nsPresContext* aPresContext, uint32_t aCh,
uint32_t aNextCh, Script aRunScript,
eFontPresentation aPresentation,
const gfxFontStyle* aMatchStyle,
uint32_t& aCmapCount, FontFamily& aMatchedFamily);
uint32_t& aCmapCount, FontFamily& aMatchedFamily)
REQUIRES(mLock);
// Platform-specific implementation of global font fallback, if any;
// this may return nullptr in which case the default cmap-based fallback
@ -752,45 +815,52 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
virtual bool UsesSystemFallback() { return false; }
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t& aLen,
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
eFontPrefLang aCharLang, eFontPrefLang aPageLang)
REQUIRES(mLock);
// verifies that a family contains a non-zero font count
gfxFontFamily* CheckFamily(gfxFontFamily* aFamily);
gfxFontFamily* CheckFamily(gfxFontFamily* aFamily) REQUIRES(mLock);
// initialize localized family names
void InitOtherFamilyNamesInternal(bool aDeferOtherFamilyNamesLoading);
void CancelInitOtherFamilyNamesTask();
void AddToMissedNames(const nsCString& aKey) REQUIRES(mLock);
// search through font families, looking for a given name, initializing
// facename lists along the way. first checks all families with names
// close to face name, then searchs all families if not found.
gfxFontEntry* SearchFamiliesForFaceName(const nsACString& aFaceName);
gfxFontEntry* SearchFamiliesForFaceName(const nsACString& aFaceName)
REQUIRES(mLock);
// helper method for finding fullname/postscript names in facename lists
gfxFontEntry* FindFaceName(const nsACString& aFaceName);
gfxFontEntry* FindFaceName(const nsACString& aFaceName) REQUIRES(mLock);
// look up a font by name, for cases where platform font list
// maintains explicit mappings of fullname/psname ==> font
virtual gfxFontEntry* LookupInFaceNameLists(const nsACString& aFontName);
virtual gfxFontEntry* LookupInFaceNameLists(const nsACString& aFaceName)
REQUIRES(mLock);
gfxFontEntry* LookupInSharedFaceNameList(nsPresContext* aPresContext,
const nsACString& aFaceName,
WeightRange aWeightForEntry,
StretchRange aStretchForEntry,
SlantStyleRange aStyleForEntry);
SlantStyleRange aStyleForEntry)
REQUIRES(mLock);
// load the bad underline blocklist from pref.
void LoadBadUnderlineList();
void GenerateFontListKey(const nsACString& aKeyName, nsACString& aResult);
virtual void GetFontFamilyNames(nsTArray<nsCString>& aFontFamilyNames);
virtual void GetFontFamilyNames(nsTArray<nsCString>& aFontFamilyNames)
REQUIRES(mLock);
// helper function to map lang to lang group
nsAtom* GetLangGroup(nsAtom* aLanguage);
// gfxFontInfoLoader overrides, used to load in font cmaps
void InitLoader() override;
void InitLoader() REQUIRES(mLock) override;
bool LoadFontInfo() override;
void CleanupLoader() override;
@ -800,23 +870,23 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// If aForgetLocalFaces is true, all gfxFontEntries for src:local fonts must
// be discarded (not potentially reused to satisfy the rebuilt rules),
// because they may no longer be valid.
void RebuildLocalFonts(bool aForgetLocalFaces = false);
void RebuildLocalFonts(bool aForgetLocalFaces = false) REQUIRES(mLock);
void ResolveGenericFontNames(nsPresContext* aPresContext,
mozilla::StyleGenericFontFamily aGenericType,
eFontPrefLang aPrefLang,
PrefFontList* aGenericFamilies);
PrefFontList* aGenericFamilies) REQUIRES(mLock);
void ResolveEmojiFontNames(nsPresContext* aPresContext,
PrefFontList* aGenericFamilies);
PrefFontList* aGenericFamilies) REQUIRES(mLock);
void GetFontFamiliesFromGenericFamilies(
nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType,
nsTArray<nsCString>& aGenericNameFamilies, nsAtom* aLangGroup,
PrefFontList* aFontFamilies);
PrefFontList* aFontFamilies) REQUIRES(mLock);
virtual nsresult InitFontListForPlatform() = 0;
virtual void InitSharedFontListForPlatform() {}
virtual nsresult InitFontListForPlatform() REQUIRES(mLock) = 0;
virtual void InitSharedFontListForPlatform() REQUIRES(mLock) {}
virtual gfxFontEntry* CreateFontEntry(
mozilla::fontlist::Face* aFace,
@ -831,7 +901,7 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
* There are separate implementations of this for the per-process font list
* and for the shared-memory font list.
*/
void ApplyWhitelist();
void ApplyWhitelist() REQUIRES(mLock);
void ApplyWhitelist(nsTArray<mozilla::fontlist::Family::InitData>& aFamilies);
// Create a new gfxFontFamily of the appropriate subclass for the platform,
@ -850,7 +920,8 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
* case this method is unused.
*/
virtual void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily,
bool aNeedFullnamePostscriptNames) {}
bool aNeedFullnamePostscriptNames)
REQUIRES(mLock) {}
typedef nsRefPtrHashtable<nsCStringHashKey, gfxFontFamily> FontFamilyTable;
typedef nsRefPtrHashtable<nsCStringHashKey, gfxFontEntry> FontEntryTable;
@ -864,26 +935,24 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// Platform-specific helper for GetDefaultFont(...).
virtual FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext,
const gfxFontStyle* aStyle,
nsAtom* aLanguage = nullptr) = 0;
// Protects mFontFamilies.
mozilla::Mutex mFontFamiliesMutex MOZ_UNANNOTATED;
nsAtom* aLanguage = nullptr)
REQUIRES(mLock) = 0;
// canonical family name ==> family entry (unique, one name per family entry)
FontFamilyTable mFontFamilies;
FontFamilyTable mFontFamilies GUARDED_BY(mLock);
// other family name ==> family entry (not unique, can have multiple names per
// family entry, only names *other* than the canonical names are stored here)
FontFamilyTable mOtherFamilyNames;
FontFamilyTable mOtherFamilyNames GUARDED_BY(mLock);
// flag set after InitOtherFamilyNames is called upon first name lookup miss
bool mOtherFamilyNamesInitialized = false;
mozilla::Atomic<bool> mOtherFamilyNamesInitialized;
// The pending InitOtherFamilyNames() task.
RefPtr<mozilla::CancelableRunnable> mPendingOtherFamilyNameTask;
// flag set after fullname and Postcript name lists are populated
bool mFaceNameListsInitialized = false;
mozilla::Atomic<bool> mFaceNameListsInitialized;
struct ExtraNames {
ExtraNames() = default;
@ -893,13 +962,16 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// Postscript name ==> font entry (unique, one name per font entry)
FontEntryTable mPostscriptNames{64};
};
mozilla::UniquePtr<ExtraNames> mExtraNames;
// The lock is needed to guard access to the actual name tables, but does not
// need to be held to just test whether mExtraNames is non-null as it is set
// during initialization before other threads have a chance to see it.
mozilla::UniquePtr<ExtraNames> mExtraNames PT_GUARDED_BY(mLock);
// face names missed when face name loading takes a long time
mozilla::UniquePtr<nsTHashSet<nsCString>> mFaceNamesMissed;
mozilla::UniquePtr<nsTHashSet<nsCString>> mFaceNamesMissed GUARDED_BY(mLock);
// localized family names missed when face name loading takes a long time
mozilla::UniquePtr<nsTHashSet<nsCString>> mOtherNamesMissed;
mozilla::UniquePtr<nsTHashSet<nsCString>> mOtherNamesMissed GUARDED_BY(mLock);
typedef mozilla::RangedArray<mozilla::UniquePtr<PrefFontList>,
size_t(mozilla::StyleGenericFontFamily::None),
@ -908,28 +980,28 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
PrefFontsForLangGroup;
mozilla::RangedArray<PrefFontsForLangGroup, eFontPrefLang_First,
eFontPrefLang_Count>
mLangGroupPrefFonts;
mozilla::UniquePtr<PrefFontList> mEmojiPrefFont;
mLangGroupPrefFonts GUARDED_BY(mLock);
mozilla::UniquePtr<PrefFontList> mEmojiPrefFont GUARDED_BY(mLock);
// When system-wide font lookup fails for a character, cache it to skip future
// searches. This is an array of bitsets, one for each FontVisibility level.
mozilla::EnumeratedArray<FontVisibility, FontVisibility::Count,
gfxSparseBitSet>
mCodepointsWithNoFonts;
mCodepointsWithNoFonts GUARDED_BY(mLock);
// the family to use for U+FFFD fallback, to avoid expensive search every time
// on pages with lots of problems
mozilla::EnumeratedArray<FontVisibility, FontVisibility::Count, FontFamily>
mReplacementCharFallbackFamily;
mReplacementCharFallbackFamily GUARDED_BY(mLock);
// Sorted array of lowercased family names; use ContainsSorted to test
nsTArray<nsCString> mBadUnderlineFamilyNames;
// character map data shared across families
// contains weak ptrs to cmaps shared by font entry objects
nsTHashtable<CharMapHashKey> mSharedCmaps;
nsTHashtable<CharMapHashKey> mSharedCmaps GUARDED_BY(mLock);
nsTHashtable<ShmemCharMapHashEntry> mShmemCharMaps;
nsTHashtable<ShmemCharMapHashEntry> mShmemCharMaps GUARDED_BY(mLock);
// data used as part of the font cmap loading process
nsTArray<RefPtr<gfxFontFamily>> mFontFamiliesToLoad;
@ -940,12 +1012,13 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// see bugs 636957, 1070983, 1189129
uint32_t mFontlistInitCount = 0; // num times InitFontList called
nsTHashSet<gfxUserFontSet*> mUserFontSetList;
nsTHashSet<gfxUserFontSet*> mUserFontSetList GUARDED_BY(mLock);
nsLanguageAtomService* mLangService = nullptr;
nsTArray<uint32_t> mCJKPrefLangs;
nsTArray<mozilla::StyleGenericFontFamily> mDefaultGenericsLangGroup;
nsTArray<uint32_t> mCJKPrefLangs GUARDED_BY(mLock);
nsTArray<mozilla::StyleGenericFontFamily> mDefaultGenericsLangGroup
GUARDED_BY(mLock);
nsTArray<nsCString> mEnabledFontsList;
@ -956,11 +1029,11 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
mLocalNameTable;
nsRefPtrHashtable<nsPtrHashKey<mozilla::fontlist::Face>, gfxFontEntry>
mFontEntries;
mFontEntries GUARDED_BY(mLock);
mozilla::UniquePtr<FontPrefs> mFontPrefs;
RefPtr<gfxFontEntry> mDefaultFontEntry;
RefPtr<gfxFontEntry> mDefaultFontEntry GUARDED_BY(mLock);
RefPtr<mozilla::CancelableRunnable> mLoadCmapsRunnable;
uint32_t mStartedLoadingCmapsFrom = 0xffffffffu;

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

@ -172,6 +172,7 @@ class gfxUserFontFamily : public gfxFontFamily {
// add the given font entry to the end of the family's list
void AddFontEntry(gfxFontEntry* aFontEntry) {
mozilla::AutoWriteLock lock(mLock);
MOZ_ASSERT(!mIsSimpleFamily, "not valid for user-font families");
// keep ref while removing existing entry
RefPtr<gfxFontEntry> fe = aFontEntry;
@ -196,12 +197,16 @@ class gfxUserFontFamily : public gfxFontFamily {
}
void RemoveFontEntry(gfxFontEntry* aFontEntry) {
mozilla::AutoWriteLock lock(mLock);
MOZ_ASSERT(!mIsSimpleFamily, "not valid for user-font families");
mAvailableFonts.RemoveElement(aFontEntry);
}
// Remove all font entries from the family
void DetachFontEntries() { mAvailableFonts.Clear(); }
void DetachFontEntries() {
mozilla::AutoWriteLock lock(mLock);
mAvailableFonts.Clear();
}
};
class gfxUserFontEntry;

36
gfx/wr/Cargo.lock сгенерированный
Просмотреть файл

@ -193,12 +193,15 @@ dependencies = [
[[package]]
name = "chrono"
version = "0.2.25"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"num",
"libc",
"num-integer",
"num-traits",
"time",
"winapi",
]
[[package]]
@ -809,9 +812,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.68"
version = "0.2.122"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259"
[[package]]
name = "libloading"
@ -948,17 +951,6 @@ dependencies = [
"version_check",
]
[[package]]
name = "num"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
dependencies = [
"num-integer",
"num-iter",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.42"
@ -1531,12 +1523,12 @@ dependencies = [
[[package]]
name = "time"
version = "0.1.42"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"redox_syscall",
"wasi",
"winapi",
]
@ -1596,6 +1588,12 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wayland-client"
version = "0.21.13"

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

@ -17,7 +17,7 @@ log = "0.4"
yaml-rust = "0.4"
serde_json = "1.0"
time = "0.1"
chrono = "0.2"
chrono = "0.4"
crossbeam = "0.2"
osmesa-sys = { version = "0.1.2", optional = true }
osmesa-src = { version = "0.2", git = "https://github.com/servo/osmesa-src", optional = true }

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

@ -16,28 +16,54 @@ implementing the trivial example visible in `EmptyUtil
- Define a new IPC actor, e.g., ``PEmptyUtil`` that allows to get some string
via ``GetSomeString()`` from the child to the parent
- In the ``PUtilityProcess`` definition, expose a new child-level method,
e.g., ``StartEmptyUtilService(Endpoint<PEmptyUtilChild>)``
- Implement ``EmptyUtilChild`` and ``EmptyUtilParent`` classes both deriving
from their ``PEmptyUtilXX``. If you want or need to run things from a
different thread, you can have a look at ``UtilityProcessGenericActor``
- Make sure both are refcounted
- Expose your new service on ``UtilityProcessManager`` with a method
performing the heavy lifting of starting your process, you can take
inspiration from ``StartEmptyUtil()`` there.
inspiration from ``StartEmptyUtil()`` in the sample.
- Ideally, this starting method should rely on `StartUtility() <https://searchfox.org/mozilla-central/rev/fb511723f821ceabeea23b123f1c50c9e93bde9d/ipc/glue/UtilityProcessManager.cpp#210-258,266>`_
- To use ``StartUtility()`` mentioned above, please ensure that you provide
a ``nsresult BindToUtilityProcess(RefPtr<UtilityProcessParent>
aUtilityParent)``. Usually, it should be in charge of creating a set of
endpoints and performing ``Bind()`` to setup the IPC. You can see some example for `Utility AudioDecoder <https://searchfox.org/mozilla-central/rev/4b3039b48c3cb67774270ebcc2a7d8624d888092/ipc/glue/UtilityAudioDecoderChild.h#31-51>`_
- For proper user-facing exposition in ``about:processes`` you will have to also provide an actor
name via a method ``UtilityActorName GetActorName() { return UtilityActorName::EmptyUtil; }``
+ Add member within `enum WebIDLUtilityActorName in <https://searchfox.org/mozilla-central/rev/fb511723f821ceabeea23b123f1c50c9e93bde9d/dom/chrome-webidl/ChromeUtils.webidl#686-689>`_
+ Add member within `enum class UtilityActorName of <https://searchfox.org/mozilla-central/rev/fb511723f821ceabeea23b123f1c50c9e93bde9d/toolkit/components/processtools/ProcInfo.h#71-74>`_
+ Update mapping in `switch case <https://searchfox.org/mozilla-central/rev/fb511723f821ceabeea23b123f1c50c9e93bde9d/dom/base/ChromeUtils.cpp#916-919>`_ and update the `static assert <https://searchfox.org/mozilla-central/rev/fb511723f821ceabeea23b123f1c50c9e93bde9d/dom/base/ChromeUtils.cpp#910-911>`_
- Handle reception of ``StartEmptyUtilService`` on the child side of
``UtilityProcess`` within ``RecvStartEmptyUtilService()``
- The specific sandboxing requirements can be implemented by tracking
``SandboxingKind``, and it starts within `UtilityProcessSandboxing header
<https://searchfox.org/mozilla-central/source/ipc/glue/UtilityProcessSandboxing.h>`_
- Try and make sure you at least add some ``gtest`` coverage of your new
actor, for example like in `existing gtest
<https://searchfox.org/mozilla-central/source/ipc/glue/test/gtest/TestUtilityProcess.cpp>`_
- Also ensure actual sandbox testing within
+ ``SandboxTest`` to start your new process,
`<https://searchfox.org/mozilla-central/source/security/sandbox/common/test/SandboxTest.cpp>`_
+ ``SandboxTestingChildTests`` to define the test
`<https://searchfox.org/mozilla-central/source/security/sandbox/common/test/SandboxTestingChildTests.h>`_
+ ``SandboxTestingChild`` to run your test
`<https://searchfox.org/mozilla-central/source/security/sandbox/common/test/SandboxTestingChild.cpp>`_

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

@ -1710,23 +1710,26 @@ static MOZ_ALWAYS_INLINE bool ValueToAtomOrSymbolPure(JSContext* cx,
return false;
}
}
*id = AtomToId(atom);
} else if (idVal.isSymbol()) {
*id = PropertyKey::Symbol(idVal.toSymbol());
} else {
if (!ValueToIdPure(idVal, id)) {
// Watch out for integer ids because they may be stored in dense elements.
static_assert(PropertyKey::IntMin == 0);
static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT < PropertyKey::IntMax,
"All dense elements must have integer jsids");
uint32_t index;
if (MOZ_UNLIKELY(atom->isIndex(&index) && index <= PropertyKey::IntMax)) {
return false;
}
*id = PropertyKey::NonIntAtom(atom);
return true;
}
// Watch out for ids that may be stored in dense elements.
static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT < PropertyKey::IntMax,
"All dense elements must have integer jsids");
if (MOZ_UNLIKELY(id->isInt())) {
return false;
if (idVal.isSymbol()) {
*id = PropertyKey::Symbol(idVal.toSymbol());
return true;
}
return true;
return false;
}
bool GetNativeDataPropertyByValuePure(JSContext* cx, JSObject* obj, Value* vp) {

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

@ -609,9 +609,6 @@ skip script test262/built-ins/RegExp/named-groups/non-unicode-property-names-val
# https://bugzilla.mozilla.org/show_bug.cgi?id=1761989
skip script test262/built-ins/TypedArrayConstructors/ctors/no-species.js
# https://bugzilla.mozilla.org/show_bug.cgi?id=1763605
skip script test262/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js
# https://bugzilla.mozilla.org/show_bug.cgi?id=1763606
skip script test262/built-ins/TypedArray/prototype/sort/sort-tonumber.js

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

@ -119,7 +119,7 @@ if (typeof detachArrayBuffer === "function") {
}
}
// Test a TypeError is thrown when the typed array is detached and
// Test no TypeError is thrown when the typed array is detached and
// srcLength > 0.
for (let {typedArray, buffer} of createTypedArrays()) {
let source = {
@ -130,8 +130,11 @@ if (typeof detachArrayBuffer === "function") {
}
}
};
let err = typedArray.length === 0 ? RangeError : TypeError;
assertThrowsInstanceOf(() => typedArray.set(source), err);
if (typedArray.length === 0) {
assertThrowsInstanceOf(() => typedArray.set(source), RangeError);
} else {
typedArray.set(source);
}
}
// Same as above, but with side-effect when executing Get(src, "0").
@ -182,13 +185,17 @@ if (typeof detachArrayBuffer === "function") {
}
}
});
let err = typedArray.length === 0 ? RangeError : TypeError;
assertThrowsInstanceOf(() => typedArray.set(source), err);
if (typedArray.length === 0) {
assertThrowsInstanceOf(() => typedArray.set(source), RangeError);
} else {
typedArray.set(source);
}
}
// Side-effects when getting the source elements detach the buffer. Also
// ensure other elements aren't accessed.
// ensure other elements are accessed.
for (let {typedArray, buffer} of createTypedArrays()) {
let accessed = false;
let source = Object.defineProperties([], {
0: {
get() {
@ -198,12 +205,19 @@ if (typeof detachArrayBuffer === "function") {
},
1: {
get() {
throw new Error("Unexpected access");
assertEq(accessed, false);
accessed = true;
return 2;
}
}
});
let err = typedArray.length <= 1 ? RangeError : TypeError;
assertThrowsInstanceOf(() => typedArray.set(source), err);
if (typedArray.length <= 1) {
assertThrowsInstanceOf(() => typedArray.set(source), RangeError);
} else {
assertEq(accessed, false);
typedArray.set(source);
assertEq(accessed, true);
}
}
// Side-effects when converting the source elements detach the buffer.
@ -214,13 +228,17 @@ if (typeof detachArrayBuffer === "function") {
return 1;
}
}];
let err = typedArray.length === 0 ? RangeError : TypeError;
assertThrowsInstanceOf(() => typedArray.set(source), err);
if (typedArray.length === 0) {
assertThrowsInstanceOf(() => typedArray.set(source), RangeError);
} else {
typedArray.set(source);
}
}
// Side-effects when converting the source elements detach the buffer. Also
// ensure other elements aren't accessed.
// ensure other elements are accessed.
for (let {typedArray, buffer} of createTypedArrays()) {
let accessed = false;
let source = [{
valueOf() {
detachArrayBuffer(buffer);
@ -228,11 +246,18 @@ if (typeof detachArrayBuffer === "function") {
}
}, {
valueOf() {
throw new Error("Unexpected access");
assertEq(accessed, false);
accessed = true;
return 2;
}
}];
let err = typedArray.length <= 1 ? RangeError : TypeError;
assertThrowsInstanceOf(() => typedArray.set(source), err);
if (typedArray.length <= 1) {
assertThrowsInstanceOf(() => typedArray.set(source), RangeError);
} else {
assertEq(accessed, false);
typedArray.set(source);
assertEq(accessed, true);
}
}
}

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

@ -44,17 +44,7 @@ ctors.forEach(function(TypedArray) {
}
};
var passed = false;
try
{
ta.set(arraylike, 0x1234);
}
catch (e)
{
passed = true;
}
assertEq(passed, true);
ta.set(arraylike, 0x1234);
});
/******************************************************************************/

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

@ -35,7 +35,7 @@ Object.defineProperty(src, 4, {
}
});
assertThrowsInstanceOf(() => a.set(src), TypeError);
a.set(src);
/******************************************************************************/

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

@ -15,6 +15,7 @@
#include "jsnum.h"
#include "gc/MaybeRooted.h"
#include "vm/JSContext.h"
#include "vm/Runtime.h"
#include "vm/StringType.h"
@ -34,42 +35,10 @@ MOZ_ALWAYS_INLINE jsid AtomToId(JSAtom* atom) {
// Use the NameToId method instead!
inline jsid AtomToId(PropertyName* name) = delete;
MOZ_ALWAYS_INLINE bool ValueToIntId(const Value& v, jsid* id) {
int32_t i;
if (v.isInt32()) {
i = v.toInt32();
} else if (!v.isDouble() || !mozilla::NumberEqualsInt32(v.toDouble(), &i)) {
return false;
}
if (!PropertyKey::fitsInInt(i)) {
return false;
}
*id = PropertyKey::Int(i);
return true;
}
inline bool ValueToIdPure(const Value& v, jsid* id) {
if (v.isString()) {
if (v.toString()->isAtom()) {
*id = AtomToId(&v.toString()->asAtom());
return true;
}
return false;
}
if (ValueToIntId(v, id)) {
return true;
}
if (v.isSymbol()) {
*id = PropertyKey::Symbol(v.toSymbol());
return true;
}
return false;
}
template <AllowGC allowGC>
extern bool PrimitiveValueToIdSlow(
JSContext* cx, typename MaybeRooted<JS::Value, allowGC>::HandleType v,
typename MaybeRooted<jsid, allowGC>::MutableHandleType idp);
template <AllowGC allowGC>
inline bool PrimitiveValueToId(
@ -79,28 +48,33 @@ inline bool PrimitiveValueToId(
MOZ_ASSERT(v.isPrimitive());
if (v.isString()) {
JSAtom* atom;
if (v.toString()->isAtom()) {
idp.set(AtomToId(&v.toString()->asAtom()));
return true;
}
} else {
if (ValueToIntId(v, idp.address())) {
return true;
}
if (v.isSymbol()) {
idp.set(PropertyKey::Symbol(v.toSymbol()));
return true;
atom = &v.toString()->asAtom();
} else {
atom = AtomizeString(cx, v.toString());
if (!atom) {
if constexpr (!allowGC) {
cx->recoverFromOutOfMemory();
}
return false;
}
}
idp.set(AtomToId(atom));
return true;
}
JSAtom* atom = ToAtom<allowGC>(cx, v);
if (!atom) {
return false;
if (v.isInt32()) {
if (PropertyKey::fitsInInt(v.toInt32())) {
idp.set(PropertyKey::Int(v.toInt32()));
return true;
}
} else if (v.isSymbol()) {
idp.set(PropertyKey::Symbol(v.toSymbol()));
return true;
}
idp.set(AtomToId(atom));
return true;
return PrimitiveValueToIdSlow<allowGC>(cx, v, idp);
}
/*

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

@ -955,6 +955,60 @@ bool js::IndexToIdSlow(JSContext* cx, uint32_t index, MutableHandleId idp) {
return true;
}
template <AllowGC allowGC>
static MOZ_ALWAYS_INLINE JSAtom* PrimitiveToAtom(JSContext* cx,
const Value& v) {
MOZ_ASSERT(v.isPrimitive());
switch (v.type()) {
case ValueType::String: {
JSAtom* atom = AtomizeString(cx, v.toString());
if (!allowGC && !atom) {
cx->recoverFromOutOfMemory();
}
return atom;
}
case ValueType::Int32: {
JSAtom* atom = Int32ToAtom(cx, v.toInt32());
if (!allowGC && !atom) {
cx->recoverFromOutOfMemory();
}
return atom;
}
case ValueType::Double: {
JSAtom* atom = NumberToAtom(cx, v.toDouble());
if (!allowGC && !atom) {
cx->recoverFromOutOfMemory();
}
return atom;
}
case ValueType::Boolean:
return v.toBoolean() ? cx->names().true_ : cx->names().false_;
case ValueType::Null:
return cx->names().null;
case ValueType::Undefined:
return cx->names().undefined;
case ValueType::Symbol:
MOZ_ASSERT(!cx->isHelperThreadContext());
if constexpr (allowGC) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_SYMBOL_TO_STRING);
}
return nullptr;
case ValueType::BigInt: {
RootedBigInt i(cx, v.toBigInt());
return BigIntToAtom<allowGC>(cx, i);
}
#ifdef ENABLE_RECORD_TUPLE
case ValueType::ExtendedPrimitive:
#endif
case ValueType::Object:
case ValueType::Magic:
case ValueType::PrivateGCThing:
break;
}
MOZ_CRASH("Unexpected type");
}
template <AllowGC allowGC>
static JSAtom* ToAtomSlow(
JSContext* cx, typename MaybeRooted<Value, allowGC>::HandleType arg) {
@ -973,47 +1027,7 @@ static JSAtom* ToAtomSlow(
v = v2;
}
if (v.isString()) {
JSAtom* atom = AtomizeString(cx, v.toString());
if (!allowGC && !atom) {
cx->recoverFromOutOfMemory();
}
return atom;
}
if (v.isInt32()) {
JSAtom* atom = Int32ToAtom(cx, v.toInt32());
if (!allowGC && !atom) {
cx->recoverFromOutOfMemory();
}
return atom;
}
if (v.isDouble()) {
JSAtom* atom = NumberToAtom(cx, v.toDouble());
if (!allowGC && !atom) {
cx->recoverFromOutOfMemory();
}
return atom;
}
if (v.isBoolean()) {
return v.toBoolean() ? cx->names().true_ : cx->names().false_;
}
if (v.isNull()) {
return cx->names().null;
}
if (v.isSymbol()) {
MOZ_ASSERT(!cx->isHelperThreadContext());
if (allowGC) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_SYMBOL_TO_STRING);
}
return nullptr;
}
if (v.isBigInt()) {
RootedBigInt i(cx, v.toBigInt());
return BigIntToAtom<allowGC>(cx, i);
}
MOZ_ASSERT(v.isUndefined());
return cx->names().undefined;
return PrimitiveToAtom<allowGC>(cx, v);
}
template <AllowGC allowGC>
@ -1037,9 +1051,38 @@ JSAtom* js::ToAtom(JSContext* cx,
}
template JSAtom* js::ToAtom<CanGC>(JSContext* cx, HandleValue v);
template JSAtom* js::ToAtom<NoGC>(JSContext* cx, const Value& v);
template <AllowGC allowGC>
bool js::PrimitiveValueToIdSlow(
JSContext* cx, typename MaybeRooted<Value, allowGC>::HandleType v,
typename MaybeRooted<jsid, allowGC>::MutableHandleType idp) {
MOZ_ASSERT(v.isPrimitive());
MOZ_ASSERT(!v.isString());
MOZ_ASSERT(!v.isSymbol());
MOZ_ASSERT_IF(v.isInt32(), !PropertyKey::fitsInInt(v.toInt32()));
int32_t i;
if (v.isDouble() && mozilla::NumberEqualsInt32(v.toDouble(), &i) &&
PropertyKey::fitsInInt(i)) {
idp.set(PropertyKey::Int(i));
return true;
}
JSAtom* atom = PrimitiveToAtom<allowGC>(cx, v);
if (!atom) {
return false;
}
idp.set(AtomToId(atom));
return true;
}
template bool js::PrimitiveValueToIdSlow<CanGC>(JSContext* cx, HandleValue v,
MutableHandleId idp);
template bool js::PrimitiveValueToIdSlow<NoGC>(JSContext* cx, const Value& v,
FakeMutableHandle<jsid> idp);
#ifdef ENABLE_RECORD_TUPLE
bool js::EnsureAtomized(JSContext* cx, MutableHandleValue v, bool* updated) {
if (v.isString()) {

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

@ -412,12 +412,15 @@ class ElementSpecific {
size_t offset = 0) {
MOZ_ASSERT(target->type() == TypeIDOfType<T>::id,
"target type and NativeType must match");
MOZ_ASSERT(!target->hasDetachedBuffer(), "target isn't detached");
MOZ_ASSERT(!source->is<TypedArrayObject>(),
"use setFromTypedArray instead of this method");
MOZ_ASSERT_IF(target->hasDetachedBuffer(), target->length() == 0);
MOZ_ASSERT_IF(!target->hasDetachedBuffer(), offset <= target->length());
MOZ_ASSERT_IF(!target->hasDetachedBuffer(),
len <= target->length() - offset);
size_t i = 0;
if (source->is<NativeObject>()) {
if (source->is<NativeObject>() && !target->hasDetachedBuffer()) {
// Attempt fast-path infallible conversion of dense elements up to
// the first potentially side-effectful lookup or conversion.
size_t bound = std::min<size_t>(
@ -459,11 +462,14 @@ class ElementSpecific {
return false;
}
len = std::min<size_t>(len, target->length());
if (i >= len) {
break;
// Ignore out-of-bounds writes, but still execute getElement/valueToNative
// because of observable side-effects.
if (offset + i >= target->length()) {
continue;
}
MOZ_ASSERT(!target->hasDetachedBuffer());
// Compute every iteration in case getElement/valueToNative
// detaches the underlying array buffer or GC moves the data.
SharedMem<T*> dest =

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

@ -1626,41 +1626,162 @@ static inline bool SetFromNonTypedArray(JSContext* cx,
cx, target, source, len, offset);
}
// ES2017 draft rev c57ef95c45a371f9c9485bb1c3881dbdc04524a2
// 22.2.3.23 %TypedArray%.prototype.set ( overloaded [ , offset ] )
// 22.2.3.23.1 %TypedArray%.prototype.set ( array [ , offset ] )
// 22.2.3.23.2 %TypedArray%.prototype.set( typedArray [ , offset ] )
// ES2023 draft rev 22cc56ab08fcab92a865978c0aa5c6f1d8ce250f
// 23.2.3.24.1 SetTypedArrayFromTypedArray ( target, targetOffset, source )
static bool SetTypedArrayFromTypedArray(JSContext* cx,
Handle<TypedArrayObject*> target,
double targetOffset,
Handle<TypedArrayObject*> source) {
// WARNING: |source| may be an unwrapped typed array from a different
// compartment. Proceed with caution!
MOZ_ASSERT(targetOffset >= 0);
// Steps 1-2. (Performed in caller.)
MOZ_ASSERT(!target->hasDetachedBuffer());
// Steps 4-5.
if (source->hasDetachedBuffer()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_TYPED_ARRAY_DETACHED);
return false;
}
// Step 3 (Reordered).
size_t targetLength = target->length();
// Steps 13-14 (Split into two checks to provide better error messages).
if (targetOffset > targetLength) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
return false;
}
// Step 14 (Cont'd).
size_t offset = size_t(targetOffset);
if (source->length() > targetLength - offset) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_SOURCE_ARRAY_TOO_LONG);
return false;
}
// Step 15.
if (Scalar::isBigIntType(target->type()) !=
Scalar::isBigIntType(source->type())) {
JS_ReportErrorNumberASCII(
cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_NOT_COMPATIBLE,
source->getClass()->name, target->getClass()->name);
return false;
}
// Steps 6-12, 16-24.
switch (target->type()) {
#define SET_FROM_TYPED_ARRAY(_, T, N) \
case Scalar::N: \
if (!SetFromTypedArray<T>(target, source, offset)) return false; \
break;
JS_FOR_EACH_TYPED_ARRAY(SET_FROM_TYPED_ARRAY)
#undef SET_FROM_TYPED_ARRAY
default:
MOZ_CRASH("Unsupported TypedArray type");
}
return true;
}
// ES2023 draft rev 22cc56ab08fcab92a865978c0aa5c6f1d8ce250f
// 23.2.3.24.1 SetTypedArrayFromArrayLike ( target, targetOffset, source )
static bool SetTypedArrayFromArrayLike(JSContext* cx,
Handle<TypedArrayObject*> target,
double targetOffset, HandleObject src) {
MOZ_ASSERT(targetOffset >= 0);
// Steps 1-2. (Performed in caller.)
MOZ_ASSERT(!target->hasDetachedBuffer());
// Step 3.
// We can't reorder this step because side-effects in step 5 can detach the
// underlying array buffer from the typed array.
size_t targetLength = target->length();
// Step 4. (Performed in caller.)
// Step 5.
uint64_t srcLength;
if (!GetLengthProperty(cx, src, &srcLength)) {
return false;
}
// Steps 6-7 (Split into two checks to provide better error messages).
if (targetOffset > targetLength) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
return false;
}
// Step 7 (Cont'd).
size_t offset = size_t(targetOffset);
if (srcLength > targetLength - offset) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_SOURCE_ARRAY_TOO_LONG);
return false;
}
MOZ_ASSERT(srcLength <= targetLength);
// Steps 8-9.
if (srcLength > 0) {
switch (target->type()) {
#define SET_FROM_NON_TYPED_ARRAY(_, T, N) \
case Scalar::N: \
if (!SetFromNonTypedArray<T>(cx, target, src, srcLength, offset)) \
return false; \
break;
JS_FOR_EACH_TYPED_ARRAY(SET_FROM_NON_TYPED_ARRAY)
#undef SET_FROM_NON_TYPED_ARRAY
default:
MOZ_CRASH("Unsupported TypedArray type");
}
}
// Step 10.
return true;
}
// ES2023 draft rev 22cc56ab08fcab92a865978c0aa5c6f1d8ce250f
// 23.2.3.24 %TypedArray%.prototype.set ( source [ , offset ] )
// 23.2.3.24.1 SetTypedArrayFromTypedArray ( target, targetOffset, source )
// 23.2.3.24.2 SetTypedArrayFromArrayLike ( target, targetOffset, source )
/* static */
bool TypedArrayObject::set_impl(JSContext* cx, const CallArgs& args) {
MOZ_ASSERT(TypedArrayObject::is(args.thisv()));
// Steps 1-5 (Validation performed as part of CallNonGenericMethod).
// Steps 1-3 (Validation performed as part of CallNonGenericMethod).
Rooted<TypedArrayObject*> target(
cx, &args.thisv().toObject().as<TypedArrayObject>());
// Steps 6-7.
// Steps 4-5.
double targetOffset = 0;
if (args.length() > 1) {
// Step 6.
// Step 4.
if (!ToInteger(cx, args[1], &targetOffset)) {
return false;
}
// Step 7.
// Step 5.
if (targetOffset < 0) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
return false;
}
}
// Steps 8-9.
// 23.2.3.24.1, steps 1-2.
// 23.2.3.24.2, steps 1-2.
if (target->hasDetachedBuffer()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_TYPED_ARRAY_DETACHED);
return false;
}
// 22.2.3.23.1, step 15. (22.2.3.23.2 only applies if args[0] is a typed
// 23.2.3.24.2, step 4. (23.2.3.24.1 only applies if args[0] is a typed
// array, so it doesn't make a difference there to apply ToObject here.)
RootedObject src(cx, ToObject(cx, args.get(0)));
if (!src) {
@ -1680,133 +1801,18 @@ bool TypedArrayObject::set_impl(JSContext* cx, const CallArgs& args) {
}
}
// Steps 6-7.
if (srcTypedArray) {
// Remaining steps of 22.2.3.23.2.
// WARNING: |srcTypedArray| may be an unwrapped typed array from a
// different compartment. Proceed with caution!
// Steps 11-12.
if (srcTypedArray->hasDetachedBuffer()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_TYPED_ARRAY_DETACHED);
if (!SetTypedArrayFromTypedArray(cx, target, targetOffset, srcTypedArray)) {
return false;
}
// Step 10 (Reordered).
size_t targetLength = target->length();
// Step 22 (Split into two checks to provide better error messages).
if (targetOffset > targetLength) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
return false;
}
// Step 22 (Cont'd).
size_t offset = size_t(targetOffset);
if (srcTypedArray->length() > targetLength - offset) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_SOURCE_ARRAY_TOO_LONG);
return false;
}
if (Scalar::isBigIntType(target->type()) !=
Scalar::isBigIntType(srcTypedArray->type())) {
JS_ReportErrorNumberASCII(
cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_NOT_COMPATIBLE,
srcTypedArray->getClass()->name, target->getClass()->name);
return false;
}
// Steps 13-21, 23-28.
switch (target->type()) {
#define SET_FROM_TYPED_ARRAY(_, T, N) \
case Scalar::N: \
if (!SetFromTypedArray<T>(target, srcTypedArray, offset)) return false; \
break;
JS_FOR_EACH_TYPED_ARRAY(SET_FROM_TYPED_ARRAY)
#undef SET_FROM_TYPED_ARRAY
default:
MOZ_CRASH("Unsupported TypedArray type");
}
} else {
// Remaining steps of 22.2.3.23.1.
// Step 10.
// We can't reorder this step because side-effects in step 16 can
// detach the underlying array buffer from the typed array.
size_t targetLength = target->length();
// Step 16.
uint64_t srcLength;
if (!GetLengthProperty(cx, src, &srcLength)) {
if (!SetTypedArrayFromArrayLike(cx, target, targetOffset, src)) {
return false;
}
// Step 17 (Split into two checks to provide better error messages).
if (targetOffset > targetLength) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
return false;
}
// Step 17 (Cont'd).
size_t offset = size_t(targetOffset);
if (srcLength > targetLength - offset) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_SOURCE_ARRAY_TOO_LONG);
return false;
}
MOZ_ASSERT(srcLength <= targetLength);
// Steps 11-14, 18-21.
if (srcLength > 0) {
// GetLengthProperty in step 16 can lead to the execution of user
// code which may detach the buffer. Handle this case here to
// ensure SetFromNonTypedArray is never called with a detached
// buffer. We still need to execute steps 21.a-b for their
// possible side-effects.
if (target->hasDetachedBuffer()) {
// Steps 21.a-b.
RootedValue v(cx);
if (!GetElement(cx, src, src, 0, &v)) {
return false;
}
if (!target->convertForSideEffect(cx, v)) {
return false;
}
// Step 21.c.
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_TYPED_ARRAY_DETACHED);
return false;
}
switch (target->type()) {
#define SET_FROM_NON_TYPED_ARRAY(_, T, N) \
case Scalar::N: \
if (!SetFromNonTypedArray<T>(cx, target, src, srcLength, offset)) \
return false; \
break;
JS_FOR_EACH_TYPED_ARRAY(SET_FROM_NON_TYPED_ARRAY)
#undef SET_FROM_NON_TYPED_ARRAY
default:
MOZ_CRASH("Unsupported TypedArray type");
}
// Step 21.c.
// SetFromNonTypedArray doesn't throw when the array buffer gets
// detached.
if (target->hasDetachedBuffer()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_TYPED_ARRAY_DETACHED);
return false;
}
}
}
// Step 29/22.
// Step 8.
args.rval().setUndefined();
return true;
}

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

@ -1493,12 +1493,14 @@ nsresult nsMathMLChar::StretchInternal(
AutoTArray<nsCString, 16> mathFallbacks;
nsAutoCString value;
gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
pfl->Lock();
if (pfl->GetFontPrefs()->LookupName("serif.x-math"_ns, value)) {
gfxFontUtils::ParseFontList(value, mathFallbacks);
}
if (pfl->GetFontPrefs()->LookupNameList("serif.x-math"_ns, value)) {
gfxFontUtils::ParseFontList(value, mathFallbacks);
}
pfl->Unlock();
InsertMathFallbacks(font.family.families, mathFallbacks);
#ifdef NOISY_SEARCH

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

@ -0,0 +1,9 @@
<!doctype html>
<style>
input { height: 4em; color: GrayText }
</style>
<input value="Autofill">
<script>
let input = SpecialPowers.wrap(document.querySelector("input"));
SpecialPowers.wrap(window).windowUtils.addManuallyManagedState(input, "autofill");
</script>

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

@ -0,0 +1,12 @@
<!doctype html>
<style>
input { height: 4em }
</style>
<input value="Autofill">
<script>
let input = SpecialPowers.wrap(document.querySelector("input"));
SpecialPowers.Cc["@mozilla.org/satchel/form-fill-controller;1"].getService(SpecialPowers.Ci.nsIFormFillController).markAsAutofillField(input);
input.getBoundingClientRect(); // previewValue setter depends on the reframe posted by markAsAutofillField() having being processed...
input.previewValue = "Autofill";
SpecialPowers.wrap(window).windowUtils.addManuallyManagedState(input, "-moz-autofill-preview");
</script>

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

@ -17,6 +17,7 @@ fuzzy(0-1,0-500) needs-focus == select.html select-ref.html
!= autofill-preview.html autofill-preview-blank.html
!= autofill.html autofill-preview.html
== autofill-prefilled-value.html autofill-preview.html
== autofill-preview-line-height.html autofill-line-height.html
== pseudo-class-lock.html pseudo-class-lock-ref.html

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

@ -102,13 +102,6 @@ input {
}
}
input::-moz-text-control-editing-root,
input::placeholder {
word-wrap: normal;
/* Make the line-height equal to the available height */
line-height: -moz-block-height !important;
}
textarea {
display: inline-block;
appearance: auto;
@ -161,41 +154,6 @@ textarea > scrollbar {
visibility: hidden;
}
::-moz-text-control-preview {
overflow: hidden;
font-family: system-ui;
}
:not(:-moz-autofill-preview)::-moz-text-control-editing-root,
:placeholder-shown:not(:autofill)::placeholder,
:autofill::-moz-text-control-preview {
visibility: inherit;
}
input::-moz-text-control-editing-root,
input::placeholder,
input::-moz-text-control-preview {
white-space: pre;
}
input[type=password]::-moz-text-control-editing-root,
input[type=password]::-moz-text-control-preview {
/*
* In password fields, any character should be put same direction. Otherwise,
* caret position at typing tells everybody whether the character is an RTL
* or an LTR character. Unfortunately, this makes odd rendering when bidi
* text is unmasked.
*/
unicode-bidi: bidi-override;
}
textarea::-moz-text-control-editing-root {
scroll-behavior: inherit;
overscroll-behavior: inherit;
/* StyleAdjuster makes sure that the overflow value ends up being scrollable */
overflow: inherit;
}
::placeholder,
::-moz-text-control-preview {
/*
@ -219,10 +177,47 @@ textarea::-moz-text-control-editing-root {
user-select: none;
}
::-moz-text-control-preview {
font-family: system-ui;
}
::placeholder {
opacity: 0.54;
}
:not(:-moz-autofill-preview)::-moz-text-control-editing-root,
:placeholder-shown:not(:autofill)::placeholder,
:autofill::-moz-text-control-preview {
visibility: inherit;
}
input::placeholder,
input::-moz-text-control-editing-root,
input::-moz-text-control-preview {
word-wrap: normal;
white-space: pre;
/* Make the line-height equal to the available height */
line-height: -moz-block-height !important;
}
input[type=password]::-moz-text-control-editing-root,
input[type=password]::-moz-text-control-preview {
/*
* In password fields, any character should be put same direction. Otherwise,
* caret position at typing tells everybody whether the character is an RTL
* or an LTR character. Unfortunately, this makes odd rendering when bidi
* text is unmasked.
*/
unicode-bidi: bidi-override;
}
textarea::-moz-text-control-editing-root {
scroll-behavior: inherit;
overscroll-behavior: inherit;
/* StyleAdjuster makes sure that the overflow value ends up being scrollable */
overflow: inherit;
}
input:read-write,
textarea:read-write {
-moz-user-modify: read-write !important;

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

@ -145,14 +145,14 @@ class BrowsingContextModule extends Module {
/**
* Returns a tree of all browsing contexts that are descendents of the
* given context, or all top-level contexts when no parent is provided.
* given context, or all top-level contexts when no root is provided.
*
* @param {Object=} options
* @param {number=} maxDepth
* Depth of the browsing context tree to traverse. If not specified
* the whole tree is returned.
* @param {string=} parent
* Id of the parent browsing context.
* @param {string=} root
* Id of the root browsing context.
*
* @returns {BrowsingContextGetTreeResult}
* Tree of browsing context information.
@ -160,7 +160,7 @@ class BrowsingContextModule extends Module {
* If the browsing context cannot be found.
*/
getTree(options = {}) {
const { maxDepth = null, parent: parentId = null } = options;
const { maxDepth = null, root: rootId = null } = options;
if (maxDepth !== null) {
assert.positiveInteger(
@ -170,16 +170,11 @@ class BrowsingContextModule extends Module {
}
let contexts;
if (parentId !== null) {
// With a parent id specified return the context info for itself
if (rootId !== null) {
// With a root id specified return the context info for itself
// and the full tree.
assert.string(
parentId,
`Expected "parent" to be a string, got ${parentId}`
);
contexts = [this.#getBrowsingContext(parentId)];
assert.string(rootId, `Expected "root" to be a string, got ${rootId}`);
contexts = [this.#getBrowsingContext(rootId)];
} else {
// Return all top-level browsing contexts.
contexts = TabManager.browsers.map(browser => browser.browsingContext);

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

@ -372,17 +372,11 @@ class SendTab {
}
async _decrypt(ciphertext) {
let sendTabKeys = await this._getPersistedSendTabKeys();
if (!sendTabKeys) {
// If we lost the user's send tab keys for any reason,
// `generateAndPersistEncryptedSendTabKeys` will regenerate the send tab keys,
// persist them, then persist an encrypted bundle of the keys.
// It should be impossible for us to hit this for new devices
// this was added to recover users who hit Bug 1752609
await this._generateAndPersistEncryptedSendTabKey();
sendTabKeys = await this._getPersistedSendTabKeys();
}
let { privateKey, publicKey, authSecret } = sendTabKeys;
let {
privateKey,
publicKey,
authSecret,
} = await this._getPersistedSendTabKeys();
publicKey = urlsafeBase64Decode(publicKey);
authSecret = urlsafeBase64Decode(authSecret);
ciphertext = new Uint8Array(urlsafeBase64Decode(ciphertext));
@ -468,7 +462,8 @@ class SendTab {
async getEncryptedSendTabKeys() {
let encryptedSendTabKeys = await this._getPersistedEncryptedSendTabKey();
if (!encryptedSendTabKeys) {
const sendTabKeys = await this._getPersistedSendTabKeys();
if (!encryptedSendTabKeys || !sendTabKeys) {
log.info("Generating and persisting encrypted sendtab keys");
// `_generateAndPersistEncryptedKeys` requires the sync key
// which cannot be accessed if the login manager is locked

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

@ -243,24 +243,8 @@ class FxAccountsDevice {
log.info(
`Got new device list: ${devices.map(d => d.id).join(", ")}`
);
// Check if our push registration previously succeeded and is still
// good (although background device registration means it's possible
// we'll be fetching the device list before we've actually
// registered ourself!)
// (For a missing subscription we check for an explicit 'null' -
// both to help tests and as a safety valve - missing might mean
// "no push available" for self-hosters or similar?)
const ourDevice = devices.find(device => device.isCurrentDevice);
if (
ourDevice &&
(ourDevice.pushCallback === null || ourDevice.pushEndpointExpired)
) {
log.warn(`Our push endpoint needs resubscription`);
await this._fxai.fxaPushService.unsubscribe();
await this._registerOrUpdateDevice(currentState, accountData);
// and there's a reasonable chance there are commands waiting.
await this._fxai.commands.pollDeviceCommands();
}
await this._refreshRemoteDevice(currentState, accountData, devices);
return devices;
}
);
@ -279,6 +263,33 @@ class FxAccountsDevice {
return this._fetchAndCacheDeviceListPromise;
}
async _refreshRemoteDevice(currentState, accountData, remoteDevices) {
// Check if our push registration previously succeeded and is still
// good (although background device registration means it's possible
// we'll be fetching the device list before we've actually
// registered ourself!)
// (For a missing subscription we check for an explicit 'null' -
// both to help tests and as a safety valve - missing might mean
// "no push available" for self-hosters or similar?)
const ourDevice = remoteDevices.find(device => device.isCurrentDevice);
if (
ourDevice &&
(ourDevice.pushCallback === null || ourDevice.pushEndpointExpired)
) {
log.warn(`Our push endpoint needs resubscription`);
await this._fxai.fxaPushService.unsubscribe();
await this._registerOrUpdateDevice(currentState, accountData);
// and there's a reasonable chance there are commands waiting.
await this._fxai.commands.pollDeviceCommands();
} else if (
ourDevice &&
(await this._checkRemoteCommandsUpdateNeeded(ourDevice.availableCommands))
) {
log.warn(`Our commands need to be updated on the server`);
await this._registerOrUpdateDevice(currentState, accountData);
}
}
async updateDeviceRegistration() {
return this._withCurrentAccountState(async currentState => {
const signedInUser = await currentState.getUserAccountData([
@ -355,6 +366,35 @@ class FxAccountsDevice {
);
}
async _checkRemoteCommandsUpdateNeeded(remoteAvailableCommands) {
if (!remoteAvailableCommands) {
return true;
}
const remoteAvailableCommandsKeys = Object.keys(
remoteAvailableCommands
).sort();
const localAvailableCommands = await this._fxai.commands.availableCommands();
const localAvailableCommandsKeys = Object.keys(
localAvailableCommands
).sort();
if (
!CommonUtils.arrayEqual(
localAvailableCommandsKeys,
remoteAvailableCommandsKeys
)
) {
return true;
}
for (const key of localAvailableCommandsKeys) {
if (remoteAvailableCommands[key] !== localAvailableCommands[key]) {
return true;
}
}
return false;
}
async _updateDeviceRegistrationIfNecessary(currentState) {
let data = await currentState.getUserAccountData([
"sessionToken",

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

@ -211,6 +211,7 @@ function MockFxAccounts(credentials = null) {
observerPreloads: [],
device: {
_registerOrUpdateDevice() {},
_checkRemoteCommandsUpdateNeeded: async () => false,
},
profile: {
getProfile() {
@ -245,10 +246,12 @@ async function MakeFxAccounts({ internal = {}, credentials } = {}) {
if (internal.device) {
if (!internal.device._registerOrUpdateDevice) {
internal.device._registerOrUpdateDevice = () => Promise.resolve();
internal.device._checkRemoteCommandsUpdateNeeded = async () => false;
}
} else {
internal.device = {
_registerOrUpdateDevice() {},
_checkRemoteCommandsUpdateNeeded: async () => false,
};
}
if (!internal.observerPreloads) {

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

@ -162,6 +162,7 @@ async function MockFxAccounts(credentials, device = {}) {
},
device: {
DEVICE_REGISTRATION_VERSION,
_checkRemoteCommandsUpdateNeeded: async () => false,
},
VERIFICATION_POLL_TIMEOUT_INITIAL: 1,
});
@ -817,6 +818,7 @@ add_task(async function test_refreshDeviceList() {
fxaPushService: null,
};
let device = new FxAccountsDevice(fxai);
device._checkRemoteCommandsUpdateNeeded = async () => false;
Assert.equal(
device.recentDeviceList,
@ -908,6 +910,56 @@ add_task(async function test_refreshDeviceList() {
);
});
add_task(async function test_checking_remote_availableCommands_mismatch() {
const credentials = getTestUser("baz");
credentials.verified = true;
const fxa = await MockFxAccounts(credentials);
fxa.device._checkRemoteCommandsUpdateNeeded =
FxAccountsDevice.prototype._checkRemoteCommandsUpdateNeeded;
fxa.commands.availableCommands = async () => {
return {
"https://identity.mozilla.com/cmd/open-uri": "local-keys",
};
};
const ourDevice = {
isCurrentDevice: true,
availableCommands: {
"https://identity.mozilla.com/cmd/open-uri": "remote-keys",
},
};
Assert.ok(
await fxa.device._checkRemoteCommandsUpdateNeeded(
ourDevice.availableCommands
)
);
});
add_task(async function test_checking_remote_availableCommands_match() {
const credentials = getTestUser("baz");
credentials.verified = true;
const fxa = await MockFxAccounts(credentials);
fxa.device._checkRemoteCommandsUpdateNeeded =
FxAccountsDevice.prototype._checkRemoteCommandsUpdateNeeded;
fxa.commands.availableCommands = async () => {
return {
"https://identity.mozilla.com/cmd/open-uri": "local-keys",
};
};
const ourDevice = {
isCurrentDevice: true,
availableCommands: {
"https://identity.mozilla.com/cmd/open-uri": "local-keys",
},
};
Assert.ok(
!(await fxa.device._checkRemoteCommandsUpdateNeeded(
ourDevice.availableCommands
))
);
});
function expandHex(two_hex) {
// Return a 64-character hex string, encoding 32 identical bytes.
let eight_hex = two_hex + two_hex + two_hex + two_hex;

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

@ -639,9 +639,9 @@ add_task(async function test_send_tab_keys_regenerated_if_lost() {
const accountState = {
data: {
// Since the device object has no
// sendTabKeys, when we _decrypt,
// we will attempt to regenerate the
// keys.
// sendTabKeys, it will recover
// when we attempt to get the
// encryptedSendTabKeys
device: {
lastCommandIndex: 10,
},
@ -664,39 +664,12 @@ add_task(async function test_send_tab_keys_regenerated_if_lost() {
},
telemetry: new TelemetryMock(),
};
const sendTab = new SendTab(commands, fxAccounts);
sendTab._encrypt = (bytes, device) => {
return bytes;
};
let generateEncryptedKeysCalled = false;
sendTab._generateAndPersistEncryptedSendTabKey = async () => {
generateEncryptedKeysCalled = true;
};
sendTab._fxai = fxAccounts;
const tab = { title: "tab title", url: "http://example.com" };
const to = [{ id: "devid", name: "The Device" }];
const reason = "push";
await sendTab.send(to, tab);
Assert.equal(commands._invokes.length, 1);
for (let { cmd, device, payload } of commands._invokes) {
Assert.equal(cmd, COMMAND_SENDTAB);
sendTab._fxai = fxAccounts;
try {
await sendTab.handle(device.id, payload, reason);
} catch {
// The `handle` function will throw an error
// since we are not mocking the `_decrypt`
// function. This is intentional, since
// we want to capture that `_decrypt` will
// call `_generateEncryptedSendTabKeys` if
// it fails to retrieve the keys.
// Receiving a send tab is covered
// in the above test_sendtab_receive test.
}
}
await sendTab.getEncryptedSendTabKeys();
Assert.ok(generateEncryptedKeysCalled);
});
@ -712,8 +685,10 @@ add_task(async function test_send_tab_keys_are_not_regenerated_if_not_lost() {
const accountState = {
data: {
// Since the device object has
// sendTabKeys, when we _decrypt,
// we will not try to regenerate them
// sendTabKeys, it will not try
// to regenerate them
// when we attempt to get the
// encryptedSendTabKeys
device: {
lastCommandIndex: 10,
sendTabKeys: "keys",
@ -737,38 +712,11 @@ add_task(async function test_send_tab_keys_are_not_regenerated_if_not_lost() {
},
telemetry: new TelemetryMock(),
};
const sendTab = new SendTab(commands, fxAccounts);
sendTab._encrypt = (bytes, device) => {
return bytes;
};
let generateEncryptedKeysCalled = false;
sendTab._generateAndPersistEncryptedSendTabKey = async () => {
generateEncryptedKeysCalled = true;
};
sendTab._fxai = fxAccounts;
const tab = { title: "tab title", url: "http://example.com" };
const to = [{ id: "devid", name: "The Device" }];
const reason = "push";
await sendTab.send(to, tab);
Assert.equal(commands._invokes.length, 1);
for (let { cmd, device, payload } of commands._invokes) {
Assert.equal(cmd, COMMAND_SENDTAB);
sendTab._fxai = fxAccounts;
try {
await sendTab.handle(device.id, payload, reason);
} catch {
// The `handle` function will throw an error
// since we are not mocking the `_decrypt`
// function. This is intentional, since
// we want to capture that `_decrypt` will
// not call `_generateEncryptedSendTabKeys` if
// it succeeds to retrieve the keys.
// Receiving a send tab is covered
// in the above test_sendtab_receive test.
}
}
await sendTab.getEncryptedSendTabKeys();
Assert.ok(!generateEncryptedKeysCalled);
});

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

@ -13,6 +13,8 @@ const { PREF_ACCOUNT_ROOT } = ChromeUtils.import(
_("Misc tests for FxAccounts.device");
fxAccounts.device._checkRemoteCommandsUpdateNeeded = async () => false;
add_test(function test_default_device_name() {
// Note that head_helpers overrides getDefaultLocalName - this test is
// really just to ensure the actual implementation is sane - we can't

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

@ -92,9 +92,10 @@ XPCOMUtils.defineLazyGetter(this, "SyncPingSchema", function() {
});
XPCOMUtils.defineLazyGetter(this, "SyncPingValidator", function() {
let { Ajv } = ChromeUtils.import("resource://testing-common/ajv-6.12.6.js");
let ajv = new Ajv({ async: "co*" });
return ajv.compile(SyncPingSchema);
const { JsonSchema } = ChromeUtils.import(
"resource://gre/modules/JsonSchema.jsm"
);
return new JsonSchema.Validator(SyncPingSchema);
});
// This is needed for loadAddonTestFunctions().
@ -283,13 +284,18 @@ function get_sync_test_telemetry() {
}
function assert_valid_ping(record) {
// Our JSON validator does not like `undefined` values, even though they will
// be skipped when we serialize to JSON.
record = JSON.parse(JSON.stringify(record));
// This is called as the test harness tears down due to shutdown. This
// will typically have no recorded syncs, and the validator complains about
// it. So ignore such records (but only ignore when *both* shutdown and
// no Syncs - either of them not being true might be an actual problem)
if (record && (record.why != "shutdown" || record.syncs.length != 0)) {
if (!SyncPingValidator(record)) {
if (SyncPingValidator.errors.length) {
const result = SyncPingValidator.validate(record);
if (!result.valid) {
if (result.errors.length) {
// validation failed - using a simple |deepEqual([], errors)| tends to
// truncate the validation errors in the output and doesn't show that
// the ping actually was - so be helpful.
@ -297,7 +303,7 @@ function assert_valid_ping(record) {
info("the ping data is: " + JSON.stringify(record, undefined, 2));
info(
"the validation failures: " +
JSON.stringify(SyncPingValidator.errors, undefined, 2)
JSON.stringify(result.errors, undefined, 2)
);
ok(
false,

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

@ -193,6 +193,78 @@ jobs:
- name: public/condprof
path: archive
type: directory
android-hw-a51-11-0-arm7-geckoview:
worker-type: t-bitbar-gw-perf-a51
description: Creates or update conditioned profiles on GeckoView+A51
run-on-projects: [] # bug 1765348
treeherder:
symbol: condprof(geckoview)
platform: android-hw-a51-11-0-arm7/opt
index:
product: firefox
job-name: condprof-a51-geckoview_example
dependencies:
build: build-android-arm-shippable/opt
fetches:
build:
- artifact: en-US/target.condprof.tests.tar.gz
- artifact: geckoview_example.apk
extract: false
toolchain:
- linux64-geckodriver
run:
run-as-root: true
command: >-
adb install -r $MOZ_FETCHES_DIR/geckoview_example.apk &&
python3 virtualenv/virtualenv.py . &&
bin/python3 condprof/main.py
--force-new
--geckodriver ${MOZ_FETCHES_DIR}/geckodriver
--device-name a51
--firefox org.mozilla.geckoview_example
--scenario settled
../../archive
worker:
artifacts:
- name: public/condprof
path: archive
type: directory
android-hw-a51-11-0-arm7-fenix:
worker-type: t-bitbar-gw-perf-a51
description: Creates or update conditioned profiles on Fenix+A51
run-on-projects: [] # bug 1765348
treeherder:
symbol: condprof(fenix)
platform: android-hw-a51-11-0-arm7/opt
index:
product: firefox
job-name: condprof-a51-fenix
dependencies:
build: build-linux64-shippable/opt
fetches:
build:
- artifact: target.condprof.tests.tar.gz
toolchain:
- linux64-geckodriver
run:
run-as-root: true
command: >-
curl -L -o target.apk https://firefox-ci-tc.services.mozilla.com/api/index/v1/task/mobile.v2.fenix.nightly.latest.armeabi-v7a/artifacts/public/build/armeabi-v7a/target.apk &&
adb install -r target.apk &&
rm -rf target.apk &&
python3 virtualenv/virtualenv.py . &&
bin/python3 condprof/main.py
--force-new
--geckodriver ${MOZ_FETCHES_DIR}/geckodriver
--device-name a51
--firefox org.mozilla.fenix
--scenario settled
../../archive
worker:
artifacts:
- name: public/condprof
path: archive
type: directory
android-hw-p2-8-0-aarch64-fenix:
worker-type: t-bitbar-gw-perf-p2
description: Creates or update conditioned profiles on Fenix+P2

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

@ -25,6 +25,13 @@ hw-g5:
symbol: perftest-g5
platform: android-hw-g5-7-0-arm7-shippable/opt
hw-a51:
worker-type: t-bitbar-gw-perf-a51
description: Run ./mach perftest on a Samsung Galaxy a51
treeherder:
symbol: perftest-a51
platform: android-hw-a51-11-0-arm7-shippable/opt
hw-p2:
worker-type: t-bitbar-gw-perf-p2
description: Run ./mach perftest on a Pixel 2
@ -32,13 +39,6 @@ hw-p2:
symbol: perftest-p2
platform: android-hw-p2-8-0-android-aarch64-shippable/opt
hw-s7:
worker-type: t-bitbar-gw-perf-s7
description: Run ./mach perftest on a Samsung Galaxy S7
treeherder:
symbol: perftest-s7
platform: android-hw-s7-8-0-android-aarch64-shippable/opt
hw-g5-view-fenix:
worker-type: t-bitbar-gw-perf-g5
description: Run VIEW perftest on Fenix on a G5
@ -69,6 +69,36 @@ hw-g5-view-fenix:
--output $MOZ_FETCHES_DIR/../artifacts
testing/performance/perftest_android_view.js
hw-a51-view-fenix:
worker-type: t-bitbar-gw-perf-a51
description: Run VIEW perftest on Fenix on a Samsung A51
treeherder:
symbol: perftest(view-fenix)
platform: android-hw-a51-11-0-arm7-shippable/opt
attributes:
cron: true
batch: true
run:
command: >-
mkdir -p $MOZ_FETCHES_DIR/../artifacts &&
cd $GECKO_PATH &&
python3 python/mozperftest/mozperftest/runner.py
--flavor mobile-browser
--android
--android-app-name org.mozilla.fenix
--android-activity org.mozilla.fenix.IntentReceiverActivity
--android-clear-logcat
--android-capture-logcat logcat
--perfherder-metrics name:processLaunchToNavStart,shouldAlert:True
--android-install-apk fenix_nightly_armeabi_v7a
--hooks testing/performance/hooks_android_view.py
--perfherder
--perfherder-app fenix
--browsertime-geckodriver ${MOZ_FETCHES_DIR}/geckodriver
--browsertime-iterations 25
--output $MOZ_FETCHES_DIR/../artifacts
testing/performance/perftest_android_view.js
hw-p2-view-fenix:
worker-type: t-bitbar-gw-perf-p2
description: Run VIEW perftest on Fenix on a Pixel2
@ -106,6 +136,35 @@ hw-g5-view-gv:
treeherder:
symbol: perftest(view-gv)
platform: android-hw-g5-7-0-arm7-shippable/opt
attributes:
cron: false
run:
command: >-
mkdir -p $MOZ_FETCHES_DIR/../artifacts &&
cd $GECKO_PATH &&
python3 python/mozperftest/mozperftest/runner.py
--flavor mobile-browser
--android
--android-app-name org.mozilla.geckoview_example
--android-activity org.mozilla.geckoview_example.GeckoViewActivity
--android-clear-logcat
--android-capture-logcat logcat
--perfherder-metrics processLaunchToNavStart
--android-install-apk gve_nightly_api16
--hooks testing/performance/hooks_android_view.py
--perfherder
--perfherder-app geckoview
--browsertime-geckodriver ${MOZ_FETCHES_DIR}/geckodriver
--browsertime-iterations 14
--output $MOZ_FETCHES_DIR/../artifacts
testing/performance/perftest_android_view.js
hw-a51-view-gv:
worker-type: t-bitbar-gw-perf-a51
description: Run VIEW perftest on GV on a Samsung A51
treeherder:
symbol: perftest(view-gv)
platform: android-hw-a51-11-0-arm7-shippable/opt
attributes:
cron: true
run:
@ -191,6 +250,38 @@ hw-g5-main-fenix:
--browsertime-iterations 14
testing/performance/perftest_android_main.js
hw-a51-main-fenix:
worker-type: t-bitbar-gw-perf-a51
description: Run main (home activity) perftest on Fenix on a Samsung A51
treeherder:
symbol: perftest(main-fenix)
platform: android-hw-a51-11-0-arm7-shippable/opt
attributes:
cron: false
run:
command: >-
mkdir -p $MOZ_FETCHES_DIR/../artifacts &&
cd $GECKO_PATH &&
python3 python/mozperftest/mozperftest/runner.py
--flavor mobile-browser
--android
--android-app-name org.mozilla.fenix
--android-activity .App
--android-clear-logcat
--android-capture-logcat logcat
--androidlog
--androidlog-first-timestamp ".*Start proc.*org\.mozilla\..*\..*App.*"
--androidlog-second-timestamp ".*Fully drawn.*org\.mozilla\..*"
--androidlog-subtest-name "MAIN"
--android-install-apk fenix_nightly_armeabi_v7a
--hooks testing/performance/hooks_android_main.py
--perfherder
--perfherder-app fenix
--browsertime-geckodriver ${MOZ_FETCHES_DIR}/geckodriver
--output $MOZ_FETCHES_DIR/../artifacts
--browsertime-iterations 14
testing/performance/perftest_android_main.js
hw-p2-main-fenix:
worker-type: t-bitbar-gw-perf-p2
description: Run main (home activity) perftest on Fenix on a Pixel 2
@ -253,6 +344,35 @@ hw-g5-perfstats-gv:
--hooks testing/performance/hooks_perfstats.py
testing/performance/perftest_perfstats.js
hw-a51-perfstats-gv:
worker-type: t-bitbar-gw-perf-a51
description: Run PerfStats perftest on GeckoView on a Samsung A51
treeherder:
symbol: perftest(perfstats-gv)
platform: android-hw-a51-11-0-arm7-shippable/opt
attributes:
cron: false
run:
command: >-
mkdir -p $MOZ_FETCHES_DIR/../artifacts &&
cd $GECKO_PATH &&
python3 python/mozperftest/mozperftest/runner.py
--flavor mobile-browser
--android
--android-app-name org.mozilla.geckoview_example
--android-activity org.mozilla.geckoview_example.GeckoViewActivity
--android-clear-logcat
--android-capture-logcat logcat
--android-install-apk gve_nightly_api16
--browsertime-geckodriver ${MOZ_FETCHES_DIR}/geckodriver
--output $MOZ_FETCHES_DIR/../artifacts
--perfherder
--perfherder-app geckoview
--perfherder-metrics name:HttpChannelCompletion,unit:ms name:HttpChannelCompletion_Cache,unit:ms name:HttpChannelCompletion_Network,unit:ms name:DisplayListBuilding,unit:ms name:Reflowing,unit:ms name:Styling,unit:ms
--browsertime-iterations 10
--hooks testing/performance/hooks_perfstats.py
testing/performance/perftest_perfstats.js
hw-p2-perfstats-gv:
worker-type: t-bitbar-gw-perf-p2
description: Run PerfStats pageload test on GeckoView on a Pixel 2
@ -311,6 +431,35 @@ hw-g5-perfstats-fenix:
--hooks testing/performance/hooks_perfstats.py
testing/performance/perftest_perfstats.js
hw-a51-perfstats-fenix:
worker-type: t-bitbar-gw-perf-a51
description: Run PerfStats perftest on Fenix on a Samsung A51
treeherder:
symbol: perftest(perfstats-fenix)
platform: android-hw-a51-11-0-arm7-shippable/opt
attributes:
cron: false
run:
command: >-
mkdir -p $MOZ_FETCHES_DIR/../artifacts &&
cd $GECKO_PATH &&
python3 python/mozperftest/mozperftest/runner.py
--flavor mobile-browser
--android
--android-app-name org.mozilla.fenix
--android-activity org.mozilla.fenix.IntentReceiverActivity
--android-clear-logcat
--android-capture-logcat logcat
--android-install-apk fenix_nightly_armeabi_v7a
--browsertime-geckodriver ${MOZ_FETCHES_DIR}/geckodriver
--output $MOZ_FETCHES_DIR/../artifacts
--perfherder
--perfherder-app fenix
--perfherder-metrics name:HttpChannelCompletion,unit:ms name:HttpChannelCompletion_Cache,unit:ms name:HttpChannelCompletion_Network,unit:ms name:DisplayListBuilding,unit:ms name:Reflowing,unit:ms name:Styling,unit:ms
--browsertime-iterations 10
--hooks testing/performance/hooks_perfstats.py
testing/performance/perftest_perfstats.js
hw-p2-perfstats-fenix:
worker-type: t-bitbar-gw-perf-p2
description: Run PerfStats perftest on Fenix on a Pixel2

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

@ -105,7 +105,7 @@ browsertime-tp6m:
by-app:
geckoview:
by-test-platform:
android-hw-g5.*shippable-qr.*: [trunk, mozilla-beta, mozilla-release]
android-hw-(g5|a51).*shippable-qr.*: [trunk, mozilla-beta, mozilla-release]
android-hw-p2.*aarch64-shippable-qr.*: [trunk, mozilla-beta, mozilla-release]
default: []
default: []
@ -128,19 +128,15 @@ browsertime-tp6m-essential:
by-app:
geckoview:
by-test-platform:
android-hw-g5.*shippable.*: [trunk, mozilla-beta, mozilla-release]
android-hw-(g5|a51).*shippable.*: [trunk, mozilla-beta, mozilla-release]
android-hw-p2.*aarch64-shippable.*: [trunk, mozilla-beta, mozilla-release]
android-hw-s7-.*: []
default: []
default: []
tier:
by-test-platform:
android-hw-s7-.*: 3
default:
by-app:
geckoview: 1
refbrow: 2
default: 3
by-app:
geckoview: 1
refbrow: 2
default: 3
browsertime-youtube-playback-mobile:
description: Browsertime YouTube Playback on Android
@ -149,7 +145,7 @@ browsertime-youtube-playback-mobile:
apps: [fenix, geckoview, refbrow]
subtests:
by-test-platform:
android-hw-g5.*:
android-hw-(g5|a51).*:
- [youtube-playback-h264-sfr, ytp-h264-sfr]
- [youtube-playback-hfr, ytp-hfr]
# Bug 1699469 - Disabled until a crash is fixed.
@ -163,7 +159,6 @@ browsertime-youtube-playback-mobile:
# - [youtube-playback-widevine-h264-sfr, ytp-widevine-h264-sfr]
# - [youtube-playback-widevine-hfr, ytp-widevine-hfr]
# - [youtube-playback-widevine-vp9-sfr, ytp-widevine-vp9-sfr]
android-hw-s7.*: []
test-url-param:
by-subtest:
youtube-playback-h264-sfr: # remove high resolution tests
@ -171,7 +166,7 @@ browsertime-youtube-playback-mobile:
23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38
youtube-playback-hfr:
by-test-platform:
android-hw-g5.*: # remove VP9(1-34) and AV1(51-74) tests
android-hw-(g5|a51).*: # remove VP9(1-34) and AV1(51-74) tests
exclude=1,2,
3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,
51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74
@ -181,7 +176,7 @@ browsertime-youtube-playback-mobile:
default: ""
youtube-playback-widevine-hfr:
by-test-platform:
android-hw-g5.*: # remove VP9(1-34) tests
android-hw-(g5|a51).*: # remove VP9(1-34) tests
exclude=1,2,
3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34
default: ""
@ -190,7 +185,7 @@ browsertime-youtube-playback-mobile:
by-app:
geckoview:
by-test-platform:
android-hw-g5.*shippable.*: [mozilla-central, mozilla-release]
android-hw-(g5|a51).*shippable.*: [mozilla-central, mozilla-release]
android-hw-p2.*aarch64-shippable.*: [mozilla-central, mozilla-release]
default: []
default: []
@ -253,7 +248,7 @@ browsertime-tp6m-live:
by-app:
geckoview:
by-test-platform:
android-hw-g5.*shippable-qr.*: [autoland]
android-hw-(g5|a51).*shippable-qr.*: [autoland]
android-hw-p2.*aarch64-shippable-qr.*: [autoland]
default: []
default: []
@ -293,7 +288,7 @@ browsertime-speedometer-mobile:
refbrow: []
geckoview:
by-test-platform:
android-hw-g5.*shippable-qr.*: [trunk, mozilla-beta, mozilla-release]
android-hw-(g5|a51).*shippable-qr.*: [trunk, mozilla-beta, mozilla-release]
android-hw-p2.*aarch64-shippable-qr.*: [trunk, mozilla-beta, mozilla-release]
default: []
default:
@ -316,7 +311,7 @@ browsertime-unity-webgl-mobile:
refbrow: []
geckoview:
by-test-platform:
android-hw-g5.*shippable-qr.*: [trunk, mozilla-beta, mozilla-release]
android-hw-(g5|a51).*shippable-qr.*: [trunk, mozilla-beta, mozilla-release]
android-hw-p2.*aarch64-shippable-qr.*: [trunk, mozilla-beta, mozilla-release]
default: []
default:

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

@ -366,6 +366,26 @@ android-hw-g5-7-0-arm7-shippable-qr/opt:
- android-hw-arm7-raptor-cpu-memory
- android-hw-arm7-raptor-cpu-memory-power
# android-hw-a51-11-0 Samsung Galaxy A51 Android 11.0
android-hw-a51-11-0-arm7-qr/opt:
build-platform: android-arm/opt
test-sets:
- android-hw-browsertime-a51
# - android-hw-browsertime
# - android-hw-browsertime-power
# - android-hw-arm7-raptor-cpu-memory
# - android-hw-arm7-raptor-cpu-memory-power
android-hw-a51-11-0-arm7-shippable-qr/opt:
build-platform: android-arm-shippable/opt
test-sets:
- android-hw-browsertime-a51
# - android-hw-browsertime
# - android-hw-browsertime-power
# - android-hw-arm7-raptor-cpu-memory
# - android-hw-arm7-raptor-cpu-memory-power
# android-hw-p2-8-0 Google Pixel 2 Android 8.0
android-hw-p2-8-0-arm7-qr/opt:
@ -417,25 +437,3 @@ android-hw-p2-8-0-android-aarch64-qr/debug:
test-sets:
- android-hw-aarch64
- android-hw-aarch64-debug-unittests
# android-hw-s7-8-0 Samsung Galaxy S7 Android 8.0
android-hw-s7-8-0-arm7-api-16-qr/opt:
build-platform: android-api-16/opt
test-sets:
- android-hw-browsertime
android-hw-s7-8-0-arm7-api-16-shippable-qr/opt:
build-platform: android-api-16-shippable/opt
test-sets:
- android-hw-browsertime
android-hw-s7-8-0-android-aarch64-qr/opt:
build-platform: android-aarch64/opt
test-sets:
- android-hw-browsertime
android-hw-s7-8-0-android-aarch64-shippable-qr/opt:
build-platform: android-aarch64-shippable/opt
test-sets:
- android-hw-browsertime

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

@ -445,6 +445,13 @@ android-hw-aarch64-raptor-cpu-memory-power:
android-hw-browsertime-power:
- browsertime-power
android-hw-browsertime-a51:
- browsertime-tp6m-essential
- browsertime-speedometer-mobile
- browsertime-youtube-playback-mobile
- browsertime-unity-webgl-mobile
# not live, or tp6 proper
android-hw-browsertime:
- browsertime-tp6m
- browsertime-tp6m-essential

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

@ -1165,42 +1165,6 @@ def target_tasks_raptor_tp6m(full_task_graph, parameters, graph_config):
return [l for l, t in full_task_graph.tasks.items() if filter(t)]
@_target_task("perftest_s7")
def target_tasks_perftest_s7(full_task_graph, parameters, graph_config):
"""
Select tasks required for running raptor page-load tests on geckoview against S7
"""
def filter(task):
build_platform = task.attributes.get("build_platform", "")
test_platform = task.attributes.get("test_platform", "")
attributes = task.attributes
vismet = attributes.get("kind") == "visual-metrics-dep"
try_name = attributes.get("raptor_try_name")
if vismet:
# Visual metric tasks are configured a bit differently
test_platform = task.task.get("extra").get("treeherder-platform")
try_name = task.label
if build_platform and "android" not in build_platform:
return False
if attributes.get("unittest_suite") != "raptor" and not vismet:
return False
if "s7" in test_platform and "-qr" in test_platform:
if "geckoview" in try_name and (
"unity-webgl" in try_name
or "speedometer" in try_name
or "tp6m-essential" in try_name
):
if "power" in try_name:
return False
else:
return True
return [l for l, t in full_task_graph.tasks.items() if filter(t)]
@_target_task("condprof")
def target_tasks_condprof(full_task_graph, parameters, graph_config):
"""

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

@ -185,15 +185,15 @@ def test_split_variants(monkeypatch, run_transform, make_test_task):
pytest.param(
{
"attributes": {},
"test-platform": "android-hw-s7-8-0-android-aarch64-shippable-qr/opt",
"test-platform": "android-hw-a51-11-0-arm7-shippable-qr/opt",
},
{
"platform": {
"arch": "aarch64",
"device": "s7",
"arch": "arm7",
"device": "a51",
"os": {
"name": "android",
"version": "8.0",
"version": "11.0",
},
},
"build": {

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

@ -262,6 +262,8 @@ def add_extra_options(config, tests):
test_platform = test["test-platform"]
if test_platform.startswith("android-hw-g5"):
extra_options.append("--device-name=g5")
elif test_platform.startswith("android-hw-a51"):
extra_options.append("--device-name=a51")
elif test_platform.startswith("android-hw-p2"):
extra_options.append("--device-name=p2_aarch64")

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

@ -209,11 +209,6 @@ def set_worker_type(config, tasks):
task["worker-type"] = "t-bitbar-gw-unit-p2"
else:
task["worker-type"] = "t-bitbar-gw-perf-p2"
elif test_platform.startswith("android-hw-s7"):
if task["suite"] != "raptor":
task["worker-type"] = "t-bitbar-gw-unit-s7"
else:
task["worker-type"] = "t-bitbar-gw-perf-s7"
elif test_platform.startswith("android-hw-a51"):
if task["suite"] != "raptor":
task["worker-type"] = "t-bitbar-gw-unit-a51"

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

@ -123,6 +123,7 @@ UNITTEST_PLATFORM_PRETTY_NAMES = {
],
"x64": ["linux64", "linux64-asan", "linux1804-64", "linux1804-64-asan"],
"Android 7.0 Moto G5 32bit": ["android-hw-g5-7.0-arm7"],
"Android 7.0 Samsung A51 32bit": ["android-hw-a51-11.0-arm7"],
"Android 8.0 Google Pixel 2 32bit": ["android-hw-p2-8.0-arm7"],
"Android 8.0 Google Pixel 2 64bit": ["android-hw-p2-8.0-android-aarch64"],
"10.14": ["macosx1014-64"],

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -1,4 +1,4 @@
[parent.py]
[root.py]
disabled:
if release_or_beta: https://bugzilla.mozilla.org/show_bug.cgi?id=1712902

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

@ -16,13 +16,13 @@ class BrowsingContext(BidiModule):
@command
def get_tree(self,
max_depth: Optional[int] = None,
parent: Optional[str] = None) -> Mapping[str, Any]:
root: Optional[str] = None) -> Mapping[str, Any]:
params: MutableMapping[str, Any] = {}
if max_depth is not None:
params["maxDepth"] = max_depth
if parent is not None:
params["parent"] = parent
if root is not None:
params["root"] = root
return params

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

@ -129,11 +129,11 @@ async def test_navigate_creates_iframes(
assert len(events) == 2
# Get all browsing contexts from the current tab
contexts = await bidi_session.browsing_context.get_tree(parent=current_session.window_handle)
contexts = await bidi_session.browsing_context.get_tree(root=current_session.window_handle)
assert len(contexts) == 1
parent_info = contexts[0]
children_info = parent_info["children"]
root_info = contexts[0]
children_info = root_info["children"]
assert len(children_info) == 2
assert_browsing_context(
@ -141,7 +141,7 @@ async def test_navigate_creates_iframes(
children_info[0]["context"],
children=None,
url=children_info[0]["url"],
parent=parent_info["context"],
parent=root_info["context"],
)
assert_browsing_context(
@ -149,7 +149,7 @@ async def test_navigate_creates_iframes(
children_info[1]["context"],
children=None,
url=children_info[1]["url"],
parent=parent_info["context"],
parent=root_info["context"],
)
remove_listener()
@ -181,12 +181,12 @@ async def test_navigate_creates_nested_iframes(
assert len(events) == 2
# Get all browsing contexts from the current tab
contexts = await bidi_session.browsing_context.get_tree(parent=current_session.window_handle)
contexts = await bidi_session.browsing_context.get_tree(root=current_session.window_handle)
assert len(contexts) == 1
parent_info = contexts[0]
assert len(parent_info["children"]) == 1
child1_info = parent_info["children"][0]
root_info = contexts[0]
assert len(root_info["children"]) == 1
child1_info = root_info["children"][0]
assert len(child1_info["children"]) == 1
child2_info = child1_info["children"][0]
@ -195,7 +195,7 @@ async def test_navigate_creates_nested_iframes(
child1_info["context"],
children=None,
url=child1_info["url"],
parent=parent_info["context"],
parent=root_info["context"],
)
assert_browsing_context(

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше