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

This commit is contained in:
shindli 2019-06-29 02:23:28 +03:00
Родитель 1aa241f2d1 26d40d0bf2
Коммит 67c134b492
211 изменённых файлов: 4047 добавлений и 1656 удалений

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

@ -156,7 +156,7 @@ var gPluginHandler = {
case "block":
permission = Ci.nsIPermissionManager.PROMPT_ACTION;
expireType = Ci.nsIPermissionManager.EXPIRE_NEVER;
expireType = Ci.nsIPermissionManager.EXPIRE_SESSION;
expireTime = 0;
histogram.add(2);
switch (aPluginInfo.blocklistState) {
@ -259,8 +259,6 @@ var gPluginHandler = {
if (plugins.length == 1) {
let pluginInfo = plugins[0];
let isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
let active = pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE;
let options = {
@ -308,25 +306,21 @@ var gPluginHandler = {
accessKey: gNavigatorBundle.getString("flashActivate.allow.accesskey"),
dismiss: true,
};
let secondaryActions = null;
if (!isWindowPrivate) {
secondaryActions = [{
callback: () => {
let browserRef = weakBrowser.get();
if (browserRef) {
if (pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
this._updatePluginPermission(browserRef, pluginInfo, "block");
} else {
this._updatePluginPermission(browserRef, pluginInfo, "continueblocking");
}
let secondaryActions = [{
callback: () => {
let browserRef = weakBrowser.get();
if (browserRef) {
if (pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
this._updatePluginPermission(browserRef, pluginInfo, "block");
} else {
this._updatePluginPermission(browserRef, pluginInfo, "continueblocking");
}
},
label: gNavigatorBundle.getString("flashActivate.noAllow"),
accessKey: gNavigatorBundle.getString("flashActivate.noAllow.accesskey"),
dismiss: true,
}];
}
}
},
label: gNavigatorBundle.getString("flashActivate.noAllow"),
accessKey: gNavigatorBundle.getString("flashActivate.noAllow.accesskey"),
dismiss: true,
}];
PopupNotifications.show(browser, "click-to-play-plugins",
description, "plugins-notification-icon",

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

@ -650,10 +650,6 @@ function setUp(aNoEngine) {
}
function msg(type, data = null) {
gMsgMan.sendAsyncMessage(TEST_MSG, {
type,
data,
});
return new Promise(resolve => {
gMsgMan.addMessageListener(TEST_MSG, function onMsg(msgObj) {
if (msgObj.data.type != type) {
@ -662,6 +658,10 @@ function msg(type, data = null) {
gMsgMan.removeMessageListener(TEST_MSG, onMsg);
resolve(msgObj.data.data);
});
gMsgMan.sendAsyncMessage(TEST_MSG, {
type,
data,
});
});
}

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

@ -262,7 +262,7 @@ add_task(async function() {
});
}
let tmpPath = expandWhitelistPath("TmpD:").toLowerCase();
let tmpPath = expandWhitelistPath(MAC ? "TmpD:" : "/dev/shm").toLowerCase();
let shouldPass = true;
for (let procName in processes) {
let whitelist = processes[procName];
@ -311,22 +311,15 @@ add_task(async function() {
continue;
}
if (!WIN && filename == "/dev/urandom") {
continue;
}
if (!WIN) {
if (filename == "/dev/urandom") {
continue;
}
// /dev/shm is always tmpfs (a memory filesystem); this isn't
// really I/O any more than mmap/munmap are.
if (LINUX && filename.startsWith("/dev/shm/")) {
continue;
}
// Shared memory uses temporary files on MacOS <= 10.11 to avoid
// a kernel security bug that will never be patched (see
// https://crbug.com/project-zero/1671 for details). This can
// be removed when we no longer support those OS versions.
if (MAC && filename.startsWith(tmpPath + "/org.mozilla.ipc.")) {
continue;
// Ignore I/O due to IPC. This doesn't really touch the disk.
if (filename.startsWith(tmpPath + "/org.chromium.")) {
continue;
}
}
let expected = false;

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

@ -802,7 +802,7 @@ add_task(async function() {
});
}
let tmpPath = expandWhitelistPath("TmpD:").toLowerCase();
let tmpPath = expandWhitelistPath(MAC ? "TmpD:" : "/dev/shm").toLowerCase();
let shouldPass = true;
for (let phase in phases) {
let whitelist = startupPhases[phase];
@ -832,22 +832,15 @@ add_task(async function() {
continue;
}
if (!WIN && filename == "/dev/urandom") {
continue;
}
if (!WIN) {
if (filename == "/dev/urandom") {
continue;
}
// /dev/shm is always tmpfs (a memory filesystem); this isn't
// really I/O any more than mmap/munmap are.
if (LINUX && filename.startsWith("/dev/shm/")) {
continue;
}
// Shared memory uses temporary files on MacOS <= 10.11 to avoid
// a kernel security bug that will never be patched (see
// https://crbug.com/project-zero/1671 for details). This can
// be removed when we no longer support those OS versions.
if (MAC && filename.startsWith(tmpPath + "/org.mozilla.ipc.")) {
continue;
// Ignore I/O due to IPC. This doesn't really touch the disk.
if (filename.startsWith(tmpPath + "/org.chromium.")) {
continue;
}
}
let expected = false;

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

@ -125,8 +125,8 @@ add_task(async function test2c() {
"Shown");
popupNotification.reshow();
await promiseShown;
is(gPrivateWindow.PopupNotifications.panel.firstElementChild.secondaryButton.hidden, true,
"Test 2c, Activated plugin in a private window should not have visible 'Block' button.");
is(gPrivateWindow.PopupNotifications.panel.firstElementChild.secondaryButton.hidden, false,
"Test 2c, Activated plugin in a private window should have visible 'Block' button.");
is(gPrivateWindow.PopupNotifications.panel.firstElementChild.checkbox.hidden, true,
"Test 2c, Activated plugin in a private window should not have visible 'Remember' checkbox.");
@ -183,10 +183,10 @@ add_task(async function test3c() {
"Shown");
popupNotification.reshow();
await promiseShown;
is(gPrivateWindow.PopupNotifications.panel.firstElementChild.secondaryButton.hidden, true,
"Test 2c, Activated plugin in a private window should not have visible 'Block' button.");
is(gPrivateWindow.PopupNotifications.panel.firstElementChild.secondaryButton.hidden, false,
"Test 3c, Activated plugin in a private window should have visible 'Block' button.");
is(gPrivateWindow.PopupNotifications.panel.firstElementChild.checkbox.hidden, true,
"Test 2c, Activated plugin in a private window should not have visible 'Remember' checkbox.");
"Test 3c, Activated plugin in a private window should not have visible 'Remember' checkbox.");
BrowserTestUtils.loadURI(gPrivateBrowser, gHttpTestRoot + "plugin_two_types.html");
await BrowserTestUtils.browserLoaded(gPrivateBrowser);

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

@ -56,11 +56,6 @@ function getBrowser(panel) {
/* fission */ false,
E10SUtils.EXTENSION_REMOTE_TYPE));
readyPromise = promiseEvent(browser, "XULFrameLoaderCreated");
window.messageManager.addMessageListener("contextmenu", openContextMenu);
window.addEventListener("unload", () => {
window.messageManager.removeMessageListener("contextmenu", openContextMenu);
}, {once: true});
} else {
readyPromise = Promise.resolve();
}

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

@ -72,7 +72,7 @@ var AboutLoginsParent = {
_subscribers: new WeakSet(),
// Listeners are added in BrowserGlue.jsm
receiveMessage(message) {
async receiveMessage(message) {
// Only respond to messages sent from about:logins.
if (message.target.remoteType != EXPECTED_ABOUTLOGINS_REMOTE_TYPE ||
message.target.contentPrincipal.originNoSuffix != ABOUT_LOGINS_ORIGIN) {
@ -139,7 +139,7 @@ var AboutLoginsParent = {
this._subscribers.add(message.target);
let messageManager = message.target.messageManager;
messageManager.sendAsyncMessage("AboutLogins:AllLogins", this.getAllLogins());
messageManager.sendAsyncMessage("AboutLogins:AllLogins", await this.getAllLogins());
break;
}
case "AboutLogins:UpdateLogin": {
@ -164,7 +164,7 @@ var AboutLoginsParent = {
}
},
observe(subject, topic, type) {
async observe(subject, topic, type) {
if (!ChromeUtils.nondeterministicGetWeakSetKeys(this._subscribers).length) {
Services.obs.removeObserver(this, "passwordmgr-crypto-login");
Services.obs.removeObserver(this, "passwordmgr-crypto-loginCanceled");
@ -174,7 +174,7 @@ var AboutLoginsParent = {
if (topic == "passwordmgr-crypto-login") {
this.removeMasterPasswordLoginNotifications();
this.messageSubscribers("AboutLogins:AllLogins", this.getAllLogins());
this.messageSubscribers("AboutLogins:AllLogins", await this.getAllLogins());
return;
}
@ -282,11 +282,18 @@ var AboutLoginsParent = {
}
},
getAllLogins() {
return Services.logins
.getAllLogins()
.filter(isValidLogin)
async getAllLogins() {
try {
let logins = await Services.logins.getAllLoginsAsync();
return logins.filter(isValidLogin)
.map(LoginHelper.loginToVanillaObject)
.map(augmentVanillaLoginObject);
} catch (e) {
if (e.result == Cr.NS_ERROR_ABORT) {
// If the user cancels the MP prompt then return no logins.
return [];
}
throw e;
}
},
};

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

@ -1,6 +1,8 @@
[DEFAULT]
prefs =
signon.management.page.enabled=true
support-files =
head.js
# Run first so content events from previous tests won't trickle in.
# Skip ASAN and debug since waiting for content events is already slow.

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

@ -5,11 +5,6 @@ requestLongerTimeout(2);
ChromeUtils.import("resource://testing-common/TelemetryTestUtils.jsm", this);
let nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
Ci.nsILoginInfo, "init");
const LOGIN_URL = "https://example.com/";
let TEST_LOGIN1 = new nsLoginInfo(LOGIN_URL, LOGIN_URL, null, "user1", "pass1");
function waitForTelemetryEventCount(count) {
return TestUtils.waitForCondition(() => {
let events = Services.telemetry.snapshotEvents(
@ -61,14 +56,14 @@ add_task(async function test_telemetry_events() {
});
await waitForTelemetryEventCount(3);
let promiseNewTab = BrowserTestUtils.waitForNewTab(gBrowser, LOGIN_URL);
let promiseNewTab = BrowserTestUtils.waitForNewTab(gBrowser, TEST_LOGIN1.origin);
await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
let loginItem = content.document.querySelector("login-item");
let openSiteButton = loginItem.shadowRoot.querySelector(".open-site-button");
openSiteButton.click();
});
let newTab = await promiseNewTab;
ok(true, "New tab opened to " + LOGIN_URL);
ok(true, "New tab opened to " + TEST_LOGIN1.origin);
BrowserTestUtils.removeTab(newTab);
await waitForTelemetryEventCount(4);

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

@ -1,31 +1,19 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
let gLogins = [{
guid: "70a",
username: "jared",
password: "deraj",
origin: "https://www.example.com",
}, {
guid: "70b",
username: "firefox",
password: "xoferif",
origin: "https://www.example.com",
},
];
add_task(async function setup() {
await BrowserTestUtils.openNewForegroundTab({gBrowser, url: "about:logins"});
registerCleanupFunction(() => {
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
TEST_LOGIN1 = await addLogin(TEST_LOGIN1);
TEST_LOGIN2 = await addLogin(TEST_LOGIN2);
});
add_task(async function test_show_logins() {
let browser = gBrowser.selectedBrowser;
browser.messageManager.sendAsyncMessage("AboutLogins:AllLogins", gLogins);
await ContentTask.spawn(browser, gLogins, async (logins) => {
await ContentTask.spawn(browser, [TEST_LOGIN1, TEST_LOGIN2], async (logins) => {
let loginList = Cu.waiveXrays(content.document.querySelector("login-list"));
let loginFound = await ContentTaskUtils.waitForCondition(() => {
return loginList._logins.length == 2 &&
@ -43,7 +31,7 @@ add_task(async function test_login_item() {
deleteLoginMessageReceived = true;
browser.messageManager.removeMessageListener("AboutLogins:DeleteLogin", onMsg);
});
await ContentTask.spawn(browser, gLogins, async (logins) => {
await ContentTask.spawn(browser, [TEST_LOGIN1, TEST_LOGIN2], async (logins) => {
let loginList = content.document.querySelector("login-list");
let loginListItem = loginList.shadowRoot.querySelector("login-list-item[data-guid]");
info("Clicking on the first login");

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

@ -24,22 +24,18 @@ function waitForMPDialog(action) {
});
}
function getNumberOfLoginsDisplayed(browser) {
return ContentTask.spawn(browser, null, async () => {
function waitForLoginCountToReach(browser, loginCount) {
return ContentTask.spawn(browser, loginCount, async (expectedLoginCount) => {
let loginList = Cu.waiveXrays(content.document.querySelector("login-list"));
await ContentTaskUtils.waitForCondition(() => {
return loginList._logins.length == expectedLoginCount;
});
return loginList._logins.length;
});
}
add_task(async function test() {
let login = LoginTestUtils.testData.formLogin({
origin: "https://example.com",
formActionOrigin: "https://example.com",
username: "username",
password: "password",
});
Services.logins.addLogin(login);
TEST_LOGIN1 = await addLogin(TEST_LOGIN1);
LoginTestUtils.masterPassword.enable();
let mpDialogShown = waitForMPDialog("cancel");
@ -53,7 +49,7 @@ add_task(async function test() {
});
let browser = gBrowser.selectedBrowser;
let logins = await getNumberOfLoginsDisplayed(browser);
let logins = await waitForLoginCountToReach(browser, 0);
is(logins, 0, "No logins should be displayed when MP is set and unauthenticated");
let notification;
@ -76,6 +72,6 @@ add_task(async function test() {
await mpDialogShown;
info("Master Password dialog shown and authenticated");
logins = await getNumberOfLoginsDisplayed(browser);
logins = await waitForLoginCountToReach(browser, 1);
is(logins, 1, "Logins should be displayed when MP is set and authenticated");
});

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

@ -1,11 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
let nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
Ci.nsILoginInfo, "init");
let TEST_LOGIN1 = new nsLoginInfo("https://example.com/", "https://example.com/", null, "user1", "pass1", "username", "password");
let TEST_LOGIN2 = new nsLoginInfo("https://example2.com/", "https://example2.com/", null, "user2", "pass2", "username", "password");
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({"set": [["signon.management.overrideURI", "about:logins?filter=%DOMAIN%"]] });

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

@ -1,16 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
let nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
Ci.nsILoginInfo, "init");
const LOGIN_URL = "https://example.com/";
let TEST_LOGIN1 = new nsLoginInfo(LOGIN_URL, LOGIN_URL, null, "user1", "pass1");
add_task(async function setup() {
let storageChangedPromised = TestUtils.topicObserved("passwordmgr-storage-changed",
(_, data) => data == "addLogin");
TEST_LOGIN1 = Services.logins.addLogin(TEST_LOGIN1);
await storageChangedPromised;
TEST_LOGIN1 = await addLogin(TEST_LOGIN1);
await BrowserTestUtils.openNewForegroundTab({gBrowser, url: "about:logins"});
registerCleanupFunction(() => {
BrowserTestUtils.removeTab(gBrowser.selectedTab);
@ -19,7 +11,7 @@ add_task(async function setup() {
});
add_task(async function test_launch_login_item() {
let promiseNewTab = BrowserTestUtils.waitForNewTab(gBrowser, LOGIN_URL);
let promiseNewTab = BrowserTestUtils.waitForNewTab(gBrowser, TEST_LOGIN1.origin);
let browser = gBrowser.selectedBrowser;
await ContentTask.spawn(browser, LoginHelper.loginToVanillaObject(TEST_LOGIN1), async (login) => {
@ -31,7 +23,7 @@ add_task(async function test_launch_login_item() {
info("waiting for new tab to get opened");
let newTab = await promiseNewTab;
ok(true, "New tab opened to " + LOGIN_URL);
ok(true, "New tab opened to " + TEST_LOGIN1.origin);
BrowserTestUtils.removeTab(newTab);
});

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

@ -1,16 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
let nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
Ci.nsILoginInfo, "init");
const LOGIN_URL = "https://www.example.com";
let TEST_LOGIN1 = new nsLoginInfo(LOGIN_URL, LOGIN_URL, null, "user1", "pass1");
add_task(async function setup() {
let storageChangedPromised = TestUtils.topicObserved("passwordmgr-storage-changed",
(_, data) => data == "addLogin");
TEST_LOGIN1 = Services.logins.addLogin(TEST_LOGIN1);
await storageChangedPromised;
TEST_LOGIN1 = await addLogin(TEST_LOGIN1);
await BrowserTestUtils.openNewForegroundTab({gBrowser, url: "about:logins"});
registerCleanupFunction(() => {
BrowserTestUtils.removeTab(gBrowser.selectedTab);

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

@ -0,0 +1,23 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
let nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
Ci.nsILoginInfo, "init");
let TEST_LOGIN1 = new nsLoginInfo("https://example.com/", "https://example.com/", null, "user1", "pass1", "username", "password");
let TEST_LOGIN2 = new nsLoginInfo("https://2.example.com/", "https://2.example.com/", null, "user2", "pass2", "username", "password");
async function addLogin(login) {
let storageChangedPromised = TestUtils.topicObserved("passwordmgr-storage-changed",
(_, data) => data == "addLogin");
login = Services.logins.addLogin(login);
await storageChangedPromised;
registerCleanupFunction(() => {
let matchData = Cc["@mozilla.org/hash-property-bag;1"].createInstance(Ci.nsIWritablePropertyBag2);
matchData.setPropertyAsAUTF8String("guid", login.guid);
if (!Services.logins.searchLogins(matchData).length) {
return;
}
Services.logins.removeLogin(login);
});
return login;
}

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

@ -5,7 +5,6 @@ prefs =
support-files =
silence.ogg
head_browserAction.js
head_devtools.js
head_pageAction.js
head_sessions.js
head_webNavigation.js
@ -26,7 +25,6 @@ support-files =
file_language_tlh.html
file_dummy.html
file_title.html
file_inspectedwindow_reload_target.sjs
file_indexedDB.html
file_serviceWorker.html
install_other-1.0-fx.xpi
@ -96,17 +94,6 @@ support-files = !/browser/components/places/tests/browser/head.js
[browser_ext_contextMenus_uninstall.js]
[browser_ext_contextMenus_urlPatterns.js]
[browser_ext_currentWindow.js]
[browser_ext_devtools_inspectedWindow.js]
[browser_ext_devtools_inspectedWindow_eval_bindings.js]
[browser_ext_devtools_inspectedWindow_reload.js]
[browser_ext_devtools_network.js]
[browser_ext_devtools_page.js]
[browser_ext_devtools_page_incognito.js]
[browser_ext_devtools_panel.js]
[browser_ext_devtools_panels_elements.js]
[browser_ext_devtools_panels_elements_sidebar.js]
support-files =
../../../../../devtools/client/inspector/extensions/test/head_devtools_inspector_sidebar.js
[browser_ext_find.js]
skip-if = (verify && (os == 'linux' || os == 'mac'))
[browser_ext_getViews.js]

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

@ -10,8 +10,21 @@ tags = webextensions remote-webextensions
skip-if = !e10s
support-files =
head.js
head_devtools.js
file_inspectedwindow_reload_target.sjs
[browser_ext_contentscript_nontab_connect.js]
[browser_ext_devtools_inspectedWindow.js]
[browser_ext_devtools_inspectedWindow_eval_bindings.js]
[browser_ext_devtools_inspectedWindow_reload.js]
[browser_ext_devtools_network.js]
[browser_ext_devtools_page.js]
[browser_ext_devtools_page_incognito.js]
[browser_ext_devtools_panel.js]
[browser_ext_devtools_panels_elements.js]
[browser_ext_devtools_panels_elements_sidebar.js]
support-files =
../../../../../devtools/client/inspector/extensions/test/head_devtools_inspector_sidebar.js
[browser_ext_optionsPage_popups.js]
[browser_ext_popup_select.js]
skip-if = debug || os != 'win' # FIXME: re-enable on debug build (bug 1442822)

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

@ -11,7 +11,7 @@ loadTestSubscript("head_devtools.js");
// Small helper which provides the common steps to the following reload test cases.
async function runReloadTestCase({urlParams, background, devtoolsPage, testCase}) {
const BASE = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/";
const TEST_TARGET_URL = `${BASE}file_inspectedwindow_reload_target.sjs?${urlParams}`;
const TEST_TARGET_URL = `${BASE}/test-oop-extensions/file_inspectedwindow_reload_target.sjs?${urlParams}`;
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_TARGET_URL);
let extension = ExtensionTestUtils.loadExtension({

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

@ -17,10 +17,10 @@
/* Prevent accent color overriding the window background for
* light and dark theme on Aero Basic. This is copied from browser-aero.css. */
@media (-moz-windows-default-theme) {
#main-window {
:root {
background-color: rgb(185,209,234) !important;
}
#main-window:-moz-window-inactive {
:root:-moz-window-inactive {
background-color: rgb(215,228,242) !important;
}
}
@ -66,7 +66,7 @@
@media (-moz-os-version: windows-win7),
(-moz-os-version: windows-win8) {
@media (-moz-windows-compositor) {
#main-window {
:root {
background: transparent !important;
}
@ -120,7 +120,7 @@
color: InactiveCaptionText;
}
#main-window[tabsintitlebar] #main-menubar > menu {
:root[tabsintitlebar] #main-menubar > menu {
color: inherit;
}
}

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

@ -1,8 +1,8 @@
.. _test_certificates:
==============
===============================
Adding Certificates for Testing
==============
===============================
Sometimes we need to write tests for scenarios that require custom client, server or certificate authority (CA) certificates. For that purpose, you can generate such certificates using ``build/pgo/genpgocert.py``.

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

@ -2484,15 +2484,9 @@ set_config('AR_FLAGS', ar_config.flags)
# Frame pointers
# ==============================================================
@depends(c_compiler, target)
def frame_pointer_flags(compiler, target):
@depends(c_compiler)
def frame_pointer_flags(compiler):
if compiler.type == 'clang-cl':
if target.cpu == 'aarch64':
# Some version of clang-cl don't support -Oy-; accomodate them.
return namespace(
enable=['-Xclang', '-mdisable-fp-elim'],
disable=['-Xclang', '-mdisable-fp-elim'],
)
return namespace(
enable=['-Oy-'],
disable=['-Oy'],

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

@ -133,6 +133,7 @@ endif
# Enable profile-based feedback
ifneq (1,$(NO_PROFILE_GUIDED_OPTIMIZE))
ifdef MOZ_PROFILE_GENERATE
PGO_CFLAGS += -DNS_FREE_PERMANENT_DATA=1
PGO_CFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_GEN_CFLAGS))
PGO_LDFLAGS += $(PROFILE_GEN_LDFLAGS)
ifeq (WINNT,$(OS_ARCH))

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

@ -320,6 +320,11 @@ module.exports = {
"no-regex-spaces": "off",
// Don't restrict usage of specified node modules (not a node environment).
"no-restricted-modules": "off",
// Prevent using some properties
"no-restricted-properties": ["error", {
"property": "setupInParent",
"message": "avoid child/parent communication with setupInParent"
}],
// Disallow use of assignment in return statement. It is preferable for a
// single line of code to have only one easily predictable effect.
"no-return-assign": "error",

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

@ -72,6 +72,15 @@ function getIframeFromEvent(event) {
return iframe;
}
// This function takes the button element, and returns a function that's used to
// update the profiler button whenever the profiler activation status changed.
const updateButtonColorForElement = buttonElement => () => {
const isRunning = Services.profiler.IsActive();
// Use photon blue-60 when active.
buttonElement.style.fill = isRunning ? "#0060df" : "";
};
/**
* This function creates the widget definition for the CustomizableUI. It should
* only be run if the profiler button is enabled.
@ -112,33 +121,20 @@ function initialize() {
},
onBeforeCreated: (document) => {
setMenuItemChecked(document, true);
observer = {
observe(subject, topic, data) {
switch (topic) {
case "profiler-started": {
const button = document.querySelector("#profiler-button");
if (button) {
// Photon blue-60.
button.style.fill = "#0060df";
}
break;
}
case "profiler-stopped": {
const button = document.querySelector("#profiler-button");
if (button) {
button.style.fill = "";
}
break;
}
}
},
};
},
onCreated: (buttonElement) => {
observer = updateButtonColorForElement(buttonElement);
Services.obs.addObserver(observer, "profiler-started");
Services.obs.addObserver(observer, "profiler-stopped");
// Also run the observer right away to update the color if the profiler is
// already running at startup.
observer();
},
onDestroyed: () => {
Services.obs.removeObserver(observer, "profiler-started");
Services.obs.removeObserver(observer, "profiler-stopped");
observer = null;
},
};
CustomizableUI.createWidget(item);

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

@ -210,7 +210,7 @@ class JSTerm extends Component {
autofocus: true,
enableCodeFolding: false,
autoCloseBrackets: false,
gutters: [],
lineNumbers: this.props.editorMode,
lineWrapping: true,
mode: Editor.modes.js,
styleActiveLine: false,
@ -458,13 +458,20 @@ class JSTerm extends Component {
* @param {Object} nextProps: props passed from shouldComponentUpdate.
*/
imperativeUpdate(nextProps) {
if (!nextProps) {
return;
}
if (
nextProps &&
nextProps.autocompleteData !== this.props.autocompleteData &&
nextProps.autocompleteData.pendingRequestId === null
) {
this.updateAutocompletionPopup(nextProps.autocompleteData);
}
if (this.editor && nextProps.editorMode !== this.props.editorMode) {
this.editor.setOption("lineNumbers", nextProps.editorMode);
}
}
/**

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

@ -212,6 +212,7 @@ skip-if = os != 'mac' # The tested ctrl+key shortcuts are OSX only
[browser_jsterm_editor.js]
[browser_jsterm_editor_enter.js]
[browser_jsterm_editor_execute.js]
[browser_jsterm_editor_gutter.js]
[browser_jsterm_editor_toggle_keyboard_shortcut.js]
[browser_jsterm_editor_toolbar.js]
[browser_jsterm_error_docs.js]

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

@ -0,0 +1,34 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that CodeMirror's gutter in console input is displayed when
// 'devtools.webconsole.input.editor' is true.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1519315
"use strict";
const TEST_URI = "data:text/html;charset=utf-8,Test JsTerm editor line gutters";
add_task(async function() {
await pushPref("devtools.webconsole.input.editor", true);
const hud = await openNewTabAndConsole(TEST_URI);
info("Check that the line numbers gutter is rendered when in editor layout");
ok(getLineNumbersGutterElement(hud),
"line numbers gutter is rendered on the input when in editor mode.");
info("Check that the line numbers gutter is hidden we switch to the inline layout");
await toggleLayout(hud);
ok(!getLineNumbersGutterElement(hud),
"line numbers gutter is hidden on the input when in inline mode.");
info("Check that the line numbers gutter is rendered again we switch back to editor");
await toggleLayout(hud);
ok(getLineNumbersGutterElement(hud), "line numbers gutter is rendered again on the " +
" input when switching back to editor mode.");
});
function getLineNumbersGutterElement(hud) {
return hud.ui.outputNode.querySelector(".CodeMirror-linenumbers");
}

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

@ -48,14 +48,3 @@ async function performTest() {
Services.prefs.clearUserPref(EDITOR_PREF);
}
function toggleLayout(hud) {
const isMacOS = Services.appinfo.OS === "Darwin";
const enabled = isEditorModeEnabled(hud);
EventUtils.synthesizeKey("b", {
[isMacOS ? "metaKey" : "ctrlKey"]: true,
});
return waitFor(() => isEditorModeEnabled(hud) === !enabled);
}

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

@ -1402,3 +1402,20 @@ function isEditorModeEnabled(hud) {
const appNode = outputNode.querySelector(".webconsole-app");
return appNode.classList.contains("jsterm-editor");
}
/**
* Toggle the layout between in-line and editor.
*
* @param {WebConsole} hud
* @returns {Promise} A promise that resolves once the layout change was rendered.
*/
function toggleLayout(hud) {
const isMacOS = Services.appinfo.OS === "Darwin";
const enabled = isEditorModeEnabled(hud);
EventUtils.synthesizeKey("b", {
[isMacOS ? "metaKey" : "ctrlKey"]: true,
});
return waitFor(() => isEditorModeEnabled(hud) === !enabled);
}

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

@ -2,6 +2,14 @@
In multi-process environments, most devtools actors are created and initialized in the child content process, to be able to access the resources they are exposing to the toolbox. But sometimes, these actors need to access things in the parent process too. Here's why and how.
{% hint style="error" %}
This documentation page is **deprecated**. `setupInParent` relies on the message manager which is being deprecated. Furthermore, communications between parent and content processes should be avoided for security reasons. If possible, the client should be responsible for calling actors both on the parent and content process.
This page will be removed when all actors relying on this API are removed.
{% endhint %}
## Use case and examples
Some actors need to exchange messages between the parent and the child process (typically when some components aren't available in the child process).

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

@ -28,6 +28,7 @@ const AccessibilityActor = ActorClassWithSpec(accessibilitySpec, {
if (DebuggerServer.isInChildProcess) {
this._msgName = `debug:${this.conn.prefix}accessibility`;
// eslint-disable-next-line no-restricted-properties
this.conn.setupInParent({
module: "devtools/server/actors/accessibility/accessibility-parent",
setupParent: "setupParentProcess",

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

@ -751,6 +751,7 @@ StorageActors.createActor({
const mm = this.conn.parentMessageManager;
// eslint-disable-next-line no-restricted-properties
this.conn.setupInParent({
module: "devtools/server/actors/storage",
setupParent: "setupParentProcessForCookies",
@ -1877,6 +1878,7 @@ StorageActors.createActor({
const mm = this.conn.parentMessageManager;
// eslint-disable-next-line no-restricted-properties
this.conn.setupInParent({
module: "devtools/server/actors/storage",
setupParent: "setupParentProcessForIndexedDB",

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

@ -12,6 +12,7 @@ exports.callParent = function() {
// Hack! Fetch DebuggerServerConnection objects directly within DebuggerServer guts.
for (const id in DebuggerServer._connections) {
const conn = DebuggerServer._connections[id];
// eslint-disable-next-line no-restricted-properties
conn.setupInParent({
module: "chrome://mochitests/content/chrome/devtools/server/tests/mochitest/setup-in-parent.js",
setupParent: "setupParent",

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

@ -2591,29 +2591,29 @@ bool nsFrameLoader::TryRemoteBrowserInternal() {
// out of process iframes also get to skip this check.
if (!OwnerIsMozBrowserFrame() && !XRE_IsContentProcess()) {
if (parentDocShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
// Allow about:addon an exception to this rule so it can load remote
// extension options pages.
// Allow two exceptions to this rule :
// - about:addon so it can load remote extension options pages
// - DevTools webext panels if DevTools is loaded in a content frame
//
// Note that the new frame's message manager will not be a child of the
// chrome window message manager, and, the values of window.top and
// window.parent will be different than they would be for a non-remote
// frame.
nsCOMPtr<nsIWebNavigation> parentWebNav;
nsCOMPtr<nsIURI> aboutAddons;
nsCOMPtr<nsIURI> parentURI;
bool equals;
if (!((parentWebNav = do_GetInterface(parentDocShell)) &&
NS_SUCCEEDED(
parentWebNav->GetCurrentURI(getter_AddRefs(parentURI))) &&
((NS_SUCCEEDED(
NS_NewURI(getter_AddRefs(aboutAddons), "about:addons")) &&
NS_SUCCEEDED(parentURI->EqualsExceptRef(aboutAddons, &equals)) &&
equals) ||
(NS_SUCCEEDED(NS_NewURI(
getter_AddRefs(aboutAddons),
"chrome://mozapps/content/extensions/aboutaddons.html")) &&
NS_SUCCEEDED(parentURI->EqualsExceptRef(aboutAddons, &equals)) &&
equals)))) {
nsIURI* parentURI = parentWin->GetDocumentURI();
if (!parentURI) {
return false;
}
nsAutoCString specIgnoringRef;
if (NS_FAILED(parentURI->GetSpecIgnoringRef(specIgnoringRef))) {
return false;
}
if (!(specIgnoringRef.EqualsLiteral("about:addons") ||
specIgnoringRef.EqualsLiteral(
"chrome://mozapps/content/extensions/aboutaddons.html") ||
specIgnoringRef.EqualsLiteral(
"chrome://browser/content/webext-panels.xul"))) {
return false;
}
}

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

@ -2417,9 +2417,9 @@ static void SetMemoryGCSliceTimePrefChangedCallback(const char* aPrefName,
// handle overflow and negative pref values
if (pref > 0 && pref < 100000) {
sActiveIntersliceGCBudget = pref;
SetGCParameter(JSGC_SLICE_TIME_BUDGET, pref);
SetGCParameter(JSGC_SLICE_TIME_BUDGET_MS, pref);
} else {
ResetGCParameter(JSGC_SLICE_TIME_BUDGET);
ResetGCParameter(JSGC_SLICE_TIME_BUDGET_MS);
}
}

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

@ -6,41 +6,109 @@
#include "MemMapSnapshot.h"
#include "mozilla/AutoMemMap.h"
#include "base/eintr_wrapper.h"
#include "base/file_util.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/ipc/FileDescriptorUtils.h"
#include "nsIFile.h"
#ifdef XP_UNIX
# include <sys/stat.h>
#endif
namespace mozilla {
using loader::AutoMemMap;
namespace ipc {
Result<Ok, nsresult> MemMapSnapshot::Init(size_t aSize) {
MOZ_ASSERT(!mInitialized);
if (NS_WARN_IF(!mMem.CreateFreezeable(aSize))) {
return Err(NS_ERROR_FAILURE);
}
if (NS_WARN_IF(!mMem.Map(aSize))) {
return Err(NS_ERROR_FAILURE);
}
MOZ_TRY(Create(aSize));
mInitialized = true;
return Ok();
}
Result<Ok, nsresult> MemMapSnapshot::Finalize(loader::AutoMemMap& aMem) {
Result<Ok, nsresult> MemMapSnapshot::Finalize(AutoMemMap& aMem) {
MOZ_ASSERT(mInitialized);
if (NS_WARN_IF(!mMem.Freeze())) {
return Err(NS_ERROR_FAILURE);
}
// TakeHandle resets mMem, so call max_size first.
size_t size = mMem.max_size();
FileDescriptor memHandle(mMem.TakeHandle());
MOZ_TRY(aMem.initWithHandle(memHandle, size));
MOZ_TRY(Freeze(aMem));
mInitialized = false;
return Ok();
}
#if defined(XP_WIN)
Result<Ok, nsresult> MemMapSnapshot::Create(size_t aSize) {
HANDLE handle = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr,
PAGE_READWRITE, 0, DWORD(aSize), nullptr);
if (!handle) {
return Err(NS_ERROR_FAILURE);
}
mFile.emplace(handle);
return mMem.initWithHandle(mFile.ref(), aSize, PR_PROT_READWRITE);
}
Result<Ok, nsresult> MemMapSnapshot::Freeze(AutoMemMap& aMem) {
auto orig = mFile.ref().ClonePlatformHandle();
mFile.reset();
HANDLE handle;
if (!::DuplicateHandle(
GetCurrentProcess(), orig.release(), GetCurrentProcess(), &handle,
GENERIC_READ | FILE_MAP_READ, false, DUPLICATE_CLOSE_SOURCE)) {
return Err(NS_ERROR_FAILURE);
}
return aMem.initWithHandle(FileDescriptor(handle), mMem.size());
}
#elif defined(XP_UNIX)
Result<Ok, nsresult> MemMapSnapshot::Create(size_t aSize) {
FilePath path;
ScopedCloseFile fd(file_util::CreateAndOpenTemporaryShmemFile(&path));
if (!fd) {
return Err(NS_ERROR_FAILURE);
}
if (HANDLE_EINTR(ftruncate(fileno(fd), aSize)) != 0) {
return Err(NS_ERROR_FAILURE);
}
MOZ_TRY(mMem.init(FILEToFileDescriptor(fd), PR_PROT_READWRITE));
mPath.Assign(path.value().data(), path.value().length());
return Ok();
}
Result<Ok, nsresult> MemMapSnapshot::Freeze(AutoMemMap& aMem) {
// Delete the shm file after we're done here, whether we succeed or not. The
// open file descriptor will keep it alive until all remaining references
// are closed, at which point it will be automatically freed.
auto cleanup = MakeScopeExit([&]() { PR_Delete(mPath.get()); });
// Make the shm file readonly. This doesn't make a difference in practice,
// since we open and share a read-only file descriptor, and then delete the
// file. But it doesn't hurt, either.
chmod(mPath.get(), 0400);
nsCOMPtr<nsIFile> file;
MOZ_TRY(NS_NewNativeLocalFile(mPath, /* followLinks = */ false,
getter_AddRefs(file)));
return aMem.init(file);
}
#else
# error "Unsupported build configuration"
#endif
} // namespace ipc
} // namespace mozilla

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

@ -7,17 +7,16 @@
#ifndef dom_ipc_MemMapSnapshot_h
#define dom_ipc_MemMapSnapshot_h
#include "mozilla/AutoMemMap.h"
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/RangedPtr.h"
#include "mozilla/Result.h"
#include "base/shared_memory.h"
#ifdef XP_WIN
# include "mozilla/ipc/FileDescriptor.h"
#endif
namespace mozilla {
namespace loader {
class AutoMemMap;
}
namespace ipc {
/**
@ -36,15 +35,25 @@ class MOZ_RAII MemMapSnapshot {
Result<Ok, nsresult> Init(size_t aSize);
Result<Ok, nsresult> Finalize(loader::AutoMemMap& aMap);
template <typename T>
template <typename T = void>
RangedPtr<T> Get() {
MOZ_ASSERT(mInitialized);
return {static_cast<T*>(mMem.memory()), mMem.max_size() / sizeof(T)};
return mMem.get<T>();
}
private:
base::SharedMemory mMem;
Result<Ok, nsresult> Create(size_t aSize);
Result<Ok, nsresult> Freeze(loader::AutoMemMap& aMem);
loader::AutoMemMap mMem;
bool mInitialized = false;
#ifdef XP_WIN
Maybe<FileDescriptor> mFile;
#else
nsCString mPath;
#endif
};
} // namespace ipc

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

@ -21,8 +21,6 @@ using namespace ipc;
namespace dom {
namespace ipc {
static constexpr uint32_t kSharedStringMapMagic = 0x9e3779b9;
static inline size_t GetAlignmentOffset(size_t aOffset, size_t aAlign) {
auto mod = aOffset % aAlign;
return mod ? aAlign - mod : 0;
@ -32,7 +30,6 @@ SharedStringMap::SharedStringMap(const FileDescriptor& aMapFile,
size_t aMapSize) {
auto result = mMap.initWithHandle(aMapFile, aMapSize);
MOZ_RELEASE_ASSERT(result.isOk());
MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic);
// We return literal nsStrings and nsCStrings pointing to the mapped data,
// which means that we may still have references to the mapped data even
// after this instance is destroyed. That means that we need to keep the
@ -43,7 +40,6 @@ SharedStringMap::SharedStringMap(const FileDescriptor& aMapFile,
SharedStringMap::SharedStringMap(SharedStringMapBuilder&& aBuilder) {
auto result = aBuilder.Finalize(mMap);
MOZ_RELEASE_ASSERT(result.isOk());
MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic);
mMap.setPersistent();
}
@ -96,7 +92,7 @@ Result<Ok, nsresult> SharedStringMapBuilder::Finalize(
}
keys.Sort();
Header header = {kSharedStringMapMagic, uint32_t(keys.Length())};
Header header = {uint32_t(keys.Length())};
size_t offset = sizeof(header);
offset += GetAlignmentOffset(offset, alignof(Header));

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

@ -59,7 +59,6 @@ class SharedStringMap {
* encoded as character (*not* byte) offsets into this region.
*/
struct Header {
uint32_t mMagic;
// The number of entries in this map.
uint32_t mEntryCount;

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

@ -272,7 +272,9 @@ tags = mcb
[test_match_all.html]
[test_match_all_advanced.html]
[test_match_all_client_id.html]
skip-if = toolkit == 'android' && !is_fennec
[test_match_all_client_properties.html]
skip-if = toolkit == 'android' && !is_fennec
[test_navigator.html]
[test_not_intercept_plugin.html]
[test_notification_constructor_error.html]

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

@ -504,7 +504,7 @@ void LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */) {
int32_t prefValue = GetWorkerPref(matchName, -1);
uint32_t value =
(prefValue <= 0 || prefValue >= 100000) ? 0 : uint32_t(prefValue);
UpdateOtherJSGCMemoryOption(rts, JSGC_SLICE_TIME_BUDGET, value);
UpdateOtherJSGCMemoryOption(rts, JSGC_SLICE_TIME_BUDGET_MS, value);
continue;
}

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

@ -57,6 +57,16 @@ OFFSET_COMMAND4(MaskSurface, const Pattern&, SourceSurface*, Point,
const DrawOptions&)
OFFSET_COMMAND4(FillGlyphs, ScaledFont*, const GlyphBuffer&, const Pattern&,
const DrawOptions&)
OFFSET_COMMAND5(StrokeGlyphs, ScaledFont*, const GlyphBuffer&, const Pattern&,
const StrokeOptions&, const DrawOptions&)
OFFSET_COMMAND3(FillRoundedRect, const RoundedRect&, const Pattern&,
const DrawOptions&)
bool DrawTargetOffset::Draw3DTransformedSurface(SourceSurface *aSrc,
const Matrix4x4& aMatrix) {
return mDrawTarget->Draw3DTransformedSurface(aSrc, aMatrix);
}
OFFSET_COMMAND3(Mask, const Pattern&, const Pattern&, const DrawOptions&)
void DrawTargetOffset::DrawFilter(FilterNode* aNode, const Rect& aSourceRect,

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

@ -95,6 +95,9 @@ class DrawTargetOffset : public DrawTarget {
virtual void FillRect(const Rect& aRect, const Pattern& aPattern,
const DrawOptions& aOptions = DrawOptions()) override;
virtual void FillRoundedRect(const RoundedRect& aRect,
const Pattern& aPattern,
const DrawOptions& aOptions = DrawOptions()) override;
virtual void StrokeRect(const Rect& aRect, const Pattern& aPattern,
const StrokeOptions& aStrokeOptions = StrokeOptions(),
const DrawOptions& aOptions = DrawOptions()) override;
@ -110,6 +113,10 @@ class DrawTargetOffset : public DrawTarget {
virtual void FillGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
const Pattern& aPattern,
const DrawOptions& aOptions = DrawOptions()) override;
virtual void StrokeGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
const Pattern& aPattern,
const StrokeOptions& aStrokeOptions = StrokeOptions(),
const DrawOptions& aOptions = DrawOptions()) override;
virtual void Mask(const Pattern& aSource, const Pattern& aMask,
const DrawOptions& aOptions = DrawOptions()) override;
virtual void PushClip(const Path* aPath) override;
@ -124,6 +131,8 @@ class DrawTargetOffset : public DrawTarget {
const Matrix& aMaskTransform, const IntRect& aBounds = IntRect(),
bool aCopyBackground = false,
CompositionOp = CompositionOp::OP_OVER) override;
virtual bool Draw3DTransformedSurface(SourceSurface* aSurface,
const Matrix4x4& aMatrix) override;
virtual void PopLayer() override;
virtual void SetTransform(const Matrix& aTransform) override;

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

@ -22,7 +22,11 @@ nsresult SharedDIB::Create(uint32_t aSize) {
return NS_OK;
}
bool SharedDIB::IsValid() { return mShMem && mShMem->IsValid(); }
bool SharedDIB::IsValid() {
if (!mShMem) return false;
return base::SharedMemory::IsHandleValid(mShMem->handle());
}
nsresult SharedDIB::Close() {
delete mShMem;

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

@ -100,9 +100,8 @@ nsresult SharedDIBWin::SetupSurface(HDC aHdc, BITMAPV4HEADER* aHdr) {
if (!mSharedHdc) return NS_ERROR_FAILURE;
mSharedBmp =
::CreateDIBSection(mSharedHdc, (BITMAPINFO*)aHdr, DIB_RGB_COLORS,
&mBitmapBits, mShMem->GetHandle(), kHeaderBytes);
mSharedBmp = ::CreateDIBSection(mSharedHdc, (BITMAPINFO*)aHdr, DIB_RGB_COLORS,
&mBitmapBits, mShMem->handle(), kHeaderBytes);
if (!mSharedBmp) return NS_ERROR_FAILURE;
mOldObj = SelectObject(mSharedHdc, mSharedBmp);

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

@ -5,7 +5,7 @@ fuzzy-if(Android,0-4,0-5) skip-if(!asyncPan) pref(apz.allow_zooming,true) == asy
fuzzy-if(Android,0-3,0-5) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
fuzzy-if(Android,1-1,1-2) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
fuzzy-if(Android,0-4,0-5) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
fuzzy-if(Android,0-3,0-7) skip-if(!asyncPan) pref(apz.allow_zooming,true) fuzzy-if(geckoview,2-2,9-9) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
fuzzy-if(Android,0-3,0-7) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
# Different async zoom levels. Since the scrollthumb gets async-scaled in the
# compositor, the border-radius ends of the scrollthumb are going to be a little
@ -29,5 +29,5 @@ skip-if(!asyncPan) == frame-reconstruction-scroll-clamping.html frame-reconstruc
# Test that position:fixed and position:sticky elements are attached to the
# layout viewport.
pref(apz.allow_zooming,true) fuzzy-if(geckoview,3-3,4000-4000) == pinch-zoom-position-fixed.html pinch-zoom-position-fixed-ref.html
pref(apz.allow_zooming,true) == pinch-zoom-position-fixed.html pinch-zoom-position-fixed-ref.html
pref(apz.allow_zooming,true) == pinch-zoom-position-sticky.html pinch-zoom-position-sticky-ref.html

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

@ -39,6 +39,7 @@
#include "mozilla/Unused.h"
#include "base/eintr_wrapper.h"
#include "base/file_util.h"
#include <locale.h>

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

@ -22,7 +22,6 @@ from mozbuild.base import MachCommandBase
import mozpack.path as mozpath
import json
import requests
GITHUB_ROOT = 'https://github.com/'
@ -51,6 +50,7 @@ class PullRequestImporter(MachCommandBase):
help='URL to the pull request to import (e.g. '
'https://github.com/servo/webrender/pull/3665).')
def import_pr(self, pull_request, bug_number=None, bugzilla_token=None, reviewer=None):
import requests
pr_number = None
repository = None
for r in PR_REPOSITORIES.values():
@ -109,6 +109,7 @@ class PullRequestImporter(MachCommandBase):
'Committed successfully.')
def _file_bug(self, token, repo, pr_number):
import requests
bug = requests.post('https://bugzilla.mozilla.org/rest/bug?api_key=%s' % token,
json={
'product': repo['bugzilla_product'],

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

@ -11,6 +11,7 @@ UNIFIED_SOURCES += [
'src/base/at_exit.cc',
'src/base/command_line.cc',
'src/base/file_path.cc',
'src/base/file_util.cc',
'src/base/histogram.cc',
'src/base/logging.cc',
'src/base/message_loop.cc',
@ -34,6 +35,7 @@ UNIFIED_SOURCES += [
if os_win:
SOURCES += [
'src/base/condition_variable_win.cc',
'src/base/file_util_win.cc',
'src/base/lock_impl_win.cc',
'src/base/message_pump_win.cc',
'src/base/object_watcher.cc',
@ -55,6 +57,7 @@ elif not CONFIG['MOZ_SYSTEM_LIBEVENT']:
if os_posix:
UNIFIED_SOURCES += [
'src/base/condition_variable_posix.cc',
'src/base/file_util_posix.cc',
'src/base/lock_impl_posix.cc',
'src/base/message_pump_libevent.cc',
'src/base/platform_thread_posix.cc',
@ -71,6 +74,7 @@ if os_posix:
if os_macosx:
UNIFIED_SOURCES += [
'src/base/chrome_application_mac.mm',
'src/base/file_util_mac.mm',
'src/base/mac_util.mm',
'src/base/message_pump_mac.mm',
'src/base/process_util_mac.mm',

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

@ -0,0 +1,234 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/file_util.h"
#if defined(OS_WIN)
# include <io.h>
#endif
#include <stdio.h>
#if defined(ANDROID) || defined(OS_POSIX)
# include <unistd.h>
#endif
#include <fstream>
#include "base/file_path.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "base/string_piece.h"
#include "base/sys_string_conversions.h"
namespace {
const FilePath::CharType kExtensionSeparator = FILE_PATH_LITERAL('.');
} // namespace
namespace file_util {
bool EndsWithSeparator(const FilePath& path) {
FilePath::StringType value = path.value();
if (value.empty()) return false;
return FilePath::IsSeparator(value[value.size() - 1]);
}
void TrimTrailingSeparator(std::wstring* dir) {
while (dir->length() > 1 && EndsWithSeparator(dir))
dir->resize(dir->length() - 1);
}
FilePath::StringType GetFileExtensionFromPath(const FilePath& path) {
FilePath::StringType file_name = path.BaseName().value();
const FilePath::StringType::size_type last_dot =
file_name.rfind(kExtensionSeparator);
return FilePath::StringType(last_dot == FilePath::StringType::npos
? FILE_PATH_LITERAL("")
: file_name,
last_dot + 1);
}
void InsertBeforeExtension(FilePath* path, const FilePath::StringType& suffix) {
FilePath::StringType& value =
const_cast<FilePath::StringType&>(path->value());
const FilePath::StringType::size_type last_dot =
value.rfind(kExtensionSeparator);
const FilePath::StringType::size_type last_separator =
value.find_last_of(FilePath::StringType(FilePath::kSeparators));
if (last_dot == FilePath::StringType::npos ||
(last_separator != std::wstring::npos && last_dot < last_separator)) {
// The path looks something like "C:\pics.old\jojo" or "C:\pics\jojo".
// We should just append the suffix to the entire path.
value.append(suffix);
return;
}
value.insert(last_dot, suffix);
}
void ReplaceExtension(FilePath* path, const FilePath::StringType& extension) {
FilePath::StringType clean_extension;
// If the new extension is "" or ".", then we will just remove the current
// extension.
if (!extension.empty() &&
extension != FilePath::StringType(&kExtensionSeparator, 1)) {
if (extension[0] != kExtensionSeparator)
clean_extension.append(&kExtensionSeparator, 1);
clean_extension.append(extension);
}
FilePath::StringType& value =
const_cast<FilePath::StringType&>(path->value());
const FilePath::StringType::size_type last_dot =
value.rfind(kExtensionSeparator);
const FilePath::StringType::size_type last_separator =
value.find_last_of(FilePath::StringType(FilePath::kSeparators));
// Erase the current extension, if any.
if ((last_dot > last_separator ||
last_separator == FilePath::StringType::npos) &&
last_dot != FilePath::StringType::npos)
value.erase(last_dot);
value.append(clean_extension);
}
FILE* CreateAndOpenTemporaryFile(FilePath* path) {
FilePath directory;
if (!GetTempDir(&directory)) return NULL;
return CreateAndOpenTemporaryFileInDir(directory, path);
}
bool GetFileSize(const FilePath& file_path, int64_t* file_size) {
FileInfo info;
if (!GetFileInfo(file_path, &info)) return false;
*file_size = info.size;
return true;
}
bool CloseFile(FILE* file) {
if (file == NULL) return true;
return fclose(file) == 0;
}
// Deprecated functions ----------------------------------------------------
bool AbsolutePath(std::wstring* path_str) {
FilePath path(FilePath::FromWStringHack(*path_str));
if (!AbsolutePath(&path)) return false;
*path_str = path.ToWStringHack();
return true;
}
void AppendToPath(std::wstring* path, const std::wstring& new_ending) {
if (!path) {
NOTREACHED();
return; // Don't crash in this function in release builds.
}
if (!EndsWithSeparator(path)) path->push_back(FilePath::kSeparators[0]);
path->append(new_ending);
}
bool CopyFile(const std::wstring& from_path, const std::wstring& to_path) {
return CopyFile(FilePath::FromWStringHack(from_path),
FilePath::FromWStringHack(to_path));
}
bool CreateDirectory(const std::wstring& full_path) {
return CreateDirectory(FilePath::FromWStringHack(full_path));
}
bool CreateNewTempDirectory(const std::wstring& prefix,
std::wstring* new_temp_path) {
#if defined(OS_WIN)
FilePath::StringType dir_prefix(prefix);
#elif defined(OS_POSIX)
FilePath::StringType dir_prefix = WideToUTF8(prefix);
#endif
FilePath temp_path;
if (!CreateNewTempDirectory(dir_prefix, &temp_path)) return false;
*new_temp_path = temp_path.ToWStringHack();
return true;
}
bool CreateTemporaryFileName(std::wstring* temp_file) {
FilePath temp_file_path;
if (!CreateTemporaryFileName(&temp_file_path)) return false;
*temp_file = temp_file_path.ToWStringHack();
return true;
}
bool Delete(const std::wstring& path) {
return Delete(FilePath::FromWStringHack(path));
}
bool DirectoryExists(const std::wstring& path) {
return DirectoryExists(FilePath::FromWStringHack(path));
}
bool EndsWithSeparator(std::wstring* path) {
return EndsWithSeparator(FilePath::FromWStringHack(*path));
}
bool EndsWithSeparator(const std::wstring& path) {
return EndsWithSeparator(FilePath::FromWStringHack(path));
}
bool GetCurrentDirectory(std::wstring* path_str) {
FilePath path;
if (!GetCurrentDirectory(&path)) return false;
*path_str = path.ToWStringHack();
return true;
}
std::wstring GetFileExtensionFromPath(const std::wstring& path) {
FilePath::StringType extension =
GetFileExtensionFromPath(FilePath::FromWStringHack(path));
#if defined(OS_WIN)
return extension;
#elif defined(OS_POSIX)
return UTF8ToWide(extension);
#endif
}
bool GetFileInfo(const std::wstring& file_path, FileInfo* results) {
return GetFileInfo(FilePath::FromWStringHack(file_path), results);
}
std::wstring GetFilenameFromPath(const std::wstring& path) {
if (path.empty() || EndsWithSeparator(path)) return std::wstring();
return FilePath::FromWStringHack(path).BaseName().ToWStringHack();
}
bool GetFileSize(const std::wstring& file_path, int64_t* file_size) {
return GetFileSize(FilePath::FromWStringHack(file_path), file_size);
}
bool GetTempDir(std::wstring* path_str) {
FilePath path;
if (!GetTempDir(&path)) return false;
*path_str = path.ToWStringHack();
return true;
}
FILE* OpenFile(const std::wstring& filename, const char* mode) {
return OpenFile(FilePath::FromWStringHack(filename), mode);
}
bool PathExists(const std::wstring& path) {
return PathExists(FilePath::FromWStringHack(path));
}
bool PathIsWritable(const std::wstring& path) {
return PathIsWritable(FilePath::FromWStringHack(path));
}
int ReadFile(const std::wstring& filename, char* data, int size) {
return ReadFile(FilePath::FromWStringHack(filename), data, size);
}
bool SetCurrentDirectory(const std::wstring& directory) {
return SetCurrentDirectory(FilePath::FromWStringHack(directory));
}
void UpOneDirectory(std::wstring* dir) {
FilePath path = FilePath::FromWStringHack(*dir);
FilePath directory = path.DirName();
// If there is no separator, we will get back kCurrentDirectory.
// In this case don't change |dir|.
if (directory.value() != FilePath::kCurrentDirectory)
*dir = directory.ToWStringHack();
}
int WriteFile(const std::wstring& filename, const char* data, int size) {
return WriteFile(FilePath::FromWStringHack(filename), data, size);
}
} // namespace file_util

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

@ -0,0 +1,229 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file contains utility functions for dealing with the local
// filesystem.
#ifndef BASE_FILE_UTIL_H_
#define BASE_FILE_UTIL_H_
#include "build/build_config.h"
#if defined(OS_WIN)
# include <windows.h>
#elif defined(ANDROID)
# include <sys/stat.h>
#elif defined(OS_POSIX)
# include <sys/types.h>
# include <sys/stat.h>
#endif
#include <stdio.h>
#include <stack>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/file_path.h"
namespace file_util {
//-----------------------------------------------------------------------------
// Functions that operate purely on a path string w/o touching the filesystem:
// Returns true if the given path ends with a path separator character.
bool EndsWithSeparator(const FilePath& path);
// These two versions are both deprecated. TODO(estade): remove them.
bool EndsWithSeparator(std::wstring* path);
bool EndsWithSeparator(const std::wstring& path);
// Modifies a string by trimming all trailing separators from the end.
// Deprecated. FilePath does this automatically, and if it's constructed from a
// path with a trailing separator, StripTrailingSeparators() may be used.
void TrimTrailingSeparator(std::wstring* dir);
// Strips the topmost directory from the end of 'dir'. Assumes 'dir' does not
// refer to a file.
// If 'dir' is a root directory, return without change.
// Deprecated. Use FilePath::DirName instead.
void UpOneDirectory(std::wstring* dir);
// Returns the filename portion of 'path', without any leading \'s or /'s.
// Deprecated. Use FilePath::BaseName instead.
std::wstring GetFilenameFromPath(const std::wstring& path);
// Deprecated compatibility function. Use FilePath::Extension.
FilePath::StringType GetFileExtensionFromPath(const FilePath& path);
// Deprecated temporary compatibility function.
std::wstring GetFileExtensionFromPath(const std::wstring& path);
// Appends new_ending to path, adding a separator between the two if necessary.
void AppendToPath(std::wstring* path, const std::wstring& new_ending);
// Convert provided relative path into an absolute path. Returns false on
// error. On POSIX, this function fails if the path does not exist.
bool AbsolutePath(FilePath* path);
// Deprecated temporary compatibility function.
bool AbsolutePath(std::wstring* path);
// Deprecated compatibility function. Use FilePath::InsertBeforeExtension.
void InsertBeforeExtension(FilePath* path, const FilePath::StringType& suffix);
// Deprecated compatibility function. Use FilePath::ReplaceExtension.
void ReplaceExtension(FilePath* file_name,
const FilePath::StringType& extension);
#if defined(OS_WIN)
// Deprecated temporary compatibility functions.
void InsertBeforeExtension(std::wstring* path, const std::wstring& suffix);
void ReplaceExtension(std::wstring* file_name, const std::wstring& extension);
#endif
//-----------------------------------------------------------------------------
// Functions that involve filesystem access or modification:
// Deletes the given path, whether it's a file or a directory.
// If it's a directory, it's perfectly happy to delete all of the
// directory's contents.
// Returns true if successful, false otherwise.
bool Delete(const FilePath& path);
// Deprecated temporary compatibility function.
bool Delete(const std::wstring& path);
// Copies a single file. Use CopyDirectory to copy directories.
bool CopyFile(const FilePath& from_path, const FilePath& to_path);
// Deprecated temporary compatibility function.
bool CopyFile(const std::wstring& from_path, const std::wstring& to_path);
// Returns true if the given path exists on the local filesystem,
// false otherwise.
bool PathExists(const FilePath& path);
// Deprecated temporary compatibility function.
bool PathExists(const std::wstring& path);
// Returns true if the given path is writable by the user, false otherwise.
bool PathIsWritable(const FilePath& path);
// Deprecated temporary compatibility function.
bool PathIsWritable(const std::wstring& path);
// Returns true if the given path exists and is a directory, false otherwise.
bool DirectoryExists(const FilePath& path);
// Deprecated temporary compatibility function.
bool DirectoryExists(const std::wstring& path);
#if defined(OS_POSIX)
// Read exactly |bytes| bytes from file descriptor |fd|, storing the result
// in |buffer|. This function is protected against EINTR and partial reads.
// Returns true iff |bytes| bytes have been successfuly read from |fd|.
bool ReadFromFD(int fd, char* buffer, size_t bytes);
#endif // defined(OS_POSIX)
// Get the temporary directory provided by the system.
bool GetTempDir(FilePath* path);
// Deprecated temporary compatibility function.
bool GetTempDir(std::wstring* path);
// Get a temporary directory for shared memory files.
// Only useful on POSIX; redirects to GetTempDir() on Windows.
bool GetShmemTempDir(FilePath* path);
// Creates a temporary file. The full path is placed in |path|, and the
// function returns true if was successful in creating the file. The file will
// be empty and all handles closed after this function returns.
// TODO(erikkay): rename this function and track down all of the callers.
// (Clarification of erik's comment: the intent is to rename the BlahFileName()
// calls into BlahFile(), since they create temp files (not temp filenames).)
bool CreateTemporaryFileName(FilePath* path);
// Deprecated temporary compatibility function.
bool CreateTemporaryFileName(std::wstring* temp_file);
// Create and open a temporary file. File is opened for read/write.
// The full path is placed in |path|, and the function returns true if
// was successful in creating and opening the file.
FILE* CreateAndOpenTemporaryFile(FilePath* path);
// Like above but for shmem files. Only useful for POSIX.
FILE* CreateAndOpenTemporaryShmemFile(FilePath* path);
// Similar to CreateAndOpenTemporaryFile, but the file is created in |dir|.
FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path);
// Same as CreateTemporaryFileName but the file is created in |dir|.
bool CreateTemporaryFileNameInDir(const std::wstring& dir,
std::wstring* temp_file);
// Create a new directory under TempPath. If prefix is provided, the new
// directory name is in the format of prefixyyyy.
// NOTE: prefix is ignored in the POSIX implementation.
// TODO(erikkay): is this OK?
// If success, return true and output the full path of the directory created.
bool CreateNewTempDirectory(const FilePath::StringType& prefix,
FilePath* new_temp_path);
// Deprecated temporary compatibility function.
bool CreateNewTempDirectory(const std::wstring& prefix,
std::wstring* new_temp_path);
// Creates a directory, as well as creating any parent directories, if they
// don't exist. Returns 'true' on successful creation, or if the directory
// already exists.
bool CreateDirectory(const FilePath& full_path);
// Deprecated temporary compatibility function.
bool CreateDirectory(const std::wstring& full_path);
// Returns the file size. Returns true on success.
bool GetFileSize(const FilePath& file_path, int64_t* file_size);
// Deprecated temporary compatibility function.
bool GetFileSize(const std::wstring& file_path, int64_t* file_size);
// Used to hold information about a given file path. See GetFileInfo below.
struct FileInfo {
// The size of the file in bytes. Undefined when is_directory is true.
int64_t size;
// True if the file corresponds to a directory.
bool is_directory;
// Add additional fields here as needed.
};
// Returns information about the given file path.
bool GetFileInfo(const FilePath& file_path, FileInfo* info);
// Deprecated temporary compatibility function.
bool GetFileInfo(const std::wstring& file_path, FileInfo* info);
// Wrapper for fopen-like calls. Returns non-NULL FILE* on success.
FILE* OpenFile(const FilePath& filename, const char* mode);
// Deprecated temporary compatibility functions.
FILE* OpenFile(const std::string& filename, const char* mode);
FILE* OpenFile(const std::wstring& filename, const char* mode);
// Closes file opened by OpenFile. Returns true on success.
bool CloseFile(FILE* file);
// Reads the given number of bytes from the file into the buffer. Returns
// the number of read bytes, or -1 on error.
int ReadFile(const FilePath& filename, char* data, int size);
// Deprecated temporary compatibility function.
int ReadFile(const std::wstring& filename, char* data, int size);
// Writes the given buffer into the file, overwriting any data that was
// previously there. Returns the number of bytes written, or -1 on error.
int WriteFile(const FilePath& filename, const char* data, int size);
// Deprecated temporary compatibility function.
int WriteFile(const std::wstring& filename, const char* data, int size);
// Gets the current working directory for the process.
bool GetCurrentDirectory(FilePath* path);
// Deprecated temporary compatibility function.
bool GetCurrentDirectory(std::wstring* path);
// Sets the current working directory for the process.
bool SetCurrentDirectory(const FilePath& path);
// Deprecated temporary compatibility function.
bool SetCurrentDirectory(const std::wstring& current_directory);
} // namespace file_util
#endif // BASE_FILE_UTIL_H_

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

@ -0,0 +1,31 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/file_util.h"
#import <Cocoa/Cocoa.h>
#include <copyfile.h>
#include "base/file_path.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "base/scoped_nsautorelease_pool.h"
namespace file_util {
bool GetTempDir(FilePath* path) {
base::ScopedNSAutoreleasePool autorelease_pool;
NSString* tmp = NSTemporaryDirectory();
if (tmp == nil) return false;
*path = FilePath([tmp fileSystemRepresentation]);
return true;
}
bool GetShmemTempDir(FilePath* path) { return GetTempDir(path); }
bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
return (copyfile(from_path.value().c_str(), to_path.value().c_str(), NULL, COPYFILE_ALL) == 0);
}
} // namespace

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

@ -0,0 +1,316 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/file_util.h"
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <libgen.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#define _DARWIN_USE_64_BIT_INODE // Use 64-bit inode data structures
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <fstream>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/eintr_wrapper.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "base/time.h"
namespace file_util {
#if defined(GOOGLE_CHROME_BUILD)
static const char* kTempFileName = "com.google.chrome.XXXXXX";
#else
static const char* kTempFileName = "org.chromium.XXXXXX";
#endif
bool AbsolutePath(FilePath* path) {
char full_path[PATH_MAX];
if (realpath(path->value().c_str(), full_path) == NULL) return false;
*path = FilePath(full_path);
return true;
}
// TODO(erikkay): The Windows version of this accepts paths like "foo/bar/*"
// which works both with and without the recursive flag. I'm not sure we need
// that functionality. If not, remove from file_util_win.cc, otherwise add it
// here.
bool Delete(const FilePath& path) {
const char* path_str = path.value().c_str();
struct stat file_info;
int test = stat(path_str, &file_info);
if (test != 0) {
// The Windows version defines this condition as success.
bool ret = (errno == ENOENT || errno == ENOTDIR);
return ret;
}
if (!S_ISDIR(file_info.st_mode)) return (unlink(path_str) == 0);
return (rmdir(path_str) == 0);
}
bool PathExists(const FilePath& path) {
struct stat file_info;
return (stat(path.value().c_str(), &file_info) == 0);
}
bool PathIsWritable(const FilePath& path) {
FilePath test_path(path);
struct stat file_info;
if (stat(test_path.value().c_str(), &file_info) != 0) {
// If the path doesn't exist, test the parent dir.
test_path = test_path.DirName();
// If the parent dir doesn't exist, then return false (the path is not
// directly writable).
if (stat(test_path.value().c_str(), &file_info) != 0) return false;
}
if (S_IWOTH & file_info.st_mode) return true;
if (getegid() == file_info.st_gid && (S_IWGRP & file_info.st_mode))
return true;
if (geteuid() == file_info.st_uid && (S_IWUSR & file_info.st_mode))
return true;
return false;
}
bool DirectoryExists(const FilePath& path) {
struct stat file_info;
if (stat(path.value().c_str(), &file_info) == 0)
return S_ISDIR(file_info.st_mode);
return false;
}
bool ReadFromFD(int fd, char* buffer, size_t bytes) {
size_t total_read = 0;
while (total_read < bytes) {
ssize_t bytes_read =
HANDLE_EINTR(read(fd, buffer + total_read, bytes - total_read));
if (bytes_read <= 0) break;
total_read += bytes_read;
}
return total_read == bytes;
}
// Creates and opens a temporary file in |directory|, returning the
// file descriptor. |path| is set to the temporary file path.
// Note TODO(erikkay) comment in header for BlahFileName() calls; the
// intent is to rename these files BlahFile() (since they create
// files, not filenames). This function does NOT unlink() the file.
int CreateAndOpenFdForTemporaryFile(FilePath directory, FilePath* path) {
*path = directory.Append(kTempFileName);
const std::string& tmpdir_string = path->value();
// this should be OK since mkstemp just replaces characters in place
char* buffer = const_cast<char*>(tmpdir_string.c_str());
return mkstemp(buffer);
}
bool CreateTemporaryFileName(FilePath* path) {
FilePath directory;
if (!GetTempDir(&directory)) return false;
int fd = CreateAndOpenFdForTemporaryFile(directory, path);
if (fd < 0) return false;
close(fd);
return true;
}
FILE* CreateAndOpenTemporaryShmemFile(FilePath* path) {
FilePath directory;
if (!GetShmemTempDir(&directory)) return NULL;
return CreateAndOpenTemporaryFileInDir(directory, path);
}
FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path) {
int fd = CreateAndOpenFdForTemporaryFile(dir, path);
if (fd < 0) return NULL;
return fdopen(fd, "a+");
}
bool CreateTemporaryFileNameInDir(const std::wstring& dir,
std::wstring* temp_file) {
// Not implemented yet.
NOTREACHED();
return false;
}
bool CreateNewTempDirectory(const FilePath::StringType& prefix,
FilePath* new_temp_path) {
FilePath tmpdir;
if (!GetTempDir(&tmpdir)) return false;
tmpdir = tmpdir.Append(kTempFileName);
std::string tmpdir_string = tmpdir.value();
#ifdef ANDROID
char* dtemp = NULL;
#else
// this should be OK since mkdtemp just replaces characters in place
char* buffer = const_cast<char*>(tmpdir_string.c_str());
char* dtemp = mkdtemp(buffer);
#endif
if (!dtemp) return false;
*new_temp_path = FilePath(dtemp);
return true;
}
bool CreateDirectory(const FilePath& full_path) {
std::vector<FilePath> subpaths;
// Collect a list of all parent directories.
FilePath last_path = full_path;
subpaths.push_back(full_path);
for (FilePath path = full_path.DirName(); path.value() != last_path.value();
path = path.DirName()) {
subpaths.push_back(path);
last_path = path;
}
// Iterate through the parents and create the missing ones.
for (std::vector<FilePath>::reverse_iterator i = subpaths.rbegin();
i != subpaths.rend(); ++i) {
if (!DirectoryExists(*i)) {
if (mkdir(i->value().c_str(), 0777) != 0) return false;
}
}
return true;
}
bool GetFileInfo(const FilePath& file_path, FileInfo* results) {
struct stat file_info;
if (stat(file_path.value().c_str(), &file_info) != 0) return false;
results->is_directory = S_ISDIR(file_info.st_mode);
results->size = file_info.st_size;
return true;
}
FILE* OpenFile(const std::string& filename, const char* mode) {
return OpenFile(FilePath(filename), mode);
}
FILE* OpenFile(const FilePath& filename, const char* mode) {
return fopen(filename.value().c_str(), mode);
}
int ReadFile(const FilePath& filename, char* data, int size) {
int fd = open(filename.value().c_str(), O_RDONLY);
if (fd < 0) return -1;
int ret_value = HANDLE_EINTR(read(fd, data, size));
IGNORE_EINTR(close(fd));
return ret_value;
}
int WriteFile(const FilePath& filename, const char* data, int size) {
int fd = creat(filename.value().c_str(), 0666);
if (fd < 0) return -1;
// Allow for partial writes
ssize_t bytes_written_total = 0;
do {
ssize_t bytes_written_partial = HANDLE_EINTR(
write(fd, data + bytes_written_total, size - bytes_written_total));
if (bytes_written_partial < 0) {
IGNORE_EINTR(close(fd));
return -1;
}
bytes_written_total += bytes_written_partial;
} while (bytes_written_total < size);
IGNORE_EINTR(close(fd));
return bytes_written_total;
}
// Gets the current working directory for the process.
bool GetCurrentDirectory(FilePath* dir) {
char system_buffer[PATH_MAX] = "";
if (!getcwd(system_buffer, sizeof(system_buffer))) {
NOTREACHED();
return false;
}
*dir = FilePath(system_buffer);
return true;
}
// Sets the current working directory for the process.
bool SetCurrentDirectory(const FilePath& path) {
int ret = chdir(path.value().c_str());
return !ret;
}
#if !defined(OS_MACOSX)
bool GetTempDir(FilePath* path) {
const char* tmp = getenv("TMPDIR");
if (tmp)
*path = FilePath(tmp);
else
*path = FilePath("/tmp");
return true;
}
bool GetShmemTempDir(FilePath* path) {
# if defined(OS_LINUX) && !defined(ANDROID)
*path = FilePath("/dev/shm");
return true;
# else
return GetTempDir(path);
# endif
}
bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
int infile = open(from_path.value().c_str(), O_RDONLY);
if (infile < 0) return false;
int outfile = creat(to_path.value().c_str(), 0666);
if (outfile < 0) {
close(infile);
return false;
}
const size_t kBufferSize = 32768;
std::vector<char> buffer(kBufferSize);
bool result = true;
while (result) {
ssize_t bytes_read = HANDLE_EINTR(read(infile, &buffer[0], buffer.size()));
if (bytes_read < 0) {
result = false;
break;
}
if (bytes_read == 0) break;
// Allow for partial writes
ssize_t bytes_written_per_read = 0;
do {
ssize_t bytes_written_partial =
HANDLE_EINTR(write(outfile, &buffer[bytes_written_per_read],
bytes_read - bytes_written_per_read));
if (bytes_written_partial < 0) {
result = false;
break;
}
bytes_written_per_read += bytes_written_partial;
} while (bytes_written_per_read < bytes_read);
}
if (IGNORE_EINTR(close(infile)) < 0) result = false;
if (IGNORE_EINTR(close(outfile)) < 0) result = false;
return result;
}
#endif // !defined(OS_MACOSX)
} // namespace file_util

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

@ -0,0 +1,330 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/file_util.h"
#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
#include <time.h>
#include <string>
#include "base/file_path.h"
#include "base/logging.h"
#include "base/scoped_handle.h"
#include "base/string_util.h"
#include "base/time.h"
#include "base/win_util.h"
namespace file_util {
bool AbsolutePath(FilePath* path) {
wchar_t file_path_buf[MAX_PATH];
if (!_wfullpath(file_path_buf, path->value().c_str(), MAX_PATH)) return false;
*path = FilePath(file_path_buf);
return true;
}
bool Delete(const FilePath& path) {
if (path.value().length() >= MAX_PATH) return false;
// Use DeleteFile; it should be faster. DeleteFile
// fails if passed a directory though, which is why we fall through on
// failure to the SHFileOperation.
if (DeleteFile(path.value().c_str()) != 0) return true;
// SHFILEOPSTRUCT wants the path to be terminated with two NULLs,
// so we have to use wcscpy because wcscpy_s writes non-NULLs
// into the rest of the buffer.
wchar_t double_terminated_path[MAX_PATH + 1] = {0};
#pragma warning(suppress : 4996) // don't complain about wcscpy deprecation
wcscpy(double_terminated_path, path.value().c_str());
SHFILEOPSTRUCT file_operation = {0};
file_operation.wFunc = FO_DELETE;
file_operation.pFrom = double_terminated_path;
file_operation.fFlags = FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION;
file_operation.fFlags |= FOF_NORECURSION | FOF_FILESONLY;
int err = SHFileOperation(&file_operation);
// Some versions of Windows return ERROR_FILE_NOT_FOUND when
// deleting an empty directory.
return (err == 0 || err == ERROR_FILE_NOT_FOUND);
}
bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
// NOTE: I suspect we could support longer paths, but that would involve
// analyzing all our usage of files.
if (from_path.value().length() >= MAX_PATH ||
to_path.value().length() >= MAX_PATH) {
return false;
}
return (::CopyFile(from_path.value().c_str(), to_path.value().c_str(),
false) != 0);
}
bool ShellCopy(const FilePath& from_path, const FilePath& to_path,
bool recursive) {
// NOTE: I suspect we could support longer paths, but that would involve
// analyzing all our usage of files.
if (from_path.value().length() >= MAX_PATH ||
to_path.value().length() >= MAX_PATH) {
return false;
}
// SHFILEOPSTRUCT wants the path to be terminated with two NULLs,
// so we have to use wcscpy because wcscpy_s writes non-NULLs
// into the rest of the buffer.
wchar_t double_terminated_path_from[MAX_PATH + 1] = {0};
wchar_t double_terminated_path_to[MAX_PATH + 1] = {0};
#pragma warning(suppress : 4996) // don't complain about wcscpy deprecation
wcscpy(double_terminated_path_from, from_path.value().c_str());
#pragma warning(suppress : 4996) // don't complain about wcscpy deprecation
wcscpy(double_terminated_path_to, to_path.value().c_str());
SHFILEOPSTRUCT file_operation = {0};
file_operation.wFunc = FO_COPY;
file_operation.pFrom = double_terminated_path_from;
file_operation.pTo = double_terminated_path_to;
file_operation.fFlags =
FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR;
if (!recursive) file_operation.fFlags |= FOF_NORECURSION | FOF_FILESONLY;
return (SHFileOperation(&file_operation) == 0);
}
bool PathExists(const FilePath& path) {
return (GetFileAttributes(path.value().c_str()) != INVALID_FILE_ATTRIBUTES);
}
bool PathIsWritable(const FilePath& path) {
HANDLE dir =
CreateFile(path.value().c_str(), FILE_ADD_FILE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (dir == INVALID_HANDLE_VALUE) return false;
CloseHandle(dir);
return true;
}
bool DirectoryExists(const FilePath& path) {
DWORD fileattr = GetFileAttributes(path.value().c_str());
if (fileattr != INVALID_FILE_ATTRIBUTES)
return (fileattr & FILE_ATTRIBUTE_DIRECTORY) != 0;
return false;
}
bool GetTempDir(FilePath* path) {
wchar_t temp_path[MAX_PATH + 1];
DWORD path_len = ::GetTempPath(MAX_PATH, temp_path);
if (path_len >= MAX_PATH || path_len <= 0) return false;
// TODO(evanm): the old behavior of this function was to always strip the
// trailing slash. We duplicate this here, but it shouldn't be necessary
// when everyone is using the appropriate FilePath APIs.
std::wstring path_str(temp_path);
TrimTrailingSeparator(&path_str);
*path = FilePath(path_str);
return true;
}
bool GetShmemTempDir(FilePath* path) { return GetTempDir(path); }
bool CreateTemporaryFileName(FilePath* path) {
std::wstring temp_path, temp_file;
if (!GetTempDir(&temp_path)) return false;
if (CreateTemporaryFileNameInDir(temp_path, &temp_file)) {
*path = FilePath(temp_file);
return true;
}
return false;
}
FILE* CreateAndOpenTemporaryShmemFile(FilePath* path) {
return CreateAndOpenTemporaryFile(path);
}
// On POSIX we have semantics to create and open a temporary file
// atomically.
// TODO(jrg): is there equivalent call to use on Windows instead of
// going 2-step?
FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path) {
std::wstring wstring_path;
if (!CreateTemporaryFileNameInDir(dir.value(), &wstring_path)) {
return NULL;
}
*path = FilePath(wstring_path);
// Open file in binary mode, to avoid problems with fwrite. On Windows
// it replaces \n's with \r\n's, which may surprise you.
// Reference: http://msdn.microsoft.com/en-us/library/h9t88zwz(VS.71).aspx
return OpenFile(*path, "wb+");
}
bool CreateTemporaryFileNameInDir(const std::wstring& dir,
std::wstring* temp_file) {
wchar_t temp_name[MAX_PATH + 1];
if (!GetTempFileName(dir.c_str(), L"", 0, temp_name)) return false; // fail!
DWORD path_len = GetLongPathName(temp_name, temp_name, MAX_PATH);
if (path_len > MAX_PATH + 1 || path_len == 0) return false; // fail!
temp_file->assign(temp_name, path_len);
return true;
}
bool CreateNewTempDirectory(const FilePath::StringType& prefix,
FilePath* new_temp_path) {
FilePath system_temp_dir;
if (!GetTempDir(&system_temp_dir)) return false;
FilePath path_to_create;
srand(static_cast<uint32_t>(time(NULL)));
int count = 0;
while (count < 50) {
// Try create a new temporary directory with random generated name. If
// the one exists, keep trying another path name until we reach some limit.
path_to_create = system_temp_dir;
std::wstring new_dir_name;
new_dir_name.assign(prefix);
new_dir_name.append(IntToWString(rand() % kint16max));
path_to_create = path_to_create.Append(new_dir_name);
if (::CreateDirectory(path_to_create.value().c_str(), NULL)) break;
count++;
}
if (count == 50) {
return false;
}
*new_temp_path = path_to_create;
return true;
}
bool CreateDirectory(const FilePath& full_path) {
if (DirectoryExists(full_path)) return true;
int err = SHCreateDirectoryEx(NULL, full_path.value().c_str(), NULL);
return err == ERROR_SUCCESS;
}
bool GetFileInfo(const FilePath& file_path, FileInfo* results) {
WIN32_FILE_ATTRIBUTE_DATA attr;
if (!GetFileAttributesEx(file_path.ToWStringHack().c_str(),
GetFileExInfoStandard, &attr)) {
return false;
}
ULARGE_INTEGER size;
size.HighPart = attr.nFileSizeHigh;
size.LowPart = attr.nFileSizeLow;
results->size = size.QuadPart;
results->is_directory =
(attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
return true;
}
FILE* OpenFile(const FilePath& filename, const char* mode) {
std::wstring w_mode = ASCIIToWide(std::string(mode));
FILE* file;
if (_wfopen_s(&file, filename.value().c_str(), w_mode.c_str()) != 0) {
return NULL;
}
return file;
}
FILE* OpenFile(const std::string& filename, const char* mode) {
FILE* file;
if (fopen_s(&file, filename.c_str(), mode) != 0) {
return NULL;
}
return file;
}
int ReadFile(const FilePath& filename, char* data, int size) {
ScopedHandle file(CreateFile(filename.value().c_str(), GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL));
if (file == INVALID_HANDLE_VALUE) return -1;
int ret_value;
DWORD read;
if (::ReadFile(file, data, size, &read, NULL) && read == size) {
ret_value = static_cast<int>(read);
} else {
ret_value = -1;
}
return ret_value;
}
int WriteFile(const FilePath& filename, const char* data, int size) {
ScopedHandle file(CreateFile(filename.value().c_str(), GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, 0, NULL));
if (file == INVALID_HANDLE_VALUE) {
CHROMIUM_LOG(WARNING) << "CreateFile failed for path " << filename.value()
<< " error code=" << GetLastError()
<< " error text=" << win_util::FormatLastWin32Error();
return -1;
}
DWORD written;
BOOL result = ::WriteFile(file, data, size, &written, NULL);
if (result && written == size) return static_cast<int>(written);
if (!result) {
// WriteFile failed.
CHROMIUM_LOG(WARNING) << "writing file " << filename.value()
<< " failed, error code=" << GetLastError()
<< " description="
<< win_util::FormatLastWin32Error();
} else {
// Didn't write all the bytes.
CHROMIUM_LOG(WARNING) << "wrote" << written << " bytes to "
<< filename.value() << " expected " << size;
}
return -1;
}
// Gets the current working directory for the process.
bool GetCurrentDirectory(FilePath* dir) {
wchar_t system_buffer[MAX_PATH];
system_buffer[0] = 0;
DWORD len = ::GetCurrentDirectory(MAX_PATH, system_buffer);
if (len == 0 || len > MAX_PATH) return false;
// TODO(evanm): the old behavior of this function was to always strip the
// trailing slash. We duplicate this here, but it shouldn't be necessary
// when everyone is using the appropriate FilePath APIs.
std::wstring dir_str(system_buffer);
file_util::TrimTrailingSeparator(&dir_str);
*dir = FilePath(dir_str);
return true;
}
// Sets the current working directory for the process.
bool SetCurrentDirectory(const FilePath& directory) {
BOOL ret = ::SetCurrentDirectory(directory.value().c_str());
return ret != 0;
}
// Deprecated functions ----------------------------------------------------
void InsertBeforeExtension(std::wstring* path_str, const std::wstring& suffix) {
FilePath path(*path_str);
InsertBeforeExtension(&path, suffix);
path_str->assign(path.value());
}
void ReplaceExtension(std::wstring* file_name, const std::wstring& extension) {
FilePath path(*file_name);
ReplaceExtension(&path, extension);
file_name->assign(path.value());
}
} // namespace file_util

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

@ -18,8 +18,6 @@
#include "base/basictypes.h"
#include "base/process.h"
#include "mozilla/Attributes.h"
#include "mozilla/UniquePtrExtensions.h"
namespace base {
@ -59,21 +57,12 @@ class SharedMemory {
// invalid value; NULL for a HANDLE and -1 for a file descriptor)
static bool IsHandleValid(const SharedMemoryHandle& handle);
// IsHandleValid applied to this object's handle.
bool IsValid() const;
// Return invalid handle (see comment above for exact definition).
static SharedMemoryHandle NULLHandle();
// Creates a shared memory segment.
// Returns true on success, false on failure.
bool Create(size_t size) { return CreateInternal(size, false); }
// Creates a shared memory segment that supports the Freeze()
// method; see below. (Warning: creating freezeable shared memory
// within a sandboxed process isn't possible on some platforms.)
// Returns true on success, false on failure.
bool CreateFreezeable(size_t size) { return CreateInternal(size, true); }
bool Create(size_t size);
// Maps the shared memory into the caller's address space.
// Returns true on success, false otherwise. The memory address
@ -100,29 +89,10 @@ class SharedMemory {
// Mapped via Map(). Returns NULL if it is not mapped.
void* memory() const { return memory_; }
// Extracts the underlying file handle; similar to
// GiveToProcess(GetCurrentProcId(), ...) but returns a RAII type.
// Like GiveToProcess, this unmaps the memory as a side-effect.
mozilla::UniqueFileHandle TakeHandle();
#ifdef OS_WIN
// Used only in gfx/ipc/SharedDIBWin.cpp; should be removable once
// NPAPI goes away.
HANDLE GetHandle() {
freezeable_ = false;
return mapped_file_;
}
#endif
// Make the shared memory object read-only, such that it cannot be
// written even if it's sent to an untrusted process. If it was
// mapped in this process, it will be unmapped. The object must
// have been created with CreateFreezeable(), and must not have
// already been shared to another process.
//
// (See bug 1479960 comment #0 for OS-specific implementation
// details.)
MOZ_MUST_USE bool Freeze();
// Get access to the underlying OS handle for this segment.
// Use of this handle for anything other than an opaque
// identifier is not portable.
SharedMemoryHandle handle() const;
// Closes the open shared memory segment.
// It is safe to call Close repeatedly.
@ -170,8 +140,6 @@ class SharedMemory {
bool ShareToProcessCommon(ProcessId target_pid,
SharedMemoryHandle* new_handle, bool close_self);
bool CreateInternal(size_t size, bool freezeable);
#if defined(OS_WIN)
// If true indicates this came from an external source so needs extra checks
// before being mapped.
@ -179,12 +147,9 @@ class SharedMemory {
HANDLE mapped_file_;
#elif defined(OS_POSIX)
int mapped_file_;
int frozen_file_;
size_t mapped_size_;
#endif
void* memory_;
bool read_only_;
bool freezeable_;
size_t max_size_;
DISALLOW_EVIL_CONSTRUCTORS(SharedMemory);

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

@ -20,19 +20,12 @@
#include "base/logging.h"
#include "base/string_util.h"
#include "mozilla/Atomics.h"
#include "mozilla/UniquePtrExtensions.h"
#include "prenv.h"
namespace base {
SharedMemory::SharedMemory()
: mapped_file_(-1),
frozen_file_(-1),
mapped_size_(0),
memory_(nullptr),
read_only_(false),
freezeable_(false),
max_size_(0) {}
: mapped_file_(-1), memory_(NULL), read_only_(false), max_size_(0) {}
SharedMemory::SharedMemory(SharedMemory&& other) {
if (this == &other) {
@ -40,16 +33,11 @@ SharedMemory::SharedMemory(SharedMemory&& other) {
}
mapped_file_ = other.mapped_file_;
mapped_size_ = other.mapped_size_;
frozen_file_ = other.frozen_file_;
memory_ = other.memory_;
read_only_ = other.read_only_;
freezeable_ = other.freezeable_;
max_size_ = other.max_size_;
other.mapped_file_ = -1;
other.mapped_size_ = 0;
other.frozen_file_ = -1;
other.memory_ = nullptr;
}
@ -57,9 +45,7 @@ SharedMemory::~SharedMemory() { Close(); }
bool SharedMemory::SetHandle(SharedMemoryHandle handle, bool read_only) {
DCHECK(mapped_file_ == -1);
DCHECK(frozen_file_ == -1);
freezeable_ = false;
mapped_file_ = handle.fd;
read_only_ = read_only;
return true;
@ -70,97 +56,12 @@ bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) {
return handle.fd >= 0;
}
bool SharedMemory::IsValid() const { return mapped_file_ >= 0; }
// static
SharedMemoryHandle SharedMemory::NULLHandle() { return SharedMemoryHandle(); }
// Workaround for CVE-2018-4435 (https://crbug.com/project-zero/1671);
// can be removed when minimum OS version is at least 10.12.
#ifdef OS_MACOSX
static const char* GetTmpDir() {
static const char* const kTmpDir = [] {
const char* tmpdir = PR_GetEnv("TMPDIR");
if (tmpdir) {
return tmpdir;
}
return "/tmp";
}();
return kTmpDir;
}
static int FakeShmOpen(const char* name, int oflag, int mode) {
CHECK(name[0] == '/');
std::string path(GetTmpDir());
path += name;
return open(path.c_str(), oflag | O_CLOEXEC | O_NOCTTY, mode);
}
static int FakeShmUnlink(const char* name) {
CHECK(name[0] == '/');
std::string path(GetTmpDir());
path += name;
return unlink(path.c_str());
}
static bool IsShmOpenSecure() {
static const bool kIsSecure = [] {
mozilla::UniqueFileHandle rwfd, rofd;
std::string name;
CHECK(SharedMemory::AppendPosixShmPrefix(&name, getpid()));
name += "sectest";
// The prefix includes the pid and this will be called at most
// once per process, so no need for a counter.
rwfd.reset(
HANDLE_EINTR(shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600)));
// An adversary could steal the name. Handle this semi-gracefully.
DCHECK(rwfd);
if (!rwfd) {
return false;
}
rofd.reset(shm_open(name.c_str(), O_RDONLY, 0400));
CHECK(rofd);
CHECK(shm_unlink(name.c_str()) == 0);
CHECK(ftruncate(rwfd.get(), 1) == 0);
rwfd = nullptr;
void* map = mmap(nullptr, 1, PROT_READ, MAP_SHARED, rofd.get(), 0);
CHECK(map != MAP_FAILED);
bool ok = mprotect(map, 1, PROT_READ | PROT_WRITE) != 0;
munmap(map, 1);
return ok;
}();
return kIsSecure;
}
static int SafeShmOpen(bool freezeable, const char* name, int oflag, int mode) {
if (!freezeable || IsShmOpenSecure()) {
return shm_open(name, oflag, mode);
} else {
return FakeShmOpen(name, oflag, mode);
}
}
static int SafeShmUnlink(bool freezeable, const char* name) {
if (!freezeable || IsShmOpenSecure()) {
return shm_unlink(name);
} else {
return FakeShmUnlink(name);
}
}
#elif !defined(ANDROID)
static int SafeShmOpen(bool freezeable, const char* name, int oflag, int mode) {
return shm_open(name, oflag, mode);
}
static int SafeShmUnlink(bool freezeable, const char* name) {
return shm_unlink(name);
}
#endif
// static
bool SharedMemory::AppendPosixShmPrefix(std::string* str, pid_t pid) {
#if defined(ANDROID)
#if defined(ANDROID) || defined(SHM_ANON)
return false;
#else
*str += '/';
@ -186,32 +87,35 @@ bool SharedMemory::AppendPosixShmPrefix(std::string* str, pid_t pid) {
// enough for this.
StringAppendF(str, "org.mozilla.ipc.%d.", static_cast<int>(pid));
return true;
#endif // !ANDROID
#endif // !ANDROID && !SHM_ANON
}
bool SharedMemory::CreateInternal(size_t size, bool freezeable) {
bool SharedMemory::Create(size_t size) {
read_only_ = false;
DCHECK(size > 0);
DCHECK(mapped_file_ == -1);
DCHECK(frozen_file_ == -1);
mozilla::UniqueFileHandle fd;
mozilla::UniqueFileHandle frozen_fd;
int fd;
bool needs_truncate = true;
#ifdef ANDROID
// Android has its own shared memory facility:
fd.reset(open("/" ASHMEM_NAME_DEF, O_RDWR, 0600));
if (!fd) {
fd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600);
if (fd < 0) {
CHROMIUM_LOG(WARNING) << "failed to open shm: " << strerror(errno);
return false;
}
if (ioctl(fd.get(), ASHMEM_SET_SIZE, size) != 0) {
if (ioctl(fd, ASHMEM_SET_SIZE, size) != 0) {
CHROMIUM_LOG(WARNING) << "failed to set shm size: " << strerror(errno);
close(fd);
return false;
}
needs_truncate = false;
#elif defined(SHM_ANON)
// FreeBSD (or any other Unix that might decide to implement this
// nice, simple API):
fd = shm_open(SHM_ANON, O_RDWR, 0600);
#else
// Generic Unix: shm_open + shm_unlink
do {
@ -222,104 +126,69 @@ bool SharedMemory::CreateInternal(size_t size, bool freezeable) {
CHECK(AppendPosixShmPrefix(&name, getpid()));
StringAppendF(&name, "%zu", sNameCounter++);
// O_EXCL means the names being predictable shouldn't be a problem.
fd.reset(HANDLE_EINTR(SafeShmOpen(freezeable, name.c_str(),
O_RDWR | O_CREAT | O_EXCL, 0600)));
if (fd) {
if (freezeable) {
frozen_fd.reset(HANDLE_EINTR(
SafeShmOpen(freezeable, name.c_str(), O_RDONLY, 0400)));
if (!frozen_fd) {
int open_err = errno;
SafeShmUnlink(freezeable, name.c_str());
DLOG(FATAL) << "failed to re-open freezeable shm: "
<< strerror(open_err);
return false;
}
}
if (SafeShmUnlink(freezeable, name.c_str()) != 0) {
fd = HANDLE_EINTR(shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600));
if (fd >= 0) {
if (shm_unlink(name.c_str()) != 0) {
// This shouldn't happen, but if it does: assume the file is
// in fact leaked, and bail out now while it's still 0-length.
DLOG(FATAL) << "failed to unlink shm: " << strerror(errno);
return false;
}
}
} while (!fd && errno == EEXIST);
} while (fd < 0 && errno == EEXIST);
#endif
if (!fd) {
if (fd < 0) {
CHROMIUM_LOG(WARNING) << "failed to open shm: " << strerror(errno);
return false;
}
if (needs_truncate) {
if (HANDLE_EINTR(ftruncate(fd.get(), static_cast<off_t>(size))) != 0) {
if (HANDLE_EINTR(ftruncate(fd, static_cast<off_t>(size))) != 0) {
CHROMIUM_LOG(WARNING) << "failed to set shm size: " << strerror(errno);
close(fd);
return false;
}
}
mapped_file_ = fd.release();
frozen_file_ = frozen_fd.release();
mapped_file_ = fd;
max_size_ = size;
freezeable_ = freezeable;
return true;
}
bool SharedMemory::Freeze() {
DCHECK(!read_only_);
CHECK(freezeable_);
Unmap();
#ifdef ANDROID
if (ioctl(mapped_file_, ASHMEM_SET_PROT_MASK, PROT_READ) != 0) {
CHROMIUM_LOG(WARNING) << "failed to freeze shm: " << strerror(errno);
return false;
}
#else
DCHECK(frozen_file_ >= 0);
DCHECK(mapped_file_ >= 0);
close(mapped_file_);
mapped_file_ = frozen_file_;
frozen_file_ = -1;
#endif
read_only_ = true;
freezeable_ = false;
return true;
}
bool SharedMemory::Map(size_t bytes, void* fixed_address) {
if (mapped_file_ == -1) return false;
DCHECK(!memory_);
// Don't use MAP_FIXED when a fixed_address was specified, since that can
// replace pages that are alread mapped at that address.
void* mem =
memory_ =
mmap(fixed_address, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE),
MAP_SHARED, mapped_file_, 0);
if (mem == MAP_FAILED) {
CHROMIUM_LOG(WARNING) << "Call to mmap failed: " << strerror(errno);
return false;
bool mmap_succeeded = memory_ != MAP_FAILED;
DCHECK(mmap_succeeded) << "Call to mmap failed, errno=" << errno;
if (mmap_succeeded) {
if (fixed_address && memory_ != fixed_address) {
bool munmap_succeeded = munmap(memory_, bytes) == 0;
DCHECK(munmap_succeeded) << "Call to munmap failed, errno=" << errno;
memory_ = NULL;
return false;
}
max_size_ = bytes;
}
if (fixed_address && mem != fixed_address) {
bool munmap_succeeded = munmap(mem, bytes) == 0;
DCHECK(munmap_succeeded) << "Call to munmap failed, errno=" << errno;
return false;
}
memory_ = mem;
mapped_size_ = bytes;
return true;
return mmap_succeeded;
}
bool SharedMemory::Unmap() {
if (memory_ == NULL) return false;
munmap(memory_, mapped_size_);
munmap(memory_, max_size_);
memory_ = NULL;
mapped_size_ = 0;
max_size_ = 0;
return true;
}
@ -333,7 +202,6 @@ void* SharedMemory::FindFreeAddressSpace(size_t size) {
bool SharedMemory::ShareToProcessCommon(ProcessId processId,
SharedMemoryHandle* new_handle,
bool close_self) {
freezeable_ = false;
const int new_fd = dup(mapped_file_);
DCHECK(new_fd >= -1);
new_handle->fd = new_fd;
@ -353,20 +221,10 @@ void SharedMemory::Close(bool unmap_view) {
close(mapped_file_);
mapped_file_ = -1;
}
if (frozen_file_ >= 0) {
CHROMIUM_LOG(WARNING) << "freezeable shared memory was never frozen";
close(frozen_file_);
frozen_file_ = -1;
}
}
mozilla::UniqueFileHandle SharedMemory::TakeHandle() {
mozilla::UniqueFileHandle fh(mapped_file_);
mapped_file_ = -1;
// Now that the main fd is removed, reset everything else: close the
// frozen fd if present and unmap the memory if mapped.
Close();
return fh;
SharedMemoryHandle SharedMemory::handle() const {
return FileDescriptor(mapped_file_, false);
}
} // namespace base

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

@ -59,7 +59,6 @@ SharedMemory::SharedMemory()
mapped_file_(NULL),
memory_(NULL),
read_only_(false),
freezeable_(false),
max_size_(0) {}
SharedMemory::SharedMemory(SharedMemory&& other) {
@ -71,7 +70,6 @@ SharedMemory::SharedMemory(SharedMemory&& other) {
memory_ = other.memory_;
read_only_ = other.read_only_;
max_size_ = other.max_size_;
freezeable_ = other.freezeable_;
external_section_ = other.external_section_;
other.mapped_file_ = nullptr;
@ -87,7 +85,6 @@ bool SharedMemory::SetHandle(SharedMemoryHandle handle, bool read_only) {
DCHECK(mapped_file_ == NULL);
external_section_ = true;
freezeable_ = false; // just in case
mapped_file_ = handle;
read_only_ = read_only;
return true;
@ -98,12 +95,10 @@ bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) {
return handle != NULL;
}
bool SharedMemory::IsValid() const { return mapped_file_ != NULL; }
// static
SharedMemoryHandle SharedMemory::NULLHandle() { return NULL; }
bool SharedMemory::CreateInternal(size_t size, bool freezeable) {
bool SharedMemory::Create(size_t size) {
DCHECK(mapped_file_ == NULL);
read_only_ = false;
mapped_file_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
@ -111,23 +106,6 @@ bool SharedMemory::CreateInternal(size_t size, bool freezeable) {
if (!mapped_file_) return false;
max_size_ = size;
freezeable_ = freezeable;
return true;
}
bool SharedMemory::Freeze() {
DCHECK(!read_only_);
CHECK(freezeable_);
Unmap();
if (!::DuplicateHandle(GetCurrentProcess(), mapped_file_, GetCurrentProcess(),
&mapped_file_, GENERIC_READ | FILE_MAP_READ, false,
DUPLICATE_CLOSE_SOURCE)) {
return false;
}
read_only_ = true;
freezeable_ = false;
return true;
}
@ -168,7 +146,6 @@ void* SharedMemory::FindFreeAddressSpace(size_t size) {
bool SharedMemory::ShareToProcessCommon(ProcessId processId,
SharedMemoryHandle* new_handle,
bool close_self) {
freezeable_ = false;
*new_handle = 0;
DWORD access = FILE_MAP_READ | SECTION_QUERY;
DWORD options = 0;
@ -207,11 +184,6 @@ void SharedMemory::Close(bool unmap_view) {
}
}
mozilla::UniqueFileHandle SharedMemory::TakeHandle() {
mozilla::UniqueFileHandle fh(mapped_file_);
mapped_file_ = NULL;
Unmap();
return fh;
}
SharedMemoryHandle SharedMemory::handle() const { return mapped_file_; }
} // namespace base

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

@ -7,74 +7,104 @@
#include "FileDescriptor.h"
#include "mozilla/Assertions.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Move.h"
#include "nsDebug.h"
#ifdef XP_WIN
# include <windows.h>
# include "ProtocolUtils.h"
# define INVALID_HANDLE INVALID_HANDLE_VALUE
#else // XP_WIN
# include <unistd.h>
# ifndef OS_POSIX
# define OS_POSIX
# endif
# include "base/eintr_wrapper.h"
# define INVALID_HANDLE -1
#endif // XP_WIN
namespace mozilla {
namespace ipc {
FileDescriptor::FileDescriptor() = default;
FileDescriptor::FileDescriptor() : mHandle(INVALID_HANDLE) {}
FileDescriptor::FileDescriptor(const FileDescriptor& aOther)
: mHandle(Clone(aOther.mHandle.get())) {}
: mHandle(INVALID_HANDLE) {
Assign(aOther);
}
FileDescriptor::FileDescriptor(FileDescriptor&& aOther)
: mHandle(std::move(aOther.mHandle)) {}
: mHandle(INVALID_HANDLE) {
*this = std::move(aOther);
}
FileDescriptor::FileDescriptor(PlatformHandleType aHandle)
: mHandle(Clone(aHandle)) {}
: mHandle(INVALID_HANDLE) {
mHandle = Clone(aHandle);
}
FileDescriptor::FileDescriptor(UniquePlatformHandle&& aHandle)
: mHandle(std::move(aHandle)) {}
FileDescriptor::FileDescriptor(const IPDLPrivate&, const PickleType& aPickle) {
FileDescriptor::FileDescriptor(const IPDLPrivate&, const PickleType& aPickle)
: mHandle(INVALID_HANDLE) {
#ifdef XP_WIN
mHandle.reset(aPickle);
mHandle = aPickle;
#else
mHandle.reset(aPickle.fd);
mHandle = aPickle.fd;
#endif
}
FileDescriptor::~FileDescriptor() = default;
FileDescriptor::~FileDescriptor() { Close(); }
FileDescriptor& FileDescriptor::operator=(const FileDescriptor& aOther) {
if (this != &aOther) {
mHandle = Clone(aOther.mHandle.get());
Assign(aOther);
}
return *this;
}
FileDescriptor& FileDescriptor::operator=(FileDescriptor&& aOther) {
if (this != &aOther) {
mHandle = std::move(aOther.mHandle);
Close();
mHandle = aOther.mHandle;
aOther.mHandle = INVALID_HANDLE;
}
return *this;
}
bool FileDescriptor::IsValid() const { return IsValid(mHandle); }
void FileDescriptor::Assign(const FileDescriptor& aOther) {
Close();
mHandle = Clone(aOther.mHandle);
}
void FileDescriptor::Close() {
Close(mHandle);
mHandle = INVALID_HANDLE;
}
FileDescriptor::PickleType FileDescriptor::ShareTo(
const FileDescriptor::IPDLPrivate&,
FileDescriptor::ProcessId aTargetPid) const {
PlatformHandleType newHandle;
#ifdef XP_WIN
if (IsValid()) {
if (mozilla::ipc::DuplicateHandle(mHandle.get(), aTargetPid, &newHandle, 0,
if (mozilla::ipc::DuplicateHandle(mHandle, aTargetPid, &newHandle, 0,
DUPLICATE_SAME_ACCESS)) {
return newHandle;
}
NS_WARNING("Failed to duplicate file handle for other process!");
}
return INVALID_HANDLE_VALUE;
return INVALID_HANDLE;
#else // XP_WIN
if (IsValid()) {
newHandle = dup(mHandle.get());
if (newHandle >= 0) {
newHandle = dup(mHandle);
if (IsValid(newHandle)) {
return base::FileDescriptor(newHandle, /* auto_close */ true);
}
NS_WARNING("Failed to duplicate file handle for other process!");
@ -85,15 +115,9 @@ FileDescriptor::PickleType FileDescriptor::ShareTo(
MOZ_CRASH("Must not get here!");
}
bool FileDescriptor::IsValid() const { return mHandle != nullptr; }
FileDescriptor::UniquePlatformHandle FileDescriptor::ClonePlatformHandle()
const {
return Clone(mHandle.get());
}
FileDescriptor::UniquePlatformHandle FileDescriptor::TakePlatformHandle() {
return UniquePlatformHandle(mHandle.release());
return UniquePlatformHandle(Clone(mHandle));
}
bool FileDescriptor::operator==(const FileDescriptor& aOther) const {
@ -101,29 +125,67 @@ bool FileDescriptor::operator==(const FileDescriptor& aOther) const {
}
// static
FileDescriptor::UniquePlatformHandle FileDescriptor::Clone(
PlatformHandleType aHandle) {
FileDescriptor::PlatformHandleType newHandle;
bool FileDescriptor::IsValid(PlatformHandleType aHandle) {
return aHandle != INVALID_HANDLE;
}
#ifdef XP_WIN
if (aHandle == INVALID_HANDLE_VALUE) {
return UniqueFileHandle();
// static
FileDescriptor::PlatformHandleType FileDescriptor::Clone(
PlatformHandleType aHandle) {
if (!IsValid(aHandle)) {
return INVALID_HANDLE;
}
FileDescriptor::PlatformHandleType newHandle;
#ifdef XP_WIN
if (::DuplicateHandle(GetCurrentProcess(), aHandle, GetCurrentProcess(),
&newHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
return UniqueFileHandle(newHandle);
}
#else // XP_WIN
if (aHandle < 0) {
return UniqueFileHandle();
}
newHandle = dup(aHandle);
if (newHandle >= 0) {
return UniqueFileHandle(newHandle);
}
if ((newHandle = dup(aHandle)) != INVALID_HANDLE) {
#endif
return newHandle;
}
NS_WARNING("Failed to duplicate file handle for current process!");
return UniqueFileHandle();
return INVALID_HANDLE;
}
// static
void FileDescriptor::Close(PlatformHandleType aHandle) {
if (IsValid(aHandle)) {
#ifdef XP_WIN
if (!CloseHandle(aHandle)) {
NS_WARNING("Failed to close file handle for current process!");
}
#else // XP_WIN
IGNORE_EINTR(close(aHandle));
#endif
}
}
FileDescriptor::PlatformHandleHelper::PlatformHandleHelper(
FileDescriptor::PlatformHandleType aHandle)
: mHandle(aHandle) {}
FileDescriptor::PlatformHandleHelper::PlatformHandleHelper(std::nullptr_t)
: mHandle(INVALID_HANDLE) {}
bool FileDescriptor::PlatformHandleHelper::operator!=(std::nullptr_t) const {
return mHandle != INVALID_HANDLE;
}
FileDescriptor::PlatformHandleHelper::
operator FileDescriptor::PlatformHandleType() const {
return mHandle;
}
#ifdef XP_WIN
FileDescriptor::PlatformHandleHelper::operator std::intptr_t() const {
return reinterpret_cast<std::intptr_t>(mHandle);
}
#endif
void FileDescriptor::PlatformHandleDeleter::operator()(
FileDescriptor::PlatformHandleHelper aHelper) {
FileDescriptor::Close(aHelper);
}
void IPDLParamTraits<FileDescriptor>::Write(IPC::Message* aMsg,

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

@ -9,11 +9,15 @@
#include "base/basictypes.h"
#include "base/process.h"
#include "mozilla/UniquePtr.h"
#include "ipc/IPCMessageUtils.h"
#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/ipc/IPDLParamTraits.h"
#ifdef XP_UNIX
#ifdef XP_WIN
// Need the HANDLE typedef.
# include <winnt.h>
# include <cstdint>
#else
# include "base/file_descriptor_posix.h"
#endif
@ -36,15 +40,32 @@ class FileDescriptor {
public:
typedef base::ProcessId ProcessId;
using UniquePlatformHandle = mozilla::UniqueFileHandle;
using PlatformHandleType = UniquePlatformHandle::ElementType;
#ifdef XP_WIN
typedef PlatformHandleType PickleType;
typedef HANDLE PlatformHandleType;
typedef HANDLE PickleType;
#else
typedef int PlatformHandleType;
typedef base::FileDescriptor PickleType;
#endif
struct PlatformHandleHelper {
MOZ_IMPLICIT PlatformHandleHelper(PlatformHandleType aHandle);
MOZ_IMPLICIT PlatformHandleHelper(std::nullptr_t);
bool operator!=(std::nullptr_t) const;
operator PlatformHandleType() const;
#ifdef XP_WIN
operator std::intptr_t() const;
#endif
private:
PlatformHandleType mHandle;
};
struct PlatformHandleDeleter {
typedef PlatformHandleHelper pointer;
void operator()(PlatformHandleHelper aHelper);
};
typedef UniquePtr<PlatformHandleType, PlatformHandleDeleter>
UniquePlatformHandle;
// This should only ever be created by IPDL.
struct IPDLPrivate {};
@ -60,8 +81,6 @@ class FileDescriptor {
// The caller still have to close aHandle.
explicit FileDescriptor(PlatformHandleType aHandle);
explicit FileDescriptor(UniquePlatformHandle&& aHandle);
// This constructor WILL NOT duplicate the handle.
// FileDescriptor takes the ownership from IPC message.
FileDescriptor(const IPDLPrivate&, const PickleType& aPickle);
@ -85,17 +104,23 @@ class FileDescriptor {
// handle.
UniquePlatformHandle ClonePlatformHandle() const;
// Extracts the underlying handle and makes this object an invalid handle.
// (Compare UniquePtr::release.)
UniquePlatformHandle TakePlatformHandle();
// Only used in nsTArray.
bool operator==(const FileDescriptor& aOther) const;
private:
static UniqueFileHandle Clone(PlatformHandleType aHandle);
friend struct PlatformHandleTrait;
UniquePlatformHandle mHandle;
void Assign(const FileDescriptor& aOther);
void Close();
static bool IsValid(PlatformHandleType aHandle);
static PlatformHandleType Clone(PlatformHandleType aHandle);
static void Close(PlatformHandleType aHandle);
PlatformHandleType mHandle;
};
template <>

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

@ -27,12 +27,17 @@ class SharedPreferenceSerializer final {
bool SerializeToSharedMemory();
base::SharedMemoryHandle GetSharedMemoryHandle() const {
return mShm.handle();
}
const FileDescriptor::UniquePlatformHandle& GetPrefMapHandle() const {
return mPrefMapHandle;
}
nsACString::size_type GetPrefLength() const { return mPrefs.Length(); }
size_t GetPrefMapSize() const { return mPrefMapSize; }
size_t GetPrefsLength() const { return mPrefsLength; }
const UniqueFileHandle& GetPrefsHandle() const { return mPrefsHandle; }
const UniqueFileHandle& GetPrefMapHandle() const { return mPrefMapHandle; }
void AddSharedPrefCmdLineArgs(GeckoChildProcessHost& procHost,
std::vector<std::string>& aExtraOpts) const;
@ -40,9 +45,9 @@ class SharedPreferenceSerializer final {
private:
DISALLOW_COPY_AND_ASSIGN(SharedPreferenceSerializer);
size_t mPrefMapSize;
size_t mPrefsLength;
UniqueFileHandle mPrefMapHandle;
UniqueFileHandle mPrefsHandle;
FileDescriptor::UniquePlatformHandle mPrefMapHandle;
base::SharedMemory mShm;
nsAutoCStringN<1024> mPrefs;
};
class SharedPreferenceDeserializer final {

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

@ -8,7 +8,6 @@
#include "mozilla/Preferences.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/UniquePtrExtensions.h"
namespace mozilla {
namespace ipc {
@ -24,36 +23,32 @@ SharedPreferenceSerializer::~SharedPreferenceSerializer() {
SharedPreferenceSerializer::SharedPreferenceSerializer(
SharedPreferenceSerializer&& aOther)
: mPrefMapSize(aOther.mPrefMapSize),
mPrefsLength(aOther.mPrefsLength),
mPrefMapHandle(std::move(aOther.mPrefMapHandle)),
mPrefsHandle(std::move(aOther.mPrefsHandle)) {
mShm(std::move(aOther.mShm)),
mPrefs(std::move(aOther.mPrefs)) {
MOZ_COUNT_CTOR(SharedPreferenceSerializer);
}
bool SharedPreferenceSerializer::SerializeToSharedMemory() {
mPrefMapHandle =
Preferences::EnsureSnapshot(&mPrefMapSize).TakePlatformHandle();
Preferences::EnsureSnapshot(&mPrefMapSize).ClonePlatformHandle();
// Serialize the early prefs.
nsAutoCStringN<1024> prefs;
Preferences::SerializePreferences(prefs);
mPrefsLength = prefs.Length();
Preferences::SerializePreferences(mPrefs);
base::SharedMemory shm;
// Set up the shared memory.
if (!shm.Create(prefs.Length())) {
if (!mShm.Create(mPrefs.Length())) {
NS_ERROR("failed to create shared memory in the parent");
return false;
}
if (!shm.Map(prefs.Length())) {
if (!mShm.Map(mPrefs.Length())) {
NS_ERROR("failed to map shared memory in the parent");
return false;
}
// Copy the serialized prefs into the shared memory.
memcpy(static_cast<char*>(shm.memory()), prefs.get(), mPrefsLength);
memcpy(static_cast<char*>(mShm.memory()), mPrefs.get(), mPrefs.Length());
mPrefsHandle = shm.TakeHandle();
return true;
}
@ -69,10 +64,11 @@ void SharedPreferenceSerializer::AddSharedPrefCmdLineArgs(
#if defined(XP_WIN)
// Record the handle as to-be-shared, and pass it via a command flag. This
// works because Windows handles are system-wide.
procHost.AddHandleToShare(GetPrefsHandle().get());
HANDLE prefsHandle = GetSharedMemoryHandle();
procHost.AddHandleToShare(prefsHandle);
procHost.AddHandleToShare(GetPrefMapHandle().get());
aExtraOpts.push_back("-prefsHandle");
aExtraOpts.push_back(formatPtrArg(GetPrefsHandle().get()).get());
aExtraOpts.push_back(formatPtrArg(prefsHandle).get());
aExtraOpts.push_back("-prefMapHandle");
aExtraOpts.push_back(formatPtrArg(GetPrefMapHandle().get()).get());
#else
@ -83,13 +79,13 @@ void SharedPreferenceSerializer::AddSharedPrefCmdLineArgs(
// Note: on Android, AddFdToRemap() sets up the fd to be passed via a Parcel,
// and the fixed fd isn't used. However, we still need to mark it for
// remapping so it doesn't get closed in the child.
procHost.AddFdToRemap(GetPrefsHandle().get(), kPrefsFileDescriptor);
procHost.AddFdToRemap(GetSharedMemoryHandle().fd, kPrefsFileDescriptor);
procHost.AddFdToRemap(GetPrefMapHandle().get(), kPrefMapFileDescriptor);
#endif
// Pass the lengths via command line flags.
aExtraOpts.push_back("-prefsLen");
aExtraOpts.push_back(formatPtrArg(GetPrefsLength()).get());
aExtraOpts.push_back(formatPtrArg(GetPrefLength()).get());
aExtraOpts.push_back("-prefMapSize");
aExtraOpts.push_back(formatPtrArg(GetPrefMapSize()).get());
}
@ -137,13 +133,16 @@ bool SharedPreferenceDeserializer::DeserializeFromSharedMemory(
return false;
}
// The FileDescriptor constructor will clone this handle when constructed,
// so store it in a UniquePlatformHandle to make sure the original gets
// closed.
FileDescriptor::UniquePlatformHandle handle(
parseHandleArg(aPrefMapHandleStr));
if (!aPrefMapHandleStr || aPrefMapHandleStr[0] != '\0') {
return false;
}
mPrefMapHandle.emplace(std::move(handle));
mPrefMapHandle.emplace(handle.get());
#endif
mPrefsLen = Some(parseUIntPtrArg(aPrefsLenStr));
@ -161,12 +160,17 @@ bool SharedPreferenceDeserializer::DeserializeFromSharedMemory(
MOZ_RELEASE_ASSERT(gPrefsFd != -1);
mPrefsHandle = Some(base::FileDescriptor(gPrefsFd, /* auto_close */ true));
mPrefMapHandle.emplace(UniqueFileHandle(gPrefMapFd));
FileDescriptor::UniquePlatformHandle handle(gPrefMapFd);
mPrefMapHandle.emplace(handle.get());
#elif XP_UNIX
mPrefsHandle = Some(base::FileDescriptor(kPrefsFileDescriptor,
/* auto_close */ true));
mPrefMapHandle.emplace(UniqueFileHandle(kPrefMapFileDescriptor));
// The FileDescriptor constructor will clone this handle when constructed,
// so store it in a UniquePlatformHandle to make sure the original gets
// closed.
FileDescriptor::UniquePlatformHandle handle(kPrefMapFileDescriptor);
mPrefMapHandle.emplace(handle.get());
#endif
if (mPrefsHandle.isNothing() || mPrefsLen.isNothing() ||

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

@ -83,8 +83,6 @@ class SharedMemory {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedMemory)
static void SystemProtect(char* aAddr, size_t aSize, int aRights);
static MOZ_MUST_USE bool SystemProtectFallible(char* aAddr, size_t aSize,
int aRights);
static size_t SystemPageSize();
static size_t PageAlignedSize(size_t aSize);

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

@ -13,19 +13,12 @@ namespace mozilla {
namespace ipc {
void SharedMemory::SystemProtect(char* aAddr, size_t aSize, int aRights) {
if (!SystemProtectFallible(aAddr, aSize, aRights)) {
MOZ_CRASH("can't mprotect()");
}
}
bool SharedMemory::SystemProtectFallible(char* aAddr, size_t aSize,
int aRights) {
int flags = 0;
if (aRights & RightsRead) flags |= PROT_READ;
if (aRights & RightsWrite) flags |= PROT_WRITE;
if (RightsNone == aRights) flags = PROT_NONE;
return 0 == mprotect(aAddr, aSize, flags);
if (0 < mprotect(aAddr, aSize, flags)) MOZ_CRASH("can't mprotect()");
}
size_t SharedMemory::SystemPageSize() { return sysconf(_SC_PAGESIZE); }

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

@ -12,13 +12,6 @@ namespace mozilla {
namespace ipc {
void SharedMemory::SystemProtect(char* aAddr, size_t aSize, int aRights) {
if (!SystemProtectFallible(aAddr, aSize, aRights)) {
MOZ_CRASH("can't VirtualProtect()");
}
}
bool SharedMemory::SystemProtectFallible(char* aAddr, size_t aSize,
int aRights) {
DWORD flags;
if ((aRights & RightsRead) && (aRights & RightsWrite))
flags = PAGE_READWRITE;
@ -28,7 +21,8 @@ bool SharedMemory::SystemProtectFallible(char* aAddr, size_t aSize,
flags = PAGE_NOACCESS;
DWORD oldflags;
return VirtualProtect(aAddr, aSize, flags, &oldflags);
if (!VirtualProtect(aAddr, aSize, flags, &oldflags))
MOZ_CRASH("can't VirtualProtect()");
}
size_t SharedMemory::SystemPageSize() {

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

@ -1,109 +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/. */
#include "gtest/gtest.h"
#include "base/shared_memory.h"
#include "base/process_util.h"
#include "mozilla/ipc/SharedMemory.h"
namespace mozilla {
// Try to map a frozen shm for writing. Threat model: the process is
// compromised and then receives a frozen handle.
TEST(IPCSharedMemory, FreezeAndMapRW)
{
base::SharedMemory shm;
// Create and initialize
ASSERT_TRUE(shm.CreateFreezeable(1));
ASSERT_TRUE(shm.Map(1));
auto mem = reinterpret_cast<char*>(shm.memory());
ASSERT_TRUE(mem);
*mem = 'A';
// Freeze
ASSERT_TRUE(shm.Freeze());
ASSERT_FALSE(shm.memory());
// Re-create as writeable
auto handle = base::SharedMemory::NULLHandle();
ASSERT_TRUE(shm.GiveToProcess(base::GetCurrentProcId(), &handle));
ASSERT_TRUE(shm.IsHandleValid(handle));
ASSERT_FALSE(shm.IsValid());
ASSERT_TRUE(shm.SetHandle(handle, /* read-only */ false));
ASSERT_TRUE(shm.IsValid());
// This should fail
EXPECT_FALSE(shm.Map(1));
}
// Try to restore write permissions to a frozen mapping. Threat
// model: the process has mapped frozen shm normally and then is
// compromised, or as for FreezeAndMapRW (see also the
// proof-of-concept at https://crbug.com/project-zero/1671 ).
TEST(IPCSharedMemory, FreezeAndReprotect)
{
base::SharedMemory shm;
// Create and initialize
ASSERT_TRUE(shm.CreateFreezeable(1));
ASSERT_TRUE(shm.Map(1));
auto mem = reinterpret_cast<char*>(shm.memory());
ASSERT_TRUE(mem);
*mem = 'A';
// Freeze
ASSERT_TRUE(shm.Freeze());
ASSERT_FALSE(shm.memory());
// Re-map
ASSERT_TRUE(shm.Map(1));
mem = reinterpret_cast<char*>(shm.memory());
ASSERT_EQ(*mem, 'A');
// Try to alter protection; should fail
EXPECT_FALSE(ipc::SharedMemory::SystemProtectFallible(
mem, 1, ipc::SharedMemory::RightsReadWrite));
}
#ifndef XP_WIN
// This essentially tests whether FreezeAndReprotect would have failed
// without the freeze. It doesn't work on Windows: VirtualProtect
// can't exceed the permissions set in MapViewOfFile regardless of the
// security status of the original handle.
TEST(IPCSharedMemory, Reprotect)
{
base::SharedMemory shm;
// Create and initialize
ASSERT_TRUE(shm.CreateFreezeable(1));
ASSERT_TRUE(shm.Map(1));
auto mem = reinterpret_cast<char*>(shm.memory());
ASSERT_TRUE(mem);
*mem = 'A';
// Re-create as read-only
auto handle = base::SharedMemory::NULLHandle();
ASSERT_TRUE(shm.GiveToProcess(base::GetCurrentProcId(), &handle));
ASSERT_TRUE(shm.IsHandleValid(handle));
ASSERT_FALSE(shm.IsValid());
ASSERT_TRUE(shm.SetHandle(handle, /* read-only */ true));
ASSERT_TRUE(shm.IsValid());
// Re-map
ASSERT_TRUE(shm.Map(1));
mem = reinterpret_cast<char*>(shm.memory());
ASSERT_EQ(*mem, 'A');
// Try to alter protection; should succeed, because not frozen
EXPECT_TRUE(ipc::SharedMemory::SystemProtectFallible(
mem, 1, ipc::SharedMemory::RightsReadWrite));
}
#endif
} // namespace mozilla

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

@ -1,15 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
Library('ipctest')
SOURCES += [
'TestSharedMemory.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul-gtest'

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

@ -5,7 +5,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += [
'app',
'chromium',
'glue',
'ipdl',
@ -18,9 +17,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
if CONFIG['OS_ARCH'] == 'WINNT':
DIRS += ['mscom']
TEST_DIRS += [
'gtest',
]
DIRS += ['app']
with Files("**"):
BUG_COMPONENT = ("Core", "IPC")

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

@ -125,9 +125,9 @@ typedef enum JSGCParamKey {
* Max milliseconds to spend in an incremental GC slice.
*
* Pref: javascript.options.mem.gc_incremental_slice_ms
* Default: DefaultTimeBudget.
* Default: DefaultTimeBudgetMS.
*/
JSGC_SLICE_TIME_BUDGET = 9,
JSGC_SLICE_TIME_BUDGET_MS = 9,
/**
* Maximum size the GC mark stack can grow to.

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

@ -306,6 +306,30 @@ static inline bool ShouldFailWithOOM() { return false; }
# endif /* DEBUG || JS_OOM_BREAKPOINT */
# ifdef FUZZING
namespace js {
namespace oom {
extern JS_PUBLIC_DATA size_t largeAllocLimit;
extern void InitLargeAllocLimit();
} /* namespace oom */
} /* namespace js */
# define JS_CHECK_LARGE_ALLOC(x) \
do { \
if (js::oom::largeAllocLimit && x > js::oom::largeAllocLimit) { \
if (getenv("MOZ_FUZZ_CRASH_ON_LARGE_ALLOC")) { \
MOZ_CRASH("Large allocation"); \
} else { \
return nullptr; \
} \
} \
} while (0)
# else
# define JS_CHECK_LARGE_ALLOC(x) \
do { \
} while (0)
# endif
namespace js {
/* Disable OOM testing in sections which are not OOM safe. */
@ -365,6 +389,7 @@ extern void AssertJSStringBufferInCorrectArena(const void* ptr);
static inline void* js_arena_malloc(arena_id_t arena, size_t bytes) {
JS_OOM_POSSIBLY_FAIL();
JS_CHECK_LARGE_ALLOC(bytes);
return moz_arena_malloc(arena, bytes);
}
@ -374,12 +399,14 @@ static inline void* js_malloc(size_t bytes) {
static inline void* js_arena_calloc(arena_id_t arena, size_t bytes) {
JS_OOM_POSSIBLY_FAIL();
JS_CHECK_LARGE_ALLOC(bytes);
return moz_arena_calloc(arena, bytes, 1);
}
static inline void* js_arena_calloc(arena_id_t arena, size_t nmemb,
size_t size) {
JS_OOM_POSSIBLY_FAIL();
JS_CHECK_LARGE_ALLOC(nmemb * size);
return moz_arena_calloc(arena, nmemb, size);
}
@ -398,6 +425,7 @@ static inline void* js_arena_realloc(arena_id_t arena, void* p, size_t bytes) {
MOZ_ASSERT(bytes != 0);
JS_OOM_POSSIBLY_FAIL();
JS_CHECK_LARGE_ALLOC(bytes);
return moz_arena_realloc(arena, p, bytes);
}

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

@ -503,7 +503,7 @@ static bool MinorGC(JSContext* cx, unsigned argc, Value* vp) {
_("mode", JSGC_MODE, true) \
_("unusedChunks", JSGC_UNUSED_CHUNKS, false) \
_("totalChunks", JSGC_TOTAL_CHUNKS, false) \
_("sliceTimeBudget", JSGC_SLICE_TIME_BUDGET, true) \
_("sliceTimeBudgetMS", JSGC_SLICE_TIME_BUDGET_MS, true) \
_("markStackLimit", JSGC_MARK_STACK_LIMIT, true) \
_("highFrequencyTimeLimit", JSGC_HIGH_FREQUENCY_TIME_LIMIT, true) \
_("highFrequencyLowLimit", JSGC_HIGH_FREQUENCY_LOW_LIMIT, true) \

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

@ -343,8 +343,8 @@ static const uint32_t MinEmptyChunkCount = 1;
/* JSGC_MAX_EMPTY_CHUNK_COUNT */
static const uint32_t MaxEmptyChunkCount = 30;
/* JSGC_SLICE_TIME_BUDGET */
static const int64_t DefaultTimeBudget = SliceBudget::UnlimitedTimeBudget;
/* JSGC_SLICE_TIME_BUDGET_MS */
static const int64_t DefaultTimeBudgetMS = SliceBudget::UnlimitedTimeBudget;
/* JSGC_MODE */
static const JSGCMode Mode = JSGC_MODE_ZONE_INCREMENTAL;
@ -1024,7 +1024,7 @@ GCRuntime::GCRuntime(JSRuntime* rt)
#ifdef JS_GC_ZEAL
markingValidator(nullptr),
#endif
defaultTimeBudget_(TuningDefaults::DefaultTimeBudget),
defaultTimeBudgetMS_(TuningDefaults::DefaultTimeBudgetMS),
incrementalAllowed(true),
compactingEnabled(TuningDefaults::CompactingEnabled),
rootsRemoved(false),
@ -1437,8 +1437,8 @@ bool GCRuntime::setParameter(JSGCParamKey key, uint32_t value,
case JSGC_MAX_MALLOC_BYTES:
setMaxMallocBytes(value, lock);
break;
case JSGC_SLICE_TIME_BUDGET:
defaultTimeBudget_ = value ? value : SliceBudget::UnlimitedTimeBudget;
case JSGC_SLICE_TIME_BUDGET_MS:
defaultTimeBudgetMS_ = value ? value : SliceBudget::UnlimitedTimeBudget;
break;
case JSGC_MARK_STACK_LIMIT:
if (value == 0) {
@ -1705,8 +1705,8 @@ void GCRuntime::resetParameter(JSGCParamKey key, AutoLockGC& lock) {
case JSGC_MAX_MALLOC_BYTES:
setMaxMallocBytes(TuningDefaults::MaxMallocBytes, lock);
break;
case JSGC_SLICE_TIME_BUDGET:
defaultTimeBudget_ = TuningDefaults::DefaultTimeBudget;
case JSGC_SLICE_TIME_BUDGET_MS:
defaultTimeBudgetMS_ = TuningDefaults::DefaultTimeBudgetMS;
break;
case JSGC_MARK_STACK_LIMIT:
setMarkStackLimit(MarkStack::DefaultCapacity, lock);
@ -1827,13 +1827,13 @@ uint32_t GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC& lock) {
case JSGC_TOTAL_CHUNKS:
return uint32_t(fullChunks(lock).count() + availableChunks(lock).count() +
emptyChunks(lock).count());
case JSGC_SLICE_TIME_BUDGET:
if (defaultTimeBudget_.ref() == SliceBudget::UnlimitedTimeBudget) {
case JSGC_SLICE_TIME_BUDGET_MS:
if (defaultTimeBudgetMS_.ref() == SliceBudget::UnlimitedTimeBudget) {
return 0;
} else {
MOZ_RELEASE_ASSERT(defaultTimeBudget_ >= 0);
MOZ_RELEASE_ASSERT(defaultTimeBudget_ <= UINT32_MAX);
return uint32_t(defaultTimeBudget_);
MOZ_RELEASE_ASSERT(defaultTimeBudgetMS_ >= 0);
MOZ_RELEASE_ASSERT(defaultTimeBudgetMS_ <= UINT32_MAX);
return uint32_t(defaultTimeBudgetMS_);
}
case JSGC_MARK_STACK_LIMIT:
return marker.maxCapacity();
@ -7932,12 +7932,12 @@ js::AutoEnqueuePendingParseTasksAfterGC::
SliceBudget GCRuntime::defaultBudget(JS::GCReason reason, int64_t millis) {
if (millis == 0) {
if (reason == JS::GCReason::ALLOC_TRIGGER) {
millis = defaultSliceBudget();
millis = defaultSliceBudgetMS();
} else if (schedulingState.inHighFrequencyGCMode() &&
tunables.isDynamicMarkSliceEnabled()) {
millis = defaultSliceBudget() * IGC_MARK_SLICE_MULTIPLIER;
millis = defaultSliceBudgetMS() * IGC_MARK_SLICE_MULTIPLIER;
} else {
millis = defaultSliceBudget();
millis = defaultSliceBudgetMS();
}
}

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

@ -130,6 +130,7 @@ class MarkStack {
static const size_t DefaultCapacity = SIZE_MAX;
// The unit for MarkStack::capacity() is mark stack entries.
size_t capacity() { return stack().length(); }
size_t position() const { return topIndex_; }

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

@ -430,7 +430,7 @@ class GCRuntime {
uint64_t majorGCCount() const { return majorGCNumber; }
void incMajorGcNumber() { ++majorGCNumber; }
int64_t defaultSliceBudget() const { return defaultTimeBudget_; }
int64_t defaultSliceBudgetMS() const { return defaultTimeBudgetMS_; }
bool isIncrementalGc() const { return isIncremental; }
bool isFullGc() const { return isFull; }
@ -934,10 +934,10 @@ class GCRuntime {
/*
* Default budget for incremental GC slice. See js/SliceBudget.h.
*
* JSGC_SLICE_TIME_BUDGET
* JSGC_SLICE_TIME_BUDGET_MS
* pref: javascript.options.mem.gc_incremental_slice_ms,
*/
MainThreadData<int64_t> defaultTimeBudget_;
MainThreadData<int64_t> defaultTimeBudgetMS_;
/*
* We disable incremental GC if we encounter a Class with a trace hook

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

@ -59,7 +59,7 @@ struct NurseryChunk {
gc::ChunkTrailer trailer;
static NurseryChunk* fromChunk(gc::Chunk* chunk);
void poisonAndInit(JSRuntime* rt, size_t extent = ChunkSize);
void poisonAfterSweep(size_t extent = ChunkSize);
void poisonAfterEvict(size_t extent = ChunkSize);
uintptr_t start() const { return uintptr_t(&data); }
uintptr_t end() const { return uintptr_t(&trailer); }
gc::Chunk* toChunk(JSRuntime* rt);
@ -78,7 +78,7 @@ inline void js::NurseryChunk::poisonAndInit(JSRuntime* rt, size_t extent) {
new (&trailer) gc::ChunkTrailer(rt, &rt->gc.storeBuffer());
}
inline void js::NurseryChunk::poisonAfterSweep(size_t extent) {
inline void js::NurseryChunk::poisonAfterEvict(size_t extent) {
MOZ_ASSERT(extent <= ChunkSize);
// We can poison the same chunk more than once, so first make sure memory
// sanitizers will let us poison it.
@ -1125,11 +1125,11 @@ void js::Nursery::clear() {
#if defined(JS_GC_ZEAL) || defined(JS_CRASH_DIAGNOSTICS)
/* Poison the nursery contents so touching a freed object will crash. */
for (unsigned i = currentStartChunk_; i < currentChunk_; ++i) {
chunk(i).poisonAfterSweep();
chunk(i).poisonAfterEvict();
}
MOZ_ASSERT(maxChunkCount() > 0);
chunk(currentChunk_)
.poisonAfterSweep(position() - chunk(currentChunk_).start());
.poisonAfterEvict(position() - chunk(currentChunk_).start());
#endif
if (runtime()->hasZealMode(ZealMode::GenerationalGC)) {

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

@ -640,8 +640,8 @@ class Nursery {
void sweep(JSTracer* trc);
/*
* Frees all non-live nursery-allocated things at the end of a minor
* collection.
* Reset the current chunk and position after a minor collection. Also poison
* the nursery on debug & nightly builds.
*/
void clear();

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

@ -0,0 +1,24 @@
// Bug 1561935. Test interaction between debug traps for step mode and
// DebugAfterYield.
let g = newGlobal({newCompartment: true});
g.eval('function* f() { yield 1; yield 2; }');
let dbg = Debugger(g);
let genObj = null;
let hits = 0;
dbg.onEnterFrame = frame => {
// The first time onEnterFrame fires, there is no generator object, so
// there's nothing to test. The generator object doesn't exist until
// JSOP_GENERATOR is reached, right before the initial yield.
if (genObj === null) {
// Trigger step mode.
frame.onStep = function() {};
} else {
dbg.removeDebuggee(g);
dbg.addDebuggee(g);
hits++;
}
};
genObj = g.f();
for (let x of genObj) {}
assertEq(hits, 3);

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

@ -0,0 +1,23 @@
// Bug 1561935. Test interaction between debug traps for step mode and
// DebugAfterYield.
let g = newGlobal({newCompartment: true});
g.eval('function* f() { yield 1; yield 2; }');
let dbg = Debugger(g);
let genObj = null;
let hits = 0;
dbg.onEnterFrame = frame => {
// The first time onEnterFrame fires, there is no generator object, so
// there's nothing to test. The generator object doesn't exist until
// JSOP_GENERATOR is reached, right before the initial yield.
if (genObj === null) {
// Trigger step mode.
frame.onStep = function() {};
} else {
dbg.removeDebuggee(g);
hits++;
}
};
genObj = g.f();
for (let x of genObj) {}
assertEq(hits, 1);

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

@ -1,2 +1,2 @@
// |jit-test| error: Error
gcparam("sliceTimeBudget", -1);
gcparam("sliceTimeBudgetMS", -1);

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

@ -37,7 +37,7 @@ testGetParam("totalChunks");
testChangeParam("maxBytes");
testChangeParam("maxMallocBytes");
testChangeParam("mode");
testChangeParam("sliceTimeBudget");
testChangeParam("sliceTimeBudgetMS");
testChangeParam("markStackLimit");
testChangeParam("highFrequencyTimeLimit");
testChangeParam("highFrequencyLowLimit");

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

@ -1120,6 +1120,15 @@ bool HandleDebugTrap(JSContext* cx, BaselineFrame* frame, uint8_t* retAddr,
pc = blScript->retAddrEntryFromReturnAddress(retAddr).pc(script);
}
// The Baseline Interpreter calls HandleDebugTrap for every op when the script
// is in step mode or has breakpoints. The Baseline Compiler can toggle
// breakpoints more granularly for specific bytecode PCs.
if (frame->runningInInterpreter()) {
MOZ_ASSERT(script->hasAnyBreakpointsOrStepMode());
} else {
MOZ_ASSERT(script->stepModeEnabled() || script->hasBreakpointsAt(pc));
}
if (*pc == JSOP_AFTERYIELD) {
// JSOP_AFTERYIELD will set the frame's debuggee flag and call the
// onEnterFrame handler, but if we set a breakpoint there we have to do
@ -1132,19 +1141,16 @@ bool HandleDebugTrap(JSContext* cx, BaselineFrame* frame, uint8_t* retAddr,
if (*mustReturn) {
return true;
}
// If the frame is not a debuggee we're done. This can happen, for instance,
// if the onEnterFrame hook called removeDebuggee.
if (!frame->isDebuggee()) {
return true;
}
}
MOZ_ASSERT(frame->isDebuggee());
// The Baseline Interpreter calls HandleDebugTrap for every op when the script
// is in step mode or has breakpoints. The Baseline Compiler can toggle
// breakpoints more granularly for specific bytecode PCs.
if (frame->runningInInterpreter()) {
MOZ_ASSERT(script->hasAnyBreakpointsOrStepMode());
} else {
MOZ_ASSERT(script->stepModeEnabled() || script->hasBreakpointsAt(pc));
}
RootedValue rval(cx);
ResumeMode resumeMode = ResumeMode::Continue;

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

@ -1293,7 +1293,7 @@ JS_PUBLIC_API void JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx,
static const JSGCConfig minimal[] = {
{JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
{JSGC_SLICE_TIME_BUDGET, 30},
{JSGC_SLICE_TIME_BUDGET_MS, 30},
{JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
{JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 40},
{JSGC_HIGH_FREQUENCY_LOW_LIMIT, 0},
@ -1308,7 +1308,7 @@ JS_PUBLIC_API void JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx,
static const JSGCConfig nominal[] = {
{JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
{JSGC_SLICE_TIME_BUDGET, 30},
{JSGC_SLICE_TIME_BUDGET_MS, 30},
{JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1000},
{JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 500},
{JSGC_HIGH_FREQUENCY_LOW_LIMIT, 100},

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

@ -79,6 +79,20 @@ void FailureSimulator::reset() {
} // namespace js
#endif // defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
#if defined(FUZZING)
namespace js {
namespace oom {
JS_PUBLIC_DATA size_t largeAllocLimit = 0;
void InitLargeAllocLimit() {
char* limitStr = getenv("MOZ_FUZZ_LARGE_ALLOC_LIMIT");
if (limitStr) {
largeAllocLimit = atoll(limitStr);
}
}
} // namespace oom
} // namespace js
#endif
bool js::gDisablePoisoning = false;
JS_PUBLIC_DATA arena_id_t js::MallocArena;

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

@ -11354,7 +11354,7 @@ int main(int argc, char** argv, char** envp) {
if (!op.getBoolOption("no-incremental-gc")) {
JS_SetGCParameter(cx, JSGC_DYNAMIC_HEAP_GROWTH, 1);
JS_SetGCParameter(cx, JSGC_DYNAMIC_MARK_SLICE, 1);
JS_SetGCParameter(cx, JSGC_SLICE_TIME_BUDGET, 10);
JS_SetGCParameter(cx, JSGC_SLICE_TIME_BUDGET_MS, 10);
}
#endif

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

@ -127,6 +127,10 @@ JS_PUBLIC_API const char* JS::detail::InitWithFailureDiagnostic(
RETURN_IF_FAIL(js::oom::InitThreadType());
#endif
#if defined(FUZZING)
js::oom::InitLargeAllocLimit();
#endif
js::gDisablePoisoning = bool(getenv("JSGC_DISABLE_POISONING"));
js::InitMallocAllocator();

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

@ -39,7 +39,8 @@ Result<Ok, nsresult> AutoMemMap::init(nsIFile* file, int flags, int mode,
}
Result<Ok, nsresult> AutoMemMap::init(const FileDescriptor& file,
PRFileMapProtect prot, size_t maybeSize) {
PRFileMapProtect prot,
size_t expectedSize) {
MOZ_ASSERT(!fd);
if (!file.IsValid()) {
return Err(NS_ERROR_INVALID_ARG);
@ -53,29 +54,19 @@ Result<Ok, nsresult> AutoMemMap::init(const FileDescriptor& file,
}
Unused << handle.release();
return initInternal(prot, maybeSize);
return initInternal(prot, expectedSize);
}
Result<Ok, nsresult> AutoMemMap::initInternal(PRFileMapProtect prot,
size_t maybeSize) {
size_t expectedSize) {
MOZ_ASSERT(!fileMap);
MOZ_ASSERT(!addr);
if (maybeSize > 0) {
// Some OSes' shared memory objects can't be stat()ed, either at
// all (Android) or without loosening the sandbox (Mac) so just
// use the size.
size_ = maybeSize;
} else {
// But if we don't have the size, assume it's a regular file and
// ask for it.
PRFileInfo64 fileInfo;
MOZ_TRY(PR_GetOpenFileInfo64(fd.get(), &fileInfo));
PRFileInfo64 fileInfo;
MOZ_TRY(PR_GetOpenFileInfo64(fd.get(), &fileInfo));
if (fileInfo.size > UINT32_MAX) {
return Err(NS_ERROR_INVALID_ARG);
}
size_ = fileInfo.size;
if (fileInfo.size > UINT32_MAX) {
return Err(NS_ERROR_INVALID_ARG);
}
fileMap = PR_CreateFileMap(fd, 0, prot);
@ -83,6 +74,13 @@ Result<Ok, nsresult> AutoMemMap::initInternal(PRFileMapProtect prot,
return Err(NS_ERROR_FAILURE);
}
size_ = fileInfo.size;
// The memory region size passed in certain IPC messages isn't necessary on
// Unix-like systems, since we can always stat the file descriptor to
// determine it accurately. But since we have it, anyway, sanity check that
// it matches the size returned by the stat.
MOZ_ASSERT_IF(expectedSize > 0, size_ == expectedSize);
addr = PR_MemMap(fileMap, 0, size_);
if (!addr) {
return Err(NS_ERROR_FAILURE);
@ -124,8 +122,7 @@ FileDescriptor AutoMemMap::cloneHandle() const {
Result<Ok, nsresult> AutoMemMap::initWithHandle(const FileDescriptor& file,
size_t size,
PRFileMapProtect prot) {
MOZ_DIAGNOSTIC_ASSERT(size > 0);
return init(file, prot, size);
return init(file, prot);
}
FileDescriptor AutoMemMap::cloneHandle() const { return cloneFileDescriptor(); }

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

@ -36,7 +36,7 @@ class AutoMemMap {
Result<Ok, nsresult> init(const FileDescriptor& file,
PRFileMapProtect prot = PR_PROT_READONLY,
size_t maybeSize = 0);
size_t expectedSize = 0);
// Initializes the mapped memory with a shared memory handle. On
// Unix-like systems, this is identical to the above init() method. On
@ -73,8 +73,8 @@ class AutoMemMap {
void setPersistent() { persistent_ = true; }
private:
Result<Ok, nsresult> initInternal(PRFileMapProtect prot,
size_t maybeSize = 0);
Result<Ok, nsresult> initInternal(PRFileMapProtect prot = PR_PROT_READONLY,
size_t expectedSize = 0);
AutoFDClose fd;
PRFileMap* fileMap = nullptr;

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

@ -15,8 +15,8 @@ skip-if(!asyncPan) == bg-fixed-child-no-culling-3.html bg-fixed-child-no-culling
fuzzy-if(Android,0-2,0-4000) fuzzy-if(browserIsRemote&&cocoaWidget,0-2,0-179524) fuzzy-if(browserIsRemote&&winWidget,0-1,0-74590) fuzzy-if(gtkWidget&&layersGPUAccelerated,0-1,0-3528) fuzzy-if((/^Windows\x20NT\x2010\.0/.test(http.oscpu))&&(/^aarch64-msvc/.test(xulRuntime.XPCOMABI)),0-1,0-75900) skip-if(!asyncPan) fuzzy-if(geckoview,0-1,0-74590) == bg-fixed-transformed-image.html bg-fixed-transformed-image-ref.html
test-pref(layout.css.contain.enabled,true) skip-if(!asyncPan) == contain-paint-scrollable-frame-1.html contain-paint-scrollable-frame-1-ref.html
skip-if(!asyncPan) == element-1.html element-1-ref.html
pref(layers.force-active,true) skip-if(!asyncPan) fuzzy-if(geckoview,1-1,1-1) == iframe-1.html iframe-1-ref.html
skip-if(!asyncPan) fuzzy-if(geckoview,1-1,43-43) == nested-1.html nested-1-ref.html
pref(layers.force-active,true) skip-if(!asyncPan) == iframe-1.html iframe-1-ref.html
skip-if(!asyncPan) == nested-1.html nested-1-ref.html
skip-if(!asyncPan) == nested-2.html nested-2-ref.html
skip-if(!asyncPan) == position-fixed-1.html position-fixed-1-ref.html
skip-if(!asyncPan) == position-fixed-2.html position-fixed-2-ref.html
@ -28,12 +28,12 @@ fuzzy-if(Android,0-5,0-4) skip-if(!asyncPan) == position-fixed-transformed-1.htm
skip-if(!asyncPan) == split-layers-1.html split-layers-1-ref.html
skip-if(!asyncPan) == split-layers-multi-scrolling-1.html split-layers-multi-scrolling-1-ref.html
fuzzy-if(skiaContent,0-2,0-240000) fuzzy-if(browserIsRemote&&!skiaContent&&(cocoaWidget||winWidget),0-1,0-240000) skip-if(!asyncPan) == split-opacity-layers-1.html split-opacity-layers-1-ref.html
skip-if(!asyncPan) fuzzy-if(geckoview,1-1,389-389) == sticky-pos-scrollable-1.html sticky-pos-scrollable-1-ref.html
skip-if(!asyncPan) == sticky-pos-scrollable-1.html sticky-pos-scrollable-1-ref.html
skip-if(!asyncPan) == sticky-pos-scrollable-2.html sticky-pos-scrollable-2-ref.html
skip-if(!asyncPan) == sticky-pos-scrollable-3.html sticky-pos-scrollable-3-ref.html
skip-if(!asyncPan) == sticky-pos-scrollable-4.html sticky-pos-scrollable-4-ref.html
skip-if(!asyncPan) == sticky-pos-scrollable-5.html sticky-pos-scrollable-5-ref.html
skip-if(!asyncPan) fuzzy-if(geckoview,1-1,15-15) == sticky-pos-scrollable-6.html sticky-pos-scrollable-6-ref.html
skip-if(!asyncPan) == sticky-pos-scrollable-6.html sticky-pos-scrollable-6-ref.html
skip-if(!asyncPan) == sticky-pos-scrollable-7.html sticky-pos-scrollable-7-ref.html
skip-if(!asyncPan) == fixed-pos-scrollable-1.html fixed-pos-scrollable-1-ref.html
skip-if(!asyncPan) == culling-1.html culling-1-ref.html
@ -44,16 +44,16 @@ fuzzy-if(Android,0-1,0-800) skip-if(!asyncPan) == position-fixed-inside-clip-pat
skip-if(!asyncPan) == position-fixed-inside-sticky-1.html position-fixed-inside-sticky-1-ref.html
skip-if(!asyncPan) == position-fixed-inside-sticky-2.html position-fixed-inside-sticky-2-ref.html
skip-if(!asyncPan) == position-fixed-inside-sticky-3.html position-fixed-inside-sticky-3-ref.html
skip-if(!asyncPan) fuzzy-if(geckoview,1-1,100-100) == sticky-inside-fixed-1.html sticky-inside-fixed-1-ref.html
skip-if(!asyncPan) == sticky-inside-fixed-1.html sticky-inside-fixed-1-ref.html
skip-if(!asyncPan) fails-if(!webrender) == sticky-inside-transform-1.html sticky-inside-transform-1-ref.html
fuzzy(0-1,0-60000) skip-if(!asyncPan) fuzzy-if(geckoview,2-2,60000-60000) == group-opacity-surface-size-1.html group-opacity-surface-size-1-ref.html
fuzzy(0-1,0-60000) skip-if(!asyncPan) == group-opacity-surface-size-1.html group-opacity-surface-size-1-ref.html
fuzzy-if(Android,0-1,0-197) fuzzy-if(webrender,0-1,0-1) skip-if(!asyncPan) == position-sticky-transformed.html position-sticky-transformed-ref.html
skip-if(!asyncPan) == offscreen-prerendered-active-opacity.html offscreen-prerendered-active-opacity-ref.html
fuzzy-if(Android,0-6,0-4) fuzzy-if(skiaContent&&!Android,0-1,0-34) skip-if(!asyncPan) fuzzy-if(geckoview,1-1,50-50) == offscreen-clipped-blendmode-1.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-6,0-4) fuzzy-if(skiaContent&&!Android,0-1,0-34) skip-if(!asyncPan) == offscreen-clipped-blendmode-1.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-6,0-4) skip-if(!asyncPan) == offscreen-clipped-blendmode-2.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-6,0-4) skip == offscreen-clipped-blendmode-3.html offscreen-clipped-blendmode-ref.html # bug 1251588 - wrong AGR on mix-blend-mode item
fuzzy-if(Android,0-6,0-4) skip-if(!asyncPan) == offscreen-clipped-blendmode-4.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-7,0-4) skip-if(!asyncPan) fuzzy-if(geckoview,1-1,43-43) == perspective-scrolling-1.html perspective-scrolling-1-ref.html
fuzzy-if(Android,0-7,0-4) skip-if(!asyncPan) == perspective-scrolling-1.html perspective-scrolling-1-ref.html
fuzzy-if(Android,0-7,0-4) skip-if(!asyncPan) == perspective-scrolling-2.html perspective-scrolling-2-ref.html
fuzzy-if(Android,0-7,0-4) skip-if(!asyncPan) == perspective-scrolling-3.html perspective-scrolling-3-ref.html
fuzzy-if(Android,0-7,0-4) skip-if(!asyncPan) == perspective-scrolling-4.html perspective-scrolling-4-ref.html
@ -64,7 +64,7 @@ skip-if(Android||!asyncPan) != opaque-fractional-displayport-1.html about:blank
skip-if(Android||!asyncPan) != opaque-fractional-displayport-2.html about:blank
fuzzy-if(Android,0-6,0-4) skip-if(!asyncPan) == fixed-pos-scrolled-clip-1.html fixed-pos-scrolled-clip-1-ref.html
fuzzy-if(Android,0-6,0-8) skip-if(!asyncPan) == fixed-pos-scrolled-clip-2.html fixed-pos-scrolled-clip-2-ref.html
fuzzy-if(Android,0-6,0-8) skip-if(!asyncPan) fuzzy-if(geckoview,2-2,132-132) == fixed-pos-scrolled-clip-3.html fixed-pos-scrolled-clip-3-ref.html
fuzzy-if(Android,0-6,0-8) skip-if(!asyncPan) == fixed-pos-scrolled-clip-3.html fixed-pos-scrolled-clip-3-ref.html
fuzzy-if(Android,0-6,0-8) skip-if(!asyncPan) == fixed-pos-scrolled-clip-4.html fixed-pos-scrolled-clip-4-ref.html
skip-if(!asyncPan) == fixed-pos-scrolled-clip-5.html fixed-pos-scrolled-clip-5-ref.html
skip-if(!asyncPan) == position-sticky-bug1434250.html position-sticky-bug1434250-ref.html

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

@ -51,8 +51,8 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-1,0-5) == clipping-5-image
fuzzy-if(skiaContent,0-1,0-77) == clipping-5-overflow-hidden.html clipping-5-ref.html
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-1,0-4) fuzzy-if(Android,0-5,0-21) fuzzy-if(skiaContent,0-1,0-97) == clipping-5-refi.html clipping-5-ref.html
fuzzy-if(true,0-1,0-7) fuzzy-if(d2d,0-55,0-95) fuzzy-if(cocoaWidget,0-1,0-99) fuzzy-if(Android,0-99,0-115) fuzzy-if(skiaContent,0-1,0-77) == clipping-5-refc.html clipping-5-ref.html # bug 732535
fuzzy-if(Android,0-8,0-469) fuzzy-if(skiaContent,0-21,0-76) fuzzy-if(winWidget,0-144,0-335) fuzzy-if(webrender&&cocoaWidget,1-1,8-8) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy-if(geckoview,11-11,119-119) == clipping-6.html clipping-6-ref.html # PaintedLayer and MaskLayer with transforms that aren't identical, bug 1392106
fuzzy-if(true,0-2,0-29) fuzzy-if(d2d,0-46,0-71) fuzzy-if(Android,0-255,0-586) fuzzy-if(skiaContent,0-28,0-97) fuzzy-if(geckoview,29-29,95-95) == clipping-7.html clipping-7-ref.html # ColorLayer and MaskLayer with transforms that aren't identical. Reference image rendered without using layers (which causes fuzzy failures).
fuzzy-if(Android,0-8,0-469) fuzzy-if(skiaContent,0-21,0-76) fuzzy-if(winWidget,0-144,0-335) fuzzy-if(webrender&&cocoaWidget,1-1,8-8) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == clipping-6.html clipping-6-ref.html # PaintedLayer and MaskLayer with transforms that aren't identical, bug 1392106
fuzzy-if(true,0-2,0-29) fuzzy-if(d2d,0-46,0-71) fuzzy-if(Android,0-255,0-586) fuzzy-if(skiaContent,0-28,0-97) == clipping-7.html clipping-7-ref.html # ColorLayer and MaskLayer with transforms that aren't identical. Reference image rendered without using layers (which causes fuzzy failures).
fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),0-1,0-5) == clipping-and-zindex-1.html clipping-and-zindex-1-ref.html
fuzzy-if(cocoaWidget,0-1,0-4) fuzzy-if(d2d,0-59,0-342) fuzzy-if(d3d11&&advancedLayers&&!d2d,0-30,0-3) == intersecting-clipping-1-canvas.html intersecting-clipping-1-refc.html
== intersecting-clipping-1-image.html intersecting-clipping-1-refi.html
@ -78,7 +78,7 @@ fails-if(Android) == scrollbar-clamping-2.html scrollbar-clamping-2-ref.html
fuzzy-if(true,0-1,0-1) == corner-joins-1.xhtml corner-joins-1-ref.xhtml
fuzzy(0-255,0-20) random-if(winWidget) fuzzy-if(skiaContent,0-255,0-610) == corner-joins-2.xhtml corner-joins-2-ref.xhtml
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.2/.test(http.oscpu),0-1,0-20) fuzzy-if(d2d,0-98,0-157) fuzzy-if(Android,0-166,0-400) fuzzy-if(skiaContent,0-59,0-146) fuzzy-if(geckoview,54-54,151-151) == scroll-1.html scroll-1-ref.html # see bug 732535 #Bug 959166
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.2/.test(http.oscpu),0-1,0-20) fuzzy-if(d2d,0-98,0-157) fuzzy-if(Android,0-166,0-400) fuzzy-if(skiaContent,0-59,0-146) == scroll-1.html scroll-1-ref.html # see bug 732535 #Bug 959166
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-35,0-194) == transforms-1.html transforms-1-ref.html # bug 1507152

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

@ -276,12 +276,12 @@ skip-if(Android&&asyncPan) == 243519-1.html 243519-1-ref.html
== 243519-6.html 243519-6-ref.html
== 243519-7.html 243519-7-ref.html
== 243519-8.svg 243519-8-ref.svg
fuzzy-if(geckoview,1-1,1799-1799) == 243519-9a.html 243519-9-ref.html
fuzzy-if(geckoview,1-1,1799-1799) == 243519-9b.html 243519-9-ref.html
fuzzy-if(geckoview,1-1,1799-1799) == 243519-9c.html 243519-9-ref.html
fuzzy-if(geckoview,1-1,1799-1799) == 243519-9d.html 243519-9-ref.html
fuzzy-if(geckoview,1-1,1799-1799) == 243519-9e.html 243519-9-ref.html
fuzzy-if(geckoview,1-1,1799-1799) == 243519-9f.html 243519-9-ref.html
== 243519-9a.html 243519-9-ref.html
== 243519-9b.html 243519-9-ref.html
== 243519-9c.html 243519-9-ref.html
== 243519-9d.html 243519-9-ref.html
== 243519-9e.html 243519-9-ref.html
== 243519-9f.html 243519-9-ref.html
== 244135-1.html 244135-1-ref.html
== 244135-2.html 244135-2-ref.html
== 244932-1.html 244932-1-ref.html
@ -869,7 +869,7 @@ fuzzy-if(gtkWidget,0-2,0-40) == 402567-4.html 402567-4-ref.html
fuzzy-if(skiaContent,0-2,0-5) == 402629-1.html 402629-1-ref.html
fuzzy-if(skiaContent,0-2,0-5) == 402629-2.html 402629-2-ref.html
fuzzy-if(skiaContent,0-2,0-5) == 402629-3.html 402629-3-ref.html
fuzzy-if(geckoview,1-1,109-109) == 402807-1.html 402807-1-ref.html
== 402807-1.html 402807-1-ref.html
== 402940-1.html 402940-1-ref.html
== 402940-1b.html 402940-1-ref.html
!= 402940-2.html 402940-2-notref.html
@ -926,7 +926,7 @@ fuzzy-if(Android,0-8,0-50) == 404553-1.html 404553-1-ref.html # assertion test,
== 406484-1.html 406484-1-ref.html
== 406568-1.html 406568-1-ref.html
== 407016-1-a.html 407016-1-ref.html
fuzzy-if(geckoview,1-1,14-14) == 407016-1-b.html 407016-1-ref.html
== 407016-1-b.html 407016-1-ref.html
== 407078-1.html 407078-1-ref.html
== 407095-1.html 407095-1-ref.html
fuzzy-if(Android,0-13,0-9) == 407111-1.html 407111-1-ref.html # Bug 1128229
@ -1228,11 +1228,11 @@ fuzzy-if(skiaContent,0-1,0-45) fuzzy-if(webrender,9-9,8-8) == 456219-2.html 4562
== 458487-1h.html 458487-1-ref.html
== 458487-2.html 458487-2-ref.html
== 458487-3.html 458487-3-ref.html
fuzzy-if(geckoview,1-1,208-210) == 458487-4a.html 458487-4-ref.html
fuzzy-if(geckoview,1-1,208-210) == 458487-4b.html 458487-4-ref.html
fuzzy-if(geckoview,1-1,208-210) == 458487-4c.html 458487-4-ref.html
fuzzy-if(geckoview,1-1,108-108) == 458487-5a.html 458487-5-ref.html
fuzzy-if(geckoview,1-1,108-108) == 458487-5b.html 458487-5-ref.html
== 458487-4a.html 458487-4-ref.html
== 458487-4b.html 458487-4-ref.html
== 458487-4c.html 458487-4-ref.html
== 458487-5a.html 458487-5-ref.html
== 458487-5b.html 458487-5-ref.html
fuzzy-if(skiaContent,0-1,0-5) == 459443-1.html 459443-1-ref.html
== 459613-1.html 459613-1-ref.html
== 460012-1.html 460012-1-ref.html
@ -1726,7 +1726,7 @@ fuzzy-if(skiaContent,0-1,0-3) needs-focus == 712130-2.html 712130-2-ref.html
== 714519-1-q.html 714519-1-ref.html
== 714519-2-as.html 714519-2-ref.html
== 714519-2-q.html 714519-2-ref.html
fuzzy-if(true,0-1,0-21) fuzzy-if(d2d,0-77,0-173) fuzzy-if(cocoaWidget,0-1,0-170) fuzzy-if(geckoview,1-1,23-23) == 718521.html 718521-ref.html # bug 773482
fuzzy-if(true,0-1,0-21) fuzzy-if(d2d,0-77,0-173) fuzzy-if(cocoaWidget,0-1,0-170) == 718521.html 718521-ref.html # bug 773482
== 720987.html 720987-ref.html
== 722888-1.html 722888-1-ref.html
fuzzy(0-2,0-40000) == 722923-1.html 722923-1-ref.html
@ -1825,9 +1825,9 @@ fuzzy-if(skiaContent,0-1,0-5) == 956513-1.svg 956513-1-ref.svg
== 957770-1.svg 957770-1-ref.svg
== 960277-1.html 960277-1-ref.html
fuzzy-if(skiaContent,0-1,0-80) == 961887-1.html 961887-1-ref.html
fuzzy-if(geckoview,2-2,40-40) == 961887-2.html 961887-2-ref.html
== 961887-2.html 961887-2-ref.html
== 961887-3.html 961887-3-ref.html
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(0-50,0-145) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-102,0-3712) fuzzy-if(webrender,0-255,0-51) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy-if(geckoview,1-1,442-442) == 966992-1.html 966992-1-ref.html # Bug 1392106
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(0-50,0-145) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-102,0-3712) fuzzy-if(webrender,0-255,0-51) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 966992-1.html 966992-1-ref.html # Bug 1392106
skip-if(Android) == 966510-1.html 966510-1-ref.html # scrollable elements other than the root probably won't work well on android until bug 776030 is fixed
skip-if(Android) == 966510-2.html 966510-2-ref.html # same as above
fuzzy-if(skiaContent,0-1,0-123) == 978911-1.svg 978911-1-ref.svg
@ -1859,7 +1859,7 @@ fuzzy-if(d2d,0-1,0-125200) fuzzy-if(skiaContent,0-1,0-126000) == 1022612-1.html
fuzzy-if(skiaContent,0-1,0-24000) == 1025914-1.html 1025914-1-ref.html
pref(layout.css.moz-document.content.enabled,true) == 1035091.html 1035091-ref.html
pref(layout.css.moz-document.content.enabled,false) == 1035091-2.html 1035091-ref.html
fuzzy-if(geckoview,1-1,94-94) == 1042104-1.html 1042104-1-ref.html
== 1042104-1.html 1042104-1-ref.html
== 1043537-1.html 1043537-1-ref.html
== 1044198-1.html 1044198-1-ref.html
== 1049499-1.html 1049499-1-ref.html
@ -1957,7 +1957,7 @@ pref(apz.allow_zooming,true) skip-if(!Android) != 1133905-ref-vh-rtl.html about:
== 1151306-1.html 1151306-1-ref.html
== 1153845-1.html 1153845-1-ref.html
== 1155828-1.html 1155828-1-ref.html
fuzzy-if(skiaContent,0-7,0-84) fuzzy-if(geckoview,7-7,113-113) == 1156129-1.html 1156129-1-ref.html
fuzzy-if(skiaContent,0-7,0-84) == 1156129-1.html 1156129-1-ref.html
pref(dom.use_xbl_scopes_for_remote_xul,true) HTTP(..) == 1157127-1.html 1157127-1-ref.html
fuzzy-if(Android,0-6,0-6) == 1169331-1.html 1169331-1-ref.html
fuzzy(0-1,0-74) fails-if(Android||gtkWidget) == 1174332-1.html 1174332-1-ref.html # bug 1312658
@ -2084,7 +2084,7 @@ test-pref(font.size.systemFontScale,200) == 1412743.html 1412743-ref.html
== 1424680.html 1424680-ref.html
== 1424798-1.html 1424798-ref.html
fuzzy-if(!webrender,0-74,0-2234) == 1425243-1.html 1425243-1-ref.html
fuzzy-if(Android,0-66,0-574) fuzzy-if(d2d,0-89,0-777) fuzzy-if(!Android&&!d2d,0-1,0-31341) fuzzy-if(webrender&&winWidget,1-1,31320-31320) fuzzy-if(geckoview,66-66,31611-31611) == 1425243-2.html 1425243-2-ref.html
fuzzy-if(Android,0-66,0-574) fuzzy-if(d2d,0-89,0-777) fuzzy-if(!Android&&!d2d,0-1,0-31341) fuzzy-if(webrender&&winWidget,1-1,31320-31320) == 1425243-2.html 1425243-2-ref.html
== 1430869.html 1430869-ref.html
== 1432541.html 1432541-ref.html
pref(layout.css.moz-document.url-prefix-hack.enabled,true) == 1446470.html 1035091-ref.html
@ -2106,7 +2106,7 @@ fuzzy-if(!webrender,1-5,66-547) fuzzy-if(geckoview,1-2,64-141) == 1529992-1.html
fuzzy-if(!webrender,0-6,0-34) fails-if(webrender) fuzzy-if(geckoview,9-9,44-44) == 1529992-2.html 1529992-2-ref.html
== 1535040-1.html 1535040-1-ref.html
== 1545360-1.xhtml 1545360-1-ref.xhtml
skip-if(!asyncPan) fuzzy-if(geckoview,1-1,165-165) == 1544895.html 1544895-ref.html
skip-if(!asyncPan) == 1544895.html 1544895-ref.html
== 1548809.html 1548809-ref.html
!= 1552789-1.html 1552789-ref-1.html
== 1558937-1.html 1558937-1-ref.html

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

@ -48,7 +48,7 @@ fuzzy(0-2,0-14400) == mix-blend-mode-child-of-blended-has-opacity.html mix-blend
== mix-blend-mode-nested-976533.html mix-blend-mode-nested-976533-ref.html
== mix-blend-mode-culling-1207041.html mix-blend-mode-culling-1207041-ref.html
== mix-blend-mode-dest-alpha-1135271.html mix-blend-mode-dest-alpha-1135271-ref.html
fuzzy-if(geckoview,1-1,280-280) == clipped-mixblendmode-containing-unclipped-stuff.html clipped-mixblendmode-containing-unclipped-stuff-ref.html
== clipped-mixblendmode-containing-unclipped-stuff.html clipped-mixblendmode-containing-unclipped-stuff-ref.html
fuzzy(0-1,0-6800) == clipped-opacity-containing-unclipped-mixblendmode.html clipped-opacity-containing-unclipped-mixblendmode-ref.html
# Test plan 5.3.1 Blending between the background layers and the background color for an element with background-blend-mode

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

@ -1,4 +1,4 @@
pref(gfx.omta.background-color,true) fuzzy-if((OSX&&!webrender)||(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!gpuProcess&&layersGPUAccelerated),1-1,10000-10000) fuzzy-if(geckoview,1-1,10000-10000) == background-color-with-opacity.html background-color-with-opacity-ref.html
pref(gfx.omta.background-color,true) fuzzy-if((OSX&&!webrender)||(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!gpuProcess&&layersGPUAccelerated),1-1,10000-10000) == background-color-with-opacity.html background-color-with-opacity-ref.html
== transitions-inline-already-wrapped-1.html transitions-inline-ref.html
== transitions-inline-already-wrapped-2.html transitions-inline-ref.html
== transitions-inline-rewrap-1.html transitions-inline-ref.html

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

@ -13,5 +13,5 @@ fuzzy-if(skiaContent,0-1,0-1) == rtl.html rtl-dynamic-attr.html
fuzzy-if(skiaContent,0-1,0-1) == rtl.html rtl-dynamic-style.html
== rtl.html in-dynamic-rtl-doc.html
fuzzy-if(skiaContent,0-1,0-3) == setvalue-framereconstruction-1.html setvalue-framereconstruction-ref.html
fuzzy-if(asyncPan&&!layersGPUAccelerated,0-102,0-4168) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy-if(geckoview,1-1,440-440) == padding-scrollbar-placement.html padding-scrollbar-placement-ref.html # Bug 1392106
fuzzy-if(asyncPan&&!layersGPUAccelerated,0-102,0-4168) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == padding-scrollbar-placement.html padding-scrollbar-placement-ref.html # Bug 1392106
== various-cols.html various-cols-ref.html

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

@ -8,7 +8,7 @@ random == bug-364968.html bug-364968-ref.html
fails-if(azureSkia&&!(webrender&&winWidget)) fails-if(cocoaWidget) == canvas-outside-document-invalidate-02.html about:blank # See bug 666800
#fails with Skia due to Skia bug http://code.google.com/p/skia/issues/detail?id=568
fuzzy-if(webrender&&winWidget,117-129,47-54) == element-paint-simple.html element-paint-simple-ref.html
fuzzy-if(geckoview,1-1,50-50) == element-paint-repeated.html element-paint-repeated-ref.html
== element-paint-repeated.html element-paint-repeated-ref.html
== element-paint-recursion.html element-paint-recursion-ref.html
== element-paint-continuation.html element-paint-continuation-ref.html
== element-paint-transform-01.html element-paint-transform-01-ref.html

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

@ -1,4 +1,4 @@
fuzzy-if(cocoaWidget,0-1,0-2) fuzzy-if(d2d,0-47,0-26) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-169,0-970) fuzzy-if(geckoview,1-1,52-100) == move-right-bottom.html move-right-bottom-ref.html
fuzzy-if(cocoaWidget,0-1,0-2) fuzzy-if(d2d,0-47,0-26) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-169,0-970) == move-right-bottom.html move-right-bottom-ref.html
fuzzy-if(cocoaWidget,0-1,0-2) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-169,0-970) == move-top-left.html move-top-left-ref.html # Bug 688545
fuzzy-if(cocoaWidget,0-1,0-3) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-144,0-580) == move-right-bottom-table.html move-right-bottom-table-ref.html
fuzzy-if(cocoaWidget,0-1,0-3) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-144,0-580) == move-top-left-table.html move-top-left-table-ref.html # Bug 688545

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

@ -11,14 +11,14 @@ fuzzy-if(Android,0-2,0-1568) == top-6.html top-6-ref.html
== bottom-3.html bottom-3-ref.html
== bottom-4.html bottom-4-ref.html
fuzzy-if(Android,0-2,0-4) == left-1.html left-1-ref.html
fuzzy-if(Android,0-2,0-4) fuzzy-if(geckoview,1-1,8-8) == left-2.html left-2-ref.html
fuzzy-if(geckoview,1-1,20-20) == left-3.html left-3-ref.html
fuzzy-if(Android,0-2,0-4) == left-2.html left-2-ref.html
== left-3.html left-3-ref.html
== right-1.html right-1-ref.html
fuzzy-if(Android,0-2,0-4) == right-2.html right-2-ref.html
fuzzy-if(Android,0-2,0-4) fuzzy-if(geckoview,1-1,10-10) == right-3.html right-3-ref.html
fuzzy-if(Android,0-2,0-4) == right-3.html right-3-ref.html
== margin-1.html margin-1-ref.html
== padding-1.html padding-1-ref.html
fuzzy-if(geckoview,1-1,6-6) == padding-2.html padding-2-ref.html
== padding-2.html padding-2-ref.html
== padding-3.html padding-3-ref.html
== overcontain-1.html overcontain-1-ref.html
== initial-1.html initial-1-ref.html

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

@ -31,7 +31,7 @@ fuzzy-if(d2d,0-1,0-4) fuzzy-if(webrender,0-1,0-42) HTTP == transformed-1.html tr
fuzzy-if(webrender,0-1,0-43) HTTP == transformed-1.html?up transformed-1.html?ref
fuzzy-if(Android,0-5,0-20000) == uncovering-1.html uncovering-1-ref.html
fuzzy-if(Android,0-5,0-20000) == uncovering-2.html uncovering-2-ref.html
fuzzy-if(asyncPan&&!layersGPUAccelerated,0-149,0-4520) fuzzy-if(geckoview,1-1,86-86) == less-than-scrollbar-height.html less-than-scrollbar-height-ref.html
fuzzy-if(asyncPan&&!layersGPUAccelerated,0-149,0-4520) == less-than-scrollbar-height.html less-than-scrollbar-height-ref.html
== huge-horizontal-overflow.html huge-horizontal-overflow-ref.html
== huge-vertical-overflow.html huge-vertical-overflow-ref.html
fuzzy-if(asyncPan&&!layersGPUAccelerated,0-102,0-6818) == iframe-scrolling-attr-1.html iframe-scrolling-attr-ref.html

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

@ -151,7 +151,7 @@ random-if(cocoaWidget) random-if(gtkWidget) == zwnj-01.xhtml zwnj-01-ref.xhtml #
== initial-zwj-1.html initial-zwj-1-ref.html
== cgj-01.html cgj-01-ref.html
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 444656.html 444656-ref.html # Bug 1392106
== 449555-1.html 449555-1-ref.html
fuzzy-if(geckoview,0-4,0-1) == 449555-1.html 449555-1-ref.html
== 467722.html 467722-ref.html
fuzzy-if(skiaContent,0-1,0-600) == 475092-sub.html 475092-ref.html
fails-if(Android) fuzzy-if(skiaContent&&!Android,0-90,0-3100) fuzzy-if(webrender&&cocoaWidget,72-72,353-353) == 475092-pos.html 475092-sub.html # bug 482596

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

@ -68,10 +68,6 @@ LONGHANDS_NOT_SERIALIZED_WITH_SERVO = [
# Resolved value should be zero when the column-rule-style is none.
"column-rule-width",
# Clamping (need to get rid of nsStyleCoord storage before removing these).
"grid-auto-columns",
"grid-auto-rows",
# These resolve auto to zero in a few cases, but not all.
"max-block-size",
"max-height",

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

@ -52,7 +52,6 @@ CSS_KEY(-moz-inline-box, _moz_inline_box)
CSS_KEY(-moz-inline-grid, _moz_inline_grid)
CSS_KEY(-moz-inline-stack, _moz_inline_stack)
CSS_KEY(-moz-left, _moz_left)
CSS_KEY(-moz-middle-with-baseline, _moz_middle_with_baseline)
CSS_KEY(-moz-none, _moz_none)
CSS_KEY(-moz-popup, _moz_popup)
CSS_KEY(-moz-right, _moz_right)
@ -64,28 +63,17 @@ CSS_KEY(-webkit-flex, _webkit_flex)
CSS_KEY(-webkit-inline-box, _webkit_inline_box)
CSS_KEY(-webkit-inline-flex, _webkit_inline_flex)
CSS_KEY(alias, alias)
CSS_KEY(all, all)
CSS_KEY(all-scroll, all_scroll)
CSS_KEY(auto, auto)
CSS_KEY(baseline, baseline)
CSS_KEY(blink, blink)
CSS_KEY(block, block)
CSS_KEY(blur, blur)
CSS_KEY(bottom, bottom)
CSS_KEY(brightness, brightness)
CSS_KEY(cell, cell)
CSS_KEY(center, center)
CSS_KEY(circle, circle)
CSS_KEY(clip, clip)
CSS_KEY(closest-side, closest_side)
CSS_KEY(col-resize, col_resize)
CSS_KEY(column, column)
CSS_KEY(content, content)
CSS_KEY(contents, contents)
CSS_KEY(context-fill, context_fill)
CSS_KEY(context-menu, context_menu)
CSS_KEY(context-stroke, context_stroke)
CSS_KEY(contrast, contrast)
CSS_KEY(copy, copy)
CSS_KEY(crosshair, crosshair)
CSS_KEY(dashed, dashed)
@ -95,15 +83,9 @@ CSS_KEY(dot, dot)
CSS_KEY(dotted, dotted)
CSS_KEY(double, double)
CSS_KEY(double-circle, double_circle)
CSS_KEY(drop-shadow, drop_shadow)
CSS_KEY(e-resize, e_resize)
CSS_KEY(ellipse, ellipse)
CSS_KEY(ellipsis, ellipsis)
CSS_KEY(end, end)
CSS_KEY(ew-resize, ew_resize)
CSS_KEY(farthest-side, farthest_side)
CSS_KEY(fill, fill)
CSS_KEY(filled, filled)
CSS_KEY(flex, flex)
CSS_KEY(flex-end, flex_end)
CSS_KEY(flex-start, flex_start)
@ -113,28 +95,17 @@ CSS_KEY(grabbing, grabbing)
CSS_KEY(grayscale, grayscale)
CSS_KEY(grid, grid)
CSS_KEY(help, help)
CSS_KEY(hue-rotate, hue_rotate)
CSS_KEY(infinite, infinite)
CSS_KEY(inline, inline)
CSS_KEY(inline-block, inline_block)
CSS_KEY(inline-flex, inline_flex)
CSS_KEY(inline-grid, inline_grid)
CSS_KEY(inline-table, inline_table)
CSS_KEY(inset, inset)
CSS_KEY(interpolatematrix, interpolatematrix)
CSS_KEY(accumulatematrix, accumulatematrix)
CSS_KEY(invert, invert)
CSS_KEY(justify, justify)
CSS_KEY(last baseline, last_baseline) // only used for DevTools auto-completion
CSS_KEY(layout, layout)
CSS_KEY(left, left)
CSS_KEY(line-through, line_through)
CSS_KEY(list-item, list_item)
CSS_KEY(manipulation, manipulation)
CSS_KEY(matrix, matrix)
CSS_KEY(matrix3d, matrix3d)
CSS_KEY(max-content, max_content)
CSS_KEY(middle, middle)
CSS_KEY(min-content, min_content)
CSS_KEY(move, move)
CSS_KEY(n-resize, n_resize)
@ -147,23 +118,9 @@ CSS_KEY(not-allowed, not_allowed)
CSS_KEY(ns-resize, ns_resize)
CSS_KEY(nw-resize, nw_resize)
CSS_KEY(nwse-resize, nwse_resize)
CSS_KEY(opacity, opacity)
CSS_KEY(open, open)
CSS_KEY(over, over)
CSS_KEY(overline, overline)
CSS_KEY(paint, paint)
CSS_KEY(pan-x, pan_x)
CSS_KEY(pan-y, pan_y)
CSS_KEY(perspective, perspective)
CSS_KEY(pointer, pointer)
CSS_KEY(polygon, polygon)
CSS_KEY(progress, progress)
CSS_KEY(right, right)
CSS_KEY(rotate, rotate)
CSS_KEY(rotate3d, rotate3d)
CSS_KEY(rotatex, rotatex)
CSS_KEY(rotatey, rotatey)
CSS_KEY(rotatez, rotatez)
CSS_KEY(row, row)
CSS_KEY(row-resize, row_resize)
CSS_KEY(ruby, ruby)
@ -172,33 +129,17 @@ CSS_KEY(ruby-base-container, ruby_base_container)
CSS_KEY(ruby-text, ruby_text)
CSS_KEY(ruby-text-container, ruby_text_container)
CSS_KEY(s-resize, s_resize)
CSS_KEY(saturate, saturate)
CSS_KEY(scale, scale)
CSS_KEY(scale3d, scale3d)
CSS_KEY(scalex, scalex)
CSS_KEY(scaley, scaley)
CSS_KEY(scalez, scalez)
CSS_KEY(se-resize, se_resize)
CSS_KEY(self-end, self_end)
CSS_KEY(self-start, self_start)
CSS_KEY(sepia, sepia)
CSS_KEY(sesame, sesame)
CSS_KEY(size, size)
CSS_KEY(skew, skew)
CSS_KEY(skewx, skewx)
CSS_KEY(skewy, skewy)
CSS_KEY(solid, solid)
CSS_KEY(space-around, space_around)
CSS_KEY(space-between, space_between)
CSS_KEY(space-evenly, space_evenly)
CSS_KEY(span, span)
CSS_KEY(start, start)
CSS_KEY(stretch, stretch)
CSS_KEY(strict, strict)
CSS_KEY(style, style)
CSS_KEY(sub, sub)
CSS_KEY(subgrid, subgrid)
CSS_KEY(super, super)
CSS_KEY(sw-resize, sw_resize)
CSS_KEY(table, table)
CSS_KEY(table-caption, table_caption)
@ -210,17 +151,7 @@ CSS_KEY(table-header-group, table_header_group)
CSS_KEY(table-row, table_row)
CSS_KEY(table-row-group, table_row_group)
CSS_KEY(text, text)
CSS_KEY(text-bottom, text_bottom)
CSS_KEY(text-top, text_top)
CSS_KEY(top, top)
CSS_KEY(translate, translate)
CSS_KEY(translate3d, translate3d)
CSS_KEY(translatex, translatex)
CSS_KEY(translatey, translatey)
CSS_KEY(translatez, translatez)
CSS_KEY(triangle, triangle)
CSS_KEY(under, under)
CSS_KEY(underline, underline)
CSS_KEY(vertical-text, vertical_text)
CSS_KEY(w-resize, w_resize)
CSS_KEY(wait, wait)
@ -229,6 +160,5 @@ CSS_KEY(zoom-in, zoom_in)
CSS_KEY(zoom-out, zoom_out)
// Appearance keywords for widget styles
//CSS_KEY(middle, middle)
//CSS_KEY(start, start)

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

@ -172,9 +172,6 @@ const nsCString& nsCSSProps::GetStringValue(nsCSSCounterDesc aCounterDesc) {
/***************************************************************************/
const KTableEntry nsCSSProps::kBoxShadowTypeKTable[] = {
{eCSSKeyword_inset, uint8_t(StyleBoxShadowType::Inset)},
{eCSSKeyword_UNKNOWN, -1}};
const KTableEntry nsCSSProps::kCursorKTable[] = {
// CSS 2.0
@ -271,81 +268,11 @@ KTableEntry nsCSSProps::kDisplayKTable[] = {
{eCSSKeyword_flow_root, StyleDisplay::FlowRoot},
{eCSSKeyword_UNKNOWN, -1}};
// <NOTE> these are only used for auto-completion, not parsing:
const KTableEntry nsCSSProps::kAutoCompletionAlignJustifySelf[] = {
{eCSSKeyword_auto, NS_STYLE_ALIGN_AUTO},
{eCSSKeyword_normal, NS_STYLE_ALIGN_NORMAL},
{eCSSKeyword_stretch, NS_STYLE_ALIGN_STRETCH},
{eCSSKeyword_baseline, NS_STYLE_ALIGN_BASELINE},
{eCSSKeyword_last_baseline, NS_STYLE_ALIGN_LAST_BASELINE},
{eCSSKeyword_start, NS_STYLE_ALIGN_START},
{eCSSKeyword_end, NS_STYLE_ALIGN_END},
{eCSSKeyword_flex_start, NS_STYLE_ALIGN_FLEX_START},
{eCSSKeyword_flex_end, NS_STYLE_ALIGN_FLEX_END},
{eCSSKeyword_center, NS_STYLE_ALIGN_CENTER},
{eCSSKeyword_left, NS_STYLE_ALIGN_LEFT},
{eCSSKeyword_right, NS_STYLE_ALIGN_RIGHT},
{eCSSKeyword_self_start, NS_STYLE_ALIGN_SELF_START},
{eCSSKeyword_self_end, NS_STYLE_ALIGN_SELF_END},
{eCSSKeyword_UNKNOWN, -1}};
const KTableEntry nsCSSProps::kAutoCompletionAlignItems[] = {
// Intentionally no 'auto' here.
{eCSSKeyword_normal, NS_STYLE_ALIGN_NORMAL},
{eCSSKeyword_stretch, NS_STYLE_ALIGN_STRETCH},
{eCSSKeyword_baseline, NS_STYLE_ALIGN_BASELINE},
{eCSSKeyword_last_baseline, NS_STYLE_ALIGN_LAST_BASELINE},
{eCSSKeyword_start, NS_STYLE_ALIGN_START},
{eCSSKeyword_end, NS_STYLE_ALIGN_END},
{eCSSKeyword_flex_start, NS_STYLE_ALIGN_FLEX_START},
{eCSSKeyword_flex_end, NS_STYLE_ALIGN_FLEX_END},
{eCSSKeyword_center, NS_STYLE_ALIGN_CENTER},
{eCSSKeyword_left, NS_STYLE_ALIGN_LEFT},
{eCSSKeyword_right, NS_STYLE_ALIGN_RIGHT},
{eCSSKeyword_self_start, NS_STYLE_ALIGN_SELF_START},
{eCSSKeyword_self_end, NS_STYLE_ALIGN_SELF_END},
{eCSSKeyword_UNKNOWN, -1}};
const KTableEntry nsCSSProps::kAutoCompletionAlignJustifyContent[] = {
// Intentionally no 'auto' here.
{eCSSKeyword_normal, NS_STYLE_ALIGN_NORMAL},
{eCSSKeyword_baseline, NS_STYLE_ALIGN_BASELINE},
{eCSSKeyword_last_baseline, NS_STYLE_ALIGN_LAST_BASELINE},
{eCSSKeyword_stretch, NS_STYLE_ALIGN_STRETCH},
{eCSSKeyword_space_between, NS_STYLE_ALIGN_SPACE_BETWEEN},
{eCSSKeyword_space_around, NS_STYLE_ALIGN_SPACE_AROUND},
{eCSSKeyword_space_evenly, NS_STYLE_ALIGN_SPACE_EVENLY},
{eCSSKeyword_start, NS_STYLE_ALIGN_START},
{eCSSKeyword_end, NS_STYLE_ALIGN_END},
{eCSSKeyword_flex_start, NS_STYLE_ALIGN_FLEX_START},
{eCSSKeyword_flex_end, NS_STYLE_ALIGN_FLEX_END},
{eCSSKeyword_center, NS_STYLE_ALIGN_CENTER},
{eCSSKeyword_left, NS_STYLE_ALIGN_LEFT},
{eCSSKeyword_right, NS_STYLE_ALIGN_RIGHT},
{eCSSKeyword_UNKNOWN, -1}};
// </NOTE>
const KTableEntry nsCSSProps::kFontSmoothingKTable[] = {
{eCSSKeyword_auto, NS_FONT_SMOOTHING_AUTO},
{eCSSKeyword_grayscale, NS_FONT_SMOOTHING_GRAYSCALE},
{eCSSKeyword_UNKNOWN, -1}};
const KTableEntry nsCSSProps::kGridAutoFlowKTable[] = {
{eCSSKeyword_row, NS_STYLE_GRID_AUTO_FLOW_ROW},
{eCSSKeyword_column, NS_STYLE_GRID_AUTO_FLOW_COLUMN},
{eCSSKeyword_dense, NS_STYLE_GRID_AUTO_FLOW_DENSE},
{eCSSKeyword_UNKNOWN, -1}};
const KTableEntry nsCSSProps::kGridTrackBreadthKTable[] = {
{eCSSKeyword_min_content, StyleGridTrackBreadth::MinContent},
{eCSSKeyword_max_content, StyleGridTrackBreadth::MaxContent},
{eCSSKeyword_UNKNOWN, -1}};
const KTableEntry nsCSSProps::kLineHeightKTable[] = {
// -moz- prefixed, intended for internal use for single-line controls
{eCSSKeyword__moz_block_height, NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT},
{eCSSKeyword_UNKNOWN, -1}};
const KTableEntry nsCSSProps::kTextAlignKTable[] = {
{eCSSKeyword_left, NS_STYLE_TEXT_ALIGN_LEFT},
{eCSSKeyword_right, NS_STYLE_TEXT_ALIGN_RIGHT},
@ -367,14 +294,6 @@ const KTableEntry nsCSSProps::kTextDecorationStyleKTable[] = {
{eCSSKeyword_wavy, NS_STYLE_TEXT_DECORATION_STYLE_WAVY},
{eCSSKeyword_UNKNOWN, -1}};
const KTableEntry nsCSSProps::kTextEmphasisStyleShapeKTable[] = {
{eCSSKeyword_dot, NS_STYLE_TEXT_EMPHASIS_STYLE_DOT},
{eCSSKeyword_circle, NS_STYLE_TEXT_EMPHASIS_STYLE_CIRCLE},
{eCSSKeyword_double_circle, NS_STYLE_TEXT_EMPHASIS_STYLE_DOUBLE_CIRCLE},
{eCSSKeyword_triangle, NS_STYLE_TEXT_EMPHASIS_STYLE_TRIANGLE},
{eCSSKeyword_sesame, NS_STYLE_TEXT_EMPHASIS_STYLE_SESAME},
{eCSSKeyword_UNKNOWN, -1}};
int32_t nsCSSProps::FindIndexOfKeyword(nsCSSKeyword aKeyword,
const KTableEntry aTable[]) {
if (eCSSKeyword_UNKNOWN == aKeyword) {

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