Merge mozilla-central to mozilla-inbound. a=merge

This commit is contained in:
Daniel Varga 2019-02-20 06:07:54 +02:00
Родитель 9c05f8de8a 4587d14668
Коммит ae9fdeccab
210 изменённых файлов: 3132 добавлений и 2319 удалений

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

@ -8,8 +8,8 @@ const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
var EXPORTED_SYMBOLS = ["BlockedSiteChild"];
const {ActorChild} = ChromeUtils.import("resource://gre/modules/ActorChild.jsm");
ChromeUtils.defineModuleGetter(this, "Utils",
"resource://gre/modules/sessionstore/Utils.jsm");
ChromeUtils.defineModuleGetter(this, "E10SUtils",
"resource://gre/modules/E10SUtils.jsm");
ChromeUtils.defineModuleGetter(this, "SafeBrowsing",
"resource://gre/modules/SafeBrowsing.jsm");
@ -31,7 +31,7 @@ function getSiteBlockedErrorDetails(docShell) {
.finalize();
}
let triggeringPrincipal = docShell.failedChannel.loadInfo ? Utils.serializePrincipal(docShell.failedChannel.loadInfo.triggeringPrincipal) : null;
let triggeringPrincipal = docShell.failedChannel.loadInfo ? E10SUtils.serializePrincipal(docShell.failedChannel.loadInfo.triggeringPrincipal) : null;
blockedInfo = { list: classifiedChannel.matchedList,
triggeringPrincipal,
provider: classifiedChannel.matchedProvider,

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

@ -483,6 +483,9 @@ pref("browser.tabs.newanimations", false);
pref("browser.tabs.remote.separatePrivilegedContentProcess", true);
#endif
// Turn on HTTP response process selection.
pref("browser.tabs.remote.useHTTPResponseProcessSelection", true);
pref("browser.ctrlTab.recentlyUsedOrder", true);
// By default, do not export HTML at shutdown.
@ -1759,7 +1762,7 @@ pref("app.normandy.first_run", true);
pref("app.normandy.logging.level", 50); // Warn
pref("app.normandy.run_interval_seconds", 21600); // 6 hours
pref("app.normandy.shieldLearnMoreUrl", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/shield");
pref("app.normandy.remotesettings.enabled", false);
pref("features.normandy-remote-settings.enabled", false);
#ifdef MOZ_DATA_REPORTING
pref("app.shield.optoutstudies.enabled", true);
#else

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

@ -4,6 +4,7 @@
var Fingerprinting = {
PREF_ENABLED: "privacy.trackingprotection.fingerprinting.enabled",
telemetryIdentifier: "fp",
strings: {
get subViewBlocked() {
@ -114,6 +115,7 @@ var Fingerprinting = {
var Cryptomining = {
PREF_ENABLED: "privacy.trackingprotection.cryptomining.enabled",
telemetryIdentifier: "cm",
strings: {
get subViewBlocked() {

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

@ -22,7 +22,7 @@
class="menuitem-iconic"
tooltip="dynamic-shortcut-tooltip"
aria-label="&reloadCmd.label;"
oncommand="gContextMenu.reload(event);"
command="Browser:ReloadOrDuplicate"
accesskey="&reloadCmd.accesskey;"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="context-stop"

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

@ -69,7 +69,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
UrlbarTokenizer: "resource:///modules/UrlbarTokenizer.jsm",
UrlbarUtils: "resource:///modules/UrlbarUtils.jsm",
UrlbarValueFormatter: "resource:///modules/UrlbarValueFormatter.jsm",
Utils: "resource://gre/modules/sessionstore/Utils.jsm",
Weave: "resource://services-sync/main.js",
WebNavigationFrames: "resource://gre/modules/WebNavigationFrames.jsm",
fxAccounts: "resource://gre/modules/FxAccounts.jsm",
@ -2060,6 +2059,8 @@ function HandleAppCommandEvent(evt) {
}
function gotoHistoryIndex(aEvent) {
aEvent = getRootEvent(aEvent);
let index = aEvent.target.getAttribute("index");
if (!index)
return false;
@ -2136,6 +2137,7 @@ function BrowserStop() {
}
function BrowserReloadOrDuplicate(aEvent) {
aEvent = getRootEvent(aEvent);
let metaKeyPressed = AppConstants.platform == "macosx"
? aEvent.metaKey
: aEvent.ctrlKey;
@ -2174,7 +2176,7 @@ function BrowserHome(aEvent) {
aEvent.button == 2) // right-click: do nothing
return;
var homePage = HomePage.get();
var homePage = HomePage.get(window);
var where = whereToOpenLink(aEvent, false, true);
var urls;
var notifyObservers;
@ -3105,7 +3107,7 @@ var BrowserOnClick = {
},
ignoreWarningLink(reason, blockedInfo) {
let triggeringPrincipal = Utils.deserializePrincipal(blockedInfo.triggeringPrincipal) || _createNullPrincipalFromTabUserContextId();
let triggeringPrincipal = E10SUtils.deserializePrincipal(blockedInfo.triggeringPrincipal) || _createNullPrincipalFromTabUserContextId();
// Allow users to override and continue through to the site,
// but add a notify bar as a reminder, so that they don't lose
// track after, e.g., tab switching.

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

@ -880,10 +880,6 @@ nsContextMenu.prototype = {
});
},
reload(event) {
BrowserReloadOrDuplicate(event);
},
// View Partial Source
viewPartialSource() {
let {browser} = this;

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

@ -2554,7 +2554,7 @@ window._gBrowser = {
entries: [{
url: lazyBrowserURI ? lazyBrowserURI.spec : "about:blank",
title: lazyTabTitle,
triggeringPrincipal_base64: Utils.serializePrincipal(triggeringPrincipal),
triggeringPrincipal_base64: E10SUtils.serializePrincipal(triggeringPrincipal),
}],
});
} else {
@ -5599,7 +5599,7 @@ var TabContextMenu = {
// from SessionStore
let tabState = JSON.parse(SessionStore.getTabState(tab));
try {
triggeringPrincipal = Utils.deserializePrincipal(tabState.triggeringPrincipal_base64);
triggeringPrincipal = E10SUtils.deserializePrincipal(tabState.triggeringPrincipal_base64);
} catch (ex) {
continue;
}

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

@ -22,6 +22,8 @@ skip-if = (os == "linux" && (debug || asan))
skip-if = (os == "linux" && (debug || asan))
[browser_popupNotification_keyboard.js]
skip-if = (os == "linux" && (debug || asan))
[browser_popupNotification_learnmore.js]
skip-if = (os == "linux" && (debug || asan))
[browser_popupNotification_no_anchors.js]
skip-if = (os == "linux" && (debug || asan))
[browser_reshow_in_background.js]

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

@ -0,0 +1,50 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
waitForExplicitFinish();
ok(PopupNotifications, "PopupNotifications object exists");
ok(PopupNotifications.panel, "PopupNotifications panel exists");
setup();
}
var tests = [
// Test checkbox being checked by default
{ id: "without_learn_more",
run() {
this.notifyObj = new BasicNotification(this.id);
showNotification(this.notifyObj);
},
onShown(popup) {
checkPopup(popup, this.notifyObj);
let notification = popup.children[0];
let link = notification.querySelector(".popup-notification-learnmore-link");
ok(!link.href, "no href");
is(window.getComputedStyle(link).getPropertyValue("display"), "none", "link hidden");
dismissNotification(popup);
},
onHidden() { },
},
// Test that passing the learnMoreURL field sets up the link.
{ id: "with_learn_more",
run() {
this.notifyObj = new BasicNotification(this.id);
this.notifyObj.options.learnMoreURL = "https://mozilla.org";
showNotification(this.notifyObj);
},
onShown(popup) {
checkPopup(popup, this.notifyObj);
let notification = popup.children[0];
let link = notification.querySelector(".popup-notification-learnmore-link");
is(link.textContent, "Learn more…", "correct label");
is(link.href, "https://mozilla.org", "correct href");
isnot(window.getComputedStyle(link).getPropertyValue("display"), "none", "link not hidden");
dismissNotification(popup);
},
onHidden() { },
},
];

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

@ -69,10 +69,8 @@ var whitelist = [
// See bug 1339424 for why this is hard to fix.
{file: "chrome://global/locale/fallbackMenubar.properties",
platforms: ["linux", "win"]},
{file: "chrome://global/locale/printPageSetup.dtd", platforms: ["linux", "macosx"]},
{file: "chrome://global/locale/printPreviewProgress.dtd",
{file: "resource://gre/localization/en-US/toolkit/printing/printDialogs.ftl",
platforms: ["macosx"]},
{file: "chrome://global/locale/printProgress.dtd", platforms: ["macosx"]},
// toolkit/content/aboutRights-unbranded.xhtml doesn't use aboutRights.css
{file: "chrome://global/skin/aboutRights.css", skipUnofficial: true},

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

@ -69,21 +69,21 @@ add_task(async function testLazyTabs() {
}
let tabsMoved = new Promise(resolve => {
// Tab tabs in the new window will be about:blank before swapping the docshells.
// The "EndSwapDocShells" event is not dispatched for lazy tabs, so listen for
// "TabClose" instead and await a tick.
let numTabsMoved = 0;
window.addEventListener("TabClose", async function listener(event) {
let tab = event.target;
let i = oldTabs.indexOf(tab);
let oldTab = event.target;
let i = oldTabs.indexOf(oldTab);
if (i == 0) {
isnot(tab.linkedPanel, "", `Old tab ${i} should continue not being lazy`);
isnot(oldTab.linkedPanel, "", `Old tab ${i} should continue not being lazy`);
} else if (i > 0) {
is(tab.linkedPanel, "", `Old tab ${i} should continue being lazy`);
is(oldTab.linkedPanel, "", `Old tab ${i} should continue being lazy`);
} else {
return;
}
await Promise.resolve();
let newTab = event.detail.adoptedBy;
await TestUtils.waitForCondition(() => {
return newTab.linkedBrowser.currentURI.spec != "about:blank";
}, `Wait for the new tab to finish the adoption of the old tab`);
if (++numTabsMoved == numTabs) {
window.removeEventListener("TabClose", listener);
resolve();

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

@ -6,9 +6,10 @@ ChromeUtils.defineModuleGetter(this, "SessionStore",
"resource:///modules/sessionstore/SessionStore.jsm");
ChromeUtils.defineModuleGetter(this, "TabStateFlusher",
"resource:///modules/sessionstore/TabStateFlusher.jsm");
ChromeUtils.defineModuleGetter(this, "E10SUtils",
"resource://gre/modules/E10SUtils.jsm");
ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm", this);
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
function promiseBrowserStateRestored(state) {
if (typeof state != "string") {

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

@ -24,10 +24,19 @@ XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
Object.defineProperty(this, "BROWSER_NEW_TAB_URL", {
enumerable: true,
get() {
if (PrivateBrowsingUtils.isWindowPrivate(window) &&
!PrivateBrowsingUtils.permanentPrivateBrowsing &&
!aboutNewTabService.overridden) {
return "about:privatebrowsing";
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
if (!PrivateBrowsingUtils.permanentPrivateBrowsing &&
!aboutNewTabService.overridden) {
return "about:privatebrowsing";
}
// If the extension does not have private browsing permission,
// use about:privatebrowsing.
if (aboutNewTabService.newTabURL.startsWith("moz-extension")) {
let url = new URL(aboutNewTabService.newTabURL);
if (!WebExtensionPolicy.getByHostname(url.hostname).privateBrowsingAllowed) {
return "about:privatebrowsing";
}
}
}
return aboutNewTabService.newTabURL;
},
@ -86,6 +95,7 @@ function doGetProtocolFlags(aURI) {
*/
function openUILink(url, event, aIgnoreButton, aIgnoreAlt, aAllowThirdPartyFixup,
aPostData, aReferrerURI) {
event = getRootEvent(event);
let params;
if (aIgnoreButton && typeof aIgnoreButton == "object") {
@ -115,6 +125,26 @@ function openUILink(url, event, aIgnoreButton, aIgnoreAlt, aAllowThirdPartyFixup
}
// Utility function to check command events for potential middle-click events
// from checkForMiddleClick and unwrap them.
function getRootEvent(aEvent) {
// Part of the fix for Bug 1523813.
// Middle-click events arrive here wrapped in different numbers (1-2) of
// command events, depending on the button originally clicked.
if (!aEvent) {
return aEvent;
}
let tempEvent = aEvent;
while (tempEvent.sourceEvent) {
if (tempEvent.sourceEvent.button == 1) {
aEvent = tempEvent.sourceEvent;
break;
}
tempEvent = tempEvent.sourceEvent;
}
return aEvent;
}
/**
* whereToOpenLink() looks at an event to decide where to open a link.
*
@ -147,6 +177,8 @@ function whereToOpenLink(e, ignoreButton, ignoreAlt) {
if (!e)
return "current";
e = getRootEvent(e);
var shift = e.shiftKey;
var ctrl = e.ctrlKey;
var meta = e.metaKey;
@ -592,13 +624,13 @@ function checkForMiddleClick(node, event) {
if (event.button == 1) {
/* Execute the node's oncommand or command.
*
* XXX: we should use node.oncommand(event) once bug 246720 is fixed.
*/
var target = node.hasAttribute("oncommand") ? node :
node.ownerDocument.getElementById(node.getAttribute("command"));
var fn = new Function("event", target.getAttribute("oncommand"));
fn.call(target, event);
let cmdEvent = document.createEvent("xulcommandevent");
cmdEvent.initCommandEvent("command", true, true, window, 0,
event.ctrlKey, event.altKey, event.shiftKey,
event.metaKey, event, event.mozInputSource);
node.dispatchEvent(cmdEvent);
// If the middle-click was on part of a menu, close the menu.
// (Menus close automatically with left-click but not with middle-click.)

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

@ -209,7 +209,7 @@ function openBrowserWindow(cmdLine, triggeringPrincipal, urlOrUrlList, postData
let args;
if (!urlOrUrlList) {
// Just pass in the defaultArgs directly. We'll use system principal on the other end.
args = [gBrowserContentHandler.defaultArgs];
args = [gBrowserContentHandler.getDefaultArgs(forcePrivate)];
} else {
let pService = Cc["@mozilla.org/toolkit/profile-service;1"].
getService(Ci.nsIToolkitProfileService);
@ -518,7 +518,7 @@ nsBrowserContentHandler.prototype = {
/* nsIBrowserHandler */
get defaultArgs() {
getDefaultArgs(forcePrivate = false) {
var prefb = Services.prefs;
if (!gFirstWindow) {
@ -603,7 +603,7 @@ nsBrowserContentHandler.prototype = {
try {
var choice = prefb.getIntPref("browser.startup.page");
if (choice == 1 || choice == 3)
startPage = HomePage.get();
startPage = forcePrivate ? HomePage.getPrivate() : HomePage.get();
} catch (e) {
Cu.reportError(e);
}
@ -621,6 +621,10 @@ nsBrowserContentHandler.prototype = {
return overridePage || startPage || "about:blank";
},
get defaultArgs() {
return this.getDefaultArgs(PrivateBrowsingUtils.permanentPrivateBrowsing);
},
mFeatures: null,
getFeatures: function bch_features(cmdLine) {

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

@ -1406,6 +1406,12 @@ BrowserGlue.prototype = {
}
}
Services.telemetry.scalarSet("contentblocking.exceptions", exceptions);
let fpEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.fingerprinting.enabled");
let cmEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.cryptomining.enabled");
Services.telemetry.scalarSet("contentblocking.fingerprinting_blocking_enabled", fpEnabled);
Services.telemetry.scalarSet("contentblocking.cryptomining_blocking_enabled", cmEnabled);
},
_sendMediaTelemetry() {

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

@ -328,6 +328,7 @@ var Policies = {
onBeforeAddons(manager, param) {
if (param) {
manager.disallowFeature("Shield");
setAndLockPref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr", false);
}
},
},
@ -682,6 +683,7 @@ var Policies = {
setAndLockPref("xpinstall.enabled", param.Default);
if (!param.Default) {
blockAboutPage(manager, "about:debugging");
setAndLockPref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr", false);
manager.disallowFeature("xpinstall");
}
}

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

@ -151,6 +151,7 @@ const POLICIES_TESTS = [
},
lockedPrefs: {
"xpinstall.enabled": false,
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr": false,
},
},
@ -255,6 +256,16 @@ const POLICIES_TESTS = [
"extensions.update.enabled": false,
},
},
// POLICY: DisableShield
{
policies: {
"DisableFirefoxStudies": true,
},
lockedPrefs: {
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr": false,
},
},
];
add_task(async function test_policy_remember_passwords() {

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

@ -31,6 +31,8 @@ ChromeUtils.defineModuleGetter(this, "CustomizableUI",
"resource:///modules/CustomizableUI.jsm");
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
"resource://gre/modules/ExtensionSettingsStore.jsm");
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
let {
makeWidgetId,
@ -195,6 +197,12 @@ class ExtensionControlledPopup {
extensionId = item && item.id;
}
let win = targetWindow || this.topWindow;
let isPrivate = PrivateBrowsingUtils.isWindowPrivate(win);
if (isPrivate && extensionId && !WebExtensionPolicy.getByID(extensionId).privateBrowsingAllowed) {
return;
}
// The item should have an extension and the user shouldn't have confirmed
// the change here, but just to be sure check that it is still controlled
// and the user hasn't already confirmed the change.
@ -203,7 +211,6 @@ class ExtensionControlledPopup {
return;
}
let win = targetWindow || this.topWindow;
// If the window closes while waiting for focus, this might reject/throw,
// and we should stop trying to show the popup.
try {

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

@ -191,8 +191,13 @@ this.windows = class extends ExtensionAPI {
args.appendElement(mkstr(createData.url));
}
} else {
let url = createData.incognito && !PrivateBrowsingUtils.permanentPrivateBrowsing ?
"about:privatebrowsing" : HomePage.get().split("|", 1)[0];
let url;
if (createData.incognito) {
url = PrivateBrowsingUtils.permanentPrivateBrowsing ?
HomePage.getPrivate().split("|", 1)[0] : "about:privatebrowsing";
} else {
url = HomePage.get().split("|", 1)[0];
}
args.appendElement(mkstr(url));
if (url.startsWith("about:") &&

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

@ -422,3 +422,127 @@ add_task(async function test_doorhanger_new_window() {
ok(!isConfirmed(ext1Id), "The confirmation is cleaned up on uninstall");
});
add_task(async function test_overriding_home_page_incognito_not_allowed() {
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
chrome_settings_overrides: {"homepage": "home.html"},
name: "extension",
},
background() {
browser.test.sendMessage("url", browser.runtime.getURL("home.html"));
},
files: {"home.html": "<h1>1</h1>"},
useAddonManager: "temporary",
});
await extension.startup();
let url = await extension.awaitMessage("url");
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow({url});
let win = OpenBrowserWindow();
await windowOpenedPromise;
let doc = win.document;
let description = doc.getElementById("extension-homepage-notification-description");
let panel = doc.getElementById("extension-notification-panel");
await promisePopupShown(panel);
let popupnotification = description.closest("popupnotification");
is(description.textContent,
"An extension, extension, changed what you see when you open your homepage and new windows.Learn more",
"The extension name is in the popup");
is(popupnotification.hidden, false, "The expected popup notification is visible");
ok(win.gURLBar.value.endsWith("home.html"), "extension is in control");
await BrowserTestUtils.closeWindow(win);
// Verify a private window does not open the extension page.
windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
win = OpenBrowserWindow({private: true});
await windowOpenedPromise;
win.BrowserHome();
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
is(win.gURLBar.value, "", "home page not used in private window");
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});
add_task(async function test_overriding_home_page_incognito_not_allowed_bypass() {
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
name: "extension",
},
background() {
browser.test.sendMessage("url", browser.runtime.getURL("home.html"));
},
files: {"home.html": "<h1>1</h1>"},
useAddonManager: "temporary",
});
await extension.startup();
let url = await extension.awaitMessage("url");
// Verify manually setting the pref to the extension page does not work.
let changed = promisePrefChangeObserved(HOMEPAGE_URL_PREF);
Services.prefs.setStringPref(HOMEPAGE_URL_PREF, url);
await changed;
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
let win = OpenBrowserWindow({private: true});
await windowOpenedPromise;
win.BrowserHome();
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
is(win.gURLBar.value, "", "home page not used in private window");
changed = promisePrefChangeObserved(HOMEPAGE_URL_PREF);
Services.prefs.clearUserPref(HOMEPAGE_URL_PREF);
await changed;
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});
add_task(async function test_overriding_home_page_incognito_spanning() {
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
chrome_settings_overrides: {"homepage": "home.html"},
name: "private extension",
applications: {
gecko: {id: "@spanning-home"},
},
},
files: {"home.html": "<h1>1</h1>"},
useAddonManager: "permanent",
incognitoOverride: "spanning",
});
await extension.startup();
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
let win = OpenBrowserWindow({private: true});
await windowOpenedPromise;
let doc = win.document;
let panel = doc.getElementById("extension-notification-panel");
let popupShown = promisePopupShown(panel);
win.BrowserHome();
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
await popupShown;
ok(getHomePageURL().endsWith("home.html"), "The homepage is set");
ok(win.gURLBar.value.endsWith("home.html"), "extension is in control in private window");
let popupHidden = promisePopupHidden(panel);
panel.hidePopup();
await popupHidden;
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});

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

@ -3,8 +3,8 @@
/* global gBrowser SessionStore */
"use strict";
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
let lazyTabState = {entries: [{url: "http://example.com/", triggeringPrincipal_base64, title: "Example Domain"}]};

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

@ -4,8 +4,8 @@ ChromeUtils.defineModuleGetter(this, "SessionStore",
"resource:///modules/sessionstore/SessionStore.jsm");
ChromeUtils.defineModuleGetter(this, "TabStateFlusher",
"resource:///modules/sessionstore/TabStateFlusher.jsm");
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
async function doorhangerTest(testFn) {
await SpecialPowers.pushPrefEnv({

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

@ -1,7 +1,7 @@
"use strict";
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
const SESSION = {
windows: [{

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

@ -5,6 +5,9 @@
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
"resource://gre/modules/ExtensionSettingsStore.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
"@mozilla.org/browser/aboutnewtab-service;1",
"nsIAboutNewTabService");
const NEWTAB_URI_1 = "webext-newtab-1.html";
@ -522,3 +525,189 @@ add_task(async function dontTemporarilyShowAboutExtensionPath() {
BrowserTestUtils.removeTab(tab);
await extension.unload();
});
add_task(async function test_overriding_newtab_incognito_not_allowed() {
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
let panel = getNewTabDoorhanger().closest("panel");
let extension = ExtensionTestUtils.loadExtension({
manifest: {
chrome_url_overrides: {"newtab": "newtab.html"},
name: "extension",
applications: {
gecko: {id: "@not-allowed-newtab"},
},
},
files: {
"newtab.html": `
<!DOCTYPE html>
<head>
<meta charset="utf-8"/></head>
<html>
<body>
<script src="newtab.js"></script>
</body>
</html>
`,
"newtab.js": function() {
window.onload = () => {
browser.test.sendMessage("from-newtab-page", window.location.href);
};
},
},
useAddonManager: "permanent",
});
await extension.startup();
let popupShown = promisePopupShown(panel);
BrowserOpenTab();
await popupShown;
let url = await extension.awaitMessage("from-newtab-page");
ok(url.endsWith("newtab.html"),
"Newtab url is overridden by the extension.");
// This will show a confirmation doorhanger, make sure we don't leave it open.
let popupHidden = promisePopupHidden(panel);
panel.hidePopup();
await popupHidden;
BrowserTestUtils.removeTab(gBrowser.selectedTab);
// Verify a private window does not open the extension page. We would
// get an extra notification that we don't listen for if it gets loaded.
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
let win = OpenBrowserWindow({private: true});
await windowOpenedPromise;
let newTabOpened = waitForNewTab();
win.BrowserOpenTab();
await newTabOpened;
is(win.gURLBar.value, "", "newtab not used in private window");
// Verify setting the pref directly doesn't bypass permissions.
let origUrl = aboutNewTabService.newTabURL;
aboutNewTabService.newTabURL = url;
newTabOpened = waitForNewTab();
win.BrowserOpenTab();
await newTabOpened;
is(win.gURLBar.value, "", "directly set newtab not used in private window");
aboutNewTabService.newTabURL = origUrl;
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});
add_task(async function test_overriding_newtab_incognito_not_allowed_bypass() {
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
name: "extension",
applications: {
gecko: {id: "@not-allowed-newtab"},
},
},
background() {
browser.test.sendMessage("url", browser.runtime.getURL("newtab.html"));
},
files: {
"newtab.html": `
<!DOCTYPE html>
<head>
<meta charset="utf-8"/></head>
<html>
<body>
</body>
</html>
`,
},
useAddonManager: "permanent",
});
await extension.startup();
let url = await extension.awaitMessage("url");
// Verify setting the pref directly doesn't bypass permissions.
let origUrl = aboutNewTabService.newTabURL;
aboutNewTabService.newTabURL = url;
// Verify a private window does not open the extension page. We would
// get an extra notification that we don't listen for if it gets loaded.
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
let win = OpenBrowserWindow({private: true});
await windowOpenedPromise;
let newTabOpened = waitForNewTab();
win.BrowserOpenTab();
await newTabOpened;
is(win.gURLBar.value, "", "directly set newtab not used in private window");
aboutNewTabService.newTabURL = origUrl;
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});
add_task(async function test_overriding_newtab_incognito_spanning() {
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
chrome_url_overrides: {"newtab": "newtab.html"},
name: "extension",
applications: {
gecko: {id: "@spanning-newtab"},
},
},
files: {
"newtab.html": `
<!DOCTYPE html>
<head>
<meta charset="utf-8"/></head>
<html>
<body>
<script src="newtab.js"></script>
</body>
</html>
`,
"newtab.js": function() {
window.onload = () => {
browser.test.sendMessage("from-newtab-page", window.location.href);
};
},
},
useAddonManager: "permanent",
incognitoOverride: "spanning",
});
await extension.startup();
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
let win = OpenBrowserWindow({private: true});
await windowOpenedPromise;
let panel = win.document.getElementById("extension-new-tab-notification").closest("panel");
let popupShown = promisePopupShown(panel);
win.BrowserOpenTab();
await popupShown;
let url = await extension.awaitMessage("from-newtab-page");
ok(url.endsWith("newtab.html"),
"Newtab url is overridden by the extension.");
// This will show a confirmation doorhanger, make sure we don't leave it open.
let popupHidden = promisePopupHidden(panel);
panel.hidePopup();
await popupHidden;
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});

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

@ -1937,6 +1937,7 @@ this.PlacesPanelview = class extends PlacesViewBase {
}
_onCommand(event) {
event = getRootEvent(event);
let button = event.originalTarget;
if (!button._placesNode)
return;

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

@ -33,10 +33,10 @@ skip-if = (os == 'win' && processor == "x86_64") # Bug 1480314
[browser_bug1018066_resetScrollPosition.js]
[browser_bug1020245_openPreferences_to_paneContent.js]
[browser_bug1184989_prevent_scrolling_when_preferences_flipped.js]
[browser_cert_export.js]
[browser_engines.js]
support-files =
browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul
[browser_cert_export.js]
[browser_engines.js]
[browser_change_app_handler.js]
skip-if = os != "win" # Windows-specific handler application selection dialog
[browser_checkspelling.js]

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

@ -1,5 +1,5 @@
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
add_task(async function() {
waitForExplicitFinish();

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

@ -212,9 +212,9 @@ ContentRestoreInternal.prototype = {
referrerInfo = new ReferrerInfo(referrerPolicy, true, referrer);
}
let postData = loadArguments.postData ?
Utils.makeInputStream(loadArguments.postData) : null;
E10SUtils.makeInputStream(loadArguments.postData) : null;
let triggeringPrincipal = loadArguments.triggeringPrincipal
? Utils.deserializePrincipal(loadArguments.triggeringPrincipal)
? E10SUtils.deserializePrincipal(loadArguments.triggeringPrincipal)
: Services.scriptSecurityManager.createNullPrincipal({});
if (loadArguments.userContextId) {

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

@ -9,8 +9,8 @@ var EXPORTED_SYMBOLS = ["SessionMigration"];
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
ChromeUtils.import("resource://gre/modules/osfile.jsm", this);
ChromeUtils.defineModuleGetter(this, "Utils",
"resource://gre/modules/sessionstore/Utils.jsm");
ChromeUtils.defineModuleGetter(this, "E10SUtils",
"resource://gre/modules/E10SUtils.jsm");
// An encoder to UTF-8.
XPCOMUtils.defineLazyGetter(this, "gEncoder", function() {
@ -63,7 +63,7 @@ var SessionMigrationInternal = {
});
let url = "about:welcomeback";
let formdata = {id: {sessionData: state}, url};
let entry = { url, triggeringPrincipal_base64: Utils.SERIALIZED_SYSTEMPRINCIPAL };
let entry = { url, triggeringPrincipal_base64: E10SUtils.SERIALIZED_SYSTEMPRINCIPAL };
return { windows: [{ tabs: [{ entries: [ entry ], formdata}]}]};
},
/**

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

@ -682,14 +682,14 @@ var SessionStoreInternal = {
// replace the crashed session with a restore-page-only session
let url = "about:sessionrestore";
let formdata = {id: {sessionData: state}, url};
let entry = {url, triggeringPrincipal_base64: Utils.SERIALIZED_SYSTEMPRINCIPAL };
let entry = {url, triggeringPrincipal_base64: E10SUtils.SERIALIZED_SYSTEMPRINCIPAL };
state = { windows: [{ tabs: [{ entries: [entry], formdata }] }] };
} else if (this._hasSingleTabWithURL(state.windows,
"about:welcomeback")) {
// On a single about:welcomeback URL that crashed, replace about:welcomeback
// with about:sessionrestore, to make clear to the user that we crashed.
state.windows[0].tabs[0].entries[0].url = "about:sessionrestore";
state.windows[0].tabs[0].entries[0].triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
state.windows[0].tabs[0].entries[0].triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
}
}
@ -3345,7 +3345,7 @@ var SessionStoreInternal = {
let tabbrowser = aWindow.gBrowser;
let startupPref = this._prefBranch.getIntPref("startup.page");
if (startupPref == 1)
homePages = homePages.concat(HomePage.get().split("|"));
homePages = homePages.concat(HomePage.get(aWindow).split("|"));
for (let i = tabbrowser._numPinnedTabs; i < tabbrowser.tabs.length; i++) {
let tab = tabbrowser.tabs[i];

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

@ -2,8 +2,8 @@
* 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/. */
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
const TAB_STATE_NEEDS_RESTORE = 1;
const TAB_STATE_RESTORING = 2;

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

@ -251,8 +251,12 @@ class UrlbarInput {
if (selectedOneOff) {
// If there's a selected one-off button then load a search using
// the button's engine.
let result = this._resultForCurrentValue;
let searchString =
(result && (result.payload.suggestion || result.payload.query)) ||
this._lastSearchString;
[url, openParams.postData] = UrlbarUtils.getSearchQueryUrl(
selectedOneOff.engine, this._lastSearchString);
selectedOneOff.engine, searchString);
this._recordSearch(selectedOneOff.engine, event);
} else {
// Use the current value if we don't have a UrlbarResult e.g. because the

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

@ -97,7 +97,6 @@ subsuite = clipboard
support-files = empty.xul
[browser_UrlbarLoadRace.js]
[browser_urlbarOneOffs_searchSuggestions.js]
skip-if = true # Bug 1528024 - Need to correctly handle suggestions and one-offs.
support-files =
../browser/searchSuggestionEngine.xml
../browser/searchSuggestionEngine.sjs

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

@ -97,12 +97,12 @@ add_task(async function overridden_engine_not_reused() {
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
let label = result.displayed.action;
// Run again the query, check the label has been replaced.
await UrlbarTestUtils.promisePopupClose(window);
await promiseAutocompleteResultPopup(typedValue, window, true);
await promiseSuggestionsPresent();
assertState(0, -1, "foo");
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
Assert.notEqual(result.displayed.action, label, "The label should have been updated");
BrowserTestUtils.removeTab(tab);
});
@ -111,11 +111,7 @@ function assertState(result, oneOff, textValue = undefined) {
"Expected result should be selected");
Assert.equal(UrlbarTestUtils.getOneOffSearchButtons(window).selectedButtonIndex,
oneOff, "Expected one-off should be selected");
// TODO Bug 1527946: Fix textValue differences for QuantumBar
if (UrlbarPrefs.get("quantumbar")) {
return;
}
if (textValue !== undefined) {
Assert.equal(gURLBar.textValue, textValue, "Expected textValue");
}
if (textValue !== undefined) {
Assert.equal(gURLBar.textValue, textValue, "Expected textValue");
}
}

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

@ -10,6 +10,8 @@
var EXPORTED_SYMBOLS = ["HomePage"];
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
const kPrefName = "browser.startup.homepage";
@ -43,7 +45,11 @@ function getHomepagePref(useDefault) {
}
let HomePage = {
get() {
get(aWindow) {
if (PrivateBrowsingUtils.permanentPrivateBrowsing ||
(aWindow && PrivateBrowsingUtils.isWindowPrivate(aWindow))) {
return this.getPrivate();
}
return getHomepagePref();
},
@ -51,6 +57,24 @@ let HomePage = {
return getHomepagePref(true);
},
getPrivate() {
let homePages = getHomepagePref();
if (!homePages.includes("moz-extension")) {
return homePages;
}
// Verify private access and build a new list.
let privateHomePages = homePages.split("|").filter(page => {
let url = new URL(page);
if (url.protocol !== "moz-extension:") {
return true;
}
let policy = WebExtensionPolicy.getByHostname(url.hostname);
return policy && policy.privateBrowsingAllowed;
});
// Extensions may not be ready on startup, fallback to defaults.
return privateHomePages.join("|") || this.getDefault();
},
get overridden() {
return Services.prefs.prefHasUserValue(kPrefName);
},

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

@ -1,7 +1,6 @@
"use strict";
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
const MAX_CONCURRENT_TABS = "browser.engagement.max_concurrent_tab_count";
const TAB_EVENT_COUNT = "browser.engagement.tab_open_event_count";

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

@ -56,7 +56,6 @@ ignored_js_src_dirs = [
# We ignore #includes of these files, because they don't follow the usual rules.
included_inclnames_to_ignore = set([
'ffi.h', # generated in ctypes/libffi/
'devtools/sharkctl.h', # we ignore devtools/ in general
'devtools/Instruments.h', # we ignore devtools/ in general
'double-conversion/double-conversion.h', # strange MFBT case
'javascript-trace.h', # generated in $OBJDIR if HAVE_DTRACE is defined

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

@ -92,6 +92,10 @@ storage.popupMenu.deleteLabel=Delete “%S”
# Label of popup menu action to add an item.
storage.popupMenu.addItemLabel=Add Item
# LOCALIZATION NOTE (storage.popupMenu.refreshItemLabel):
# Label of popup menu action to refresh an item.
storage.popupMenu.refreshItemLabel=Refresh Items
# LOCALIZATION NOTE (storage.popupMenu.deleteAllFromLabel):
# Label of popup menu action to delete all storage items.
storage.popupMenu.deleteAllFromLabel=Delete All From “%S”

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

@ -8,9 +8,8 @@ const { Cc, Ci, Cu, Cr } = require("chrome");
const ChromeUtils = require("ChromeUtils");
const Services = require("Services");
const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
const { Utils } = require("resource://gre/modules/sessionstore/Utils.jsm");
const Telemetry = require("devtools/client/shared/telemetry");
const { E10SUtils } = require("resource://gre/modules/E10SUtils.jsm");
const Telemetry = require("devtools/client/shared/telemetry");
const telemetry = new Telemetry();
@ -83,7 +82,7 @@ BrowserElementWebNavigation.prototype = {
postData: postData ? readInputStreamToString(postData) : null,
headers: headers ? readInputStreamToString(headers) : null,
baseURI: baseURI ? baseURI.spec : null,
triggeringPrincipal: Utils.serializePrincipal(
triggeringPrincipal: E10SUtils.serializePrincipal(
triggeringPrincipal ||
Services.scriptSecurityManager.createNullPrincipal({})),
requestTime: telemetry.msSystemNow(),

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

@ -2,8 +2,8 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm");
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
const testState = {
windows: [{

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

@ -48,12 +48,11 @@ const {
const { OS } = Services.appinfo;
// CM_SCRIPTS and CM_IFRAME represent the HTML and JavaScript that is
// CM_BUNDLE and CM_IFRAME represent the HTML and JavaScript that is
// injected into an iframe in order to initialize a CodeMirror instance.
const CM_SCRIPTS = [
"chrome://devtools/content/shared/sourceeditor/codemirror/codemirror.bundle.js",
];
const CM_BUNDLE =
"chrome://devtools/content/shared/sourceeditor/codemirror/codemirror.bundle.js";
const CM_IFRAME = "chrome://devtools/content/shared/sourceeditor/codemirror/cmiframe.html";
@ -217,11 +216,6 @@ function Editor(config) {
cm.replaceSelection(" ".repeat(num), "end", "+input");
};
// Allow add-ons to inject scripts for their editor instances
if (!this.config.externalScripts) {
this.config.externalScripts = [];
}
if (this.config.cssProperties) {
// Ensure that autocompletion has cssProperties if it's passed in via the options.
this.config.autocompleteOpts.cssProperties = this.config.cssProperties;
@ -326,12 +320,7 @@ Editor.prototype = {
doc = doc || el.ownerDocument;
const win = el.ownerDocument.defaultView;
const scriptsToInject = CM_SCRIPTS.concat(this.config.externalScripts);
scriptsToInject.forEach(url => {
if (url.startsWith("chrome://")) {
Services.scriptloader.loadSubScript(url, win);
}
});
Services.scriptloader.loadSubScript(CM_BUNDLE, win);
// Replace the propertyKeywords, colorKeywords and valueKeywords
// properties of the CSS MIME type with the values provided by the CSS properties

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

@ -40,7 +40,6 @@ support-files =
[browser_editor_markers.js]
[browser_editor_movelines.js]
[browser_editor_prefs.js]
[browser_editor_script_injection.js]
[browser_editor_addons.js]
[browser_codemirror.js]
[browser_css_autocompletion.js]

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

@ -1,27 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test the externalScripts option, which allows custom language modes or
// other scripts to be injected into the editor window. See Bug 1089428.
"use strict";
add_task(async function() {
await runTest();
});
async function runTest() {
const baseURL =
"chrome://mochitests/content/browser/devtools/client/shared/sourceeditor/test";
const injectedText = "Script successfully injected!";
const {ed, win} = await setup({
mode: "ruby",
externalScripts: [`${baseURL}/cm_script_injection_test.js`,
`${baseURL}/cm_mode_ruby.js`],
});
is(ed.getText(), injectedText, "The text has been injected");
is(ed.getOption("mode"), "ruby", "The ruby mode is correctly set");
teardown(ed, win);
}

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

@ -191,6 +191,8 @@ class StorageUI {
this._refreshButton = this._panelDoc.getElementById("refresh-button");
this._refreshButton.addEventListener("command", this.onRefreshTable);
this._refreshButton.setAttribute("tooltiptext",
L10N.getFormatStr("storage.popupMenu.refreshItemLabel"));
this._addButton = this._panelDoc.getElementById("add-button");
this._addButton.addEventListener("command", this.onAddItem);

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

@ -1227,6 +1227,8 @@ Document::Document(const char* aContentType)
mInUnlinkOrDeletion(false),
mHasHadScriptHandlingObject(false),
mIsBeingUsedAsImage(false),
mDocURISchemeIsChrome(false),
mInChromeDocShell(false),
mIsSyntheticDocument(false),
mHasLinksToUpdateRunnable(false),
mFlushingPendingLinkUpdates(false),
@ -2835,6 +2837,8 @@ void Document::SetDocumentURI(nsIURI* aURI) {
mDocumentURI = aURI;
nsIURI* newBase = GetDocBaseURI();
mDocURISchemeIsChrome = aURI && IsChromeURI(aURI);
bool equalBases = false;
// Changing just the ref of a URI does not change how relative URIs would
// resolve wrt to it, so we can treat the bases as equal as long as they're
@ -4301,6 +4305,9 @@ void Document::SetContainer(nsDocShell* aContainer) {
mDocumentContainer = WeakPtr<nsDocShell>();
}
mInChromeDocShell =
aContainer && aContainer->ItemType() == nsIDocShellTreeItem::typeChrome;
EnumerateActivityObservers(NotifyActivityChanged, nullptr);
// IsTopLevelWindowInactive depends on the docshell, so

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

@ -2474,6 +2474,16 @@ class Document : public nsINode,
return !mParentDocument && !mDisplayDocument;
}
bool IsDocumentURISchemeChrome() const { return mDocURISchemeIsChrome; }
bool IsInChromeDocShell() const {
const Document* root = this;
while (const Document* displayDoc = root->GetDisplayDocument()) {
root = displayDoc;
}
return root->mInChromeDocShell;
}
bool IsBeingUsedAsImage() const { return mIsBeingUsedAsImage; }
void SetIsBeingUsedAsImage() { mIsBeingUsedAsImage = true; }
@ -4007,6 +4017,12 @@ class Document : public nsINode,
// True if we're an SVG document being used as an image.
bool mIsBeingUsedAsImage : 1;
// True if our current document URI's scheme is chrome://
bool mDocURISchemeIsChrome : 1;
// True if we're loaded in a chrome docshell.
bool mInChromeDocShell : 1;
// True is this document is synthetic : stand alone image, video, audio
// file, etc.
bool mIsSyntheticDocument : 1;

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

@ -3851,10 +3851,6 @@ void nsContentUtils::LogMessageToConsole(const char* aMsg) {
sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
}
bool nsContentUtils::IsChromeDoc(const Document* aDocument) {
return aDocument && aDocument->NodePrincipal() == sSystemPrincipal;
}
bool nsContentUtils::IsChildOfSameType(Document* aDoc) {
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(aDoc->GetDocShell());
nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
@ -3888,24 +3884,6 @@ bool nsContentUtils::IsUtf8OnlyPlainTextType(const nsACString& aContentType) {
aContentType.EqualsLiteral(TEXT_VTT);
}
// static
bool nsContentUtils::IsInChromeDocshell(Document* aDocument) {
if (!aDocument) {
return false;
}
if (aDocument->GetDisplayDocument()) {
return IsInChromeDocshell(aDocument->GetDisplayDocument());
}
nsCOMPtr<nsIDocShellTreeItem> docShell = aDocument->GetDocShell();
if (!docShell) {
return false;
}
return docShell->ItemType() == nsIDocShellTreeItem::typeChrome;
}
// static
nsIContentPolicy* nsContentUtils::GetContentPolicy() {
if (!sTriedToGetContentPolicy) {

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

@ -1227,7 +1227,9 @@ class nsContentUtils {
/**
* Returns true if aDocument is a chrome document
*/
static bool IsChromeDoc(const Document* aDocument);
static bool IsChromeDoc(const Document* aDocument) {
return aDocument && aDocument->NodePrincipal() == sSystemPrincipal;
}
/**
* Returns true if aDocument is in a docshell whose parent is the same type
@ -1250,7 +1252,9 @@ class nsContentUtils {
* display purposes. Returns false for null documents or documents
* which do not belong to a docshell.
*/
static bool IsInChromeDocshell(Document* aDocument);
static bool IsInChromeDocshell(const Document* aDocument) {
return aDocument && aDocument->IsInChromeDocShell();
}
/**
* Return the content policy service

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

@ -40,6 +40,7 @@ EXPORTS += [
'LayersTypes.h',
'LayerTreeInvalidation.h',
'LayerUserData.h',
'opengl/OGLShaderConfig.h',
'opengl/OGLShaderProgram.h',
'protobuf/LayerScopePacket.pb.h',
'ReadbackLayer.h',

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

@ -45,6 +45,7 @@
#include "nsRect.h" // for mozilla::gfx::IntRect
#include "nsServiceManagerUtils.h" // for do_GetService
#include "nsString.h" // for nsString, nsAutoCString, etc
#include "OGLShaderProgram.h" // for ShaderProgramOGL, etc
#include "ScopedGLHelpers.h"
#include "GLReadTexImageHelper.h"
#include "GLBlitTextureImageHelper.h"
@ -152,6 +153,12 @@ bool AsyncReadbackBufferOGL::MapAndCopyInto(DataSourceSurface* aSurface,
return true;
}
PerUnitTexturePoolOGL::PerUnitTexturePoolOGL(gl::GLContext* aGL)
: mTextureTarget(0), // zero is never a valid texture target
mGL(aGL) {}
PerUnitTexturePoolOGL::~PerUnitTexturePoolOGL() { DestroyTextures(); }
static void BindMaskForProgram(ShaderProgramOGL* aProgram,
TextureSourceOGL* aSourceMask, GLenum aTexUnit,
const gfx::Matrix4x4& aTransform) {

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

@ -7,12 +7,13 @@
#ifndef MOZILLA_GFX_COMPOSITOROGL_H
#define MOZILLA_GFX_COMPOSITOROGL_H
#include <map>
#include <unordered_set>
#include "gfx2DGlue.h"
#include "GLContextTypes.h" // for GLContext, etc
#include "GLDefs.h" // for GLuint, LOCAL_GL_TEXTURE_2D, etc
#include "OGLShaderProgram.h" // for ShaderProgramOGL, etc
#include "OGLShaderConfig.h" // for ShaderConfigOGL
#include "Units.h" // for ScreenPoint
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/Attributes.h" // for override, final
@ -45,6 +46,7 @@ class CompositingRenderTarget;
class CompositingRenderTargetOGL;
class DataTextureSource;
class GLManagerCompositor;
class ShaderProgramOGL;
class TextureSource;
class TextureSourceOGL;
class BufferTextureHost;
@ -81,12 +83,8 @@ class CompositorTexturePoolOGL {
*/
class PerUnitTexturePoolOGL : public CompositorTexturePoolOGL {
public:
explicit PerUnitTexturePoolOGL(gl::GLContext* aGL)
: mTextureTarget(0) // zero is never a valid texture target
,
mGL(aGL) {}
virtual ~PerUnitTexturePoolOGL() { DestroyTextures(); }
explicit PerUnitTexturePoolOGL(gl::GLContext* aGL);
virtual ~PerUnitTexturePoolOGL();
virtual void Clear() override { DestroyTextures(); }

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

@ -5,8 +5,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GLManager.h"
#include "CompositorOGL.h" // for CompositorOGL
#include "GLContext.h" // for GLContext
#include "CompositorOGL.h" // for CompositorOGL
#include "GLContext.h" // for GLContext
#include "OGLShaderProgram.h"
#include "mozilla/Attributes.h" // for override
#include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/layers/Compositor.h" // for Compositor

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

@ -8,7 +8,6 @@
#define MOZILLA_GFX_GLMANAGER_H
#include "mozilla/gfx/Types.h" // for SurfaceFormat
#include "OGLShaderProgram.h"
namespace mozilla {
namespace gl {
@ -18,6 +17,7 @@ class GLContext;
namespace layers {
class LayerManagerComposite;
class ShaderProgramOGL;
/**
* Minimal interface to allow widgets to draw using OpenGL. Abstracts

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

@ -0,0 +1,266 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef GFX_OGLSHADERCONFIG_H
#define GFX_OGLSHADERCONFIG_H
#include "gfxTypes.h"
#include "ImageTypes.h"
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/Pair.h" // for Pair
#include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
#include "mozilla/gfx/Rect.h" // for Rect
#include "mozilla/gfx/Types.h"
#include "nsDebug.h" // for NS_ASSERTION
#include "nsPoint.h" // for nsIntPoint
#include "nsTArray.h" // for nsTArray
#include "mozilla/layers/CompositorTypes.h"
namespace mozilla {
namespace layers {
enum ShaderFeatures {
ENABLE_RENDER_COLOR = 0x01,
ENABLE_TEXTURE_RECT = 0x02,
ENABLE_TEXTURE_EXTERNAL = 0x04,
ENABLE_TEXTURE_YCBCR = 0x08,
ENABLE_TEXTURE_NV12 = 0x10,
ENABLE_TEXTURE_COMPONENT_ALPHA = 0x20,
ENABLE_TEXTURE_NO_ALPHA = 0x40,
ENABLE_TEXTURE_RB_SWAP = 0x80,
ENABLE_OPACITY = 0x100,
ENABLE_BLUR = 0x200,
ENABLE_COLOR_MATRIX = 0x400,
ENABLE_MASK = 0x800,
ENABLE_NO_PREMUL_ALPHA = 0x1000,
ENABLE_DEAA = 0x2000,
ENABLE_DYNAMIC_GEOMETRY = 0x4000,
ENABLE_MASK_TEXTURE_RECT = 0x8000,
};
class KnownUniform {
public:
// this needs to be kept in sync with strings in 'AddUniforms'
enum KnownUniformName {
NotAKnownUniform = -1,
LayerTransform = 0,
LayerTransformInverse,
MaskTransform,
BackdropTransform,
LayerRects,
MatrixProj,
TextureTransform,
TextureRects,
RenderTargetOffset,
LayerOpacity,
Texture,
YTexture,
CbTexture,
CrTexture,
BlackTexture,
WhiteTexture,
MaskTexture,
BackdropTexture,
RenderColor,
TexCoordMultiplier,
CbCrTexCoordMultiplier,
MaskCoordMultiplier,
TexturePass2,
ColorMatrix,
ColorMatrixVector,
BlurRadius,
BlurOffset,
BlurAlpha,
BlurGaussianKernel,
SSEdges,
ViewportSize,
VisibleCenter,
YuvColorMatrix,
KnownUniformCount
};
KnownUniform() {
mName = NotAKnownUniform;
mNameString = nullptr;
mLocation = -1;
memset(&mValue, 0, sizeof(mValue));
}
bool UpdateUniform(int32_t i1) {
if (mLocation == -1) return false;
if (mValue.i1 != i1) {
mValue.i1 = i1;
return true;
}
return false;
}
bool UpdateUniform(float f1) {
if (mLocation == -1) return false;
if (mValue.f1 != f1) {
mValue.f1 = f1;
return true;
}
return false;
}
bool UpdateUniform(float f1, float f2) {
if (mLocation == -1) return false;
if (mValue.f16v[0] != f1 || mValue.f16v[1] != f2) {
mValue.f16v[0] = f1;
mValue.f16v[1] = f2;
return true;
}
return false;
}
bool UpdateUniform(float f1, float f2, float f3, float f4) {
if (mLocation == -1) return false;
if (mValue.f16v[0] != f1 || mValue.f16v[1] != f2 || mValue.f16v[2] != f3 ||
mValue.f16v[3] != f4) {
mValue.f16v[0] = f1;
mValue.f16v[1] = f2;
mValue.f16v[2] = f3;
mValue.f16v[3] = f4;
return true;
}
return false;
}
bool UpdateUniform(int cnt, const float* fp) {
if (mLocation == -1) return false;
switch (cnt) {
case 1:
case 2:
case 3:
case 4:
case 9:
case 16:
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt) != 0) {
memcpy(mValue.f16v, fp, sizeof(float) * cnt);
return true;
}
return false;
}
MOZ_ASSERT_UNREACHABLE("cnt must be 1 2 3 4 9 or 16");
return false;
}
bool UpdateArrayUniform(int cnt, const float* fp) {
if (mLocation == -1) return false;
if (cnt > 16) {
return false;
}
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt) != 0) {
memcpy(mValue.f16v, fp, sizeof(float) * cnt);
return true;
}
return false;
}
bool UpdateArrayUniform(int cnt, const gfx::Point3D* points) {
if (mLocation == -1) return false;
if (cnt > 4) {
return false;
}
float fp[12];
float* d = fp;
for (int i = 0; i < cnt; i++) {
// Note: Do not want to make assumptions about .x, .y, .z member packing.
// If gfx::Point3D is updated to make this guarantee, SIMD optimizations
// may be possible
*d++ = points[i].x;
*d++ = points[i].y;
*d++ = points[i].z;
}
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt * 3) != 0) {
memcpy(mValue.f16v, fp, sizeof(float) * cnt * 3);
return true;
}
return false;
}
KnownUniformName mName;
const char* mNameString;
int32_t mLocation;
union {
int i1;
float f1;
float f16v[16];
} mValue;
};
class ShaderConfigOGL {
public:
ShaderConfigOGL()
: mFeatures(0),
mMultiplier(1),
mCompositionOp(gfx::CompositionOp::OP_OVER) {}
void SetRenderColor(bool aEnabled);
void SetTextureTarget(GLenum aTarget);
void SetMaskTextureTarget(GLenum aTarget);
void SetRBSwap(bool aEnabled);
void SetNoAlpha(bool aEnabled);
void SetOpacity(bool aEnabled);
void SetYCbCr(bool aEnabled);
void SetNV12(bool aEnabled);
void SetComponentAlpha(bool aEnabled);
void SetColorMatrix(bool aEnabled);
void SetBlur(bool aEnabled);
void SetMask(bool aEnabled);
void SetDEAA(bool aEnabled);
void SetCompositionOp(gfx::CompositionOp aOp);
void SetNoPremultipliedAlpha();
void SetDynamicGeometry(bool aEnabled);
void SetColorMultiplier(uint32_t aMultiplier);
bool operator<(const ShaderConfigOGL& other) const {
return mFeatures < other.mFeatures ||
(mFeatures == other.mFeatures &&
(int)mCompositionOp < (int)other.mCompositionOp) ||
(mFeatures == other.mFeatures &&
(int)mCompositionOp == (int)other.mCompositionOp &&
mMultiplier < other.mMultiplier);
}
public:
void SetFeature(int aBitmask, bool aState) {
if (aState)
mFeatures |= aBitmask;
else
mFeatures &= (~aBitmask);
}
int mFeatures;
uint32_t mMultiplier;
gfx::CompositionOp mCompositionOp;
};
static inline ShaderConfigOGL ShaderConfigFromTargetAndFormat(
GLenum aTarget, gfx::SurfaceFormat aFormat) {
ShaderConfigOGL config;
config.SetTextureTarget(aTarget);
config.SetRBSwap(aFormat == gfx::SurfaceFormat::B8G8R8A8 ||
aFormat == gfx::SurfaceFormat::B8G8R8X8);
config.SetNoAlpha(aFormat == gfx::SurfaceFormat::B8G8R8X8 ||
aFormat == gfx::SurfaceFormat::R8G8B8X8 ||
aFormat == gfx::SurfaceFormat::R5G6B5_UINT16);
return config;
}
} // namespace layers
} // namespace mozilla
#endif // GFX_OGLSHADERCONFIG_H

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

@ -5,6 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "OGLShaderProgram.h"
#include <stdint.h> // for uint32_t
#include <sstream> // for ostringstream
#include "gfxEnv.h"

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

@ -8,262 +8,27 @@
#define GFX_OGLSHADERPROGRAM_H
#include "GLContext.h" // for fast inlines of glUniform*
#include "gfxTypes.h"
#include "ImageTypes.h"
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/Pair.h" // for Pair
#include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
#include "mozilla/gfx/Rect.h" // for Rect
#include "mozilla/gfx/Types.h"
#include "nsDebug.h" // for NS_ASSERTION
#include "nsPoint.h" // for nsIntPoint
#include "nsTArray.h" // for nsTArray
#include "mozilla/layers/CompositorTypes.h"
#include "OGLShaderConfig.h"
#include <string>
namespace mozilla {
namespace layers {
class Layer;
enum ShaderFeatures {
ENABLE_RENDER_COLOR = 0x01,
ENABLE_TEXTURE_RECT = 0x02,
ENABLE_TEXTURE_EXTERNAL = 0x04,
ENABLE_TEXTURE_YCBCR = 0x08,
ENABLE_TEXTURE_NV12 = 0x10,
ENABLE_TEXTURE_COMPONENT_ALPHA = 0x20,
ENABLE_TEXTURE_NO_ALPHA = 0x40,
ENABLE_TEXTURE_RB_SWAP = 0x80,
ENABLE_OPACITY = 0x100,
ENABLE_BLUR = 0x200,
ENABLE_COLOR_MATRIX = 0x400,
ENABLE_MASK = 0x800,
ENABLE_NO_PREMUL_ALPHA = 0x1000,
ENABLE_DEAA = 0x2000,
ENABLE_DYNAMIC_GEOMETRY = 0x4000,
ENABLE_MASK_TEXTURE_RECT = 0x8000,
};
class KnownUniform {
public:
// this needs to be kept in sync with strings in 'AddUniforms'
enum KnownUniformName {
NotAKnownUniform = -1,
LayerTransform = 0,
LayerTransformInverse,
MaskTransform,
BackdropTransform,
LayerRects,
MatrixProj,
TextureTransform,
TextureRects,
RenderTargetOffset,
LayerOpacity,
Texture,
YTexture,
CbTexture,
CrTexture,
BlackTexture,
WhiteTexture,
MaskTexture,
BackdropTexture,
RenderColor,
TexCoordMultiplier,
CbCrTexCoordMultiplier,
MaskCoordMultiplier,
TexturePass2,
ColorMatrix,
ColorMatrixVector,
BlurRadius,
BlurOffset,
BlurAlpha,
BlurGaussianKernel,
SSEdges,
ViewportSize,
VisibleCenter,
YuvColorMatrix,
KnownUniformCount
};
KnownUniform() {
mName = NotAKnownUniform;
mNameString = nullptr;
mLocation = -1;
memset(&mValue, 0, sizeof(mValue));
}
bool UpdateUniform(int32_t i1) {
if (mLocation == -1) return false;
if (mValue.i1 != i1) {
mValue.i1 = i1;
return true;
}
return false;
}
bool UpdateUniform(float f1) {
if (mLocation == -1) return false;
if (mValue.f1 != f1) {
mValue.f1 = f1;
return true;
}
return false;
}
bool UpdateUniform(float f1, float f2) {
if (mLocation == -1) return false;
if (mValue.f16v[0] != f1 || mValue.f16v[1] != f2) {
mValue.f16v[0] = f1;
mValue.f16v[1] = f2;
return true;
}
return false;
}
bool UpdateUniform(float f1, float f2, float f3, float f4) {
if (mLocation == -1) return false;
if (mValue.f16v[0] != f1 || mValue.f16v[1] != f2 || mValue.f16v[2] != f3 ||
mValue.f16v[3] != f4) {
mValue.f16v[0] = f1;
mValue.f16v[1] = f2;
mValue.f16v[2] = f3;
mValue.f16v[3] = f4;
return true;
}
return false;
}
bool UpdateUniform(int cnt, const float* fp) {
if (mLocation == -1) return false;
switch (cnt) {
case 1:
case 2:
case 3:
case 4:
case 9:
case 16:
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt) != 0) {
memcpy(mValue.f16v, fp, sizeof(float) * cnt);
return true;
}
return false;
}
MOZ_ASSERT_UNREACHABLE("cnt must be 1 2 3 4 9 or 16");
return false;
}
bool UpdateArrayUniform(int cnt, const float* fp) {
if (mLocation == -1) return false;
if (cnt > 16) {
return false;
}
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt) != 0) {
memcpy(mValue.f16v, fp, sizeof(float) * cnt);
return true;
}
return false;
}
bool UpdateArrayUniform(int cnt, const gfx::Point3D* points) {
if (mLocation == -1) return false;
if (cnt > 4) {
return false;
}
float fp[12];
float* d = fp;
for (int i = 0; i < cnt; i++) {
// Note: Do not want to make assumptions about .x, .y, .z member packing.
// If gfx::Point3D is updated to make this guarantee, SIMD optimizations
// may be possible
*d++ = points[i].x;
*d++ = points[i].y;
*d++ = points[i].z;
}
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt * 3) != 0) {
memcpy(mValue.f16v, fp, sizeof(float) * cnt * 3);
return true;
}
return false;
}
KnownUniformName mName;
const char* mNameString;
int32_t mLocation;
union {
int i1;
float f1;
float f16v[16];
} mValue;
};
class ShaderConfigOGL {
public:
ShaderConfigOGL()
: mFeatures(0),
mMultiplier(1),
mCompositionOp(gfx::CompositionOp::OP_OVER) {}
void SetRenderColor(bool aEnabled);
void SetTextureTarget(GLenum aTarget);
void SetMaskTextureTarget(GLenum aTarget);
void SetRBSwap(bool aEnabled);
void SetNoAlpha(bool aEnabled);
void SetOpacity(bool aEnabled);
void SetYCbCr(bool aEnabled);
void SetNV12(bool aEnabled);
void SetComponentAlpha(bool aEnabled);
void SetColorMatrix(bool aEnabled);
void SetBlur(bool aEnabled);
void SetMask(bool aEnabled);
void SetDEAA(bool aEnabled);
void SetCompositionOp(gfx::CompositionOp aOp);
void SetNoPremultipliedAlpha();
void SetDynamicGeometry(bool aEnabled);
void SetColorMultiplier(uint32_t aMultiplier);
bool operator<(const ShaderConfigOGL& other) const {
return mFeatures < other.mFeatures ||
(mFeatures == other.mFeatures &&
(int)mCompositionOp < (int)other.mCompositionOp) ||
(mFeatures == other.mFeatures &&
(int)mCompositionOp == (int)other.mCompositionOp &&
mMultiplier < other.mMultiplier);
}
public:
void SetFeature(int aBitmask, bool aState) {
if (aState)
mFeatures |= aBitmask;
else
mFeatures &= (~aBitmask);
}
int mFeatures;
uint32_t mMultiplier;
gfx::CompositionOp mCompositionOp;
};
static inline ShaderConfigOGL ShaderConfigFromTargetAndFormat(
GLenum aTarget, gfx::SurfaceFormat aFormat) {
ShaderConfigOGL config;
config.SetTextureTarget(aTarget);
config.SetRBSwap(aFormat == gfx::SurfaceFormat::B8G8R8A8 ||
aFormat == gfx::SurfaceFormat::B8G8R8X8);
config.SetNoAlpha(aFormat == gfx::SurfaceFormat::B8G8R8X8 ||
aFormat == gfx::SurfaceFormat::R8G8B8X8 ||
aFormat == gfx::SurfaceFormat::R5G6B5_UINT16);
return config;
}
#if defined(DEBUG)
# define CHECK_CURRENT_PROGRAM 1
# define ASSERT_THIS_PROGRAM \
do { \
GLuint currentProgram; \
mGL->GetUIntegerv(LOCAL_GL_CURRENT_PROGRAM, &currentProgram); \
MOZ_ASSERT(currentProgram == mProgram, \
"SetUniform with wrong program active!"); \
} while (0)
#else
# define ASSERT_THIS_PROGRAM \
do { \
} while (0)
#endif
/**
* This struct represents the shaders that make up a program and the uniform
@ -296,21 +61,6 @@ struct ProgramProfileOGL {
std::ostringstream& fs);
};
#if defined(DEBUG)
# define CHECK_CURRENT_PROGRAM 1
# define ASSERT_THIS_PROGRAM \
do { \
GLuint currentProgram; \
mGL->GetUIntegerv(LOCAL_GL_CURRENT_PROGRAM, &currentProgram); \
MOZ_ASSERT(currentProgram == mProgram, \
"SetUniform with wrong program active!"); \
} while (0)
#else
# define ASSERT_THIS_PROGRAM \
do { \
} while (0)
#endif
/**
* Represents an OGL shader program. The details of a program are represented
* by a ProgramProfileOGL
@ -645,4 +395,4 @@ class ShaderProgramOGL {
} // namespace layers
} // namespace mozilla
#endif /* GFX_OGLSHADERPROGRAM_H */
#endif // GFX_OGLSHADERPROGRAM_H

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

@ -39,6 +39,17 @@ namespace layers {
class Compositor;
void ApplySamplingFilterToBoundTexture(gl::GLContext* aGL,
gfx::SamplingFilter aSamplingFilter,
GLuint aTarget) {
GLenum filter =
(aSamplingFilter == gfx::SamplingFilter::POINT ? LOCAL_GL_NEAREST
: LOCAL_GL_LINEAR);
aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MIN_FILTER, filter);
aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MAG_FILTER, filter);
}
already_AddRefed<TextureHost> CreateTextureHostOGL(
const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator,
LayersBackend aBackend, TextureFlags aFlags) {

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

@ -27,11 +27,10 @@
#include "mozilla/layers/TextureHost.h" // for TextureHost, etc
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "mozilla/webrender/RenderThread.h"
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsDebug.h" // for NS_WARNING
#include "nsISupportsImpl.h" // for TextureImage::Release, etc
#include "nsRegionFwd.h" // for nsIntRegion
#include "OGLShaderProgram.h" // for ShaderProgramType, etc
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsDebug.h" // for NS_WARNING
#include "nsISupportsImpl.h" // for TextureImage::Release, etc
#include "nsRegionFwd.h" // for nsIntRegion
#ifdef MOZ_WIDGET_ANDROID
# include "GeneratedJNIWrappers.h"
@ -50,16 +49,9 @@ class CompositorOGL;
class TextureImageTextureSourceOGL;
class GLTextureSource;
inline void ApplySamplingFilterToBoundTexture(
gl::GLContext* aGL, gfx::SamplingFilter aSamplingFilter,
GLuint aTarget = LOCAL_GL_TEXTURE_2D) {
GLenum filter =
(aSamplingFilter == gfx::SamplingFilter::POINT ? LOCAL_GL_NEAREST
: LOCAL_GL_LINEAR);
aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MIN_FILTER, filter);
aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MAG_FILTER, filter);
}
void ApplySamplingFilterToBoundTexture(gl::GLContext* aGL,
gfx::SamplingFilter aSamplingFilter,
GLuint aTarget = LOCAL_GL_TEXTURE_2D);
/*
* TextureHost implementations for the OpenGL backend.

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

@ -7,6 +7,7 @@
#include "X11TextureSourceOGL.h"
#include "gfxXlibSurface.h"
#include "gfx2DGlue.h"
#include "GLContext.h"
namespace mozilla {
namespace layers {

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

@ -7,6 +7,7 @@
#include "RenderAndroidSurfaceTextureHostOGL.h"
#include "mozilla/gfx/Logging.h"
#include "GLContext.h"
namespace mozilla {
namespace wr {

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

@ -20,7 +20,6 @@
#include "mozilla/UniquePtr.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "mozilla/layers/SynchronousTask.h"
#include "GLContext.h"
#include "mozilla/VsyncDispatcher.h"
#include <list>
@ -28,6 +27,9 @@
#include <unordered_map>
namespace mozilla {
namespace gl {
class GLContext;
} // namespace gl
namespace wr {
typedef MozPromise<MemoryReport, bool, true> MemoryReportPromise;

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

@ -161,14 +161,13 @@ VertexInfo write_text_vertex(RectWithSize local_clip_rect,
void main(void) {
int prim_header_address = aData.x;
int glyph_index = aData.y;
int glyph_index = aData.y & 0xffff;
int raster_space = aData.y >> 16;
int resource_address = aData.z;
int subpx_dir = aData.w >> 16;
int color_mode = aData.w & 0xffff;
PrimitiveHeader ph = fetch_prim_header(prim_header_address);
int raster_space = ph.user_data.z;
Transform transform = fetch_transform(ph.transform_id);
ClipArea clip_area = fetch_clip_area(ph.clip_task_index);
PictureTask task = fetch_picture_task(ph.render_task_index);
@ -193,8 +192,10 @@ void main(void) {
RectWithSize glyph_rect = RectWithSize(res.offset + glyph_transform * (text_offset + glyph.offset),
res.uv_rect.zw - res.uv_rect.xy);
#else
float inverse_raster_scale = float(ph.user_data.z) / 65535.0;
// Scale from glyph space to local space.
float scale = res.scale / task.device_pixel_scale;
float scale = inverse_raster_scale * res.scale / task.device_pixel_scale;
// Compute the glyph rect in local space.
RectWithSize glyph_rect = RectWithSize(scale * res.offset + text_offset + glyph.offset,

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

@ -851,7 +851,7 @@ impl AlphaBatchBuilder {
[
(run.reference_frame_relative_offset.x * 256.0) as i32,
(run.reference_frame_relative_offset.y * 256.0) as i32,
run.raster_space as i32,
(run.inverse_raster_scale * 65535.0).round() as i32,
],
);
let key = BatchKey::new(kind, blend_mode, textures);
@ -866,7 +866,8 @@ impl AlphaBatchBuilder {
for glyph in glyphs {
batch.push(base_instance.build(
glyph.index_in_text_run,
glyph.index_in_text_run |
(run.raster_space as i32) << 16,
glyph.uv_rect_address.as_int(),
(subpx_dir as u32 as i32) << 16 |
(color_mode as u32 as i32),
@ -2539,12 +2540,11 @@ pub fn resolve_image(
}
}
/// Batcher managing draw calls into the clip mask (in the RT cache).
/// A list of clip instances to be drawn into a target.
#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct ClipBatcher {
pub struct ClipBatchList {
/// Rectangle draws fill up the rectangles with rounded corners.
pub rectangles: Vec<ClipMaskInstance>,
/// Image draws apply the image masking.
@ -2552,14 +2552,42 @@ pub struct ClipBatcher {
pub box_shadows: FastHashMap<TextureSource, Vec<ClipMaskInstance>>,
}
impl ClipBatcher {
pub fn new() -> Self {
ClipBatcher {
impl ClipBatchList {
fn new() -> Self {
ClipBatchList {
rectangles: Vec::new(),
images: FastHashMap::default(),
box_shadows: FastHashMap::default(),
}
}
}
/// Batcher managing draw calls into the clip mask (in the RT cache).
#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct ClipBatcher {
/// The first clip in each clip task. This will overwrite all pixels
/// in the clip region, so we can skip doing a clear and write with
/// blending disabled, which is a big performance win on Intel GPUs.
pub primary_clips: ClipBatchList,
/// Any subsequent clip masks (rare) for a clip task get drawn in
/// a second pass with multiplicative blending enabled.
pub secondary_clips: ClipBatchList,
gpu_supports_fast_clears: bool,
}
impl ClipBatcher {
pub fn new(
gpu_supports_fast_clears: bool,
) -> Self {
ClipBatcher {
primary_clips: ClipBatchList::new(),
secondary_clips: ClipBatchList::new(),
gpu_supports_fast_clears,
}
}
pub fn add_clip_region(
&mut self,
@ -2580,7 +2608,7 @@ impl ClipBatcher {
snap_offsets: SnapOffsets::empty(),
};
self.rectangles.push(instance);
self.primary_clips.rectangles.push(instance);
}
/// Where appropriate, draw a clip rectangle as a small series of tiles,
@ -2595,6 +2623,7 @@ impl ClipBatcher {
device_pixel_scale: DevicePixelScale,
gpu_address: GpuCacheAddress,
instance: &ClipMaskInstance,
clip_node_index: u32,
) -> bool {
// Only try to draw in tiles if the clip mark is big enough.
if mask_screen_rect.area() < CLIP_RECTANGLE_AREA_THRESHOLD {
@ -2636,6 +2665,7 @@ impl ClipBatcher {
// and only for rectangles (not rounded etc), the world_device_rect is not conservative - we know
// that there is no inner_rect, and the world_device_rect should be the real, axis-aligned clip rect.
let mask_origin = mask_screen_rect.origin.to_f32().to_vector();
let clip_list = self.get_batch_list(clip_node_index);
for y in 0 .. y_tiles {
for x in 0 .. x_tiles {
@ -2660,7 +2690,7 @@ impl ClipBatcher {
// these pixels would be redundant - since this clip can't possibly
// affect the pixels in this tile, skip them!
if !world_device_rect.contains_rect(&world_sub_rect) {
self.rectangles.push(ClipMaskInstance {
clip_list.rectangles.push(ClipMaskInstance {
clip_data_address: gpu_address,
sub_rect: normalized_sub_rect,
..*instance
@ -2672,6 +2702,19 @@ impl ClipBatcher {
true
}
/// Retrieve the correct clip batch list to append to, depending
/// on whether this is the first clip mask for a clip task.
fn get_batch_list(
&mut self,
item_index: u32,
) -> &mut ClipBatchList {
if item_index == 0 && !self.gpu_supports_fast_clears {
&mut self.primary_clips
} else {
&mut self.secondary_clips
}
}
pub fn add(
&mut self,
task_address: RenderTaskAddress,
@ -2739,7 +2782,9 @@ impl ClipBatcher {
return;
}
};
self.images
self.get_batch_list(i)
.images
.entry(cache_item.texture_id)
.or_insert(Vec::new())
.push(ClipMaskInstance {
@ -2778,7 +2823,8 @@ impl ClipBatcher {
.get_texture_cache_item(&rt_cache_entry.handle);
debug_assert_ne!(cache_item.texture_id, TextureSource::Invalid);
self.box_shadows
self.get_batch_list(i)
.box_shadows
.entry(cache_item.texture_id)
.or_insert(Vec::new())
.push(ClipMaskInstance {
@ -2790,10 +2836,12 @@ impl ClipBatcher {
ClipItem::Rectangle(_, ClipMode::ClipOut) => {
let gpu_address =
gpu_cache.get_address(&clip_node.gpu_cache_handle);
self.rectangles.push(ClipMaskInstance {
clip_data_address: gpu_address,
..instance
});
self.get_batch_list(i)
.rectangles
.push(ClipMaskInstance {
clip_data_address: gpu_address,
..instance
});
}
ClipItem::Rectangle(clip_rect_size, ClipMode::Clip) => {
if !clip_instance.flags.contains(ClipNodeFlags::SAME_COORD_SYSTEM) {
@ -2808,21 +2856,26 @@ impl ClipBatcher {
device_pixel_scale,
gpu_address,
&instance,
i,
) {
self.rectangles.push(ClipMaskInstance {
clip_data_address: gpu_address,
..instance
});
self.get_batch_list(i)
.rectangles
.push(ClipMaskInstance {
clip_data_address: gpu_address,
..instance
});
}
}
}
ClipItem::RoundedRectangle(..) => {
let gpu_address =
gpu_cache.get_address(&clip_node.gpu_cache_handle);
self.rectangles.push(ClipMaskInstance {
clip_data_address: gpu_address,
..instance
});
self.get_batch_list(i)
.rectangles
.push(ClipMaskInstance {
clip_data_address: gpu_address,
..instance
});
}
}
}

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

@ -55,6 +55,7 @@ pub struct FrameBuilderConfig {
pub enable_picture_caching: bool,
/// True if we're running tests (i.e. via wrench).
pub testing: bool,
pub gpu_supports_fast_clears: bool,
}
/// A set of common / global resources that are retained between
@ -138,6 +139,7 @@ pub struct FrameBuildingContext<'a> {
pub clip_scroll_tree: &'a ClipScrollTree,
pub max_local_clip: LayoutRect,
pub debug_flags: DebugFlags,
pub fb_config: &'a FrameBuilderConfig,
}
pub struct FrameBuildingState<'a> {
@ -234,6 +236,7 @@ impl FrameBuilder {
chase_primitive: ChasePrimitive::Nothing,
enable_picture_caching: false,
testing: false,
gpu_supports_fast_clears: false,
},
}
}
@ -338,6 +341,7 @@ impl FrameBuilder {
LayoutSize::new(2.0 * MAX_CLIP_COORD, 2.0 * MAX_CLIP_COORD),
),
debug_flags,
fb_config: &self.config,
};
// Construct a dummy root surface, that represents the
@ -577,13 +581,14 @@ impl FrameBuilder {
// Add passes as required for our cached render tasks.
if !render_tasks.cacheable_render_tasks.is_empty() {
passes.push(RenderPass::new_off_screen(screen_size));
passes.push(RenderPass::new_off_screen(screen_size, self.config.gpu_supports_fast_clears));
for cacheable_render_task in &render_tasks.cacheable_render_tasks {
render_tasks.assign_to_passes(
*cacheable_render_task,
0,
screen_size,
&mut passes,
self.config.gpu_supports_fast_clears,
);
}
passes.reverse();
@ -591,12 +596,13 @@ impl FrameBuilder {
if let Some(main_render_task_id) = main_render_task_id {
let passes_start = passes.len();
passes.push(RenderPass::new_main_framebuffer(screen_size));
passes.push(RenderPass::new_main_framebuffer(screen_size, self.config.gpu_supports_fast_clears));
render_tasks.assign_to_passes(
main_render_task_id,
passes_start,
screen_size,
&mut passes,
self.config.gpu_supports_fast_clears,
);
passes[passes_start..].reverse();
}

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

@ -946,6 +946,7 @@ impl BrushSegment {
root_spatial_node_index: SpatialNodeIndex,
surface_index: SurfaceIndex,
pic_state: &mut PictureState,
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
clip_data_store: &mut ClipDataStore,
unclipped: &DeviceRect,
@ -996,6 +997,7 @@ impl BrushSegment {
clip_data_store,
snap_offsets,
device_pixel_scale,
frame_context.fb_config,
);
let clip_task_id = frame_state.render_tasks.add(clip_task);
@ -3297,6 +3299,7 @@ impl PrimitiveInstance {
root_spatial_node_index,
pic_context.surface_index,
pic_state,
frame_context,
frame_state,
&mut data_stores.clip,
unclipped,
@ -3337,6 +3340,7 @@ impl PrimitiveInstance {
root_spatial_node_index,
pic_context.surface_index,
pic_state,
frame_context,
frame_state,
&mut data_stores.clip,
unclipped,
@ -3439,6 +3443,7 @@ impl PrimitiveInstance {
&mut data_stores.clip,
snap_offsets,
device_pixel_scale,
frame_context.fb_config,
);
let clip_task_id = frame_state.render_tasks.add(clip_task);

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

@ -68,6 +68,7 @@ impl AsInstanceKind<TextRunDataHandle> for TextRunKey {
reference_frame_relative_offset,
shadow: self.shadow,
raster_space: RasterizationSpace::Screen,
inverse_raster_scale: 1.0,
});
PrimitiveInstanceKind::TextRun{ data_handle, run_index }
@ -214,6 +215,7 @@ pub struct TextRunPrimitive {
pub reference_frame_relative_offset: LayoutVector2D,
pub shadow: bool,
pub raster_space: RasterizationSpace,
pub inverse_raster_scale: f32,
}
impl TextRunPrimitive {
@ -225,8 +227,20 @@ impl TextRunPrimitive {
allow_subpixel_aa: bool,
raster_space: RasterSpace,
) -> bool {
// If local raster space is specified, include that in the scale
// of the glyphs that get rasterized.
// TODO(gw): Once we support proper local space raster modes, this
// will implicitly be part of the device pixel ratio for
// the (cached) local space surface, and so this code
// will no longer be required.
let raster_scale = match raster_space {
RasterSpace::Screen => 1.0,
RasterSpace::Local(scale) => scale.max(0.001),
};
self.inverse_raster_scale = 1.0 / raster_scale;
// Get the current font size in device pixels
let device_font_size = specified_font.size.scale_by(device_pixel_scale.0);
let device_font_size = specified_font.size.scale_by(device_pixel_scale.0 * raster_scale);
// Determine if rasterizing glyphs in local or screen space.
// Only support transforms that can be coerced to simple 2D transforms.
@ -337,5 +351,5 @@ fn test_struct_sizes() {
assert_eq!(mem::size_of::<TextRun>(), 88, "TextRun size changed");
assert_eq!(mem::size_of::<TextRunTemplate>(), 104, "TextRunTemplate size changed");
assert_eq!(mem::size_of::<TextRunKey>(), 96, "TextRunKey size changed");
assert_eq!(mem::size_of::<TextRunPrimitive>(), 96, "TextRunPrimitive size changed");
assert_eq!(mem::size_of::<TextRunPrimitive>(), 104, "TextRunPrimitive size changed");
}

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

@ -4,16 +4,17 @@
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceSize, DeviceIntSideOffsets};
use api::{DevicePixelScale, ImageDescriptor, ImageFormat, LayoutPoint};
use api::{LineStyle, LineOrientation, LayoutSize, DirtyRect};
use api::{LineStyle, LineOrientation, LayoutSize, DirtyRect, ClipMode};
#[cfg(feature = "pathfinder")]
use api::FontRenderMode;
use border::BorderSegmentCacheKey;
use box_shadow::{BoxShadowCacheKey};
use clip::{ClipDataStore, ClipItem, ClipStore, ClipNodeRange};
use clip::{ClipDataStore, ClipItem, ClipStore, ClipNodeRange, ClipNodeFlags};
use clip_scroll_tree::SpatialNodeIndex;
use device::TextureFilter;
#[cfg(feature = "pathfinder")]
use euclid::{TypedPoint2D, TypedVector2D};
use frame_builder::FrameBuilderConfig;
use freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
use glyph_rasterizer::GpuGlyphCacheKey;
use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
@ -146,6 +147,7 @@ impl RenderTaskTree {
pass_index: usize,
screen_size: DeviceIntSize,
passes: &mut Vec<RenderPass>,
gpu_supports_fast_clears: bool,
) {
debug_assert!(pass_index < passes.len());
#[cfg(debug_assertions)]
@ -155,10 +157,10 @@ impl RenderTaskTree {
if !task.children.is_empty() {
let child_index = pass_index + 1;
if passes.len() == child_index {
passes.push(RenderPass::new_off_screen(screen_size));
passes.push(RenderPass::new_off_screen(screen_size, gpu_supports_fast_clears));
}
for child in &task.children {
self.assign_to_passes(*child, child_index, screen_size, passes);
self.assign_to_passes(*child, child_index, screen_size, passes, gpu_supports_fast_clears);
}
}
@ -416,6 +418,8 @@ pub enum ClearMode {
// Applicable to color and alpha targets.
Zero,
One,
/// This task doesn't care what it is cleared to - it will completely overwrite it.
DontCare,
// Applicable to color targets only.
Transparent,
@ -566,6 +570,7 @@ impl RenderTask {
clip_data_store: &mut ClipDataStore,
snap_offsets: SnapOffsets,
device_pixel_scale: DevicePixelScale,
fb_config: &FrameBuilderConfig,
) -> Self {
// Step through the clip sources that make up this mask. If we find
// any box-shadow clip sources, request that image from the render
@ -576,6 +581,8 @@ impl RenderTask {
// TODO(gw): If this ever shows up in a profile, we could pre-calculate
// whether a ClipSources contains any box-shadows and skip
// this iteration for the majority of cases.
let mut needs_clear = fb_config.gpu_supports_fast_clears;
for i in 0 .. clip_node_range.count {
let clip_instance = clip_store.get_instance_from_range(&clip_node_range, i);
let clip_node = &mut clip_data_store[clip_instance.handle];
@ -606,6 +613,7 @@ impl RenderTask {
clip_data_address,
info.minimal_shadow_rect.origin,
device_pixel_scale,
fb_config,
);
let mask_task_id = render_tasks.add(mask_task);
@ -623,12 +631,30 @@ impl RenderTask {
}
));
}
ClipItem::Rectangle(..) |
ClipItem::Rectangle(_, ClipMode::Clip) => {
if !clip_instance.flags.contains(ClipNodeFlags::SAME_COORD_SYSTEM) {
// This is conservative - it's only the case that we actually need
// a clear here if we end up adding this mask via add_tiled_clip_mask,
// but for simplicity we will just clear if any of these are encountered,
// since they are rare.
needs_clear = true;
}
}
ClipItem::Rectangle(_, ClipMode::ClipOut) |
ClipItem::RoundedRectangle(..) |
ClipItem::Image { .. } => {}
}
}
// If we have a potentially tiled clip mask, clear the mask area first. Otherwise,
// the first (primary) clip mask will overwrite all the clip mask pixels with
// blending disabled to set to the initial value.
let clear_mode = if needs_clear {
ClearMode::One
} else {
ClearMode::DontCare
};
RenderTask::with_dynamic_location(
outer_rect.size,
vec![],
@ -639,7 +665,7 @@ impl RenderTask {
snap_offsets,
device_pixel_scale,
}),
ClearMode::One,
clear_mode,
)
}
@ -648,7 +674,14 @@ impl RenderTask {
clip_data_address: GpuCacheAddress,
local_pos: LayoutPoint,
device_pixel_scale: DevicePixelScale,
fb_config: &FrameBuilderConfig,
) -> Self {
let clear_mode = if fb_config.gpu_supports_fast_clears {
ClearMode::One
} else {
ClearMode::DontCare
};
RenderTask::with_dynamic_location(
size,
Vec::new(),
@ -657,7 +690,7 @@ impl RenderTask {
local_pos,
device_pixel_scale,
}),
ClearMode::One,
clear_mode,
)
}
@ -788,10 +821,7 @@ impl RenderTask {
uv_rect_handle: GpuCacheHandle::new(),
uv_rect_kind,
}),
match target_kind {
RenderTargetKind::Color => ClearMode::Transparent,
RenderTargetKind::Alpha => ClearMode::One,
},
ClearMode::DontCare,
)
}

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

@ -32,7 +32,7 @@ use api::{channel};
use api::DebugCommand;
pub use api::DebugFlags;
use api::channel::PayloadReceiverHelperMethods;
use batch::{BatchKind, BatchTextures, BrushBatchKind};
use batch::{BatchKind, BatchTextures, BrushBatchKind, ClipBatchList};
#[cfg(any(feature = "capture", feature = "replay"))]
use capture::{CaptureConfig, ExternalCaptureImage, PlainExternalImage};
use debug_colors;
@ -1829,6 +1829,7 @@ impl Renderer {
chase_primitive: options.chase_primitive,
enable_picture_caching: options.enable_picture_caching,
testing: options.testing,
gpu_supports_fast_clears: options.gpu_supports_fast_clears,
};
let device_pixel_ratio = options.device_pixel_ratio;
@ -2256,10 +2257,20 @@ impl Renderer {
"Zero Clears",
target.zero_clears.len(),
);
debug_target.add(
debug_server::BatchKind::Cache,
"One Clears",
target.one_clears.len(),
);
debug_target.add(
debug_server::BatchKind::Clip,
"BoxShadows",
target.clip_batcher.box_shadows.len(),
"BoxShadows [p]",
target.clip_batcher.primary_clips.box_shadows.len(),
);
debug_target.add(
debug_server::BatchKind::Clip,
"BoxShadows [s]",
target.clip_batcher.secondary_clips.box_shadows.len(),
);
debug_target.add(
debug_server::BatchKind::Cache,
@ -2273,11 +2284,19 @@ impl Renderer {
);
debug_target.add(
debug_server::BatchKind::Clip,
"Rectangles",
target.clip_batcher.rectangles.len(),
"Rectangles [p]",
target.clip_batcher.primary_clips.rectangles.len(),
);
for (_, items) in target.clip_batcher.images.iter() {
debug_target.add(debug_server::BatchKind::Clip, "Image mask", items.len());
debug_target.add(
debug_server::BatchKind::Clip,
"Rectangles [s]",
target.clip_batcher.secondary_clips.rectangles.len(),
);
for (_, items) in target.clip_batcher.primary_clips.images.iter() {
debug_target.add(debug_server::BatchKind::Clip, "Image mask [p]", items.len());
}
for (_, items) in target.clip_batcher.secondary_clips.images.iter() {
debug_target.add(debug_server::BatchKind::Clip, "Image mask [s]", items.len());
}
debug_target
@ -3265,7 +3284,12 @@ impl Renderer {
}
}
self.handle_scaling(&target.scalings, TextureSource::PrevPassColor, projection, stats);
self.handle_scaling(
&target.scalings,
TextureSource::PrevPassColor,
projection,
stats,
);
// Small helper fn to iterate a regions list, also invoking the closure
// if there are no regions.
@ -3550,6 +3574,69 @@ impl Renderer {
}
}
/// Draw all the instances in a clip batcher list to the current target.
fn draw_clip_batch_list(
&mut self,
list: &ClipBatchList,
projection: &Transform3D<f32>,
stats: &mut RendererStats,
) {
// draw rounded cornered rectangles
if !list.rectangles.is_empty() {
let _gm2 = self.gpu_profile.start_marker("clip rectangles");
self.shaders.borrow_mut().cs_clip_rectangle.bind(
&mut self.device,
projection,
&mut self.renderer_errors,
);
self.draw_instanced_batch(
&list.rectangles,
VertexArrayKind::Clip,
&BatchTextures::no_texture(),
stats,
);
}
// draw box-shadow clips
for (mask_texture_id, items) in list.box_shadows.iter() {
let _gm2 = self.gpu_profile.start_marker("box-shadows");
let textures = BatchTextures {
colors: [
mask_texture_id.clone(),
TextureSource::Invalid,
TextureSource::Invalid,
],
};
self.shaders.borrow_mut().cs_clip_box_shadow
.bind(&mut self.device, projection, &mut self.renderer_errors);
self.draw_instanced_batch(
items,
VertexArrayKind::Clip,
&textures,
stats,
);
}
// draw image masks
for (mask_texture_id, items) in list.images.iter() {
let _gm2 = self.gpu_profile.start_marker("clip images");
let textures = BatchTextures {
colors: [
mask_texture_id.clone(),
TextureSource::Invalid,
TextureSource::Invalid,
],
};
self.shaders.borrow_mut().cs_clip_image
.bind(&mut self.device, projection, &mut self.renderer_errors);
self.draw_instanced_batch(
items,
VertexArrayKind::Clip,
&textures,
stats,
);
}
}
fn draw_alpha_target(
&mut self,
draw_target: DrawTarget,
@ -3567,18 +3654,13 @@ impl Renderer {
self.device.bind_draw_target(draw_target);
self.device.disable_depth();
self.device.disable_depth_write();
self.set_blend(false, FramebufferKind::Other);
// TODO(gw): Applying a scissor rect and minimal clear here
// is a very large performance win on the Intel and nVidia
// GPUs that I have tested with. It's possible it may be a
// performance penalty on other GPU types - we should test this
// and consider different code paths.
let clear_color = [1.0, 1.0, 1.0, 0.0];
self.device.clear_target(
Some(clear_color),
None,
Some(target.used_rect()),
);
let zero_color = [0.0, 0.0, 0.0, 0.0];
for &task_id in &target.zero_clears {
@ -3589,6 +3671,16 @@ impl Renderer {
Some(rect),
);
}
let one_color = [1.0, 1.0, 1.0, 1.0];
for &task_id in &target.one_clears {
let (rect, _) = render_tasks[task_id].get_target_rect();
self.device.clear_target(
Some(one_color),
None,
Some(rect),
);
}
}
// Draw any blurs for this target.
@ -3600,7 +3692,6 @@ impl Renderer {
if !target.vertical_blurs.is_empty() || !target.horizontal_blurs.is_empty() {
let _timer = self.gpu_profile.start_timer(GPU_TAG_BLUR);
self.set_blend(false, FramebufferKind::Other);
self.shaders.borrow_mut().cs_blur_a8
.bind(&mut self.device, projection, &mut self.renderer_errors);
@ -3623,70 +3714,39 @@ impl Renderer {
}
}
self.handle_scaling(&target.scalings, TextureSource::PrevPassAlpha, projection, stats);
self.handle_scaling(
&target.scalings,
TextureSource::PrevPassAlpha,
projection,
stats,
);
// Draw the clip items into the tiled alpha mask.
{
let _timer = self.gpu_profile.start_timer(GPU_TAG_CACHE_CLIP);
// switch to multiplicative blending
// TODO(gw): Consider grouping multiple clip masks per shader
// invocation here to reduce memory bandwith further?
// Draw the primary clip mask - since this is the first mask
// for the task, we can disable blending, knowing that it will
// overwrite every pixel in the mask area.
self.set_blend(false, FramebufferKind::Other);
self.draw_clip_batch_list(
&target.clip_batcher.primary_clips,
projection,
stats,
);
// switch to multiplicative blending for secondary masks, using
// multiplicative blending to accumulate clips into the mask.
self.set_blend(true, FramebufferKind::Other);
self.set_blend_mode_multiply(FramebufferKind::Other);
// draw rounded cornered rectangles
if !target.clip_batcher.rectangles.is_empty() {
let _gm2 = self.gpu_profile.start_marker("clip rectangles");
self.shaders.borrow_mut().cs_clip_rectangle.bind(
&mut self.device,
projection,
&mut self.renderer_errors,
);
self.draw_instanced_batch(
&target.clip_batcher.rectangles,
VertexArrayKind::Clip,
&BatchTextures::no_texture(),
stats,
);
}
// draw box-shadow clips
for (mask_texture_id, items) in target.clip_batcher.box_shadows.iter() {
let _gm2 = self.gpu_profile.start_marker("box-shadows");
let textures = BatchTextures {
colors: [
mask_texture_id.clone(),
TextureSource::Invalid,
TextureSource::Invalid,
],
};
self.shaders.borrow_mut().cs_clip_box_shadow
.bind(&mut self.device, projection, &mut self.renderer_errors);
self.draw_instanced_batch(
items,
VertexArrayKind::Clip,
&textures,
stats,
);
}
// draw image masks
for (mask_texture_id, items) in target.clip_batcher.images.iter() {
let _gm2 = self.gpu_profile.start_marker("clip images");
let textures = BatchTextures {
colors: [
mask_texture_id.clone(),
TextureSource::Invalid,
TextureSource::Invalid,
],
};
self.shaders.borrow_mut().cs_clip_image
.bind(&mut self.device, projection, &mut self.renderer_errors);
self.draw_instanced_batch(
items,
VertexArrayKind::Clip,
&textures,
stats,
);
}
self.draw_clip_batch_list(
&target.clip_batcher.secondary_clips,
projection,
stats,
);
}
self.gpu_profile.finish_sampler(alpha_sampler);
@ -4934,6 +4994,11 @@ pub struct RendererOptions {
pub namespace_alloc_by_client: bool,
pub enable_picture_caching: bool,
pub testing: bool,
/// Set to true if this GPU supports hardware fast clears as a performance
/// optimization. Likely requires benchmarking on various GPUs to see if
/// it is a performance win. The default is false, which tends to be best
/// performance on lower end / integrated GPUs.
pub gpu_supports_fast_clears: bool,
}
impl Default for RendererOptions {
@ -4972,6 +5037,7 @@ impl Default for RendererOptions {
namespace_alloc_by_client: false,
enable_picture_caching: false,
testing: false,
gpu_supports_fast_clears: false,
}
}
}

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

@ -77,7 +77,10 @@ pub struct RenderTargetContext<'a, 'rc> {
/// and sometimes on its parameters. See `RenderTask::target_kind`.
pub trait RenderTarget {
/// Creates a new RenderTarget of the given type.
fn new(screen_size: DeviceIntSize) -> Self;
fn new(
screen_size: DeviceIntSize,
gpu_supports_fast_clears: bool,
) -> Self;
/// Optional hook to provide additional processing for the target at the
/// end of the build phase.
@ -170,12 +173,14 @@ pub struct RenderTargetList<T> {
pub targets: Vec<T>,
pub saved_index: Option<SavedTargetIndex>,
pub alloc_tracker: ArrayAllocationTracker,
gpu_supports_fast_clears: bool,
}
impl<T: RenderTarget> RenderTargetList<T> {
fn new(
screen_size: DeviceIntSize,
format: ImageFormat,
gpu_supports_fast_clears: bool,
) -> Self {
RenderTargetList {
screen_size,
@ -184,6 +189,7 @@ impl<T: RenderTarget> RenderTargetList<T> {
targets: Vec::new(),
saved_index: None,
alloc_tracker: ArrayAllocationTracker::new(),
gpu_supports_fast_clears,
}
}
@ -236,7 +242,7 @@ impl<T: RenderTarget> RenderTargetList<T> {
assert!(alloc_size.width <= allocator_dimensions.width &&
alloc_size.height <= allocator_dimensions.height);
let slice = FreeRectSlice(self.targets.len() as u32);
self.targets.push(T::new(self.screen_size));
self.targets.push(T::new(self.screen_size, self.gpu_supports_fast_clears));
self.alloc_tracker.extend(
slice,
@ -250,7 +256,7 @@ impl<T: RenderTarget> RenderTargetList<T> {
if alloc_size.is_empty_or_negative() && self.targets.is_empty() {
// push an unused target here, only if we don't have any
self.targets.push(T::new(self.screen_size));
self.targets.push(T::new(self.screen_size, self.gpu_supports_fast_clears));
}
self.targets[free_rect_slice.0 as usize]
@ -356,7 +362,10 @@ pub struct ColorRenderTarget {
}
impl RenderTarget for ColorRenderTarget {
fn new(screen_size: DeviceIntSize) -> Self {
fn new(
screen_size: DeviceIntSize,
_: bool,
) -> Self {
ColorRenderTarget {
alpha_batch_containers: Vec::new(),
vertical_blurs: Vec::new(),
@ -391,6 +400,7 @@ impl RenderTarget for ColorRenderTarget {
ClearMode::Zero => {
panic!("bug: invalid clear mode for color task");
}
ClearMode::DontCare |
ClearMode::Transparent => {}
}
@ -578,6 +588,7 @@ pub struct AlphaRenderTarget {
pub horizontal_blurs: Vec<BlurInstance>,
pub scalings: Vec<ScalingInstance>,
pub zero_clears: Vec<RenderTaskId>,
pub one_clears: Vec<RenderTaskId>,
// Track the used rect of the render target, so that
// we can set a scissor rect and only clear to the
// used portion of the target as an optimization.
@ -585,13 +596,17 @@ pub struct AlphaRenderTarget {
}
impl RenderTarget for AlphaRenderTarget {
fn new(_screen_size: DeviceIntSize) -> Self {
fn new(
_screen_size: DeviceIntSize,
gpu_supports_fast_clears: bool,
) -> Self {
AlphaRenderTarget {
clip_batcher: ClipBatcher::new(),
clip_batcher: ClipBatcher::new(gpu_supports_fast_clears),
vertical_blurs: Vec::new(),
horizontal_blurs: Vec::new(),
scalings: Vec::new(),
zero_clears: Vec::new(),
one_clears: Vec::new(),
used_rect: DeviceIntRect::zero(),
}
}
@ -612,7 +627,10 @@ impl RenderTarget for AlphaRenderTarget {
ClearMode::Zero => {
self.zero_clears.push(task_id);
}
ClearMode::One => {}
ClearMode::One => {
self.one_clears.push(task_id);
}
ClearMode::DontCare => {}
ClearMode::Transparent => {
panic!("bug: invalid clear mode for alpha task");
}
@ -858,8 +876,11 @@ pub struct RenderPass {
impl RenderPass {
/// Creates a pass for the main framebuffer. There is only one of these, and
/// it is always the last pass.
pub fn new_main_framebuffer(screen_size: DeviceIntSize) -> Self {
let target = ColorRenderTarget::new(screen_size);
pub fn new_main_framebuffer(
screen_size: DeviceIntSize,
gpu_supports_fast_clears: bool,
) -> Self {
let target = ColorRenderTarget::new(screen_size, gpu_supports_fast_clears);
RenderPass {
kind: RenderPassKind::MainFramebuffer(target),
tasks: vec![],
@ -867,11 +888,22 @@ impl RenderPass {
}
/// Creates an intermediate off-screen pass.
pub fn new_off_screen(screen_size: DeviceIntSize) -> Self {
pub fn new_off_screen(
screen_size: DeviceIntSize,
gpu_supports_fast_clears: bool,
) -> Self {
RenderPass {
kind: RenderPassKind::OffScreen {
color: RenderTargetList::new(screen_size, ImageFormat::BGRA8),
alpha: RenderTargetList::new(screen_size, ImageFormat::R8),
color: RenderTargetList::new(
screen_size,
ImageFormat::BGRA8,
gpu_supports_fast_clears,
),
alpha: RenderTargetList::new(
screen_size,
ImageFormat::R8,
gpu_supports_fast_clears,
),
texture_cache: FastHashMap::default(),
},
tasks: vec![],

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

@ -0,0 +1,48 @@
# Benchmark to test the cost of clears on a clip mask target that
# is large but has low usage.
---
root:
items:
-
bounds: 0 0 1000 1000
type: stacking-context
items:
- type: clip
bounds: [50, 50, 300, 300]
complex:
- rect: [50, 50, 300, 300]
radius: 50
items:
- type: rect
bounds: 50 50 300 300
color: red
- type: rect
bounds: 50 50 300 300
color: red
- type: rect
bounds: 50 50 300 300
color: red
- type: rect
bounds: 50 50 300 300
color: red
- type: rect
bounds: 50 50 300 300
color: red
- type: rect
bounds: 50 50 300 300
color: red
- type: rect
bounds: 50 50 300 300
color: red
- type: rect
bounds: 50 50 300 300
color: red
- type: rect
bounds: 50 50 300 300
color: red
- type: rect
bounds: 50 50 300 300
color: red
- type: rect
bounds: 50 50 300 300
color: red

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 35 KiB

После

Ширина:  |  Высота:  |  Размер: 35 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 148 KiB

После

Ширина:  |  Высота:  |  Размер: 148 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 59 KiB

После

Ширина:  |  Высота:  |  Размер: 59 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 16 KiB

После

Ширина:  |  Высота:  |  Размер: 16 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 84 KiB

После

Ширина:  |  Высота:  |  Размер: 84 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 24 KiB

После

Ширина:  |  Высота:  |  Размер: 24 KiB

Двоичные данные
gfx/wr/wrench/reftests/text/raster-space.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 44 KiB

После

Ширина:  |  Высота:  |  Размер: 61 KiB

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

@ -17,3 +17,12 @@ root:
origin: 20 50
size: 20
font: "FreeSans.ttf"
- type: stacking-context
transform: scale(5.0) rotate(45)
transform-origin: -80 240
raster-space: local(5.0)
items:
- text: "Local (scaled)"
origin: 20 50
size: 10
font: "FreeSans.ttf"

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

@ -5,8 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Functions for controlling profilers from within JS: Valgrind, Perf,
* Shark, etc.
* Functions for controlling profilers from within JS: Valgrind, Perf, etc
*/
#ifndef builtin_Profilers_h
#define builtin_Profilers_h

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

@ -1,190 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* 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/. */
#ifdef __APPLE__
# include "sharkctl.h"
# include <stddef.h>
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include "jsutil.h"
# define SHARK_MSG_ACQUIRE 0x29a
# define SHARK_MSG_RELEASE 0x29b
# define SHARK_MSG_STOP 0x29c
# define SHARK_MSG_START 0x29d
# define RECV_SIZEOF(ty) offsetof(ty, out)
// Private API in libSystem.dylib
extern "C" void bootstrap_look_up(mach_port_t special_port, const char* name,
mach_port_t* dest_port);
struct chud_client_acquire_msg {
mach_msg_header_t hdr;
uint32_t unk0; // always 0
uint32_t unk1; // always 1
uint32_t pid;
uint32_t out[2];
};
struct chud_client_start_msg {
mach_msg_header_t hdr;
uint32_t unk0; // always 1
uint32_t name0;
uint32_t arg2; // always 6
uint8_t unk1; // always 0
uint8_t unk2; // always 1
uint8_t unk3; // uninitialized
uint8_t unk4; // always 1
uint32_t unk5; // always 0
uint32_t unk6; // always 1
uint32_t name1; // same as name0
};
struct chud_client_stop_msg {
mach_msg_header_t hdr;
uint32_t out[5];
};
struct chud_client_release_msg {
mach_msg_header_t hdr;
uint32_t unk0; // always 0
uint32_t unk1; // always 1
uint32_t pid;
uint32_t out[2];
};
static mach_port_t CreatePort(void) {
mach_port_t bootstrap_port, shark_port = 0;
task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT, &bootstrap_port);
bootstrap_look_up(bootstrap_port, "CHUD_IPC", &shark_port);
return shark_port;
}
static mach_msg_return_t Connect(mach_port_t shark_port) {
mach_port_t reply_port = mig_get_reply_port();
struct chud_client_acquire_msg msg;
msg.hdr.msgh_bits = 0x1513;
msg.hdr.msgh_size = sizeof(mach_msg_header_t);
msg.hdr.msgh_remote_port = shark_port;
msg.hdr.msgh_local_port = reply_port;
msg.hdr.msgh_reserved = 0;
msg.hdr.msgh_id = SHARK_MSG_ACQUIRE;
msg.unk0 = 0;
msg.unk1 = 1;
msg.pid = getpid();
MOZ_ASSERT(RECV_SIZEOF(struct chud_client_acquire_msg) == 0x24);
MOZ_ASSERT(sizeof(msg) == 0x2c);
mach_msg_return_t result =
mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
RECV_SIZEOF(struct chud_client_acquire_msg), sizeof(msg),
reply_port, 0, 0);
mig_dealloc_reply_port(reply_port);
return result;
}
static mach_msg_return_t Start(mach_port_t shark_port, uint32_t name) {
mach_port_t reply_port = mig_get_reply_port();
struct chud_client_start_msg msg;
msg.hdr.msgh_bits = 0x80001513;
msg.hdr.msgh_size = sizeof(mach_msg_header_t);
msg.hdr.msgh_remote_port = shark_port;
msg.hdr.msgh_local_port = reply_port;
msg.hdr.msgh_reserved = 0;
msg.hdr.msgh_id = SHARK_MSG_START;
msg.unk0 = 1;
msg.name0 = name;
msg.arg2 = 6;
msg.unk1 = 0;
msg.unk2 = 1;
msg.unk3 = 0;
msg.unk4 = 1;
msg.unk5 = 0;
msg.unk6 = 1;
msg.name1 = name;
MOZ_ASSERT(sizeof(msg) == 0x34);
mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
sizeof(msg), 0x30, reply_port, 0, 0);
mig_dealloc_reply_port(reply_port);
return result;
}
mach_msg_return_t Stop(mach_port_t shark_port) {
mach_port_t reply_port = mig_get_reply_port();
struct chud_client_stop_msg msg;
msg.hdr.msgh_bits = 0x1513;
msg.hdr.msgh_size = sizeof(mach_msg_header_t);
msg.hdr.msgh_remote_port = shark_port;
msg.hdr.msgh_local_port = reply_port;
msg.hdr.msgh_reserved = 0;
msg.hdr.msgh_id = SHARK_MSG_STOP;
MOZ_ASSERT(RECV_SIZEOF(struct chud_client_stop_msg) == 0x18);
MOZ_ASSERT(sizeof(msg) == 0x2c);
mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
RECV_SIZEOF(struct chud_client_stop_msg),
sizeof(msg), reply_port, 0, 0);
mig_dealloc_reply_port(reply_port);
return result;
}
static mach_msg_return_t Disconnect(mach_port_t shark_port) {
mach_port_t reply_port = mig_get_reply_port();
struct chud_client_release_msg msg;
msg.hdr.msgh_bits = 0x1513;
msg.hdr.msgh_size = sizeof(mach_msg_header_t);
msg.hdr.msgh_remote_port = shark_port;
msg.hdr.msgh_local_port = reply_port;
msg.hdr.msgh_reserved = 0;
msg.hdr.msgh_id = SHARK_MSG_RELEASE;
msg.unk0 = 0;
msg.unk1 = 1;
msg.pid = getpid();
MOZ_ASSERT(RECV_SIZEOF(struct chud_client_release_msg) == 0x24);
MOZ_ASSERT(sizeof(msg) == 0x2c);
mach_msg_return_t result =
mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
RECV_SIZEOF(struct chud_client_release_msg), sizeof(msg),
reply_port, 0, 0);
mig_dealloc_reply_port(reply_port);
return result;
}
static mach_port_t shark_port = 0;
static bool connected = false;
static bool running = false;
namespace Shark {
bool Start() {
if (!shark_port && !(shark_port = CreatePort())) return false;
if (!connected && Connect(shark_port)) return false;
connected = true;
if (!running && ::Start(shark_port, 0xdeadbeef)) return false;
return running = true;
}
void Stop() {
if (!shark_port || !connected) return;
::Stop(shark_port);
running = false;
Disconnect(shark_port);
connected = false;
}
} // namespace Shark
#endif

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

@ -1,24 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* 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/. */
#ifndef devtools_sharkctl_h
#define devtools_sharkctl_h
#ifdef __APPLE__
# include <mach/mach.h>
# include <stdint.h>
namespace Shark {
bool Start();
void Stop();
} // namespace Shark
#endif /* __APPLE__ */
#endif /* devtools_sharkctl_h */

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

@ -0,0 +1,11 @@
function getarg(x) {
return arguments[x]
}
function f() {
var r = 0n;
for (var i=0;i<2000;++i) {
r += getarg(1+(i & 1), BigInt(0), 1n);
}
return r;
}
for (var i=0;i<2;++i) print(f())

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

@ -2246,7 +2246,7 @@ void LIRGenerator::visitToString(MToString* ins) {
}
default:
// Float32, symbols, and objects are not supported.
// Float32, symbols, bigint, and objects are not supported.
MOZ_CRASH("unexpected type");
}
}
@ -3166,6 +3166,7 @@ void LIRGenerator::visitLoadElementFromState(MLoadElementFromState* ins) {
case MIRType::Object:
case MIRType::String:
case MIRType::Symbol:
case MIRType::BigInt:
lir->setOperand(1 + BOX_PIECES * i, use(elem));
#ifdef JS_NUNBOX32
// Bogus second operand.

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

@ -4165,11 +4165,10 @@ class MToString : public MUnaryInstruction, public ToStringPolicy::Data {
setResultType(MIRType::String);
setMovable();
// Objects might override toString; Symbol and BigInts throw. We bailout in
// those cases and run side-effects in baseline instead.
// Objects might override toString; Symbol throws. We bailout in those cases
// and run side-effects in baseline instead.
if (def->mightBeType(MIRType::Object) ||
def->mightBeType(MIRType::Symbol) ||
def->mightBeType(MIRType::BigInt)) {
def->mightBeType(MIRType::Symbol)) {
setGuard();
}
}

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

@ -219,7 +219,6 @@ UNIFIED_SOURCES += [
'builtin/TypedObject.cpp',
'builtin/WeakMapObject.cpp',
'builtin/WeakSetObject.cpp',
'devtools/sharkctl.cpp',
'ds/Bitmap.cpp',
'ds/LifoAlloc.cpp',
'ds/MemoryProtectionExceptionHandler.cpp',

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

@ -355,10 +355,6 @@ static inline uint32_t FindScopeIndex(mozilla::Span<const GCPtrScope> scopes,
MOZ_CRASH("Scope not found");
}
static inline uint32_t FindScopeIndex(JSScript* script, Scope& scope) {
return FindScopeIndex(script->scopes(), scope);
}
template <XDRMode mode>
static XDRResult XDRInnerObject(XDRState<mode>* xdr,
js::PrivateScriptData* data,
@ -3347,19 +3343,6 @@ bool JSScript::initScriptName(JSContext* cx) {
return true;
}
static inline uint8_t* AllocScriptData(JSContext* cx, size_t size) {
if (!size) {
return nullptr;
}
uint8_t* data = cx->pod_calloc<uint8_t>(JS_ROUNDUP(size, sizeof(Value)));
if (!data) {
return nullptr;
}
MOZ_ASSERT(size_t(data) % sizeof(Value) == 0);
return data;
}
/* static */ bool JSScript::createPrivateScriptData(
JSContext* cx, HandleScript script, uint32_t nscopes, uint32_t nconsts,
uint32_t nobjects, uint32_t ntrynotes, uint32_t nscopenotes,
@ -3997,33 +3980,18 @@ static JSObject* CloneInnerInterpretedFunction(
return clone;
}
bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
MutableHandle<GCVector<Scope*>> scopes) {
// We don't copy the HideScriptFromDebugger flag and it's not clear what
// should happen if it's set on the source script.
MOZ_ASSERT(!src->hideScriptFromDebugger());
if (src->treatAsRunOnce() && !src->functionNonDelazifying()) {
JS_ReportErrorASCII(cx, "No cloning toplevel run-once scripts");
return false;
}
/* NB: Keep this in sync with XDRScript. */
/* Some embeddings are not careful to use ExposeObjectToActiveJS as needed. */
JS::AssertObjectIsNotGray(src->sourceObject());
uint32_t nscopes = src->scopes().size();
uint32_t nconsts = src->hasConsts() ? src->consts().size() : 0;
uint32_t nobjects = src->hasObjects() ? src->objects().size() : 0;
/* Script data */
size_t size = src->dataSize();
UniquePtr<uint8_t, JS::FreePolicy> data(AllocScriptData(cx, size));
if (!data) {
return false;
}
/* static */ bool PrivateScriptData::Clone(
JSContext* cx, HandleScript src, HandleScript dst,
MutableHandle<GCVector<Scope*>> scopes) {
PrivateScriptData* srcData = src->data_;
uint32_t nscopes = srcData->scopes().size();
uint32_t nconsts = srcData->hasConsts() ? srcData->consts().size() : 0;
uint32_t nobjects = srcData->hasObjects() ? srcData->objects().size() : 0;
uint32_t ntrynotes = srcData->hasTryNotes() ? srcData->tryNotes().size() : 0;
uint32_t nscopenotes =
srcData->hasScopeNotes() ? srcData->scopeNotes().size() : 0;
uint32_t nresumeoffsets =
srcData->hasResumeOffsets() ? srcData->resumeOffsets().size() : 0;
/* Scopes */
@ -4036,10 +4004,11 @@ bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
MOZ_ASSERT(src->bodyScopeIndex() + 1 == scopes.length());
RootedScope original(cx);
RootedScope clone(cx);
for (const GCPtrScope& elem : src->scopes().From(scopes.length())) {
for (const GCPtrScope& elem : srcData->scopes().From(scopes.length())) {
original = elem.get();
clone = Scope::clone(cx, original,
scopes[FindScopeIndex(src, *original->enclosing())]);
uint32_t scopeIndex =
FindScopeIndex(srcData->scopes(), *original->enclosing());
clone = Scope::clone(cx, original, scopes[scopeIndex]);
if (!clone || !scopes.append(clone)) {
return false;
}
@ -4052,7 +4021,7 @@ bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
if (nconsts != 0) {
RootedValue val(cx);
RootedValue clone(cx);
for (const GCPtrValue& elem : src->consts()) {
for (const GCPtrValue& elem : srcData->consts()) {
val = elem.get();
if (val.isDouble()) {
clone = val;
@ -4084,7 +4053,7 @@ bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
RootedObject obj(cx);
RootedObject clone(cx);
Rooted<ScriptSourceObject*> sourceObject(cx, dst->sourceObject());
for (const GCPtrObject& elem : src->objects()) {
for (const GCPtrObject& elem : srcData->objects()) {
obj = elem.get();
clone = nullptr;
if (obj->is<RegExpObject>()) {
@ -4108,8 +4077,8 @@ bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
}
Scope* enclosing = innerFun->nonLazyScript()->enclosingScope();
RootedScope enclosingClone(cx,
scopes[FindScopeIndex(src, *enclosing)]);
uint32_t scopeIndex = FindScopeIndex(srcData->scopes(), *enclosing);
RootedScope enclosingClone(cx, scopes[scopeIndex]);
clone = CloneInnerInterpretedFunction(cx, enclosingClone, innerFun,
sourceObject);
}
@ -4123,74 +4092,110 @@ bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
}
}
dst->data_ = reinterpret_cast<js::PrivateScriptData*>(data.release());
dst->dataSize_ = size;
memcpy(dst->data_, src->data_, size);
if (cx->zone() != src->zoneFromAnyThread()) {
for (size_t i = 0; i < src->scriptData()->natoms(); i++) {
cx->markAtom(src->scriptData()->atoms()[i]);
}
}
/* Script filenames, bytecodes and atoms are runtime-wide. */
dst->setScriptData(src->scriptData());
dst->lineno_ = src->lineno();
dst->mainOffset_ = src->mainOffset();
dst->nfixed_ = src->nfixed();
dst->nslots_ = src->nslots();
dst->bodyScopeIndex_ = src->bodyScopeIndex_;
dst->funLength_ = src->funLength();
dst->numBytecodeTypeSets_ = src->numBytecodeTypeSets();
dst->immutableFlags_ = src->immutableFlags_;
dst->setFlag(JSScript::ImmutableFlags::HasNonSyntacticScope,
scopes[0]->hasOnChain(ScopeKind::NonSyntactic));
if (src->argumentsHasVarBinding()) {
dst->setArgumentsHasVarBinding();
if (src->analyzedArgsUsage()) {
dst->setNeedsArgsObj(src->needsArgsObj());
}
// Create the new PrivateScriptData on |dst| and fill it in.
if (!JSScript::createPrivateScriptData(cx, dst, nscopes, nconsts, nobjects,
ntrynotes, nscopenotes,
nresumeoffsets)) {
return false;
}
PrivateScriptData* dstData = dst->data_;
{
auto array = dst->data_->scopes();
auto array = dstData->scopes();
for (uint32_t i = 0; i < nscopes; ++i) {
array[i].init(scopes[i]);
}
}
if (nconsts) {
auto array = dst->data_->consts();
auto array = dstData->consts();
for (unsigned i = 0; i < nconsts; ++i) {
array[i].init(consts[i]);
}
}
if (nobjects) {
auto array = dst->data_->objects();
auto array = dstData->objects();
for (unsigned i = 0; i < nobjects; ++i) {
array[i].init(objects[i]);
}
}
if (ntrynotes) {
std::copy_n(srcData->tryNotes().begin(), ntrynotes,
dstData->tryNotes().begin());
}
if (nscopenotes) {
std::copy_n(srcData->scopeNotes().begin(), nscopenotes,
dstData->scopeNotes().begin());
}
if (nresumeoffsets) {
std::copy_n(srcData->resumeOffsets().begin(), nresumeoffsets,
dstData->resumeOffsets().begin());
}
return true;
}
static JSScript* CreateEmptyScriptForClone(
JSContext* cx, HandleScript src, Handle<ScriptSourceObject*> sourceObject) {
MOZ_ASSERT(cx->compartment() == sourceObject->compartment());
MOZ_ASSERT_IF(src->realm()->isSelfHostingRealm(),
sourceObject == cx->realm()->selfHostingScriptSource);
JSScript* js::detail::CopyScript(JSContext* cx, HandleScript src,
HandleScriptSourceObject sourceObject,
MutableHandle<GCVector<Scope*>> scopes) {
// We don't copy the HideScriptFromDebugger flag and it's not clear what
// should happen if it's set on the source script.
MOZ_ASSERT(!src->hideScriptFromDebugger());
if (src->treatAsRunOnce() && !src->functionNonDelazifying()) {
JS_ReportErrorASCII(cx, "No cloning toplevel run-once scripts");
return nullptr;
}
/* NB: Keep this in sync with XDRScript. */
// Some embeddings are not careful to use ExposeObjectToActiveJS as needed.
JS::AssertObjectIsNotGray(sourceObject);
CompileOptions options(cx);
options.setMutedErrors(src->mutedErrors())
.setSelfHostingMode(src->selfHosted())
.setNoScriptRval(src->noScriptRval());
return JSScript::Create(cx, options, sourceObject, src->sourceStart(),
src->sourceEnd(), src->toStringStart(),
src->toStringEnd());
// Create a new JSScript to fill in
RootedScript dst(
cx, JSScript::Create(cx, options, sourceObject, src->sourceStart(),
src->sourceEnd(), src->toStringStart(),
src->toStringEnd()));
if (!dst) {
return nullptr;
}
// Copy POD fields
dst->lineno_ = src->lineno();
dst->column_ = src->column();
dst->mainOffset_ = src->mainOffset();
dst->nfixed_ = src->nfixed();
dst->nslots_ = src->nslots();
dst->bodyScopeIndex_ = src->bodyScopeIndex();
dst->immutableFlags_ = src->immutableFlags_;
dst->funLength_ = src->funLength();
dst->numBytecodeTypeSets_ = src->numBytecodeTypeSets();
dst->setFlag(JSScript::ImmutableFlags::HasNonSyntacticScope,
scopes[0]->hasOnChain(ScopeKind::NonSyntactic));
if (src->argumentsHasVarBinding()) {
dst->setArgumentsHasVarBinding();
}
// Clone the PrivateScriptData into dst
if (!PrivateScriptData::Clone(cx, src, dst, scopes)) {
return nullptr;
}
// The SharedScriptData can be reused by any zone in the Runtime as long as
// we make sure to mark first (to sync Atom pointers).
if (cx->zone() != src->zoneFromAnyThread()) {
src->scriptData()->markForCrossZone(cx);
}
dst->setScriptData(src->scriptData());
return dst;
}
JSScript* js::CloneGlobalScript(JSContext* cx, ScopeKind scopeKind,
@ -4206,11 +4211,6 @@ JSScript* js::CloneGlobalScript(JSContext* cx, ScopeKind scopeKind,
}
}
RootedScript dst(cx, CreateEmptyScriptForClone(cx, src, sourceObject));
if (!dst) {
return nullptr;
}
MOZ_ASSERT(src->bodyScopeIndex() == 0);
Rooted<GCVector<Scope*>> scopes(cx, GCVector<Scope*>(cx));
Rooted<GlobalScope*> original(cx, &src->bodyScope()->as<GlobalScope>());
@ -4219,11 +4219,7 @@ JSScript* js::CloneGlobalScript(JSContext* cx, ScopeKind scopeKind,
return nullptr;
}
if (!detail::CopyScript(cx, src, dst, &scopes)) {
return nullptr;
}
return dst;
return detail::CopyScript(cx, src, sourceObject, &scopes);
}
JSScript* js::CloneScriptIntoFunction(
@ -4232,11 +4228,6 @@ JSScript* js::CloneScriptIntoFunction(
MOZ_ASSERT(fun->isInterpreted());
MOZ_ASSERT(!fun->hasScript() || fun->hasUncompletedScript());
RootedScript dst(cx, CreateEmptyScriptForClone(cx, src, sourceObject));
if (!dst) {
return nullptr;
}
// Clone the non-intra-body scopes.
Rooted<GCVector<Scope*>> scopes(cx, GCVector<Scope*>(cx));
RootedScope original(cx);
@ -4266,7 +4257,8 @@ JSScript* js::CloneScriptIntoFunction(
// Save flags in case we need to undo the early mutations.
const int preservedFlags = fun->flags();
if (!detail::CopyScript(cx, src, dst, &scopes)) {
RootedScript dst(cx, detail::CopyScript(cx, src, sourceObject, &scopes));
if (!dst) {
fun->setFlags(preservedFlags);
return nullptr;
}
@ -4473,6 +4465,12 @@ void SharedScriptData::traceChildren(JSTracer* trc) {
}
}
void SharedScriptData::markForCrossZone(JSContext* cx) {
for (uint32_t i = 0; i < natoms(); ++i) {
cx->markAtom(atoms()[i]);
}
}
void JSScript::traceChildren(JSTracer* trc) {
// NOTE: this JSScript may be partially initialized at this point. E.g. we
// may have created it and partially initialized it with

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

@ -85,8 +85,9 @@ namespace detail {
// Do not call this directly! It is exposed for the friend declarations in
// this file.
bool CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
MutableHandle<GCVector<Scope*>> scopes);
JSScript* CopyScript(JSContext* cx, HandleScript src,
HandleScriptSourceObject sourceObject,
MutableHandle<GCVector<Scope*>> scopes);
} // namespace detail
@ -1426,6 +1427,10 @@ class alignas(JS::Value) PrivateScriptData final {
js::HandleScope scriptEnclosingScope,
js::HandleFunction fun);
// Clone src script data into dst script.
static bool Clone(JSContext* cx, js::HandleScript src, js::HandleScript dst,
js::MutableHandle<JS::GCVector<js::Scope*>> scopes);
void traceChildren(JSTracer* trc);
};
@ -1499,6 +1504,9 @@ class SharedScriptData {
static MOZ_MUST_USE XDRResult XDR(js::XDRState<mode>* xdr,
js::HandleScript script);
// Mark this SharedScriptData for use in a new zone
void markForCrossZone(JSContext* cx);
private:
SharedScriptData() = delete;
SharedScriptData(const SharedScriptData&) = delete;
@ -1836,10 +1844,15 @@ class JSScript : public js::gc::TenuredCell {
js::HandleScriptSourceObject sourceObject,
js::HandleScope scriptEnclosingScope, js::HandleFunction fun);
friend bool js::detail::CopyScript(
friend bool js::PrivateScriptData::Clone(
JSContext* cx, js::HandleScript src, js::HandleScript dst,
js::MutableHandle<JS::GCVector<js::Scope*>> scopes);
friend JSScript* js::detail::CopyScript(
JSContext* cx, js::HandleScript src,
js::HandleScriptSourceObject sourceObject,
js::MutableHandle<JS::GCVector<js::Scope*>> scopes);
private:
JSScript(JS::Realm* realm, uint8_t* stubEntry,
js::HandleScriptSourceObject sourceObject, uint32_t sourceStart,

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

@ -689,9 +689,6 @@ nsresult nsDocumentViewer::SyncParentSubDocMap() {
NS_IMETHODIMP
nsDocumentViewer::SetContainer(nsIDocShell* aContainer) {
mContainer = static_cast<nsDocShell*>(aContainer);
if (mPresContext) {
mPresContext->SetContainer(mContainer);
}
// We're loading a new document into the window where this document
// viewer lives, sync the parent document's frame element -> sub
@ -953,8 +950,6 @@ nsresult nsDocumentViewer::InitInternal(nsIWidget* aParentWidget,
nsCOMPtr<nsILinkHandler> linkHandler;
requestor->GetInterface(NS_GET_IID(nsILinkHandler),
getter_AddRefs(linkHandler));
mPresContext->SetContainer(mContainer);
mPresContext->SetLinkHandler(linkHandler);
}
@ -1476,7 +1471,6 @@ static void AttachContainerRecurse(nsIDocShell* aShell) {
}
RefPtr<nsPresContext> pc = viewer->GetPresContext();
if (pc) {
pc->SetContainer(static_cast<nsDocShell*>(aShell));
nsCOMPtr<nsILinkHandler> handler = do_QueryInterface(aShell);
pc->SetLinkHandler(handler);
}
@ -1501,7 +1495,9 @@ NS_IMETHODIMP
nsDocumentViewer::Open(nsISupports* aState, nsISHEntry* aSHEntry) {
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
if (mDocument) mDocument->SetContainer(mContainer);
if (mDocument) {
mDocument->SetContainer(mContainer);
}
nsresult rv = InitInternal(mParentWidget, aState, mBounds, false);
NS_ENSURE_SUCCESS(rv, rv);
@ -2171,8 +2167,6 @@ nsDocumentViewer::Show(void) {
if (linkHandler) {
mPresContext->SetLinkHandler(linkHandler);
}
mPresContext->SetContainer(mContainer);
}
if (mPresContext) {

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

@ -9718,26 +9718,6 @@ already_AddRefed<nsFontMetrics> nsLayoutUtils::GetMetricsFor(
return style.get();
}
static float ResolveTransformOrigin(
const nsStyleCoord& aCoord, TransformReferenceBox& aRefBox,
TransformReferenceBox::DimensionGetter aGetter) {
float result = 0.0;
const float scale = mozilla::AppUnitsPerCSSPixel();
if (aCoord.GetUnit() == eStyleUnit_Calc) {
const nsStyleCoord::Calc* calc = aCoord.GetCalcValue();
result =
NSAppUnitsToFloatPixels((aRefBox.*aGetter)(), scale) * calc->mPercent +
NSAppUnitsToFloatPixels(calc->mLength, scale);
} else if (aCoord.GetUnit() == eStyleUnit_Percent) {
result = NSAppUnitsToFloatPixels((aRefBox.*aGetter)(), scale) *
aCoord.GetPercentValue();
} else {
MOZ_ASSERT(aCoord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
result = NSAppUnitsToFloatPixels(aCoord.GetCoordValue(), scale);
}
return result;
}
/* static */ Maybe<MotionPathData> nsLayoutUtils::ResolveMotionPath(
const nsIFrame* aFrame) {
MOZ_ASSERT(aFrame);
@ -9791,11 +9771,10 @@ static float ResolveTransformOrigin(
// We need to resolve transform-origin here to calculate the correct path
// translate. (i.e. Center transform-origin on the path.)
TransformReferenceBox refBox(aFrame);
Point origin(ResolveTransformOrigin(display->mTransformOrigin[0], refBox,
&TransformReferenceBox::Width),
ResolveTransformOrigin(display->mTransformOrigin[1], refBox,
&TransformReferenceBox::Height));
auto& transformOrigin = display->mTransformOrigin;
CSSPoint origin = nsStyleTransformMatrix::Convert2DPosition(
transformOrigin.horizontal, transformOrigin.vertical, refBox);
// Bug 1186329: the translate parameters will be adjusted more after we
// implement offset-position and offset-anchor.
return Some(MotionPathData{point - origin, angle});
return Some(MotionPathData{point - origin.ToUnknownPoint(), angle});
}

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

@ -222,14 +222,11 @@ nsPresContext::nsPresContext(dom::Document* aDocument, nsPresContextType aType)
mFontFeatureValuesDirty(true),
mSuppressResizeReflow(false),
mIsVisual(false),
mIsChrome(false),
mIsChromeOriginImage(false),
mPaintFlashing(false),
mPaintFlashingInitialized(false),
mHasWarnedAboutPositionedTableParts(false),
mHasWarnedAboutTooLargeDashedOrDottedRadius(false),
mQuirkSheetAdded(false),
mNeedsPrefUpdate(false),
mHadNonBlankPaint(false),
mHadContentfulPaint(false),
mHadContentfulPaintComposite(false)
@ -359,6 +356,15 @@ static bool sLookAndFeelChanged;
// one prescontext.
static bool sThemeChanged;
bool nsPresContext::IsChrome() const {
return Document()->IsInChromeDocShell();
}
bool nsPresContext::IsChromeOriginImage() const {
return Document()->IsBeingUsedAsImage() &&
Document()->IsDocumentURISchemeChrome();
}
void nsPresContext::GetDocumentColorPreferences() {
// Make sure the preferences are initialized. In the normal run,
// they would already be, because gfxPlatform would have been created,
@ -367,7 +373,6 @@ void nsPresContext::GetDocumentColorPreferences() {
int32_t useAccessibilityTheme = 0;
bool usePrefColors = true;
bool isChromeDocShell = false;
static int32_t sDocumentColorsSetting;
static bool sDocumentColorsSettingPrefCached = false;
if (!sDocumentColorsSettingPrefCached) {
@ -376,22 +381,7 @@ void nsPresContext::GetDocumentColorPreferences() {
"browser.display.document_color_use", 0);
}
dom::Document* doc = mDocument->GetDisplayDocument();
if (doc && doc->GetDocShell()) {
isChromeDocShell =
nsIDocShellTreeItem::typeChrome == doc->GetDocShell()->ItemType();
} else {
nsCOMPtr<nsIDocShellTreeItem> docShell(mContainer);
if (docShell) {
isChromeDocShell =
nsIDocShellTreeItem::typeChrome == docShell->ItemType();
}
}
mIsChromeOriginImage = mDocument->IsBeingUsedAsImage() &&
IsChromeURI(mDocument->GetDocumentURI());
if (isChromeDocShell || mIsChromeOriginImage) {
if (IsChrome() || IsChromeOriginImage()) {
usePrefColors = false;
} else {
useAccessibilityTheme =
@ -441,11 +431,10 @@ void nsPresContext::GetDocumentColorPreferences() {
if (sDocumentColorsSetting == 1 || mDocument->IsBeingUsedAsImage()) {
mUseDocumentColors = true;
} else if (sDocumentColorsSetting == 2) {
mUseDocumentColors = isChromeDocShell || mIsChromeOriginImage;
mUseDocumentColors = IsChrome() || IsChromeOriginImage();
} else {
MOZ_ASSERT(
!useAccessibilityTheme || !(isChromeDocShell || mIsChromeOriginImage),
"The accessibility theme should only be on for non-chrome");
MOZ_ASSERT(!useAccessibilityTheme || !(IsChrome() || IsChromeOriginImage()),
"The accessibility theme should only be on for non-chrome");
mUseDocumentColors = !useAccessibilityTheme;
}
}
@ -678,14 +667,7 @@ void nsPresContext::UpdateAfterPreferencesChanged() {
return;
}
if (!mContainer) {
// Delay updating until there is a container
mNeedsPrefUpdate = true;
return;
}
nsCOMPtr<nsIDocShellTreeItem> docShell(mContainer);
if (docShell && nsIDocShellTreeItem::typeChrome == docShell->ItemType()) {
if (mDocument->IsInChromeDocShell()) {
return;
}
@ -753,7 +735,6 @@ nsresult nsPresContext::Init(nsDeviceContext* aDeviceContext) {
"How did we end up with a presshell if our parent doesn't "
"have one?");
if (parent && parent->GetPresContext()) {
// We don't have our container set yet at this point
nsCOMPtr<nsIDocShellTreeItem> ourItem = mDocument->GetDocShell();
if (ourItem) {
nsCOMPtr<nsIDocShellTreeItem> parentItem;
@ -812,32 +793,28 @@ void nsPresContext::AttachShell(nsIPresShell* aShell) {
mCounterStyleManager = new mozilla::CounterStyleManager(this);
dom::Document* doc = mShell->GetDocument();
NS_ASSERTION(doc, "expect document here");
if (doc) {
// Have to update PresContext's mDocument before calling any other methods.
mDocument = doc;
}
MOZ_ASSERT(doc);
// Have to update PresContext's mDocument before calling any other methods.
mDocument = doc;
// Initialize our state from the user preferences, now that we
// have a presshell, and hence a document.
GetUserPreferences();
if (doc) {
nsIURI* docURI = doc->GetDocumentURI();
nsIURI* docURI = doc->GetDocumentURI();
if (IsDynamic() && docURI) {
bool isChrome = false;
bool isRes = false;
docURI->SchemeIs("chrome", &isChrome);
docURI->SchemeIs("resource", &isRes);
if (IsDynamic() && docURI) {
bool isChrome = false;
bool isRes = false;
docURI->SchemeIs("chrome", &isChrome);
docURI->SchemeIs("resource", &isRes);
if (!isChrome && !isRes)
mImageAnimationMode = mImageAnimationModePref;
else
mImageAnimationMode = imgIContainer::kNormalAnimMode;
}
UpdateCharSet(doc->GetDocumentCharacterSet());
if (!isChrome && !isRes)
mImageAnimationMode = mImageAnimationModePref;
else
mImageAnimationMode = imgIContainer::kNormalAnimMode;
}
UpdateCharSet(doc->GetDocumentCharacterSet());
}
void nsPresContext::DetachShell() {
@ -1302,45 +1279,17 @@ bool nsPresContext::ElementWouldPropagateScrollStyles(const Element& aElement) {
return GetPropagatedScrollStylesForViewport(this, &dummy) == &aElement;
}
void nsPresContext::SetContainer(nsIDocShell* aDocShell) {
if (aDocShell) {
NS_ASSERTION(!(mContainer && mNeedsPrefUpdate),
"Should only need pref update if mContainer is null.");
mContainer = static_cast<nsDocShell*>(aDocShell);
if (mNeedsPrefUpdate) {
DispatchPrefChangedRunnableIfNeeded();
mNeedsPrefUpdate = false;
}
} else {
mContainer = WeakPtr<nsDocShell>();
}
UpdateIsChrome();
if (mContainer) {
GetDocumentColorPreferences();
}
nsISupports* nsPresContext::GetContainerWeak() const { return GetDocShell(); }
nsIDocShell* nsPresContext::GetDocShell() const {
return mDocument->GetDocShell();
}
nsISupports* nsPresContext::GetContainerWeak() const {
return static_cast<nsIDocShell*>(mContainer);
}
nsIDocShell* nsPresContext::GetDocShell() const { return mContainer; }
/* virtual */ void nsPresContext::Detach() {
SetContainer(nullptr);
SetLinkHandler(nullptr);
}
/* virtual */ void nsPresContext::Detach() { SetLinkHandler(nullptr); }
bool nsPresContext::BidiEnabled() const { return Document()->GetBidiEnabled(); }
void nsPresContext::SetBidiEnabled() const {
if (mShell) {
dom::Document* doc = mShell->GetDocument();
if (doc) {
doc->SetBidiEnabled();
}
}
}
void nsPresContext::SetBidiEnabled() const { Document()->SetBidiEnabled(); }
void nsPresContext::SetBidi(uint32_t aSource) {
// Don't do all this stuff unless the options have changed.
@ -1358,10 +1307,7 @@ void nsPresContext::SetBidi(uint32_t aSource) {
} else if (IBMBIDI_TEXTTYPE_LOGICAL == GET_BIDI_OPTION_TEXTTYPE(aSource)) {
SetVisualMode(false);
} else {
dom::Document* doc = mShell->GetDocument();
if (doc) {
SetVisualMode(IsVisualCharset(doc->GetDocumentCharacterSet()));
}
SetVisualMode(IsVisualCharset(Document()->GetDocumentCharacterSet()));
}
}
@ -1790,20 +1736,19 @@ void nsPresContext::SetPrintSettings(nsIPrintSettings* aPrintSettings) {
}
bool nsPresContext::EnsureVisible() {
nsCOMPtr<nsIDocShell> docShell(mContainer);
if (docShell) {
nsCOMPtr<nsIContentViewer> cv;
docShell->GetContentViewer(getter_AddRefs(cv));
// Make sure this is the content viewer we belong with
if (cv && cv->GetPresContext() == this) {
// OK, this is us. We want to call Show() on the content viewer.
nsresult result = cv->Show();
if (NS_SUCCEEDED(result)) {
return true;
}
}
nsCOMPtr<nsIDocShell> docShell(GetDocShell());
if (!docShell) {
return false;
}
return false;
nsCOMPtr<nsIContentViewer> cv;
docShell->GetContentViewer(getter_AddRefs(cv));
// Make sure this is the content viewer we belong with
if (!cv || cv->GetPresContext() != this) {
return false;
}
// OK, this is us. We want to call Show() on the content viewer.
nsresult result = cv->Show();
return NS_SUCCEEDED(result);
}
#ifdef MOZ_REFLOW_PERF
@ -1814,11 +1759,6 @@ void nsPresContext::CountReflows(const char* aName, nsIFrame* aFrame) {
}
#endif
void nsPresContext::UpdateIsChrome() {
mIsChrome =
mContainer && nsIDocShellTreeItem::typeChrome == mContainer->ItemType();
}
bool nsPresContext::HasAuthorSpecifiedRules(const nsIFrame* aFrame,
uint32_t aRuleTypeMask) const {
Element* elem = aFrame->GetContent()->AsElement();
@ -2592,12 +2532,8 @@ nscoord nsPresContext::PhysicalMillimetersToAppUnits(float aMM) const {
}
bool nsPresContext::IsDeviceSizePageSize() {
bool isDeviceSizePageSize = false;
nsCOMPtr<nsIDocShell> docShell(mContainer);
if (docShell) {
isDeviceSizePageSize = docShell->GetDeviceSizeIsPageSize();
}
return isDeviceSizePageSize;
nsIDocShell* docShell = GetDocShell();
return docShell && docShell->GetDeviceSizeIsPageSize();
}
uint64_t nsPresContext::GetRestyleGeneration() const {

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

@ -413,7 +413,6 @@ class nsPresContext : public nsISupports,
bool GetFocusRingOnAnything() const { return mFocusRingOnAnything; }
uint8_t GetFocusRingStyle() const { return mFocusRingStyle; }
void SetContainer(nsIDocShell* aContainer);
nsISupports* GetContainerWeak() const;
@ -425,7 +424,7 @@ class nsPresContext : public nsISupports,
/**
* Detach this pres context - i.e. cancel relevant timers,
* SetLinkHandler(null), SetContainer(null) etc.
* SetLinkHandler(null), etc.
* Only to be used by the DocumentViewer.
*/
virtual void Detach();
@ -871,9 +870,8 @@ class nsPresContext : public nsISupports,
}
// Is this presentation in a chrome docshell?
bool IsChrome() const { return mIsChrome; }
bool IsChromeOriginImage() const { return mIsChromeOriginImage; }
void UpdateIsChrome();
bool IsChrome() const;
bool IsChromeOriginImage() const;
// Public API for native theme code to get style internals.
bool HasAuthorSpecifiedRules(const nsIFrame* aFrame,
@ -1195,8 +1193,6 @@ class nsPresContext : public nsISupports,
bool mInflationDisabledForShrinkWrap;
protected:
mozilla::WeakPtr<nsDocShell> mContainer;
float mSystemFontScale; // Internal text zoom factor, defaults to 1.0
float mTextZoom; // Text zoom, defaults to 1.0
float mEffectiveTextZoom; // Text zoom * system font scale
@ -1323,9 +1319,6 @@ class nsPresContext : public nsISupports,
unsigned mIsVisual : 1;
unsigned mIsChrome : 1;
unsigned mIsChromeOriginImage : 1;
// Should we paint flash in this context? Do not use this variable directly.
// Use GetPaintFlashing() method instead.
mutable unsigned mPaintFlashing : 1;
@ -1338,9 +1331,6 @@ class nsPresContext : public nsISupports,
// Have we added quirk.css to the style set?
unsigned mQuirkSheetAdded : 1;
// Is there a pref update to process once we have a container?
unsigned mNeedsPrefUpdate : 1;
// Has NotifyNonBlankPaint been called on this PresContext?
unsigned mHadNonBlankPaint : 1;
// Has NotifyContentfulPaint been called on this PresContext?

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

@ -2388,9 +2388,8 @@ nscoord nsFlexContainerFrame::GetLogicalBaseline(
// http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#painting
static uint32_t GetDisplayFlagsForFlexItem(nsIFrame* aFrame) {
MOZ_ASSERT(aFrame->IsFlexItem(), "Should only be called on flex items");
const nsStylePosition* pos = aFrame->StylePosition();
if (pos->mZIndex.GetUnit() == eStyleUnit_Integer) {
if (pos->mZIndex.IsInteger()) {
return nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT;
}
return nsIFrame::DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT;
@ -3627,7 +3626,7 @@ void FlexboxAxisTracker::InitAxesFromLegacyProps(
void FlexboxAxisTracker::InitAxesFromModernProps(
const nsFlexContainerFrame* aFlexContainer) {
const nsStylePosition* stylePos = aFlexContainer->StylePosition();
uint32_t flexDirection = stylePos->mFlexDirection;
StyleFlexDirection flexDirection = stylePos->mFlexDirection;
// Inline dimension ("start-to-end"):
// (NOTE: I'm intentionally not calling these "inlineAxis"/"blockAxis", since
@ -3640,22 +3639,22 @@ void FlexboxAxisTracker::InitAxesFromModernProps(
// Determine main axis:
switch (flexDirection) {
case NS_STYLE_FLEX_DIRECTION_ROW:
case StyleFlexDirection::Row:
mMainAxis = inlineDimension;
mIsRowOriented = true;
mIsMainAxisReversed = false;
break;
case NS_STYLE_FLEX_DIRECTION_ROW_REVERSE:
case StyleFlexDirection::RowReverse:
mMainAxis = GetReverseAxis(inlineDimension);
mIsRowOriented = true;
mIsMainAxisReversed = true;
break;
case NS_STYLE_FLEX_DIRECTION_COLUMN:
case StyleFlexDirection::Column:
mMainAxis = blockDimension;
mIsRowOriented = false;
mIsMainAxisReversed = false;
break;
case NS_STYLE_FLEX_DIRECTION_COLUMN_REVERSE:
case StyleFlexDirection::ColumnReverse:
mMainAxis = GetReverseAxis(blockDimension);
mIsRowOriented = false;
mIsMainAxisReversed = true;
@ -3667,8 +3666,8 @@ void FlexboxAxisTracker::InitAxesFromModernProps(
// Determine cross axis:
// (This is set up so that a bogus |flexDirection| value will
// give us blockDimension.
if (flexDirection == NS_STYLE_FLEX_DIRECTION_COLUMN ||
flexDirection == NS_STYLE_FLEX_DIRECTION_COLUMN_REVERSE) {
if (flexDirection == StyleFlexDirection::Column ||
flexDirection == StyleFlexDirection::ColumnReverse) {
mCrossAxis = inlineDimension;
} else {
mCrossAxis = blockDimension;
@ -4447,8 +4446,8 @@ bool nsFlexContainerFrame::IsItemInlineAxisMainAxis(nsIFrame* aFrame) {
// whether the flex container's main axis is its inline axis.)
auto flexDirection = flexContainer->StylePosition()->mFlexDirection;
bool flexContainerIsRowOriented =
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW ||
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW_REVERSE;
flexDirection == StyleFlexDirection::Row ||
flexDirection == StyleFlexDirection::RowReverse;
// aFrame's inline axis is its flex container's main axis IFF the above
// questions have the same answer.

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

@ -1286,9 +1286,10 @@ void nsIFrame::SyncFrameViewProperties(nsView* aView) {
// Make sure z-index is correct
ComputedStyle* sc = Style();
const nsStylePosition* position = sc->StylePosition();
if (position->mZIndex.GetUnit() == eStyleUnit_Integer) {
zIndex = position->mZIndex.GetIntValue();
} else if (position->mZIndex.GetUnit() == eStyleUnit_Auto) {
if (position->mZIndex.IsInteger()) {
zIndex = position->mZIndex.integer._0;
} else {
MOZ_ASSERT(position->mZIndex.IsAuto());
autoZIndex = true;
}
} else {
@ -10448,7 +10449,7 @@ bool nsIFrame::IsStackingContext(const nsStyleDisplay* aStyleDisplay,
nsSVGIntegrationUtils::UsingEffectsForFrame(this) ||
(aIsPositioned &&
(aStyleDisplay->IsPositionForcingStackingContext() ||
aStylePosition->mZIndex.GetUnit() == eStyleUnit_Integer)) ||
aStylePosition->mZIndex.IsInteger())) ||
(aStyleDisplay->mWillChangeBitField &
NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) ||
aStyleDisplay->mIsolation != NS_STYLE_ISOLATION_AUTO;
@ -10526,8 +10527,9 @@ gfx::Matrix nsIFrame::ComputeWidgetTransform() {
float(appUnitsPerDevPixel));
// Apply the -moz-window-transform-origin translation to the matrix.
const StyleTransformOrigin& origin = uiReset->mWindowTransformOrigin;
Point transformOrigin = nsStyleTransformMatrix::Convert2DPosition(
uiReset->mWindowTransformOrigin, refBox, appUnitsPerDevPixel);
origin.horizontal, origin.vertical, refBox, appUnitsPerDevPixel);
matrix.ChangeBasis(Point3D(transformOrigin.x, transformOrigin.y, 0));
gfx::Matrix result2d;

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

@ -2939,10 +2939,14 @@ static Maybe<int32_t> MaxZIndexInList(nsDisplayList* aList,
Maybe<int32_t> maxZIndex = Nothing();
for (nsDisplayItem* item = aList->GetBottom(); item;
item = item->GetAbove()) {
int32_t zIndex = item->ZIndex();
if (zIndex < 0) {
continue;
}
if (!maxZIndex) {
maxZIndex = Some(item->ZIndex());
maxZIndex = Some(zIndex);
} else {
maxZIndex = Some(std::max(maxZIndex.value(), item->ZIndex()));
maxZIndex = Some(std::max(maxZIndex.value(), zIndex));
}
}
return maxZIndex;
@ -3001,9 +3005,8 @@ static void AppendToTop(nsDisplayListBuilder* aBuilder,
zIndex = Some(INT32_MAX);
} else if (aFlags & APPEND_OVERLAY) {
zIndex = MaxZIndexInList(aLists.PositionedDescendants(), aBuilder);
} else if (aSourceFrame->StylePosition()->mZIndex.GetUnit() ==
eStyleUnit_Integer) {
zIndex = Some(aSourceFrame->StylePosition()->mZIndex.GetIntValue());
} else if (aSourceFrame->StylePosition()->mZIndex.IsInteger()) {
zIndex = Some(aSourceFrame->StylePosition()->mZIndex.integer._0);
}
AppendInternalItemToTop(aLists, newItem, zIndex);
} else {

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

@ -2323,7 +2323,7 @@ void nsGridContainerFrame::GridReflowInput::CalculateTrackSizes(
*/
static uint32_t GetDisplayFlagsForGridItem(nsIFrame* aFrame) {
const nsStylePosition* pos = aFrame->StylePosition();
if (pos->mZIndex.GetUnit() == eStyleUnit_Integer) {
if (pos->mZIndex.IsInteger()) {
return nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT;
}
return nsIFrame::DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT;

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

@ -3081,9 +3081,9 @@ static int32_t ZIndexForFrame(nsIFrame* aFrame) {
return 0;
const nsStylePosition* position = aFrame->StylePosition();
if (position->mZIndex.GetUnit() == eStyleUnit_Integer)
return position->mZIndex.GetIntValue();
if (position->mZIndex.IsInteger())
return position->mZIndex.integer._0;
MOZ_ASSERT(position->mZIndex.IsAuto());
// sort the auto and 0 elements together
return 0;
}
@ -7376,49 +7376,21 @@ bool nsDisplayTransform::ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
refBox.Init(aFrame);
}
/* Allows us to access dimension getters by index. */
float transformOrigin[2];
TransformReferenceBox::DimensionGetter dimensionGetter[] = {
&TransformReferenceBox::Width, &TransformReferenceBox::Height};
TransformReferenceBox::DimensionGetter offsetGetter[] = {
&TransformReferenceBox::X, &TransformReferenceBox::Y};
const StyleTransformOrigin& transformOrigin = display->mTransformOrigin;
CSSPoint origin = nsStyleTransformMatrix::Convert2DPosition(
transformOrigin.horizontal, transformOrigin.vertical, refBox);
for (uint8_t index = 0; index < 2; ++index) {
/* If the transform-origin specifies a percentage, take the percentage
* of the size of the box.
*/
const nsStyleCoord& originValue = display->mTransformOrigin[index];
if (originValue.GetUnit() == eStyleUnit_Calc) {
const nsStyleCoord::Calc* calc = originValue.GetCalcValue();
transformOrigin[index] =
NSAppUnitsToFloatPixels((refBox.*dimensionGetter[index])(),
aAppUnitsPerPixel) *
calc->mPercent +
NSAppUnitsToFloatPixels(calc->mLength, aAppUnitsPerPixel);
} else if (originValue.GetUnit() == eStyleUnit_Percent) {
transformOrigin[index] =
NSAppUnitsToFloatPixels((refBox.*dimensionGetter[index])(),
aAppUnitsPerPixel) *
originValue.GetPercentValue();
} else {
MOZ_ASSERT(originValue.GetUnit() == eStyleUnit_Coord, "unexpected unit");
transformOrigin[index] = NSAppUnitsToFloatPixels(
originValue.GetCoordValue(), aAppUnitsPerPixel);
}
if (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
// SVG frames (unlike other frames) have a reference box that can be (and
// typically is) offset from the TopLeft() of the frame. We need to
// account for that here.
transformOrigin[index] += NSAppUnitsToFloatPixels(
(refBox.*offsetGetter[index])(), aAppUnitsPerPixel);
}
if (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
// SVG frames (unlike other frames) have a reference box that can be (and
// typically is) offset from the TopLeft() of the frame. We need to account
// for that here.
origin.x += CSSPixel::FromAppUnits(refBox.X());
origin.y += CSSPixel::FromAppUnits(refBox.Y());
}
return Point3D(
transformOrigin[0], transformOrigin[1],
NSAppUnitsToFloatPixels(display->mTransformOrigin[2].GetCoordValue(),
aAppUnitsPerPixel));
float scale = mozilla::AppUnitsPerCSSPixel() / float(aAppUnitsPerPixel);
float z = transformOrigin.depth._0;
return Point3D(origin.x * scale, origin.y * scale, z * scale);
}
/* static */ bool nsDisplayTransform::ComputePerspectiveMatrix(
@ -7446,12 +7418,15 @@ bool nsDisplayTransform::ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
}
/* Grab the values for perspective and perspective-origin (if present) */
const nsStyleDisplay* cbDisplay = cbFrame->StyleDisplay();
if (cbDisplay->mChildPerspective.GetUnit() != eStyleUnit_Coord) {
if (cbDisplay->mChildPerspective.IsNone()) {
return false;
}
nscoord perspective = cbDisplay->mChildPerspective.GetCoordValue();
MOZ_ASSERT(cbDisplay->mChildPerspective.IsLength());
// TODO(emilio): Seems quite silly to go through app units just to convert to
// float pixels below.
nscoord perspective = cbDisplay->mChildPerspective.length._0.ToAppUnits();
if (perspective < std::numeric_limits<Float>::epsilon()) {
return true;
}
@ -7459,7 +7434,8 @@ bool nsDisplayTransform::ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
TransformReferenceBox refBox(cbFrame);
Point perspectiveOrigin = nsStyleTransformMatrix::Convert2DPosition(
cbDisplay->mPerspectiveOrigin, refBox, aAppUnitsPerPixel);
cbDisplay->mPerspectiveOrigin.horizontal,
cbDisplay->mPerspectiveOrigin.vertical, refBox, aAppUnitsPerPixel);
/* GetOffsetTo computes the offset required to move from 0,0 in cbFrame to 0,0
* in aFrame. Although we actually want the inverse of this, it's faster to

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

@ -61,7 +61,7 @@ nsImageRenderer::nsImageRenderer(nsIFrame* aForFrame,
mSize(0, 0),
mFlags(aFlags),
mExtendMode(ExtendMode::CLAMP),
mMaskOp(NS_STYLE_MASK_MODE_MATCH_SOURCE) {}
mMaskOp(StyleMaskMode::MatchSource) {}
static bool ShouldTreatAsCompleteDueToSyncDecode(const nsStyleImage* aImage,
uint32_t aFlags) {
@ -428,7 +428,7 @@ ImgDrawResult nsImageRenderer::Draw(nsPresContext* aPresContext,
IntRect tmpDTRect;
if (ctx->CurrentOp() != CompositionOp::OP_OVER ||
mMaskOp == NS_STYLE_MASK_MODE_LUMINANCE) {
mMaskOp == StyleMaskMode::Luminance) {
gfxRect clipRect = ctx->GetClipExtents(gfxContext::eDeviceSpace);
tmpDTRect = RoundedOut(ToRect(clipRect));
if (tmpDTRect.IsEmpty()) {
@ -493,7 +493,7 @@ ImgDrawResult nsImageRenderer::Draw(nsPresContext* aPresContext,
DrawTarget* dt = aRenderingContext.GetDrawTarget();
Matrix oldTransform = dt->GetTransform();
dt->SetTransform(Matrix());
if (mMaskOp == NS_STYLE_MASK_MODE_LUMINANCE) {
if (mMaskOp == StyleMaskMode::Luminance) {
RefPtr<SourceSurface> surf = ctx->GetDrawTarget()->IntoLuminanceSource(
LuminanceType::LUMINANCE, 1.0f);
dt->MaskSurface(ColorPattern(Color(0, 0, 0, 1.0f)), surf,

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

@ -249,7 +249,7 @@ class nsImageRenderer {
bool IsReady() const { return mPrepareResult == ImgDrawResult::SUCCESS; }
ImgDrawResult PrepareResult() const { return mPrepareResult; }
void SetExtendMode(mozilla::gfx::ExtendMode aMode) { mExtendMode = aMode; }
void SetMaskOp(uint8_t aMaskOp) { mMaskOp = aMaskOp; }
void SetMaskOp(mozilla::StyleMaskMode aMaskOp) { mMaskOp = aMaskOp; }
void PurgeCacheForViewportChange(
const mozilla::Maybe<nsSize>& aSVGViewportSize, const bool aHasRatio);
nsStyleImageType GetType() const { return mType; }
@ -305,7 +305,7 @@ class nsImageRenderer {
nsSize mSize; // unscaled size of the image, in app units
uint32_t mFlags;
mozilla::gfx::ExtendMode mExtendMode;
uint8_t mMaskOp;
mozilla::StyleMaskMode mMaskOp;
};
} // namespace mozilla

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

@ -2270,10 +2270,6 @@ nsresult nsPrintJob::ReflowPrintObject(const UniquePtr<nsPrintObject>& aPO) {
aPO.get(), aPO->mPresShell.get(), gFrameTypesStr[aPO->mFrameType],
adjSize.width, adjSize.height));
// This docshell stuff is weird; will go away when we stop having multiple
// presentations per document
aPO->mPresContext->SetContainer(aPO->mDocShell);
aPO->mPresShell->BeginObservingDocument();
aPO->mPresContext->SetPageSize(adjSize);

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

@ -134,6 +134,7 @@ rusty-enums = [
"mozilla::StyleWhiteSpace",
"mozilla::StyleTextRendering",
"mozilla::StyleColorAdjust",
"mozilla::StyleFlexDirection",
"nsStyleImageType",
"nsStyleSVGPaintType",
"nsStyleSVGFallbackType",
@ -144,6 +145,7 @@ rusty-enums = [
"nsStyleTransformMatrix::MatrixTransformOperator",
"mozilla::StyleGeometryBox",
"mozilla::SystemColor",
"mozilla::StyleMaskMode",
]
whitelist-vars = [
"NS_AUTHOR_SPECIFIED_.*",
@ -436,7 +438,12 @@ cbindgen-types = [
{ gecko = "StyleCSSPixelLength", servo = "values::computed::length::CSSPixelLength" },
{ gecko = "StyleNonNegativeLength", servo = "values::computed::NonNegativeLength" },
{ gecko = "StyleNonNegativeNumber", servo = "values::computed::NonNegativeNumber" },
{ gecko = "StylePercentage", servo = "values::computed::Percentage" }
{ gecko = "StylePercentage", servo = "values::computed::Percentage" },
{ gecko = "StylePerspective", servo = "values::computed::Perspective" },
{ gecko = "StyleGenericPerspective", servo = "values::generics::box_::Perspective" },
{ gecko = "StyleZIndex", servo = "values::computed::ZIndex" },
{ gecko = "StyleGenericZIndex", servo = "values::generics::position::ZIndex" },
{ gecko = "StyleTransformOrigin", servo = "values::computed::TransformOrigin" },
]
mapped-generic-types = [

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