Merge autoland to mozilla-central. a=merge

This commit is contained in:
Csoregi Natalia 2019-07-12 01:59:03 +03:00
Родитель b798889d4a 094d27cb39
Коммит 65fc5da4af
68 изменённых файлов: 2656 добавлений и 907 удалений

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

@ -13,6 +13,7 @@ class BrowserTabParent extends JSWindowActorParent {
}
let gBrowser = browser.ownerGlobal.gBrowser;
if (!gBrowser) {
// Note: gBrowser might be null because this message might be received
// from the extension process. There's still an embedderElement involved,
@ -22,6 +23,15 @@ class BrowserTabParent extends JSWindowActorParent {
return;
}
if (!gBrowser.tabpanels || !gBrowser.tabpanels.contains(browser)) {
// Note: This is ignoring browser elements related to extension pages that are not loaded
// as a browser tab (like sidebars, devtools panels and options pages embedded into
// about:addons, browserAction and pageAction popup panels.
// (Ideally we could call gBrowser.getTabForBrowser, but it returns undefined early in
// the tab browser creation and we would ignore browsers related to newly created tabs).
return;
}
switch (message.name) {
case "Browser:WindowCreated": {
gBrowser.announceWindowCreated(browser, message.data.userContextId);

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

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?>
<blocklist lastupdate="1562577903535" xmlns="http://www.mozilla.org/2006/addons-blocklist">
<blocklist lastupdate="1562842544708" xmlns="http://www.mozilla.org/2006/addons-blocklist">
<emItems>
<emItem blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}">
<prefs/>
@ -2716,10 +2716,6 @@
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="9fde5729-9be6-4955-9627-67742c5ed62a" id="sourcegraph-for-firefox@sourcegraph.com">
<prefs/>
<versionRange minVersion="0" maxVersion="19.4.2.1038" severity="1"/>
</emItem>
<emItem blockID="a1c376fe-20c5-4da3-9126-3fe95b874dce" id="/^((\{00b4b65b-79d9-4e92-bc1e-2b926918b91c\})|(\{0cb66591-e935-47e4-95c2-3063786f6555\})|(\{6cf25884-f86d-4a4e-a924-d95282ce5b71\})|(\{22cce9c6-a1de-457f-8938-c981b976b6f4\})|(\{89d99d4c-e7c4-4601-91a8-216e597a826b\})|(\{998d3ac7-b475-410e-ad3d-2eeb526c1853\})|(\{9423e8df-6200-45c0-877a-479c46e91b30\})|(\{64937e0b-6e00-4d5f-bf19-190d6614aae2\})|(\{91507dc4-c005-4534-80af-d8fbdeac29ed\})|(\{a2247e60-7b89-4857-a2fa-0eaee1cad460\})|(\{c9c28751-5865-449f-8e45-b3363edf9fb7\})|(\{cdfd004f-cddc-4ad7-8e2d-a58457e42b1f\})|(\{d3e7f35d-7d9f-4d38-9a2b-1581f6b3e870\})|(\{df574ffe-cce0-42db-857b-627cb164a4d4\})|(\{e06afe6e-ed52-40f8-82bf-d070a37387fb\})|(\{e7e7fb96-cfab-4a5b-85fe-20f621e1bc2e\})|(\{e12e5afd-bd1e-43c6-9288-321dc485cb1c\})|(\{e92d8545-0396-4808-96de-830c61c0d1b3\})|(\{e883b012-1987-4f37-8053-02e59e20c242\})|(\{ed3386c6-76c6-4786-a37b-9816d5f2a260\}))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
@ -3297,6 +3293,18 @@
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="9fde5729-9be6-4955-9627-67742c5ed62a" id="sourcegraph-for-firefox@sourcegraph.com">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="1"/>
</emItem>
<emItem blockID="d38035ff-7945-49cc-88fb-6de9f8a13658" id="/^((langpacasdjasdk-de@firefox\.mozilla\.org)|(langpack-de-7@niklasb)|(langpack-de-8@niklasb)|(langpack-de-9@niklasb)|(langpack-de-10@niklasb)|(langpack-de-nightly-1@firefox\.mozilla\.org))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="9f945be6-12e7-4948-af77-668bc3996ff3" id="/^((\{9aa1f441-7c04-4b00-83b2-6a4362090b41\})|(\{3001d016-bc15-49af-a81b-2c8764139321\})|(\{0af1d242-b004-49ae-91fc-00fa0f642bf9\})|(\{95a5a094-ba8e-4fe1-80bb-6f6c0a01bc2c\})|(\{36b33158-36fc-4728-bf08-8e532100af58\})|(\{5bda1d03-6533-4d8c-adb4-7179402ddeec\})|(\{dc7d18c8-c832-42cd-b9b0-f6a46a737ad1\})|(\{56d85baf-c366-491b-b93c-733a4a36009d\})|(\{1b08c0c7-d2fd-4905-82ab-d4d759af4051\})|(\{1b8a9b33-b3d9-42ea-adce-cec910c44f29\})|(\{0be707e8-d7d6-45d5-8212-3fd3784d7de7\})|(\{fb2e3c38-be42-480f-b60c-d614d372e218\})|(\{c088d705-9f59-40ac-98eb-192f67c44f03\})|(\{9570bbbd-d761-4380-850c-d9cc15200916\})|(\{2652d5a4-26b1-4e6f-9134-304d7b57af7a\})|(\{1e0a2a5f-170c-43c1-b458-c8fc8bdd7dec\})|(\{47595710-e0b3-4a88-9bf7-54e1f3bb6772\})|(\{c25a320e-dc50-486a-9589-13ef22f75a21\})|(\{645237c8-7da2-4298-a789-e11fbaaa580e\})|(\{f2356af6-9b9d-4c69-876a-710d446a9124\})|(\{98a67ccd-599a-4675-9578-35af1824fdd2\})|(\{f3924f49-64a3-4fde-8598-76eec8e67f34\})|(\{2a46402d-b6c4-4a0b-87f0-dc90bb24fa93\})|(\{40d92297-295d-4a44-8a0f-dd69510c9c30\})|(\{a5462b0d-6528-47d5-ada5-4a23d1e0355e\})|(\{280f7325-eaf0-451a-ad2d-3b2c4e80e070\})|(\{ee5a7045-e216-4836-949a-07f5aa1dabc3\})|(\{34ee38f4-e2ba-4e9d-8b1f-dd06e8bd205f\})|(\{7c71c234-ba74-467c-b750-727ee7e38382\})|(\{a83b3b31-4bfc-4343-beab-761f21b97f57\})|(\{b85d35a4-3a03-430d-a1a0-437448a86c22\})|(\{8b6c1e29-5009-477e-a798-244b0efb1515\})|(\{64891348-7fc0-4299-bd6a-6bfaa6cf21a6\})|(\{baa828ff-1723-483b-8034-145ad2795efd\})|(\{81fd4851-7ea3-4ea5-8775-49372fe1c8c8\})|(\{ce7d8e95-c7d3-49dc-8abf-e860ee707b09\})|(\{d84109e8-9945-48bc-90e8-0dd0b1b63b73\})|(\{ec12fd66-7294-4167-8fbc-4774150c0fa4\})|(\{0c506de9-8467-4a92-8cd3-11c87e121db2\})|(\{b1671fe5-c90a-4f68-b8bf-e54a147b5d05\})|(\{8b25277a-4df8-4d2d-b3b4-f8219e2ce7d6\})|(\{5705cd04-46c2-459f-8a9a-97ce57eee1ae\})|(\{8340b371-ed61-4b07-b293-853aa5dbb866\})|(\{87bbb065-e195-48ac-989e-ba48ee63b404\})|(\{c455fc20-6e9d-418c-9b45-75fd85852b32\})|(\{a80c87a7-3366-4192-b9cc-d1e862e1c13d\})|(\{5f4ba05c-c1a5-4bc7-b8d3-c14e807b2c64\})|(\{0114315a-beda-4d55-89a3-e00f6346e7be\})|(\{0fb7b987-721e-4828-9a0e-a72860ded1b2\})|(\{c44cd2a5-bf28-4520-ab2d-187752e51a26\})|(\{3a34c1a6-3cbf-49a0-bfe9-beff60da5ec6\})|(\{677e89a4-ae10-42f3-8e9d-d51be40daf8f\})|(\{85d70eae-fde6-4ac0-ab82-0148f2eb1543\})|(\{fddac013-6d12-41a4-9924-f5ea7618f22d\})|(\{84b5ca75-a431-45c7-995d-6d7268decd0d\})|(\{7374dd37-a901-4b65-993c-3323f87e0f3c\})|(\{157a5c60-7899-4328-a90c-83d34d0844d4\})|(\{5b288e8d-f33c-4602-a945-07f96e43a041\})|(\{80f059bd-602a-42d5-9b17-9f2c6a074102\})|(\{8e5a8075-8e21-4ab2-b189-5d435208122c\})|(\{d5b94c09-0ff8-4b86-b52a-590d5e5ad9af\})|(\{a569eb31-9456-49a9-9aa9-e69a8db159d3\})|(\{0431a147-f9f5-4ee3-8dca-57303110c226\})|(\{88c77421-5ebd-46fb-92a8-e0459b6edd20\})|(\{a4a0697d-9a01-4b21-bb88-5ac949cdb7b3\})|(\{03e0da0a-da1d-46f2-85c7-08258189fc04\})|(\{351f5a4d-a0fd-4ce7-a85a-6cb74fb6c57d\})|(\{0e0b22ea-831e-4104-9c2e-612d7ebf82e2\})|(\{7b5c604f-ea41-4bfa-88d1-843f27645199\})|(\{863f023c-a2e5-4043-8e49-8e3029004b19\})|(\{20e4b367-f8ad-4c9a-b590-976be87206aa\})|(\{436ca3ce-f10a-4cdc-86c2-a46f086b5fdb\})|(\{a53983bc-545e-429a-8aaa-6332e1a6287f\})|(\{5fb1995e-ac7e-4c01-a592-8b262856e039\})|(\{56086da0-b20d-4118-9670-56e85624c875\})|(\{67ef5673-5769-4d5b-902f-ba22cb16a51b\})|(\{1d50e81b-0594-4c24-80c2-abc479be4d18\})|(\{b190f2cf-f3f0-40e7-a05b-8eed296a0c8d\})|(\{490d8bfc-fd42-4ded-9fee-1f009e777468\})|(\{1d647c69-8e4b-4fe8-b0f3-d914a1410ee8\})|(\{4958ae27-1251-49b4-a9d4-2af7c36c833b\})|(\{6e80fdc3-79c7-423a-8e95-0e123c0f2187\})|(\{d8d3230d-5642-4c3f-a64e-5ff690f7a466\})|(\{ddbe5d7a-e037-4749-89bc-3460d358aca1\})|(\{48cd023c-52ef-4fe7-a2ff-101c22c49a5e\})|(\{fef34931-b7ca-49a5-8827-bec353efaa08\})|(\{331a936b-a87e-4271-b9a6-30935dad77ed\})|(\{21084437-803c-49c3-8f84-9a615bfa5dfe\})|(\{93511e9d-badf-4b5c-9fbc-17ef6a9786ae\})|(\{470e388e-a039-43f8-a7a7-d8f54d273feb\})|(\{e4cd5604-caec-4139-9781-94add5f41ba3\})|(\{f00bc2b9-2b69-4f68-8bef-91d498686731\})|(\{7b3206c4-dc98-4ad9-88ba-5a7b3048fd92\})|(\{8e19f5f7-2445-48b1-8910-55d42d9dfe34\})|(\{770e30c6-f1b9-4df4-8551-c7f09ddbd8ed\})|(\{bb9a8679-1f82-4ab7-8ea2-bac864a38542\})|(\{13f5e078-b80a-45fb-a907-c4515a7bb0fa\})|(\{d8df47e3-5e86-4669-9a15-a37f8a8593db\})|(\{ab70d6ee-9d0a-4349-919f-2e3c9aa77927\})|(\{fe94f94a-75ff-48a9-9cab-03e626e30352\})|(\{085590fa-c340-423d-9b45-d8e963349513\})|(\{c06005f4-a53f-4503-b631-9c6fbea45e9e\})|(\{a1904bba-73b5-4fab-8556-95fdf0200c19\})|(\{4548ed4c-964e-4a53-acec-b24f5b9ea6a6\})|(\{99d68c16-4f64-463a-ad09-470a5ac07981\})|(\{14338345-a844-4c6e-9fca-d200a93f1d9b\})|(\{2bc78397-6bd3-4a2f-a737-dbc639ee9940\}))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
</emItems>
<pluginItems>
<pluginItem blockID="p332">

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

@ -1,9 +1,3 @@
:host {
/* these variable values come from about:preferences */
--in-content-dialogtitle-background: #f1f1f1;
--in-content-dialogtitle-border: #c1c1c1;
}
.overlay {
position: fixed;
z-index: 1;
@ -39,9 +33,9 @@
position: relative;
flex: 0 1 auto;
text-align: center;
background-color: var(--in-content-dialogtitle-background);
background-color: var(--in-content-dialog-header-background);
padding: 5px;
border-bottom: 1px solid var(--in-content-dialogtitle-border);
border-bottom: 1px solid var(--in-content-border-color);
}
.title {

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

@ -6,16 +6,12 @@
@namespace html "http://www.w3.org/1999/xhtml";
:root {
--in-content-dialogtitle-background: #f1f1f1;
--in-content-dialogtitle-border: #c1c1c1;
--in-content-warning-container: var(--grey-20);
}
@supports -moz-bool-pref("browser.in-content.dark-mode") {
@media (prefers-color-scheme: dark) {
:root {
--in-content-dialogtitle-background: rgba(249,249,250,0.05);
--in-content-dialogtitle-border: rgba(0,0,0,0.5);
--in-content-warning-container: var(--grey-90-a30);
}
}
@ -526,8 +522,8 @@ button > hbox > label {
.dialogTitleBar {
margin-top: 0;
padding: 3.5px 0;
background-color: var(--in-content-dialogtitle-background);
border-bottom: 1px solid var(--in-content-dialogtitle-border);
background-color: var(--in-content-dialog-header-background);
border-bottom: 1px solid var(--in-content-border-color);
}
.dialogTitle {

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

@ -14,11 +14,12 @@ import fnmatch
import glob
import errno
import re
from contextlib import contextmanager
import sys
import which
from contextlib import contextmanager
from distutils.dir_util import copy_tree
from mozfile import which
def symlink(source, link_name):
os_symlink = getattr(os, "symlink", None)
@ -436,10 +437,10 @@ def get_tool(config, key):
return f
# Assume that we have the name of some program that should be on PATH.
try:
return which.which(f) if f else which.which(key)
except which.WhichError:
raise ValueError("%s not found on PATH" % f)
tool = which(f) if f else which(key)
if not tool:
raise ValueError("%s not found on PATH" % (f or key))
return tool
# This function is intended to be called on the final build directory when

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

@ -8,6 +8,7 @@ mozilla.pth:python/mozversioncontrol
mozilla.pth:python/l10n
mozilla.pth:third_party/python/atomicwrites
mozilla.pth:third_party/python/attrs/src
python2:mozilla.pth:third_party/python/backports
mozilla.pth:third_party/python/biplist
mozilla.pth:third_party/python/blessings
mozilla.pth:third_party/python/Click

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

@ -0,0 +1,7 @@
/* 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/>. */
declare module "devtools-wasm-dwarf" {
declare module.exports: any;
}

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

@ -6,8 +6,6 @@
import { uniq, remove } from "lodash";
import { asyncStore } from "../utils/prefs";
import {
getActiveEventListeners,
getEventListenerExpanded,
@ -17,13 +15,6 @@ import type { ThunkArgs } from "./types";
async function updateBreakpoints(dispatch, client, newEvents: string[]) {
dispatch({ type: "UPDATE_EVENT_LISTENERS", active: newEvents });
const current = await asyncStore.eventListenerBreakpoints;
asyncStore.eventListenerBreakpoints = {
...current,
active: newEvents,
};
await client.setEventListenerBreakpoints(newEvents);
}
@ -32,12 +23,6 @@ async function updateExpanded(dispatch, newExpanded: string[]) {
type: "UPDATE_EVENT_LISTENER_EXPANDED",
expanded: newExpanded,
});
const current = await asyncStore.eventListenerBreakpoints;
asyncStore.eventListenerBreakpoints = {
...current,
expanded: newExpanded,
};
}
export function addEventListenerBreakpoints(eventsToAdd: string[]) {

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

@ -12,11 +12,11 @@ import type {
EventListenerExpandedList,
} from "../actions/types";
export type EventListenersState = {
active: EventListenerActiveList,
categories: EventListenerCategoryList,
expanded: EventListenerExpandedList,
};
export type EventListenersState = {|
+active: EventListenerActiveList,
+categories: EventListenerCategoryList,
+expanded: EventListenerExpandedList,
|};
export function initialEventListenerState(): EventListenersState {
return {
@ -46,19 +46,19 @@ function update(
}
export function getActiveEventListeners(state: State): EventListenerActiveList {
return state.eventListenerBreakpoints.active || [];
return state.eventListenerBreakpoints.active;
}
export function getEventListenerBreakpointTypes(
state: State
): EventListenerCategoryList {
return state.eventListenerBreakpoints.categories || [];
return state.eventListenerBreakpoints.categories;
}
export function getEventListenerExpanded(
state: State
): EventListenerExpandedList {
return state.eventListenerBreakpoints.expanded || [];
return state.eventListenerBreakpoints.expanded;
}
export default update;

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

@ -117,11 +117,14 @@ export function bootstrapApp(store: any) {
let currentPendingBreakpoints;
let currentXHRBreakpoints;
let currentEventBreakpoints;
function updatePrefs(state: any) {
const previousPendingBreakpoints = currentPendingBreakpoints;
const previousXHRBreakpoints = currentXHRBreakpoints;
const previousEventBreakpoints = currentEventBreakpoints;
currentPendingBreakpoints = selectors.getPendingBreakpoints(state);
currentXHRBreakpoints = selectors.getXHRBreakpoints(state);
currentEventBreakpoints = state.eventListenerBreakpoints;
if (
previousPendingBreakpoints &&
@ -130,6 +133,13 @@ function updatePrefs(state: any) {
asyncStore.pendingBreakpoints = currentPendingBreakpoints;
}
if (
previousEventBreakpoints &&
previousEventBreakpoints !== currentEventBreakpoints
) {
asyncStore.eventListenerBreakpoints = currentEventBreakpoints;
}
if (currentXHRBreakpoints !== previousXHRBreakpoints) {
asyncStore.xhrBreakpoints = currentXHRBreakpoints;
}

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

@ -12,7 +12,7 @@ import { asyncStoreHelper } from "./asyncStoreHelper";
// Schema version to bump when the async store format has changed incompatibly
// and old stores should be cleared. This needs to match the prefs schema
// version in devtools/client/preferences/debugger.js.
const prefsSchemaVersion = "1.0.10";
const prefsSchemaVersion = "1.0.11";
const pref = Services.pref;
if (isDevelopment()) {

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

@ -20,7 +20,7 @@ pref("devtools.debugger.workers", false);
// The default Debugger UI settings
// This schema version needs to match that in devtools/client/debugger/src/utils/prefs.js.
pref("devtools.debugger.prefs-schema-version", "1.0.10");
pref("devtools.debugger.prefs-schema-version", "1.0.11");
pref("devtools.debugger.ui.panes-workers-and-sources-width", 200);
pref("devtools.debugger.ui.panes-instruments-width", 300);
pref("devtools.debugger.ui.panes-visible-on-startup", false);

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

@ -554,6 +554,8 @@ MediaCacheStream::MediaCacheStream(ChannelMediaResource* aClient,
mIsPrivateBrowsing(aIsPrivateBrowsing) {}
size_t MediaCacheStream::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
AutoLock lock(mMediaCache->Monitor());
// Looks like these are not owned:
// - mClient
size_t size = mBlocks.ShallowSizeOfExcludingThis(aMallocSizeOf);

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

@ -1439,11 +1439,7 @@ bool RuntimeService::ScheduleWorker(WorkerPrivate* aWorkerPrivate) {
}
}
int32_t priority = aWorkerPrivate->IsChromeWorker()
? nsISupportsPriority::PRIORITY_NORMAL
: nsISupportsPriority::PRIORITY_LOW;
if (NS_FAILED(thread->SetPriority(priority))) {
if (NS_FAILED(thread->SetPriority(nsISupportsPriority::PRIORITY_NORMAL))) {
NS_WARNING("Could not set the thread's priority!");
}

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

@ -38,6 +38,7 @@
#include "mozilla/ipc/BrowserProcessSubThread.h"
#include "mozilla/ipc/EnvironmentMap.h"
#include "mozilla/LinkedList.h"
#include "mozilla/Maybe.h"
#include "mozilla/Omnijar.h"
#include "mozilla/RecordReplay.h"
#include "mozilla/RDDProcessHost.h"
@ -84,11 +85,6 @@
using mozilla::MonitorAutoLock;
using mozilla::Preferences;
using mozilla::StaticMutexAutoLock;
using mozilla::ipc::GeckoChildProcessHost;
using mozilla::ipc::LaunchError;
using mozilla::ipc::LaunchResults;
using mozilla::ipc::ProcessHandlePromise;
using mozilla::ipc::ProcessLaunchPromise;
namespace mozilla {
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPRFileDesc, PRFileDesc,
@ -111,10 +107,12 @@ static bool ShouldHaveDirectoryService() {
namespace mozilla {
namespace ipc {
class ProcessLauncher {
static Atomic<int32_t> gChildCounter;
class BaseProcessLauncher {
public:
ProcessLauncher(GeckoChildProcessHost* aHost,
std::vector<std::string>&& aExtraOpts)
BaseProcessLauncher(GeckoChildProcessHost* aHost,
std::vector<std::string>&& aExtraOpts)
: mProcessType(aHost->mProcessType),
mLaunchOptions(std::move(aHost->mLaunchOptions)),
mExtraOpts(std::move(aExtraOpts)),
@ -127,26 +125,36 @@ class ProcessLauncher {
mIsFileContent(aHost->mIsFileContent),
mEnableSandboxLogging(aHost->mEnableSandboxLogging),
#endif
mTmpDirName(aHost->mTmpDirName) {
mTmpDirName(aHost->mTmpDirName),
mChildId(++gChildCounter) {
SprintfLiteral(mPidString, "%d", base::GetCurrentProcId());
}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ProcessLauncher);
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BaseProcessLauncher);
RefPtr<ProcessLaunchPromise> Launch(GeckoChildProcessHost*);
private:
~ProcessLauncher() {}
protected:
virtual ~BaseProcessLauncher() = default;
RefPtr<ProcessLaunchPromise> PerformAsyncLaunch();
RefPtr<ProcessLaunchPromise> FinishLaunch();
// Overrideable hooks. If superclass behavior is invoked, it's always at the
// top of the override.
virtual bool DoSetup();
virtual bool DoLaunch() = 0;
virtual bool DoFinishLaunch() { return true; };
void MapChildLogging();
static BinPathType GetPathToBinary(FilePath&, GeckoProcessType);
#if defined(MOZ_WIDGET_ANDROID)
void LaunchAndroidService(
const char* type, const std::vector<std::string>& argv,
const base::file_handle_mapping_vector& fds_to_remap,
base::ProcessHandle* process_handle);
#endif // defined(MOZ_WIDGET_ANDROID)
void GetChildLogName(const char* origLogName, nsACString& buffer);
const char* ChildProcessType() {
return XRE_ChildProcessTypeToString(mProcessType);
}
GeckoProcessType mProcessType;
UniquePtr<base::LaunchOptions> mLaunchOptions;
@ -161,15 +169,112 @@ class ProcessLauncher {
bool mEnableSandboxLogging;
#endif
nsCString mTmpDirName;
LaunchResults mResults = LaunchResults();
int32_t mChildId;
TimeStamp mStartTimeStamp = TimeStamp::Now();
char mPidString[32];
// Set during launch.
IPC::Channel* mChannel;
IPC::Channel* mChannel = nullptr;
std::wstring mChannelId;
ScopedPRFileDesc mCrashAnnotationReadPipe;
ScopedPRFileDesc mCrashAnnotationWritePipe;
};
} // namespace ipc
} // namespace mozilla
#ifdef XP_WIN
class WindowsProcessLauncher : public BaseProcessLauncher {
public:
WindowsProcessLauncher(GeckoChildProcessHost* aHost,
std::vector<std::string>&& aExtraOpts)
: BaseProcessLauncher(aHost, std::move(aExtraOpts)) {}
protected:
virtual bool DoSetup() override;
virtual bool DoLaunch() override;
virtual bool DoFinishLaunch() override;
mozilla::Maybe<CommandLine> mCmdLine;
bool mUseSandbox = false;
};
typedef WindowsProcessLauncher ProcessLauncher;
#endif // XP_WIN
#ifdef OS_POSIX
class PosixProcessLauncher : public BaseProcessLauncher {
public:
PosixProcessLauncher(GeckoChildProcessHost* aHost,
std::vector<std::string>&& aExtraOpts)
: BaseProcessLauncher(aHost, std::move(aExtraOpts)) {}
protected:
virtual bool DoSetup() override;
virtual bool DoLaunch() override;
virtual bool DoFinishLaunch() override;
std::vector<std::string> mChildArgv;
};
# if defined(XP_MACOSX)
class MacProcessLauncher : public PosixProcessLauncher {
public:
MacProcessLauncher(GeckoChildProcessHost* aHost,
std::vector<std::string>&& aExtraOpts)
: PosixProcessLauncher(aHost, std::move(aExtraOpts)),
// Put a random number into the channel name, so that
// a compromised renderer can't pretend being the child
// that's forked off.
mMachConnectionName(
StringPrintf("org.mozilla.machname.%d",
base::RandInt(0, std::numeric_limits<int>::max()))),
mParentRecvPort(mMachConnectionName.c_str()) {}
protected:
virtual bool DoFinishLaunch() override;
std::string mMachConnectionName;
// We add a mach port to the command line so the child can communicate its
// 'task_t' back to the parent.
ReceivePort mParentRecvPort;
friend class PosixProcessLauncher;
};
typedef MacProcessLauncher ProcessLauncher;
# elif defined(MOZ_WIDGET_ANDROID)
class AndroidProcessLauncher : public PosixProcessLauncher {
public:
AndroidProcessLauncher(GeckoChildProcessHost* aHost,
std::vector<std::string>&& aExtraOpts)
: PosixProcessLauncher(aHost, std::move(aExtraOpts)) {}
protected:
virtual bool DoLaunch() override;
void LaunchAndroidService(
const char* type, const std::vector<std::string>& argv,
const base::file_handle_mapping_vector& fds_to_remap,
base::ProcessHandle* process_handle);
};
typedef AndroidProcessLauncher ProcessLauncher;
// NB: Technically Android is linux (i.e. XP_LINUX is defined), but we want
// orthogonal IPC machinery there. Conversely, there are tier-3 non-Linux
// platforms (BSD and Solaris) where we want the "linux" IPC machinery. So
// we use MOZ_WIDGET_* to choose the platform backend.
# elif defined(MOZ_WIDGET_GTK)
class LinuxProcessLauncher : public PosixProcessLauncher {
public:
LinuxProcessLauncher(GeckoChildProcessHost* aHost,
std::vector<std::string>&& aExtraOpts)
: PosixProcessLauncher(aHost, std::move(aExtraOpts)) {}
protected:
virtual bool DoSetup() override;
};
typedef LinuxProcessLauncher ProcessLauncher;
# elif
# error "Unknown platform"
# endif
#endif // OS_POSIX
using mozilla::ipc::BaseProcessLauncher;
using mozilla::ipc::ProcessLauncher;
mozilla::StaticAutoPtr<mozilla::LinkedList<GeckoChildProcessHost>>
@ -275,7 +380,7 @@ void GeckoChildProcessHost::Destroy() {
}
// static
mozilla::BinPathType ProcessLauncher::GetPathToBinary(
mozilla::BinPathType BaseProcessLauncher::GetPathToBinary(
FilePath& exePath, GeckoProcessType processType) {
BinPathType pathType = XRE_GetChildProcBinPathType(processType);
@ -471,7 +576,7 @@ bool GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts) {
}
#endif
RefPtr<ProcessLauncher> launcher =
RefPtr<BaseProcessLauncher> launcher =
new ProcessLauncher(this, std::move(aExtraOpts));
// Note: Destroy() waits on mHandlePromise to delete |this|. As such, we want
@ -483,7 +588,7 @@ bool GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts) {
mHandlePromise = p;
mozilla::InvokeAsync<GeckoChildProcessHost*>(
IOThread(), launcher.get(), __func__, &ProcessLauncher::Launch, this)
IOThread(), launcher.get(), __func__, &BaseProcessLauncher::Launch, this)
->Then(
IOThread(), __func__,
[this, p](const LaunchResults aResults) {
@ -619,9 +724,8 @@ void GeckoChildProcessHost::SetAlreadyDead() {
mChildProcessHandle = 0;
}
static int32_t gChildCounter = 0;
static void GetChildLogName(const char* origLogName, nsACString& buffer) {
void BaseProcessLauncher::GetChildLogName(const char* origLogName,
nsACString& buffer) {
#ifdef XP_WIN
// On Windows we must expand relative paths because sandboxing rules
// bound only to full paths. fopen fowards to NtCreateFile which checks
@ -793,21 +897,33 @@ static bool Contains(const std::vector<std::string>& aExtraOpts,
}
#endif // defined(XP_WIN) && (defined(MOZ_SANDBOX) || defined(_ARM64_))
RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
if (!DoSetup()) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
}
if (!DoLaunch()) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
}
return FinishLaunch();
}
bool BaseProcessLauncher::DoSetup() {
#ifdef MOZ_GECKO_PROFILER
RefPtr<ProcessLauncher> self = this;
RefPtr<BaseProcessLauncher> self = this;
GetProfilerEnvVarsForChildProcess([self](const char* key, const char* value) {
self->mLaunchOptions->env_map[ENVIRONMENT_STRING(key)] =
ENVIRONMENT_STRING(value);
});
#endif
const auto startTS = TimeStamp::Now();
MapChildLogging();
// - Note: this code is not called re-entrantly, nor are restoreOrig*LogName
// or gChildCounter touched by any other thread, so this is safe.
++gChildCounter;
return PR_CreatePipe(&mCrashAnnotationReadPipe.rwget(),
&mCrashAnnotationWritePipe.rwget()) == PR_SUCCESS;
}
void BaseProcessLauncher::MapChildLogging() {
const char* origNSPRLogName = PR_GetEnv("NSPR_LOG_FILE");
const char* origMozLogName = PR_GetEnv("MOZ_LOG_FILE");
@ -830,47 +946,14 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
mLaunchOptions->env_map[ENVIRONMENT_LITERAL("RUST_LOG")] =
ENVIRONMENT_STRING(childRustLog.get());
}
}
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
if (!mTmpDirName.IsEmpty()) {
// Point a bunch of things that might want to write from content to our
// shiny new content-process specific tmpdir
mLaunchOptions->env_map[ENVIRONMENT_LITERAL("TMPDIR")] =
ENVIRONMENT_STRING(mTmpDirName.get());
// Partial fix for bug 1380051 (not persistent - should be)
mLaunchOptions->env_map[ENVIRONMENT_LITERAL("MESA_GLSL_CACHE_DIR")] =
ENVIRONMENT_STRING(mTmpDirName.get());
}
#endif
LaunchResults results = LaunchResults();
results.mHandle = 0;
// send the child the PID so that it can open a ProcessHandle back to us.
// probably don't want to do this in the long run
char pidstring[32];
SprintfLiteral(pidstring, "%d", base::GetCurrentProcId());
const char* const childProcessType =
XRE_ChildProcessTypeToString(mProcessType);
ScopedPRFileDesc crashAnnotationReadPipe;
ScopedPRFileDesc crashAnnotationWritePipe;
if (PR_CreatePipe(&crashAnnotationReadPipe.rwget(),
&crashAnnotationWritePipe.rwget()) != PR_SUCCESS) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
#if defined(MOZ_WIDGET_GTK)
bool LinuxProcessLauncher::DoSetup() {
if (!PosixProcessLauncher::DoSetup()) {
return false;
}
//--------------------------------------------------
#if defined(OS_POSIX)
// For POSIX, we have to be extremely anal about *not* using
// std::wstring in code compiled with Mozilla's -fshort-wchar
// configuration, because chromium is compiled with -fno-short-wchar
// and passing wstrings from one config to the other is unsafe. So
// we split the logic here.
# if defined(OS_POSIX)
# if defined(MOZ_WIDGET_GTK)
if (mProcessType == GeckoProcessType_Content) {
// disable IM module to avoid sandbox violation
mLaunchOptions->env_map["GTK_IM_MODULE"] = "gtk-im-context-simple";
@ -880,7 +963,28 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
// anyway.
mLaunchOptions->env_map["NO_AT_BRIDGE"] = "1";
}
# endif // defined(MOZ_WIDGET_GTK)
# ifdef MOZ_SANDBOX
if (!mTmpDirName.IsEmpty()) {
// Point a bunch of things that might want to write from content to our
// shiny new content-process specific tmpdir
mLaunchOptions->env_map[ENVIRONMENT_LITERAL("TMPDIR")] =
ENVIRONMENT_STRING(mTmpDirName.get());
// Partial fix for bug 1380051 (not persistent - should be)
mLaunchOptions->env_map[ENVIRONMENT_LITERAL("MESA_GLSL_CACHE_DIR")] =
ENVIRONMENT_STRING(mTmpDirName.get());
}
# endif // MOZ_SANDBOX
return true;
}
#endif // MOZ_WIDGET_GTK
#ifdef OS_POSIX
bool PosixProcessLauncher::DoSetup() {
if (!BaseProcessLauncher::DoSetup()) {
return false;
}
// XPCOM may not be initialized in some subprocesses. We don't want
// to initialize XPCOM just for the directory service, especially
@ -890,23 +994,23 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
MOZ_ASSERT(gGREBinPath);
nsCString path;
NS_CopyUnicodeToNative(nsDependentString(gGREBinPath), path);
# if defined(OS_LINUX) || defined(OS_BSD)
# if defined(OS_LINUX) || defined(OS_BSD)
const char* ld_library_path = PR_GetEnv("LD_LIBRARY_PATH");
nsCString new_ld_lib_path(path.get());
# ifdef MOZ_WIDGET_GTK
# ifdef MOZ_WIDGET_GTK
if (mProcessType == GeckoProcessType_Plugin) {
new_ld_lib_path.AppendLiteral("/gtk2:");
new_ld_lib_path.Append(path.get());
}
# endif // MOZ_WIDGET_GTK
# endif // MOZ_WIDGET_GTK
if (ld_library_path && *ld_library_path) {
new_ld_lib_path.Append(':');
new_ld_lib_path.Append(ld_library_path);
}
mLaunchOptions->env_map["LD_LIBRARY_PATH"] = new_ld_lib_path.get();
# elif OS_MACOSX // defined(OS_LINUX) || defined(OS_BSD)
# elif OS_MACOSX // defined(OS_LINUX) || defined(OS_BSD)
mLaunchOptions->env_map["DYLD_LIBRARY_PATH"] = path.get();
// XXX DYLD_INSERT_LIBRARIES should only be set when launching a plugin
// process, and has no effect on other subprocesses (the hooks in
@ -927,9 +1031,8 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
interpose.Append(path.get());
interpose.AppendLiteral("/libplugin_child_interpose.dylib");
mLaunchOptions->env_map["DYLD_INSERT_LIBRARIES"] = interpose.get();
# endif // defined(OS_LINUX) || defined(OS_BSD)
# endif // defined(OS_LINUX) || defined(OS_BSD)
}
# endif // defined(OS_POSIX)
FilePath exePath;
BinPathType pathType = GetPathToBinary(exePath, mProcessType);
@ -944,15 +1047,13 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
// no need for kProcessChannelID, the child process inherits the
// other end of the socketpair() from us
std::vector<std::string> childArgv;
childArgv.push_back(exePath.value());
mChildArgv.push_back(exePath.value());
if (pathType == BinPathType::Self) {
childArgv.push_back("-contentproc");
mChildArgv.push_back("-contentproc");
}
childArgv.insert(childArgv.end(), mExtraOpts.begin(), mExtraOpts.end());
mChildArgv.insert(mChildArgv.end(), mExtraOpts.begin(), mExtraOpts.end());
if (mProcessType != GeckoProcessType_GMPlugin) {
if (Omnijar::IsInitialized()) {
@ -961,108 +1062,110 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
nsAutoCString path;
nsCOMPtr<nsIFile> file = Omnijar::GetPath(Omnijar::GRE);
if (file && NS_SUCCEEDED(file->GetNativePath(path))) {
childArgv.push_back("-greomni");
childArgv.push_back(path.get());
mChildArgv.push_back("-greomni");
mChildArgv.push_back(path.get());
}
file = Omnijar::GetPath(Omnijar::APP);
if (file && NS_SUCCEEDED(file->GetNativePath(path))) {
childArgv.push_back("-appomni");
childArgv.push_back(path.get());
mChildArgv.push_back("-appomni");
mChildArgv.push_back(path.get());
}
}
// Add the application directory path (-appdir path)
AddAppDirToCommandLine(childArgv);
AddAppDirToCommandLine(mChildArgv);
}
childArgv.push_back(pidstring);
mChildArgv.push_back(mPidString);
if (!CrashReporter::IsDummy()) {
# if defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
int childCrashFd, childCrashRemapFd;
if (!CrashReporter::CreateNotificationPipeForChild(&childCrashFd,
&childCrashRemapFd)) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
return false;
}
if (0 <= childCrashFd) {
mLaunchOptions->fds_to_remap.push_back(
std::pair<int, int>(childCrashFd, childCrashRemapFd));
// "true" == crash reporting enabled
childArgv.push_back("true");
mChildArgv.push_back("true");
} else {
// "false" == crash reporting disabled
childArgv.push_back("false");
mChildArgv.push_back("false");
}
# elif defined(MOZ_WIDGET_COCOA) /* defined(OS_LINUX) || defined(OS_BSD) || \
defined(OS_SOLARIS) */
childArgv.push_back(CrashReporter::GetChildNotificationPipe());
mChildArgv.push_back(CrashReporter::GetChildNotificationPipe());
# endif // defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
}
int fd = PR_FileDesc2NativeHandle(crashAnnotationWritePipe);
int fd = PR_FileDesc2NativeHandle(mCrashAnnotationWritePipe);
mLaunchOptions->fds_to_remap.push_back(
std::make_pair(fd, CrashReporter::GetAnnotationTimeCrashFd()));
# ifdef MOZ_WIDGET_COCOA
// Add a mach port to the command line so the child can communicate its
// 'task_t' back to the parent.
//
// Put a random number into the channel name, so that a compromised renderer
// can't pretend being the child that's forked off.
std::string mach_connection_name =
StringPrintf("org.mozilla.machname.%d",
base::RandInt(0, std::numeric_limits<int>::max()));
childArgv.push_back(mach_connection_name.c_str());
mChildArgv.push_back(
static_cast<MacProcessLauncher*>(this)->mMachConnectionName.c_str());
# endif // MOZ_WIDGET_COCOA
childArgv.push_back(childProcessType);
mChildArgv.push_back(ChildProcessType());
# ifdef MOZ_WIDGET_COCOA
// Register the listening port before launching the child, to ensure
// that it's there when the child tries to look it up.
ReceivePort parent_recv_port(mach_connection_name.c_str());
# endif // MOZ_WIDGET_COCOA
return true;
}
#endif // OS_POSIX
# if defined(MOZ_WIDGET_ANDROID)
LaunchAndroidService(childProcessType, childArgv,
mLaunchOptions->fds_to_remap, &results.mHandle);
if (results.mHandle == 0) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
#if defined(MOZ_WIDGET_ANDROID)
bool AndroidProcessLauncher::DoLaunch() {
LaunchAndroidService(ChildProcessType(), mChildArgv,
mLaunchOptions->fds_to_remap, &mResults.mHandle);
return mResults.mHandle != 0;
}
#endif // MOZ_WIDGET_ANDROID
#ifdef OS_POSIX
bool PosixProcessLauncher::DoLaunch() {
return base::LaunchApp(mChildArgv, *mLaunchOptions, &mResults.mHandle);
}
bool PosixProcessLauncher::DoFinishLaunch() {
if (!BaseProcessLauncher::DoFinishLaunch()) {
return false;
}
# else // goes with defined(MOZ_WIDGET_ANDROID)
if (!base::LaunchApp(childArgv, *mLaunchOptions, &results.mHandle)) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
}
# endif // defined(MOZ_WIDGET_ANDROID)
// We're in the parent and the child was launched. Close the child FD in the
// parent as soon as possible, which will allow the parent to detect when the
// child closes its FD (either due to normal exit or due to crash).
mChannel->CloseClientFileDescriptor();
# ifdef MOZ_WIDGET_COCOA
return true;
}
#endif // OS_POSIX
#ifdef XP_MACOSX
bool MacProcessLauncher::DoFinishLaunch() {
// Wait for the child process to send us its 'task_t' data.
const int kTimeoutMs = 10000;
MachReceiveMessage child_message;
kern_return_t err =
parent_recv_port.WaitForMessage(&child_message, kTimeoutMs);
mParentRecvPort.WaitForMessage(&child_message, kTimeoutMs);
if (err != KERN_SUCCESS) {
std::string errString =
StringPrintf("0x%x %s", err, mach_error_string(err));
CHROMIUM_LOG(ERROR) << "parent WaitForMessage() failed: " << errString;
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
return false;
}
task_t child_task = child_message.GetTranslatedPort(0);
if (child_task == MACH_PORT_NULL) {
CHROMIUM_LOG(ERROR) << "parent GetTranslatedPort(0) failed.";
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
return false;
}
if (child_message.GetTranslatedPort(1) == MACH_PORT_NULL) {
CHROMIUM_LOG(ERROR) << "parent GetTranslatedPort(1) failed.";
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
return false;
}
MachPortSender parent_sender(child_message.GetTranslatedPort(1));
@ -1082,7 +1185,7 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
if (!parent_message.AddDescriptor(MachMsgPortDescriptor(bootstrap_port))) {
CHROMIUM_LOG(ERROR) << "parent AddDescriptor(" << bootstrap_port
<< ") failed.";
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
return false;
}
auto* parent_recv_port_memory = new ReceivePort();
@ -1090,7 +1193,7 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
MachMsgPortDescriptor(parent_recv_port_memory->GetPort()))) {
CHROMIUM_LOG(ERROR) << "parent AddDescriptor("
<< parent_recv_port_memory->GetPort() << ") failed.";
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
return false;
}
auto* parent_send_port_memory_ack = new ReceivePort();
@ -1099,7 +1202,7 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
CHROMIUM_LOG(ERROR) << "parent AddDescriptor("
<< parent_send_port_memory_ack->GetPort()
<< ") failed.";
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
return false;
}
err = parent_sender.SendMessage(parent_message, kTimeoutMs);
@ -1107,17 +1210,27 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
std::string errString =
StringPrintf("0x%x %s", err, mach_error_string(err));
CHROMIUM_LOG(ERROR) << "parent SendMessage() failed: " << errString;
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
return false;
}
SharedMemoryBasic::SetupMachMemory(
results.mHandle, parent_recv_port_memory, parent_recv_port_memory_ack,
mResults.mHandle, parent_recv_port_memory, parent_recv_port_memory_ack,
parent_send_port_memory, parent_send_port_memory_ack, false);
# endif // MOZ_WIDGET_COCOA
// NB: on OS X, we block much longer than we need to in order to
// reach this call, waiting for the child process's task_t. The
// best way to fix that is to refactor this file, hard.
mResults.mChildTask = child_task;
//--------------------------------------------------
#elif defined(OS_WIN) // defined(OS_POSIX)
return true;
}
#endif // XP_MACOSX
#ifdef XP_WIN
bool WindowsProcessLauncher::DoSetup() {
if (!BaseProcessLauncher::DoSetup()) {
return false;
}
FilePath exePath;
BinPathType pathType = GetPathToBinary(exePath, mProcessType);
@ -1139,17 +1252,17 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
# endif // if defined(_ARM64_)
# endif // defined(MOZ_SANDBOX) || defined(_ARM64_)
CommandLine cmdLine(exePath.ToWStringHack());
mCmdLine.emplace(exePath.ToWStringHack());
if (pathType == BinPathType::Self) {
cmdLine.AppendLooseValue(UTF8ToWide("-contentproc"));
mCmdLine->AppendLooseValue(UTF8ToWide("-contentproc"));
}
cmdLine.AppendSwitchWithValue(switches::kProcessChannelID, mChannelId);
mCmdLine->AppendSwitchWithValue(switches::kProcessChannelID, mChannelId);
for (std::vector<std::string>::iterator it = mExtraOpts.begin();
it != mExtraOpts.end(); ++it) {
cmdLine.AppendLooseValue(UTF8ToWide(*it));
mCmdLine->AppendLooseValue(UTF8ToWide(*it));
}
if (Omnijar::IsInitialized()) {
@ -1158,25 +1271,23 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
nsAutoString path;
nsCOMPtr<nsIFile> file = Omnijar::GetPath(Omnijar::GRE);
if (file && NS_SUCCEEDED(file->GetPath(path))) {
cmdLine.AppendLooseValue(UTF8ToWide("-greomni"));
cmdLine.AppendLooseValue(path.get());
mCmdLine->AppendLooseValue(UTF8ToWide("-greomni"));
mCmdLine->AppendLooseValue(path.get());
}
file = Omnijar::GetPath(Omnijar::APP);
if (file && NS_SUCCEEDED(file->GetPath(path))) {
cmdLine.AppendLooseValue(UTF8ToWide("-appomni"));
cmdLine.AppendLooseValue(path.get());
mCmdLine->AppendLooseValue(UTF8ToWide("-appomni"));
mCmdLine->AppendLooseValue(path.get());
}
}
# if defined(MOZ_SANDBOX)
# if defined(_ARM64_)
if (isClearKey || isWidevine)
results.mSandboxBroker = new RemoteSandboxBroker();
mResults.mSandboxBroker = new RemoteSandboxBroker();
else
# endif // if defined(_ARM64_)
results.mSandboxBroker = new SandboxBroker();
bool shouldSandboxCurrentProcess = false;
mResults.mSandboxBroker = new SandboxBroker();
// XXX: Bug 1124167: We should get rid of the process specific logic for
// sandboxing in this class at some point. Unfortunately it will take a bit
@ -1188,19 +1299,18 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
// SetSecurityLevelForContentProcess and just crash there right away.
// Should this change in the future then we should also handle the error
// here.
results.mSandboxBroker->SetSecurityLevelForContentProcess(
mResults.mSandboxBroker->SetSecurityLevelForContentProcess(
mSandboxLevel, mIsFileContent);
shouldSandboxCurrentProcess = true;
mUseSandbox = true;
}
break;
case GeckoProcessType_Plugin:
if (mSandboxLevel > 0 && !PR_GetEnv("MOZ_DISABLE_NPAPI_SANDBOX")) {
bool ok = results.mSandboxBroker->SetSecurityLevelForPluginProcess(
mSandboxLevel);
if (!ok) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
if (!mResults.mSandboxBroker->SetSecurityLevelForPluginProcess(
mSandboxLevel)) {
return false;
}
shouldSandboxCurrentProcess = true;
mUseSandbox = true;
}
break;
case GeckoProcessType_IPDLUnitTest:
@ -1214,11 +1324,10 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
// so use sandbox level USER_RESTRICTED instead of USER_LOCKDOWN.
auto level =
isWidevine ? SandboxBroker::Restricted : SandboxBroker::LockDown;
bool ok = results.mSandboxBroker->SetSecurityLevelForGMPlugin(level);
if (!ok) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
if (!mResults.mSandboxBroker->SetSecurityLevelForGMPlugin(level)) {
return false;
}
shouldSandboxCurrentProcess = true;
mUseSandbox = true;
}
break;
case GeckoProcessType_GPU:
@ -1226,8 +1335,8 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
// For now we treat every failure as fatal in
// SetSecurityLevelForGPUProcess and just crash there right away. Should
// this change in the future then we should also handle the error here.
results.mSandboxBroker->SetSecurityLevelForGPUProcess(mSandboxLevel);
shouldSandboxCurrentProcess = true;
mResults.mSandboxBroker->SetSecurityLevelForGPUProcess(mSandboxLevel);
mUseSandbox = true;
}
break;
case GeckoProcessType_VR:
@ -1237,10 +1346,10 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
break;
case GeckoProcessType_RDD:
if (!PR_GetEnv("MOZ_DISABLE_RDD_SANDBOX")) {
if (!results.mSandboxBroker->SetSecurityLevelForRDDProcess()) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
if (!mResults.mSandboxBroker->SetSecurityLevelForRDDProcess()) {
return false;
}
shouldSandboxCurrentProcess = true;
mUseSandbox = true;
}
break;
case GeckoProcessType_Socket:
@ -1255,102 +1364,113 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::PerformAsyncLaunch() {
break;
};
if (shouldSandboxCurrentProcess) {
if (mUseSandbox) {
for (auto it = mAllowedFilesRead.begin(); it != mAllowedFilesRead.end();
++it) {
results.mSandboxBroker->AllowReadFile(it->c_str());
mResults.mSandboxBroker->AllowReadFile(it->c_str());
}
}
# endif // defined(MOZ_SANDBOX)
# endif // defined(MOZ_SANDBOX)
// Add the application directory path (-appdir path)
AddAppDirToCommandLine(cmdLine);
AddAppDirToCommandLine(mCmdLine.ref());
// XXX Command line params past this point are expected to be at
// the end of the command line string, and in a specific order.
// See XRE_InitChildProcess in nsEmbedFunction.
// Win app model id
cmdLine.AppendLooseValue(mGroupId.get());
mCmdLine->AppendLooseValue(mGroupId.get());
// Process id
cmdLine.AppendLooseValue(UTF8ToWide(pidstring));
mCmdLine->AppendLooseValue(UTF8ToWide(mPidString));
cmdLine.AppendLooseValue(
mCmdLine->AppendLooseValue(
UTF8ToWide(CrashReporter::GetChildNotificationPipe()));
if (!CrashReporter::IsDummy()) {
PROsfd h = PR_FileDesc2NativeHandle(crashAnnotationWritePipe);
PROsfd h = PR_FileDesc2NativeHandle(mCrashAnnotationWritePipe);
mLaunchOptions->handles_to_inherit.push_back(reinterpret_cast<HANDLE>(h));
std::string hStr = std::to_string(h);
cmdLine.AppendLooseValue(UTF8ToWide(hStr));
mCmdLine->AppendLooseValue(UTF8ToWide(hStr));
}
// Process type
cmdLine.AppendLooseValue(UTF8ToWide(childProcessType));
# if defined(MOZ_SANDBOX)
if (shouldSandboxCurrentProcess) {
// Mark the handles to inherit as inheritable.
for (HANDLE h : mLaunchOptions->handles_to_inherit) {
results.mSandboxBroker->AddHandleToShare(h);
}
if (results.mSandboxBroker->LaunchApp(
cmdLine.program().c_str(), cmdLine.command_line_string().c_str(),
mLaunchOptions->env_map, mProcessType, mEnableSandboxLogging,
&results.mHandle)) {
EnvironmentLog("MOZ_PROCESS_LOG")
.print("==> process %d launched child process %d (%S)\n",
base::GetCurrentProcId(), base::GetProcId(results.mHandle),
cmdLine.command_line_string().c_str());
} else {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
}
} else
# endif // defined(MOZ_SANDBOX)
{
if (!base::LaunchApp(cmdLine, *mLaunchOptions, &results.mHandle)) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
}
mCmdLine->AppendLooseValue(UTF8ToWide(ChildProcessType()));
# ifdef MOZ_SANDBOX
// We need to be able to duplicate handles to some types of non-sandboxed
// child processes.
switch (mProcessType) {
case GeckoProcessType_Default:
MOZ_CRASH("shouldn't be launching a parent process");
case GeckoProcessType_Plugin:
case GeckoProcessType_IPDLUnitTest:
// No handle duplication necessary.
break;
default:
if (!SandboxBroker::AddTargetPeer(results.mHandle)) {
NS_WARNING("Failed to add child process as target peer.");
}
break;
if (mUseSandbox) {
// Mark the handles to inherit as inheritable.
for (HANDLE h : mLaunchOptions->handles_to_inherit) {
mResults.mSandboxBroker->AddHandleToShare(h);
}
}
# endif // MOZ_SANDBOX
return true;
}
bool WindowsProcessLauncher::DoLaunch() {
# ifdef MOZ_SANDBOX
if (mUseSandbox) {
if (mResults.mSandboxBroker->LaunchApp(
mCmdLine->program().c_str(),
mCmdLine->command_line_string().c_str(), mLaunchOptions->env_map,
mProcessType, mEnableSandboxLogging, &mResults.mHandle)) {
EnvironmentLog("MOZ_PROCESS_LOG")
.print("==> process %d launched child process %d (%S)\n",
base::GetCurrentProcId(), base::GetProcId(mResults.mHandle),
mCmdLine->command_line_string().c_str());
return true;
}
return false;
}
# endif // defined(MOZ_SANDBOX)
return base::LaunchApp(mCmdLine.ref(), *mLaunchOptions, &mResults.mHandle);
}
bool WindowsProcessLauncher::DoFinishLaunch() {
if (!BaseProcessLauncher::DoFinishLaunch()) {
return false;
}
#else // goes with defined(OS_POSIX)
# error Sorry
#endif // defined(OS_POSIX)
# ifdef MOZ_SANDBOX
// We need to be able to duplicate handles to some types of non-sandboxed
// child processes.
switch (mProcessType) {
case GeckoProcessType_Default:
MOZ_CRASH("shouldn't be launching a parent process");
case GeckoProcessType_Plugin:
case GeckoProcessType_IPDLUnitTest:
// No handle duplication necessary.
break;
default:
if (!SandboxBroker::AddTargetPeer(mResults.mHandle)) {
NS_WARNING("Failed to add child process as target peer.");
}
break;
}
# endif // MOZ_SANDBOX
MOZ_DIAGNOSTIC_ASSERT(results.mHandle);
// NB: on OS X, we block much longer than we need to in order to
// reach this call, waiting for the child process's task_t. The
// best way to fix that is to refactor this file, hard.
#ifdef XP_MACOSX
results.mChildTask = child_task;
#endif // XP_MACOSX
return true;
}
#endif // XP_WIN
RefPtr<ProcessLaunchPromise> BaseProcessLauncher::FinishLaunch() {
if (!DoFinishLaunch()) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
}
MOZ_DIAGNOSTIC_ASSERT(mResults.mHandle);
CrashReporter::RegisterChildCrashAnnotationFileDescriptor(
base::GetProcId(results.mHandle), crashAnnotationReadPipe.forget());
base::GetProcId(mResults.mHandle), mCrashAnnotationReadPipe.forget());
Telemetry::AccumulateTimeDelta(Telemetry::CHILD_PROCESS_LAUNCH_MS, startTS);
Telemetry::AccumulateTimeDelta(Telemetry::CHILD_PROCESS_LAUNCH_MS,
mStartTimeStamp);
return ProcessLaunchPromise::CreateAndResolve(results, __func__);
return ProcessLaunchPromise::CreateAndResolve(mResults, __func__);
}
bool GeckoChildProcessHost::OpenPrivilegedHandle(base::ProcessId aPid) {
@ -1403,7 +1523,7 @@ void GeckoChildProcessHost::GetQueuedMessages(std::queue<IPC::Message>& queue) {
}
#ifdef MOZ_WIDGET_ANDROID
void ProcessLauncher::LaunchAndroidService(
void AndroidProcessLauncher::LaunchAndroidService(
const char* type, const std::vector<std::string>& argv,
const base::file_handle_mapping_vector& fds_to_remap,
base::ProcessHandle* process_handle) {
@ -1518,7 +1638,7 @@ void GeckoChildProcessHost::GetAll(const GeckoProcessCallback& aCallback) {
}
}
RefPtr<ProcessLaunchPromise> ProcessLauncher::Launch(
RefPtr<ProcessLaunchPromise> BaseProcessLauncher::Launch(
GeckoChildProcessHost* aHost) {
AssertIOThread();
@ -1553,5 +1673,8 @@ RefPtr<ProcessLaunchPromise> ProcessLauncher::Launch(
}
return InvokeAsync(launchThread, this, __func__,
&ProcessLauncher::PerformAsyncLaunch);
&BaseProcessLauncher::PerformAsyncLaunch);
}
} // namespace ipc
} // namespace mozilla

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

@ -174,7 +174,7 @@ class GeckoChildProcessHost : public ChildProcessHost,
// so you need to make sure the callback is as fast as possible.
static void GetAll(const GeckoProcessCallback& aCallback);
friend class ProcessLauncher;
friend class BaseProcessLauncher;
protected:
~GeckoChildProcessHost();

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

@ -37,14 +37,17 @@
# It uses the C preprocessor to process its inputs.
from __future__ import with_statement
import errno
import re
import sys
import os
import mozpack.path as mozpath
import subprocess
import shlex
import which
import buildconfig
import mozpack.path as mozpath
from mozfile import which
def ToCAsciiArray(lines):
@ -113,7 +116,11 @@ def embed(cxx, preprocessorOption, cppflags, msgs, sources, c_out, js_out, names
def preprocess(cxx, preprocessorOption, source, args=[]):
if (not os.path.exists(cxx[0])):
cxx[0] = which.which(cxx[0])
binary = cxx[0]
cxx[0] = which(binary)
if not cxx[0]:
raise OSError(errno.ENOENT, "%s not found on PATH" % binary)
# Clang seems to complain and not output anything if the extension of the
# input is not something it recognizes, so just fake a .cpp here.
tmpIn = 'self-hosting-cpp-input.cpp'

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

@ -10815,6 +10815,12 @@ apigee.io
// Submitted by Thomas Orozco <thomas@aptible.com>
on-aptible.com
// ASEINet : https://www.aseinet.com/
// Submitted by Asei SEKIGUCHI <mail@aseinet.com>
user.aseinet.ne.jp
gv.vc
d.gv.vc
// Asociación Amigos de la Informática "Euskalamiga" : http://encounter.eus/
// Submitted by Hector Martin <marcan@euskalencounter.org>
user.party.eus

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

@ -4,6 +4,7 @@
from __future__ import absolute_import, print_function, unicode_literals
import errno
import sys
from mach.decorators import (
@ -67,23 +68,24 @@ class VersionControlCommands(object):
and this command only ensures that remote repositories providing
VCS extensions are up to date.
"""
import which
import mozboot.bootstrap as bootstrap
import mozversioncontrol
from mozfile import which
repo = mozversioncontrol.get_repository_object(self._context.topdir)
vcs = 'hg'
tool = 'hg'
if repo.name == 'git':
vcs = 'git'
tool = 'git'
# "hg" is an executable script with a shebang, which will be found
# by which.which. We need to pass a win32 executable to the function
# because we spawn a process
# from it.
# "hg" is an executable script with a shebang, which will be found by
# which. We need to pass a win32 executable to the function because we
# spawn a process from it.
if sys.platform in ('win32', 'msys'):
vcs = which.which(vcs + '.exe')
else:
vcs = which.which(vcs)
tool += '.exe'
vcs = which(tool)
if not vcs:
raise OSError(errno.ENOENT, "Could not find {} on $PATH".format(tool))
if update_only:
if repo.name == 'git':

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

@ -7,12 +7,9 @@ from __future__ import absolute_import, print_function, unicode_literals
import argparse
import os
import subprocess
import which
from mozbuild.base import (
MachCommandBase,
)
from mozbuild.base import MachCommandBase
from mozfile import which
from mach.decorators import (
CommandArgument,
CommandProvider,
@ -32,13 +29,10 @@ class MachCommands(MachCommandBase):
elif ide == 'visualstudio':
backend = 'VisualStudio'
if ide == 'eclipse':
try:
which.which('eclipse')
except which.WhichError:
print('Eclipse CDT 8.4 or later must be installed in your PATH.')
print('Download: http://www.eclipse.org/cdt/downloads.php')
return 1
if ide == 'eclipse' and not which('eclipse'):
print('Eclipse CDT 8.4 or later must be installed in your PATH.')
print('Download: http://www.eclipse.org/cdt/downloads.php')
return 1
# Here we refresh the whole build. 'build export' is sufficient here and is probably more
# correct but it's also nice having a single target to get a fully built and indexed

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

@ -13,13 +13,9 @@ import six
import subprocess
import sys
import errno
try:
from shutil import which
except ImportError:
# shutil.which is not available in Python 2.7
import which
from mach.mixin.process import ProcessExecutionMixin
from mozfile import which
from mozversioncontrol import (
get_repository_from_build_config,
get_repository_object,
@ -581,9 +577,8 @@ class MozbuildObject(ProcessExecutionMixin):
try:
if sys.platform.startswith('darwin'):
try:
notifier = which.which('terminal-notifier')
except which.WhichError:
notifier = which('terminal-notifier')
if not notifier:
raise Exception('Install terminal-notifier to get '
'a notification when the build finishes.')
self.run_process([notifier, '-title',
@ -616,9 +611,8 @@ class MozbuildObject(ProcessExecutionMixin):
FLASHW_CAPTION | FLASHW_TRAY | FLASHW_TIMERNOFG, 3, 0)
FlashWindowEx(params)
else:
try:
notifier = which.which('notify-send')
except which.WhichError:
notifier = which('notify-send')
if not notifier:
raise Exception('Install notify-send (usually part of '
'the libnotify package) to get a notification when '
'the build finishes.')
@ -785,9 +779,8 @@ class MozbuildObject(ProcessExecutionMixin):
if os.path.isabs(test):
make = test
else:
try:
make = which.which(test)
except which.WhichError:
make = which(test)
if not make:
continue
result, xcode_lisense_error_tmp = validate_make(make)
if result:

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

@ -13,7 +13,6 @@ import os
import subprocess
import sys
import time
import which
from collections import (
Counter,
@ -528,15 +527,13 @@ class BuildMonitor(MozbuildObject):
def ccache_stats(self):
ccache_stats = None
try:
ccache = which.which('ccache')
output = subprocess.check_output([ccache, '-s'])
ccache_stats = CCacheStats(output)
except which.WhichError:
pass
except ValueError as e:
self.log(logging.WARNING, 'ccache', {'msg': str(e)}, '{msg}')
ccache = mozfile.which('ccache')
if ccache:
try:
output = subprocess.check_output([ccache, '-s'])
ccache_stats = CCacheStats(output)
except ValueError as e:
self.log(logging.WARNING, 'ccache', {'msg': str(e)}, '{msg}')
return ccache_stats

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

@ -7,13 +7,13 @@ from __future__ import absolute_import, print_function
import os
import subprocess
import platform
from mozboot.util import get_state_dir
import which
from distutils.version import (
StrictVersion,
)
from mozboot.util import get_state_dir
from mozfile import which
NODE_MIN_VERSION = StrictVersion("8.11.0")
NPM_MIN_VERSION = StrictVersion("5.6.0")
@ -66,21 +66,6 @@ def check_executable_version(exe, wrap_call_with_node=False):
return StrictVersion(out)
def simple_which(filename, path=None):
# Note: On windows, npm uses ".cmd"
exts = [".cmd", ".exe", ""] if platform.system() == "Windows" else [""]
for ext in exts:
try:
return which.which(filename + ext, path)
except which.WhichError:
pass
# If we got this far, we didn't find it with any of the extensions, so
# just return.
return None
def find_node_executable(nodejs_exe=os.environ.get('NODEJS'), min_version=NODE_MIN_VERSION):
"""Find a Node executable from the mozbuild directory.
@ -120,10 +105,7 @@ def find_executable(names, min_version, use_node_for_version_check=False):
found_exe = None
for name in names:
try:
exe = simple_which(name, paths)
except which.WhichError:
continue
exe = which(name, path=paths)
if not exe:
continue

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

@ -47,7 +47,7 @@ def find_python3_executable(min_version='3.5.0'):
version tuple. Both tuple entries will be None if a Python executable
could not be resolved.
"""
import which
from mozfile import which
if not min_version.startswith('3.'):
raise ValueError('min_version expected a 3.x string, got %s' %
@ -80,9 +80,8 @@ def find_python3_executable(min_version='3.5.0'):
names.append('python3.%d' % minor)
for name in names:
try:
exe = which.which(name)
except which.WhichError:
exe = which(name)
if not exe:
continue
# We always verify we can invoke the executable and its version is

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

@ -4,18 +4,20 @@
from __future__ import absolute_import, print_function, unicode_literals
from distutils.version import LooseVersion
import errno
import hashlib
import logging
from mozbuild.base import (
BuildEnvironmentNotFoundException,
MozbuildObject,
)
import mozpack.path as mozpath
import os
import re
import subprocess
import sys
from distutils.version import LooseVersion
import mozpack.path as mozpath
from mozbuild.base import (
BuildEnvironmentNotFoundException,
MozbuildObject,
)
class VendorRust(MozbuildObject):
@ -24,8 +26,11 @@ class VendorRust(MozbuildObject):
return self.substs['CARGO']
except (BuildEnvironmentNotFoundException, KeyError):
# Default if this tree isn't configured.
import which
return which.which('cargo')
from mozfile import which
cargo = which('cargo')
if not cargo:
raise OSError(errno.ENOENT, "Could not find 'cargo' on your $PATH.")
return cargo
def check_cargo_version(self, cargo):
'''

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

@ -1155,4 +1155,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1571056897017000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1571316284300000);

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

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

@ -46,6 +46,7 @@ add_task(async function test_missing_crypto_collection() {
];
// Disable addon sync because AddonManager won't be initialized here.
await Service.engineManager.unregister("addons");
await Service.engineManager.unregister("extension-storage");
for (let coll of collections) {
handlers["/1.1/johndoe/storage/" + coll] = johnU(

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

@ -40,7 +40,9 @@ add_task(async function test_locally_changed_keys() {
Service.clusterURL = Service.identity._token.endpoint;
await Service.engineManager.register(HistoryEngine);
// Disable addon sync because AddonManager won't be initialized here.
await Service.engineManager.unregister("addons");
await Service.engineManager.unregister("extension-storage");
async function corrupt_local_keys() {
Service.collectionKeys._default.keyPair = [

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

@ -26,7 +26,9 @@ async function cleanup(engine, server) {
}
add_task(async function setup() {
await Service.engineManager.unregister("addons"); // To silence errors.
// Disable addon sync because AddonManager won't be initialized here.
await Service.engineManager.unregister("addons");
await Service.engineManager.unregister("extension-storage");
});
add_task(async function test_ignored_fields() {

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

@ -91,6 +91,7 @@ async function cleanAndGo(engine, server) {
add_task(async function setup() {
// Avoid addon manager complaining about not being initialized
await Service.engineManager.unregister("addons");
await Service.engineManager.unregister("extension-storage");
});
add_task(async function test_basic() {

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

@ -5,6 +5,7 @@
from __future__ import absolute_import, print_function, unicode_literals
import argparse
import errno
import json
import logging
import os
@ -667,9 +668,8 @@ class TestInfoCommand(MachCommandBase):
@CommandArgument('--verbose', action='store_true',
help='Enable debug logging.')
def test_info(self, **params):
import which
from mozbuild.base import MozbuildObject
from mozfile import which
self.branches = params['branches']
self.start = params['start']
@ -698,17 +698,15 @@ class TestInfoCommand(MachCommandBase):
self._hg = None
if conditions.is_hg(build_obj):
if self._is_windows():
self._hg = which.which('hg.exe')
else:
self._hg = which.which('hg')
self._hg = which('hg')
if not self._hg:
raise OSError(errno.ENOENT, "Could not find 'hg' on PATH.")
self._git = None
if conditions.is_git(build_obj):
if self._is_windows():
self._git = which.which('git.exe')
else:
self._git = which.which('git')
self._git = which('git')
if not self._git:
raise OSError(errno.ENOENT, "Could not find 'git' on PATH.")
for test_name in params['test_names']:
print("===== %s =====" % test_name)

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

@ -8,13 +8,16 @@
from __future__ import absolute_import, print_function
from six.moves import urllib
from contextlib import contextmanager
import errno
import os
import stat
import sys
import time
import warnings
from contextlib import contextmanager
from six.moves import urllib
__all__ = ['extract_tarball',
'extract_zip',
@ -25,6 +28,7 @@ __all__ = ['extract_tarball',
'remove',
'rmtree',
'tree',
'which',
'NamedTemporaryFile',
'TemporaryDirectory']
@ -310,6 +314,55 @@ def tree(directory, sort_key=lambda x: x.lower()):
return '\n'.join(retval)
def which(cmd, mode=os.F_OK | os.X_OK, path=None, exts=None):
"""A wrapper around `shutil.which` to make the behavior on Windows
consistent with other platforms.
On non-Windows platforms, this is a direct call to `shutil.which`. On
Windows, this:
* Ensures that `cmd` without an extension will be found. Previously it was
only found if it had an extension in `PATHEXT`.
* Ensures the absolute path to the binary is returned. Previously if the
binary was found in `cwd`, a relative path was returned.
The arguments are the same as the ones in `shutil.which`. In addition there
is an `exts` argument that only has an effect on Windows. This is used to
set a custom value for PATHEXT and is formatted as a list of file
extensions.
"""
try:
from shutil import which as shutil_which
except ImportError:
from shutil_which import which as shutil_which
if isinstance(path, (list, tuple)):
path = os.pathsep.join(path)
if sys.platform != "win32":
return shutil_which(cmd, mode=mode, path=path)
oldexts = os.environ.get("PATHEXT", "")
if not exts:
exts = oldexts.split(os.pathsep)
# This ensures that `cmd` without any extensions will be found.
# See: https://bugs.python.org/issue31405
if "." not in exts:
exts.append(".")
os.environ["PATHEXT"] = os.pathsep.join(exts)
try:
path = shutil_which(cmd, mode=mode, path=path)
return os.path.abspath(path.rstrip('.')) if path else None
finally:
if oldexts:
os.environ["PATHEXT"] = oldexts
else:
del os.environ["PATHEXT"]
# utilities for temporary resources
class NamedTemporaryFile(object):

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

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

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

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

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

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

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

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

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

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

@ -7,3 +7,4 @@ subsuite = mozbase
[test_tempfile.py]
[test_tree.py]
[test_url.py]
[test_which.py]

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

@ -0,0 +1,44 @@
# Any copyright is dedicated to the Public Domain.
# https://creativecommons.org/publicdomain/zero/1.0/
from __future__ import absolute_import
import os
import sys
import mozunit
from mozfile import which
here = os.path.abspath(os.path.dirname(__file__))
def test_which(monkeypatch):
cwd = os.path.join(here, 'files', 'which')
monkeypatch.chdir(cwd)
if sys.platform == "win32":
bindir = os.path.join(cwd, "win")
monkeypatch.setenv("PATH", bindir)
assert which("foo.exe").lower() == os.path.join(bindir, "foo.exe")
assert which("foo").lower() == os.path.join(bindir, "foo.exe")
assert which("foo", exts=[".FOO", ".BAR"]).lower() == os.path.join(bindir, "foo")
assert os.environ.get("PATHEXT") != [".FOO", ".BAR"]
assert which("foo.txt") is None
assert which("bar").lower() == os.path.join(bindir, "bar")
assert which("baz").lower() == os.path.join(cwd, "baz.exe")
else:
bindir = os.path.join(cwd, "unix")
monkeypatch.setenv("PATH", bindir)
assert which("foo") == os.path.join(bindir, "foo")
assert which("baz") is None
assert which("baz", exts=[".EXE"]) is None
assert "PATHEXT" not in os.environ
assert which("file") is None
if __name__ == '__main__':
mozunit.main()

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

@ -1,6 +1,7 @@
[iframe_sandbox_navigation_download_block_downloads_without_user_activation.sub.tentative.html]
[Navigation resulted download in sandbox is blocked.]
disabled:
if (os == "mac") and (version == "OS X 10.14") and not debug: new os version
if (os == "mac") and (version == "OS X 10.14.5") and not debug: new os version
if (os == "mac") and (version == "OS X 10.14") and not debug: new os version
expected: FAIL

78
third_party/python/backports/shutil_which/__init__.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,78 @@
"""Backport of shutil.which from Python 3.5
The function is included unmodified from Python stdlib 3.5.1,
and is (C) Python
"""
from __future__ import absolute_import # Import system's os, not backports.os.
import os
import sys
__version__ = '3.5.1'
def backport_which(cmd, mode=os.F_OK | os.X_OK, path=None):
"""Given a command, mode, and a PATH string, return the path which
conforms to the given mode on the PATH, or None if there is no such
file.
`mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
of os.environ.get("PATH"), or can be overridden with a custom search
path.
"""
# Check that a given file can be accessed with the correct mode.
# Additionally check that `file` is not a directory, as on Windows
# directories pass the os.access check.
def _access_check(fn, mode):
return (os.path.exists(fn) and os.access(fn, mode)
and not os.path.isdir(fn))
# If we're given a path with a directory part, look it up directly rather
# than referring to PATH directories. This includes checking relative to the
# current directory, e.g. ./script
if os.path.dirname(cmd):
if _access_check(cmd, mode):
return cmd
return None
if path is None:
path = os.environ.get("PATH", os.defpath)
if not path:
return None
path = path.split(os.pathsep)
if sys.platform == "win32":
# The current directory takes precedence on Windows.
if not os.curdir in path:
path.insert(0, os.curdir)
# PATHEXT is necessary to check on Windows.
pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
# See if the given file matches any of the expected path extensions.
# This will allow us to short circuit when given "python.exe".
# If it does match, only test that one, otherwise we have to try
# others.
if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
files = [cmd]
else:
files = [cmd + ext for ext in pathext]
else:
# On other platforms you don't have things like PATHEXT to tell you
# what file suffixes are executable, so just pass on cmd as-is.
files = [cmd]
seen = set()
for dir in path:
normdir = os.path.normcase(dir)
if not normdir in seen:
seen.add(normdir)
for thefile in files:
name = os.path.join(dir, thefile)
if _access_check(name, mode):
return name
return None
try:
from shutil import which
except ImportError:
which = backport_which

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

@ -16,6 +16,9 @@ onmessage = async function(e) {
let i = win.document.createElement("iframe");
i.src = "about:blank";
win.document.body.appendChild(i);
await new Promise(resolve => {
i.onload = resolve;
});
// override win to make it point to the initial about:blank window
win = i.contentWindow;
}

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

@ -51,6 +51,7 @@ const { ExtensionUtils } = ChromeUtils.import(
);
XPCOMUtils.defineLazyModuleGetters(this, {
AddonManager: "resource://gre/modules/AddonManager.jsm",
BulkKeyBundle: "resource://services-sync/keys.js",
CollectionKeyManager: "resource://services-sync/record.js",
CommonUtils: "resource://services-common/utils.js",
@ -781,8 +782,41 @@ class ExtensionStorageSync {
this.listeners = new WeakMap();
}
/**
* Get a set of extensions to sync (including the ones with an
* active extension context that used the storage.sync API and
* the extensions that are enabled and have been synced before).
*
* @returns {Promise<Set<Extension>>}
* A promise which resolves to the set of the extensions to sync.
*/
async getExtensions() {
// Start from the set of the extensions with an active
// context that used the storage.sync APIs.
const extensions = new Set(extensionContexts.keys());
const allEnabledExtensions = await AddonManager.getAddonsByTypes([
"extension",
]);
// Get the existing extension collections salts.
const keysRecord = await this.cryptoCollection.getKeyRingRecord();
// Add any enabled extensions that have been synced before.
for (const addon of allEnabledExtensions) {
if (this.hasSaltsFor(keysRecord, [addon.id])) {
const policy = WebExtensionPolicy.getByID(addon.id);
if (policy && policy.extension) {
extensions.add(policy.extension);
}
}
}
return extensions;
}
async syncAll() {
const extensions = extensionContexts.keys();
const extensions = await this.getExtensions();
const extIds = Array.from(extensions, extension => extension.id);
log.debug(`Syncing extension settings for ${JSON.stringify(extIds)}`);
if (extIds.length == 0) {
@ -791,7 +825,7 @@ class ExtensionStorageSync {
}
await this.ensureCanSync(extIds);
await this.checkSyncKeyRing();
const promises = Array.from(extensionContexts.keys(), extension => {
const promises = Array.from(extensions, extension => {
return openCollection(this.cryptoCollection, extension).then(coll => {
return this.sync(extension, coll);
});
@ -1296,11 +1330,11 @@ class ExtensionStorageSync {
/* Wipe local data for all collections without causing the changes to be synced */
async clearAll() {
const extensions = extensionContexts.keys();
const extensions = await this.getExtensions();
const extIds = Array.from(extensions, extension => extension.id);
log.debug(`Clearing extension data for ${JSON.stringify(extIds)}`);
if (extIds.length) {
const promises = Array.from(extensionContexts.keys(), extension => {
const promises = Array.from(extensions, extension => {
return openCollection(this.cryptoCollection, extension).then(coll => {
return coll.clear();
});

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

@ -10,6 +10,7 @@ const { CommonUtils } = ChromeUtils.import(
"resource://services-common/utils.js"
);
const {
cleanUpForContext,
CollectionKeyEncryptionRemoteTransformer,
CryptoCollection,
ExtensionStorageSync,
@ -22,6 +23,12 @@ const { BulkKeyBundle } = ChromeUtils.import(
);
const { Utils } = ChromeUtils.import("resource://services-sync/util.js");
const { createAppInfo, promiseStartupManager } = AddonTestUtils;
AddonTestUtils.init(this);
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "69");
/* globals BulkKeyBundle, CommonUtils, EncryptionRemoteTransformer */
/* globals Utils */
@ -637,6 +644,10 @@ function uuid() {
return uuidgen.generateUUID().toString();
}
add_task(async function test_setup() {
await promiseStartupManager();
});
add_task(async function test_key_to_id() {
equal(keyToId("foo"), "key-foo");
equal(keyToId("my-new-key"), "key-my_2D_new_2D_key");
@ -684,46 +695,92 @@ add_task(async function test_extension_id_to_collection_id() {
});
add_task(async function ensureCanSync_clearAll() {
const extensionId = uuid();
const extension = { id: extensionId };
// A test extension that will not have any active context around
// but it is returned from a call to AddonManager.getExtensionsByType.
const extensionId = "test-wipe-on-enabled-and-synced@mochi.test";
const testExtension = ExtensionTestUtils.loadExtension({
useAddonManager: "temporary",
manifest: {
permissions: ["storage"],
applications: { gecko: { id: extensionId } },
},
});
await testExtension.startup();
// Retrieve the Extension class instance from the test extension.
const { extension } = testExtension;
// Another test extension that will have an active extension context.
const extensionId2 = "test-wipe-on-active-context@mochi.test";
const extension2 = { id: extensionId2 };
await withContextAndServer(async function(context, server) {
await withSignedInUser(loggedInUser, async function(
extensionStorageSync,
fxaService
) {
async function assertSetAndGetData(extension, data) {
await extensionStorageSync.set(extension, data, context);
let storedData = await extensionStorageSync.get(
extension,
Object.keys(data),
context
);
const extId = extensionId;
deepEqual(storedData, data, `${extId} should get back the data we set`);
}
async function assertDataCleared(extension, keys) {
const storedData = await extensionStorageSync.get(
extension,
keys,
context
);
deepEqual(storedData, {}, `${extension.id} should have lost the data`);
}
server.installCollection("storage-sync-crypto");
server.etag = 1000;
let newKeys = await extensionStorageSync.ensureCanSync([extensionId]);
let newKeys = await extensionStorageSync.ensureCanSync([
extensionId,
extensionId2,
]);
ok(
newKeys.hasKeysFor([extensionId]),
`key isn't present for ${extensionId}`
);
ok(
newKeys.hasKeysFor([extensionId2]),
`key isn't present for ${extensionId2}`
);
let posts = server.getPosts();
equal(posts.length, 1);
const post = posts[0];
assertPostedNewRecord(post);
assertPostedNewRecord(posts[0]);
// Set data for an extension and sync.
await extensionStorageSync.set(extension, { "my-key": 5 }, context);
let keyValue = await extensionStorageSync.get(
extension,
["my-key"],
context
);
equal(keyValue["my-key"], 5, "should get back the data we set");
await assertSetAndGetData(extension, { "my-key": 1 });
await assertSetAndGetData(extension2, { "my-key": 2 });
// Call cleanup for the first extension, to double check it has
// been wiped out even without an active extension context.
cleanUpForContext(extension, context);
// clear everything.
await extensionStorageSync.clearAll();
keyValue = await extensionStorageSync.get(extension, ["my-key"], context);
deepEqual(keyValue, {}, "should have lost the data");
// Assert that the data is gone for both the extensions.
await assertDataCleared(extension, ["my-key"]);
await assertDataCleared(extension2, ["my-key"]);
// should have been no posts caused by the clear.
posts = server.getPosts();
equal(posts.length, 1);
});
});
await testExtension.unload();
});
add_task(async function ensureCanSync_posts_new_keys() {
@ -1615,6 +1672,86 @@ add_task(async function test_storage_sync_pulls_changes() {
});
});
// Tests that an enabled extension which have been synced before it is going
// to be synced on ExtensionStorageSync.syncAll even if there is no active
// context that is currently using the API.
add_task(async function test_storage_sync_on_no_active_context() {
const extensionId = "sync@mochi.test";
const extension = ExtensionTestUtils.loadExtension({
useAddonManager: "temporary",
manifest: {
permissions: ["storage"],
applications: { gecko: { id: extensionId } },
},
files: {
"ext-page.html": `<!DOCTYPE html>
<html>
<head>
<script src="ext-page.js"></script>
</head>
</html>
`,
"ext-page.js": function() {
const { browser } = this;
browser.test.onMessage.addListener(async msg => {
if (msg === "get-sync-data") {
browser.test.sendMessage(
"get-sync-data:done",
await browser.storage.sync.get(["remote-key"])
);
}
});
},
},
});
await extension.startup();
await withServer(async server => {
await withSignedInUser(loggedInUser, async function(
extensionStorageSync,
fxaService
) {
const cryptoCollection = new CryptoCollection(fxaService);
let transformer = new CollectionKeyEncryptionRemoteTransformer(
cryptoCollection,
extensionId
);
server.installCollection("storage-sync-crypto");
await extensionStorageSync.ensureCanSync([extensionId]);
const collectionId = await cryptoCollection.extensionIdToCollectionId(
extensionId
);
await server.encryptAndAddRecord(transformer, {
collectionId,
data: {
id: "key-remote_2D_key",
key: "remote-key",
data: 6,
},
predicate: appearsAt(850),
});
server.etag = 1000;
await extensionStorageSync.syncAll();
});
});
const extPage = await ExtensionTestUtils.loadContentPage(
`moz-extension://${extension.uuid}/ext-page.html`,
{ extension }
);
await extension.sendMessage("get-sync-data");
const res = await extension.awaitMessage("get-sync-data:done");
Assert.deepEqual(res, { "remote-key": 6 }, "Got the expected sync data");
await extPage.close();
await extension.unload();
});
add_task(async function test_storage_sync_pushes_changes() {
// FIXME: This test relies on the fact that previous tests pushed
// keys and salts for the default extension ID

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

@ -564,6 +564,13 @@ this.LoginManagerParent = {
if (!usernameField && oldPasswordField && logins.length > 0) {
let prompter = this._getPrompter(browser, openerTopWindowID);
let { browsingContext } = browser;
let framePrincipalOrigin =
browsingContext.currentWindowGlobal.documentPrincipal.origin;
let generatedPW = this._generatedPasswordsByPrincipalOrigin.get(
framePrincipalOrigin
);
if (logins.length == 1) {
let oldLogin = logins[0];
@ -580,15 +587,14 @@ this.LoginManagerParent = {
formLogin.usernameField = oldLogin.usernameField;
prompter.promptToChangePassword(oldLogin, formLogin, dismissedPrompt);
} else {
return;
} else if (!generatedPW || generatedPW.value != newPasswordField.value) {
// Note: It's possible that that we already have the correct u+p saved
// but since we don't have the username, we don't know if the user is
// changing a second account to the new password so we ask anyways.
prompter.promptToChangePasswordWithUsernames(logins, formLogin);
return;
}
return;
}
let existingLogin = null;

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

@ -62,6 +62,8 @@ support-files =
file_focus_before_DOMContentLoaded.sjs
[browser_formless_submit_chrome.js]
[browser_generated_password_doorhangers.js]
support-files =
form_password_change.html
[browser_hasInsecureLoginForms.js]
skip-if = verify
[browser_hasInsecureLoginForms_streamConverter.js]
@ -92,4 +94,4 @@ tags = clipboard
[browser_private_window.js]
support-files =
subtst_privbrowsing_1.html
subtst_privbrowsing_2.html
form_password_change.html

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

@ -13,20 +13,25 @@ const FORM_PAGE_PATH =
const passwordInputSelector = "#form-basic-password";
const usernameInputSelector = "#form-basic-username";
let login1;
async function addOneLogin() {
login1 = LoginTestUtils.testData.formLogin({
async function addLogin({ username, password }) {
const login = LoginTestUtils.testData.formLogin({
origin: "https://example.com",
formActionOrigin: "https://example.com",
username: "username",
password: "pass1",
username,
password,
});
let storageChangedPromised = TestUtils.topicObserved(
"passwordmgr-storage-changed",
(_, data) => data == "addLogin"
);
Services.logins.addLogin(login1);
Services.logins.addLogin(login);
await storageChangedPromised;
return login;
}
let login1;
function addOneLogin() {
login1 = addLogin({ username: "username", password: "pass1" });
}
function openACPopup(popup, browser, inputSelector) {
@ -266,3 +271,45 @@ add_task(async function autocomplete_generated_password() {
}
);
});
add_task(async function password_change_without_username() {
const CHANGE_FORM_PATH =
"/browser/toolkit/components/passwordmgr/test/browser/form_password_change.html";
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: TEST_ORIGIN + CHANGE_FORM_PATH,
},
async function(browser) {
await SimpleTest.promiseFocus(browser.ownerGlobal);
// Save 2nd login different from the 1st one
addLogin({
username: "username2",
password: "pass2",
});
// Make the 2nd field use a generated password
await doFillGeneratedPasswordContextMenuItem(browser, "#newpass");
// Submit the form
await ContentTask.spawn(browser, null, function() {
content.document.querySelector("#form").submit();
});
// Check a non-dismissed prompt was shown
let notif = getCaptureDoorhanger("password-save");
ok(notif && !notif.dismissed, "Non-dismissed notification was created");
let { passwordValue, usernameValue } = await checkPromptContents(
notif.anchorElement
);
is(
passwordValue.length,
15,
"Doorhanger password field has generated 15-char value"
);
is(usernameValue, "", "Doorhanger username field has no value");
notif.remove();
}
);
});

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

@ -146,7 +146,7 @@ let login = new nsLoginInfo(
"pass"
);
const form1Url = `https://example.com/${DIRECTORY_PATH}subtst_privbrowsing_1.html`;
const form2Url = `https://example.com/${DIRECTORY_PATH}subtst_privbrowsing_2.html`;
const form2Url = `https://example.com/${DIRECTORY_PATH}form_password_change.html`;
const authUrl = `https://example.com/${DIRECTORY_PATH}authenticate.sjs`;
let normalWin;

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

@ -246,6 +246,12 @@ var SessionHistoryInternal = {
);
}
if (shEntry.storagePrincipalToInherit) {
entry.storagePrincipalToInherit_base64 = E10SUtils.serializePrincipal(
shEntry.storagePrincipalToInherit
);
}
if (shEntry.triggeringPrincipal) {
entry.triggeringPrincipal_base64 = E10SUtils.serializePrincipal(
shEntry.triggeringPrincipal
@ -521,6 +527,11 @@ var SessionHistoryInternal = {
}
);
}
if (entry.storagePrincipalToInherit_base64) {
shEntry.storagePrincipalToInherit = E10SUtils.deserializePrincipal(
entry.storagePrincipalToInherit_base64
);
}
if (entry.principalToInherit_base64) {
shEntry.principalToInherit = E10SUtils.deserializePrincipal(
entry.principalToInherit_base64

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

@ -236,6 +236,7 @@ recommended-addon-card .addon-description:not(:empty) {
.discopane-notice-content > span {
flex-grow: 1;
margin-inline-end: 4px;
}
.discopane-notice-content > button {

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

@ -5,6 +5,7 @@
--error-icon-url: url("chrome://global/skin/icons/error.svg");
--close-icon-url: url("chrome://global/skin/icons/close.svg");
--icon-size: 16px;
--close-icon-size: 32px;
}
/* MessageBar colors by message type */
@ -58,24 +59,21 @@
display: block;
}
.container {
background: inherit;
color: inherit;
::slotted(button) {
/* Enforce micro-button width. */
min-width: -moz-fit-content !important;
}
/* MessageBar Grid Layout */
.container {
padding-top: 2px;
padding-bottom: 2px;
background: inherit;
color: inherit;
padding-inline-start: 4px;
padding: 8px;
min-height: 32px;
border-radius: 4px;
font-size: 13px;
font-weight: 400;
line-height: 1.4;
display: flex;
/* Ensure that the message bar shadow dom elements are vertically aligned. */
@ -86,17 +84,8 @@
justify-content: center;
}
:host([dismissable]) .container {
/* Add padding on the end of the container when the bar is dismissable. */
padding-inline-end: 4px;
}
.icon {
flex-shrink: 0;
}
.content {
margin-inline-end: 4px;
margin: 0 4px;
display: flex;
/* Ensure that the message bar content is vertically aligned. */
align-items: center;
@ -104,63 +93,48 @@
word-break: break-word;
}
button.close {
flex-shrink: 0;
}
::slotted(button) {
/* Enforce micro-button width. */
min-width: -moz-fit-content !important;
}
/* MessageBar icon style */
.icon {
padding: 4px;
width: var(--icon-size);
height: var(--icon-size);
flex-shrink: 0;
}
.icon::after {
-moz-appearance: none;
-moz-context-properties: fill, stroke;
color: inherit !important;
fill: currentColor;
stroke: currentColor;
content: var(--message-bar-icon-url);
}
/* Use a spacer to position the close button at the end, but also support
* centering if required. */
.spacer {
flex-grow: 1;
}
/* Close icon styles */
:host(:not([dismissable])) button.close {
:host(:not([dismissable])) .close {
display: none;
}
button.close {
padding: 4px;
width: var(--icon-size);
height: var(--icon-size);
min-width: -moz-fit-content;
}
button.close {
background: var(--close-icon-url) no-repeat center center;
.close {
background-image: var(--close-icon-url);
background-repeat: no-repeat;
background-position: center center;
-moz-context-properties: fill, fill-opacity;
color: inherit !important;
fill: currentColor;
fill-opacity: 0;
min-width: auto;
min-height: auto;
width: var(--icon-size);
height: var(--icon-size);
width: var(--close-icon-size);
height: var(--close-icon-size);
margin: 0;
margin-inline-end: 4px;
padding: 0;
}
button.close:hover {
fill-opacity: 0.1;
}
button.close:hover:active {
fill-opacity: 0.2;
flex-shrink: 0;
}

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

@ -121,6 +121,10 @@ class MessageBarElement extends HTMLElement {
barcontent.append(document.createElement("slot"));
container.append(barcontent);
const spacer = document.createElement("span");
spacer.classList.add("spacer");
container.append(spacer);
const closeIcon = document.createElement("button");
closeIcon.setAttribute("class", "close");
container.append(closeIcon);

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

@ -49,6 +49,7 @@
--in-content-table-background: #ebebeb;
--in-content-table-border-dark-color: #d1d1d1;
--in-content-table-header-background: #0a84ff;
--in-content-dialog-header-background: #f1f1f1;
--panel-border-radius: 2px; /* This is overridden on Windows */
@ -131,6 +132,7 @@
--in-content-table-background: #202023;
--in-content-table-border-dark-color: rgba(249,249,250,0.2);
--in-content-table-header-background: #002b57;
--in-content-dialog-header-background: rgba(249,249,250,0.05);
--in-content-category-text-selected: var(--blue-40);
--in-content-category-text-selected-active: var(--blue-50);
@ -295,6 +297,11 @@ html|select:not([size]):not([multiple]):dir(rtl) {
background-position: left 3px center;
}
html|select:not([size]):not([multiple]) > html|option {
background-color: var(--in-content-box-background);
color: var(--in-content-text-color);
}
html|button:enabled:hover,
html|select:not([size]):not([multiple]):enabled:hover,
html|input[type="color"]:hover,

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

@ -134,19 +134,21 @@ class MachBrowsertime(MachCommandBase):
if host_platform().startswith('linux'):
# On Linux ImageMagick needs to be installed manually, and `mach bootstrap` doesn't
# do that (yet). Provide some guidance.
import which
im_programs = ('compare', 'convert', 'mogrify')
try:
for im_program in im_programs:
which.which(im_program)
except which.WhichError as e:
print('Error: {} On Linux, ImageMagick must be on the PATH. '
'Install ImageMagick manually and try again (or update PATH). '
'On Ubuntu and Debian, try `sudo apt-get install imagemagick`. '
'On Fedora, try `sudo dnf install imagemagick`. '
'On CentOS, try `sudo yum install imagemagick`.'
.format(e))
return 1
from shutil import which
except ImportError:
from shutil_which import which
im_programs = ('compare', 'convert', 'mogrify')
for im_program in im_programs:
prog = which(im_program)
if not prog:
print('Error: On Linux, ImageMagick must be on the PATH. '
'Install ImageMagick manually and try again (or update PATH). '
'On Ubuntu and Debian, try `sudo apt-get install imagemagick`. '
'On Fedora, try `sudo dnf install imagemagick`. '
'On CentOS, try `sudo yum install imagemagick`.')
return 1
# Download the visualmetrics.py requirements.
artifact_cache = ArtifactCache(self.artifact_cache_path,

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

@ -8,15 +8,13 @@ import os
import sys
from functools import partial
from mozbuild.base import MachCommandBase
from mach.decorators import (
Command,
CommandArgument,
CommandProvider,
)
import which
from mozbuild.base import MachCommandBase
here = os.path.abspath(os.path.dirname(__file__))
@ -53,9 +51,10 @@ class Documentation(MachCommandBase):
help='Upload generated files to S3.')
def build_docs(self, path=None, fmt='html', outdir=None, auto_open=True,
serve=True, http=None, archive=False, upload=False):
try:
which.which('jsdoc')
except which.WhichError:
from mozfile import which
if not which('jsdoc'):
return die('jsdoc not found - please install from npm.')
self.activate_pipenv(os.path.join(here, 'Pipfile'))

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

@ -109,6 +109,11 @@ let's call the file ``flake8_lint.py``:
from mozlint import result
try:
from shutil import which
except ImportError:
from shutil_which import which
FLAKE8_NOT_FOUND = """
Could not find flake8! Install flake8 and try again.
@ -116,13 +121,10 @@ let's call the file ``flake8_lint.py``:
def lint(files, config, **lintargs):
import which
binary = os.environ.get('FLAKE8')
if not binary:
try:
binary = which.which('flake8')
except which.WhichError:
binary = which('flake8')
if not binary:
print(FLAKE8_NOT_FOUND)
return 1

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

@ -7,10 +7,10 @@ from collections import namedtuple
import os
import signal
import which
import re
import subprocess
from mozfile import which
from mozlint import result
from mozlint.pathutils import expand_exclusions
from mozprocess import ProcessHandler
@ -105,10 +105,7 @@ def get_rustfmt_binary():
if binary:
return binary
try:
return which.which("rustfmt")
except which.WhichError:
return None
return which("rustfmt")
def is_old_rustfmt(binary):

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

@ -7,17 +7,17 @@ from __future__ import absolute_import, print_function
import os
import json
import signal
import which
# Py3/Py2 compatibility.
# py2-compat
try:
from json.decoder import JSONDecodeError
except ImportError:
JSONDecodeError = ValueError
import mozpack.path as mozpath
from mozpack.files import FileFinder
from mozfile import which
from mozlint import result
from mozpack.files import FileFinder
from mozprocess import ProcessHandlerMixin
@ -135,10 +135,7 @@ def get_shellcheck_binary():
if binary:
return binary
try:
return which.which('shellcheck')
except which.WhichError:
return None
return which('shellcheck')
def lint(paths, config, **lintargs):

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

@ -6,15 +6,15 @@ from __future__ import absolute_import, print_function
import os
import signal
import which
import re
# Py3/Py2 compatibility.
# py2-compat
try:
from json.decoder import JSONDecodeError
except ImportError:
JSONDecodeError = ValueError
from mozfile import which
from mozlint import result
from mozlint.util import pip
from mozprocess import ProcessHandlerMixin
@ -90,10 +90,7 @@ def get_codespell_binary():
if binary:
return binary
try:
return which.which('codespell')
except which.WhichError:
return None
return which('codespell')
def lint(paths, config, fix=None, **lintargs):

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

@ -8,11 +8,10 @@ import signal
import subprocess
from collections import defaultdict
import which
from mozprocess import ProcessHandlerMixin
from mozfile import which
from mozlint import result
from mozlint.pathutils import get_ancestors_by_name
from mozprocess import ProcessHandlerMixin
here = os.path.abspath(os.path.dirname(__file__))
@ -71,10 +70,7 @@ def get_yamllint_binary():
if binary:
return binary
try:
return which.which('yamllint')
except which.WhichError:
return None
return which('yamllint')
def _run_pip(*args):

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

@ -4,19 +4,25 @@
# 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/.
import errno
import sys
import os
import shlex
import subprocess
import tempfile
import which
import buildconfig
from mozfile import which
def preprocess(out, asm_file):
cxx = shlex.split(buildconfig.substs['CXX'])
if not os.path.exists(cxx[0]):
cxx[0] = which.which(cxx[0])
tool = cxx[0]
cxx[0] = which(tool)
if not cxx[0]:
raise OSError(errno.ENOENT, "Could not find {} on PATH.".format(tool))
cppflags = buildconfig.substs['OS_CPPFLAGS']
# subprocess.Popen(stdout=) only accepts actual file objects, which `out`,