Backed out 7 changesets (bug 1704500) for causing multiple failures in browser_utility_geolocation_crashed/test_geolocation_reset_accuracy CLOSED TREE

Backed out changeset c3ae64389c26 (bug 1704500)
Backed out changeset 747d84ff17c7 (bug 1704500)
Backed out changeset 313b8770dc51 (bug 1704500)
Backed out changeset 30632246ee2b (bug 1704500)
Backed out changeset 90a8d51fc17c (bug 1704500)
Backed out changeset a1d1a97a2ffa (bug 1704500)
Backed out changeset 6bfb4d8de1e1 (bug 1704500)
This commit is contained in:
Sandor Molnar
2023-01-27 05:49:32 +02:00
parent c778291852
commit 75efc1e999
36 changed files with 485 additions and 1478 deletions

View File

@@ -1063,6 +1063,35 @@ static WebIDLProcType ProcTypeToWebIDL(mozilla::ProcType aType) {
#undef PROCTYPE_TO_WEBIDL_CASE #undef PROCTYPE_TO_WEBIDL_CASE
#define UTILITYACTORNAME_TO_WEBIDL_CASE(_utilityActorName, _webidl) \
case mozilla::UtilityActorName::_utilityActorName: \
return WebIDLUtilityActorName::_webidl
static WebIDLUtilityActorName UtilityActorNameToWebIDL(
mozilla::UtilityActorName aType) {
// Max is the value of the last enum, not the length, so add one.
static_assert(WebIDLUtilityActorNameValues::Count ==
static_cast<size_t>(UtilityActorName::JSOracle) + 1,
"In order for this static cast to be okay, "
"UtilityActorName must match UtilityActorName exactly");
// These must match the similar ones in ProcInfo.h and ChromeUtils.webidl
switch (aType) {
UTILITYACTORNAME_TO_WEBIDL_CASE(Unknown, Unknown);
UTILITYACTORNAME_TO_WEBIDL_CASE(AudioDecoder_Generic, AudioDecoder_Generic);
UTILITYACTORNAME_TO_WEBIDL_CASE(AudioDecoder_AppleMedia,
AudioDecoder_AppleMedia);
UTILITYACTORNAME_TO_WEBIDL_CASE(AudioDecoder_WMF, AudioDecoder_WMF);
UTILITYACTORNAME_TO_WEBIDL_CASE(MfMediaEngineCDM, MfMediaEngineCDM);
UTILITYACTORNAME_TO_WEBIDL_CASE(JSOracle, JSOracle);
}
MOZ_ASSERT(false, "Unhandled case in WebIDLUtilityActorName");
return WebIDLUtilityActorName::Unknown;
}
#undef UTILITYACTORNAME_TO_WEBIDL_CASE
/* static */ /* static */
already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal, already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
ErrorResult& aRv) { ErrorResult& aRv) {
@@ -1347,7 +1376,8 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
return; return;
} }
dest->mActorName = source.actorName; dest->mActorName =
UtilityActorNameToWebIDL(source.actorName);
} }
} }
} }

View File

@@ -728,7 +728,6 @@ enum WebIDLUtilityActorName {
"audioDecoder_WMF", "audioDecoder_WMF",
"mfMediaEngineCDM", "mfMediaEngineCDM",
"jSOracle", "jSOracle",
"windowsUtils",
}; };
dictionary UtilityActorsDictionary { dictionary UtilityActorsDictionary {

View File

@@ -1,38 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et ft=cpp : */
/* 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 protocol PWindowsUtils;
[RefCounted] using class nsIDOMGeoPosition from "nsGeoPositionIPCSerialiser.h";
namespace mozilla {
namespace dom {
// Proxies geolocation functions to a utility process so that we
// can safely handle crashes in the ILocation API. Messages to the child
// are proxies for the ILocation COM object. Messages to the parent
// are proxied nsIGeolocationUpdate callbacks.
protocol PWindowsLocation {
manager PWindowsUtils;
child:
async Startup();
async RegisterForReport();
async UnregisterForReport();
async SetHighAccuracy(bool aEnable);
async __delete__();
parent:
// Update geolocation with new position information.
async Update(nsIDOMGeoPosition aPosition);
// The geolocation API has reported an error.
async Failed(uint16_t aError);
};
} // namespace dom
} // namespace mozilla

View File

@@ -1,22 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et ft=cpp : */
/* 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 protocol PWindowsLocation;
namespace mozilla {
namespace dom {
// Manager of utility actors that run in the windows utility process.
protocol PWindowsUtils {
manages PWindowsLocation;
child:
// Proxies the ILocation COM API for geolocation
async PWindowsLocation();
};
} // namespace dom
} // namespace mozilla

View File

@@ -1,257 +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 "WindowsLocationChild.h"
#include "nsCOMPtr.h"
#include "WindowsLocationProvider.h"
#include "mozilla/dom/GeolocationPosition.h"
#include "mozilla/dom/GeolocationPositionErrorBinding.h"
#include "mozilla/Telemetry.h"
#include "nsIGeolocationProvider.h"
#include <locationapi.h>
namespace mozilla::dom {
extern LazyLogModule gWindowsLocationProviderLog;
#define LOG(...) \
MOZ_LOG(gWindowsLocationProviderLog, LogLevel::Debug, (__VA_ARGS__))
class LocationEvent final : public ILocationEvents {
public:
explicit LocationEvent(WindowsLocationChild* aActor)
: mActor(aActor), mRefCnt(0) {}
// IUnknown interface
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
STDMETHODIMP QueryInterface(REFIID iid, void** ppv) override;
// ILocationEvents interface
STDMETHODIMP OnStatusChanged(REFIID aReportType,
LOCATION_REPORT_STATUS aStatus) override;
STDMETHODIMP OnLocationChanged(REFIID aReportType,
ILocationReport* aReport) override;
private:
// Making this a WeakPtr breaks the following cycle of strong references:
// WindowsLocationChild -> ILocation -> ILocationEvents (this)
// -> WindowsLocationChild.
WeakPtr<WindowsLocationChild> mActor;
ULONG mRefCnt;
};
STDMETHODIMP_(ULONG)
LocationEvent::AddRef() { return InterlockedIncrement(&mRefCnt); }
STDMETHODIMP_(ULONG)
LocationEvent::Release() {
ULONG count = InterlockedDecrement(&mRefCnt);
if (!count) {
delete this;
return 0;
}
return count;
}
STDMETHODIMP
LocationEvent::QueryInterface(REFIID iid, void** ppv) {
if (!ppv) {
return E_INVALIDARG;
}
if (iid == IID_IUnknown) {
*ppv = static_cast<IUnknown*>(this);
} else if (iid == IID_ILocationEvents) {
*ppv = static_cast<ILocationEvents*>(this);
} else {
*ppv = nullptr;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
STDMETHODIMP
LocationEvent::OnStatusChanged(REFIID aReportType,
LOCATION_REPORT_STATUS aStatus) {
LOG("LocationEvent::OnStatusChanged(%p, %p, %s, %04x)", this, mActor.get(),
aReportType == IID_ILatLongReport ? "true" : "false",
static_cast<uint32_t>(aStatus));
if (!mActor || aReportType != IID_ILatLongReport) {
return S_OK;
}
// When registering event, REPORT_INITIALIZING is fired at first.
// Then, when the location is found, REPORT_RUNNING is fired.
// We ignore those messages.
uint16_t err;
switch (aStatus) {
case REPORT_ACCESS_DENIED:
err = GeolocationPositionError_Binding::PERMISSION_DENIED;
break;
case REPORT_NOT_SUPPORTED:
case REPORT_ERROR:
err = GeolocationPositionError_Binding::POSITION_UNAVAILABLE;
break;
default:
return S_OK;
}
mActor->SendFailed(err);
return S_OK;
}
STDMETHODIMP
LocationEvent::OnLocationChanged(REFIID aReportType, ILocationReport* aReport) {
LOG("LocationEvent::OnLocationChanged(%p, %p, %s)", this, mActor.get(),
aReportType == IID_ILatLongReport ? "true" : "false");
if (!mActor || aReportType != IID_ILatLongReport) {
return S_OK;
}
RefPtr<ILatLongReport> latLongReport;
if (FAILED(aReport->QueryInterface(IID_ILatLongReport,
getter_AddRefs(latLongReport)))) {
return E_FAIL;
}
DOUBLE latitude = 0.0;
latLongReport->GetLatitude(&latitude);
DOUBLE longitude = 0.0;
latLongReport->GetLongitude(&longitude);
DOUBLE alt = UnspecifiedNaN<double>();
latLongReport->GetAltitude(&alt);
DOUBLE herror = 0.0;
latLongReport->GetErrorRadius(&herror);
DOUBLE verror = UnspecifiedNaN<double>();
latLongReport->GetAltitudeError(&verror);
double heading = UnspecifiedNaN<double>();
double speed = UnspecifiedNaN<double>();
// nsGeoPositionCoords will convert NaNs to null for optional properties of
// the JavaScript Coordinates object.
RefPtr<nsGeoPosition> position =
new nsGeoPosition(latitude, longitude, alt, herror, verror, heading,
speed, PR_Now() / PR_USEC_PER_MSEC);
mActor->SendUpdate(position);
return S_OK;
}
WindowsLocationChild::WindowsLocationChild() {
LOG("WindowsLocationChild::WindowsLocationChild(%p)", this);
}
WindowsLocationChild::~WindowsLocationChild() {
LOG("WindowsLocationChild::~WindowsLocationChild(%p)", this);
}
::mozilla::ipc::IPCResult WindowsLocationChild::RecvStartup() {
LOG("WindowsLocationChild::RecvStartup(%p, %p)", this, mLocation.get());
if (mLocation) {
return IPC_OK();
}
RefPtr<ILocation> location;
if (FAILED(::CoCreateInstance(CLSID_Location, nullptr, CLSCTX_INPROC_SERVER,
IID_ILocation, getter_AddRefs(location)))) {
LOG("WindowsLocationChild(%p) failed to create ILocation", this);
// We will use MLS provider
SendFailed(GeolocationPositionError_Binding::POSITION_UNAVAILABLE);
return IPC_OK();
}
IID reportTypes[] = {IID_ILatLongReport};
if (FAILED(location->RequestPermissions(nullptr, reportTypes, 1, FALSE))) {
LOG("WindowsLocationChild(%p) failed to set ILocation permissions", this);
// We will use MLS provider
SendFailed(GeolocationPositionError_Binding::POSITION_UNAVAILABLE);
return IPC_OK();
}
mLocation = location;
return IPC_OK();
}
::mozilla::ipc::IPCResult WindowsLocationChild::RecvSetHighAccuracy(
bool aEnable) {
LOG("WindowsLocationChild::RecvSetHighAccuracy(%p, %p, %s)", this,
mLocation.get(), aEnable ? "true" : "false");
// We sometimes call SetHighAccuracy before Startup, so we save the
// request and set it later, in RegisterForReport.
mHighAccuracy = aEnable;
return IPC_OK();
}
::mozilla::ipc::IPCResult WindowsLocationChild::RecvRegisterForReport() {
LOG("WindowsLocationChild::RecvRegisterForReport(%p, %p)", this,
mLocation.get());
if (!mLocation) {
SendFailed(GeolocationPositionError_Binding::POSITION_UNAVAILABLE);
return IPC_OK();
}
LOCATION_DESIRED_ACCURACY desiredAccuracy;
if (mHighAccuracy) {
desiredAccuracy = LOCATION_DESIRED_ACCURACY_HIGH;
} else {
desiredAccuracy = LOCATION_DESIRED_ACCURACY_DEFAULT;
}
if (NS_WARN_IF(FAILED(mLocation->SetDesiredAccuracy(IID_ILatLongReport,
desiredAccuracy)))) {
SendFailed(GeolocationPositionError_Binding::POSITION_UNAVAILABLE);
return IPC_OK();
}
auto event = MakeRefPtr<LocationEvent>(this);
if (NS_WARN_IF(
FAILED(mLocation->RegisterForReport(event, IID_ILatLongReport, 0)))) {
SendFailed(GeolocationPositionError_Binding::POSITION_UNAVAILABLE);
}
LOG("WindowsLocationChild::RecvRegisterForReport successfully registered");
return IPC_OK();
}
::mozilla::ipc::IPCResult WindowsLocationChild::RecvUnregisterForReport() {
LOG("WindowsLocationChild::RecvUnregisterForReport(%p, %p)", this,
mLocation.get());
if (!mLocation) {
return IPC_OK();
}
// This will free the LocationEvent we created in RecvRegisterForReport.
Unused << NS_WARN_IF(
FAILED(mLocation->UnregisterForReport(IID_ILatLongReport)));
// The ILocation object is not reusable. Unregistering, restarting and
// re-registering for reports does not work; the callback is never
// called in that case. For that reason, we re-create the ILocation
// object with a call to Startup after unregistering if we need it again.
mLocation = nullptr;
return IPC_OK();
}
void WindowsLocationChild::ActorDestroy(ActorDestroyReason aWhy) {
LOG("WindowsLocationChild::ActorDestroy(%p, %p)", this, mLocation.get());
mLocation = nullptr;
}
} // namespace mozilla::dom

View File

@@ -1,44 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_WindowsLocationChild_h__
#define mozilla_dom_WindowsLocationChild_h__
#include "mozilla/dom/PWindowsLocationChild.h"
#include "mozilla/WeakPtr.h"
class ILocation;
namespace mozilla::dom {
// Geolocation actor in utility process.
class WindowsLocationChild final : public PWindowsLocationChild,
public SupportsWeakPtr {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WindowsLocationChild, override);
public:
WindowsLocationChild();
using IPCResult = ::mozilla::ipc::IPCResult;
IPCResult RecvStartup();
IPCResult RecvRegisterForReport();
IPCResult RecvUnregisterForReport();
IPCResult RecvSetHighAccuracy(bool aEnable);
void ActorDestroy(ActorDestroyReason aWhy) override;
private:
~WindowsLocationChild() override;
// The COM object the actors are proxying calls for.
RefPtr<ILocation> mLocation;
bool mHighAccuracy = false;
};
} // namespace mozilla::dom
#endif // mozilla_dom_WindowsLocationChild_h__

View File

@@ -1,36 +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 "WindowsLocationParent.h"
#include "nsIDOMGeoPosition.h"
#include "WindowsLocationProvider.h"
namespace mozilla::dom {
::mozilla::ipc::IPCResult WindowsLocationParent::RecvUpdate(
RefPtr<nsIDOMGeoPosition> aGeoPosition) {
if (mProvider) {
mProvider->RecvUpdate(aGeoPosition);
}
return IPC_OK();
}
// A failure occurred. This may be translated into a
// nsIGeolocationUpdate::NotifyError or may be ignored if the MLS fallback
// is available.
::mozilla::ipc::IPCResult WindowsLocationParent::RecvFailed(uint16_t err) {
if (mProvider) {
mProvider->RecvFailed(err);
}
return IPC_OK();
}
void WindowsLocationParent::ActorDestroy(ActorDestroyReason aReason) {
if (mProvider) {
mProvider->ActorStopped();
}
}
} // namespace mozilla::dom

View File

@@ -1,52 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_WindowsLocationParent_h__
#define mozilla_dom_WindowsLocationParent_h__
#include "nsCOMPtr.h"
#include "mozilla/dom/PWindowsLocationParent.h"
class nsGeoPosition;
class nsIGeolocationUpdate;
namespace mozilla::dom {
class WindowsLocationProvider;
// Geolocation actor in main process.
// This may receive messages asynchronously, even after it sends Unregister
// to the child.
class WindowsLocationParent final : public PWindowsLocationParent {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WindowsLocationParent, override);
using IPCResult = ::mozilla::ipc::IPCResult;
explicit WindowsLocationParent(WindowsLocationProvider* aProvider)
: mProvider(aProvider) {}
// Update geolocation with new position information.
IPCResult RecvUpdate(RefPtr<nsIDOMGeoPosition> aGeoPosition);
// A failure occurred. This may be translated into a
// nsIGeolocationUpdate::NotifyError or may be ignored if the MLS fallback
// is available.
IPCResult RecvFailed(uint16_t err);
void ActorDestroy(ActorDestroyReason aReason) override;
// After this, the actor will simply ignore any incoming messages.
void DetachFromLocationProvider() { mProvider = nullptr; }
private:
~WindowsLocationParent() override = default;
WindowsLocationProvider* mProvider;
};
} // namespace mozilla::dom
#endif // mozilla_dom_WindowsLocationParent_h__

View File

@@ -5,12 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WindowsLocationProvider.h" #include "WindowsLocationProvider.h"
#include "WindowsLocationParent.h"
#include "WindowsUtilsParent.h"
#include "GeolocationPosition.h" #include "GeolocationPosition.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "mozilla/ipc/UtilityProcessManager.h"
#include "mozilla/ipc/UtilityProcessSandboxing.h"
#include "prtime.h" #include "prtime.h"
#include "MLSFallback.h" #include "MLSFallback.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
@@ -25,21 +21,13 @@ LazyLogModule gWindowsLocationProviderLog("WindowsLocationProvider");
#define LOG(...) \ #define LOG(...) \
MOZ_LOG(gWindowsLocationProviderLog, LogLevel::Debug, (__VA_ARGS__)) MOZ_LOG(gWindowsLocationProviderLog, LogLevel::Debug, (__VA_ARGS__))
class MLSUpdate : public nsIGeolocationUpdate { NS_IMPL_ISUPPORTS(WindowsLocationProvider::MLSUpdate, nsIGeolocationUpdate);
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIGEOLOCATIONUPDATE
explicit MLSUpdate(nsIGeolocationUpdate* aCallback) : mCallback(aCallback) {}
private: WindowsLocationProvider::MLSUpdate::MLSUpdate(nsIGeolocationUpdate* aCallback)
nsCOMPtr<nsIGeolocationUpdate> mCallback; : mCallback(aCallback) {}
virtual ~MLSUpdate() {}
};
NS_IMPL_ISUPPORTS(MLSUpdate, nsIGeolocationUpdate);
NS_IMETHODIMP NS_IMETHODIMP
MLSUpdate::Update(nsIDOMGeoPosition* aPosition) { WindowsLocationProvider::MLSUpdate::Update(nsIDOMGeoPosition* aPosition) {
if (!mCallback) { if (!mCallback) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@@ -53,7 +41,7 @@ MLSUpdate::Update(nsIDOMGeoPosition* aPosition) {
return mCallback->Update(aPosition); return mCallback->Update(aPosition);
} }
NS_IMETHODIMP NS_IMETHODIMP
MLSUpdate::NotifyError(uint16_t aError) { WindowsLocationProvider::MLSUpdate::NotifyError(uint16_t aError) {
if (!mCallback) { if (!mCallback) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@@ -61,236 +49,203 @@ MLSUpdate::NotifyError(uint16_t aError) {
return callback->NotifyError(aError); return callback->NotifyError(aError);
} }
class LocationEvent final : public ILocationEvents {
public:
LocationEvent(nsIGeolocationUpdate* aCallback,
WindowsLocationProvider* aProvider)
: mCallback(aCallback), mProvider(aProvider), mCount(0) {}
// IUnknown interface
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
STDMETHODIMP QueryInterface(REFIID iid, void** ppv) override;
// ILocationEvents interface
MOZ_CAN_RUN_SCRIPT_BOUNDARY
STDMETHODIMP OnStatusChanged(REFIID aReportType,
LOCATION_REPORT_STATUS aStatus) override;
STDMETHODIMP OnLocationChanged(REFIID aReportType,
ILocationReport* aReport) override;
private:
nsCOMPtr<nsIGeolocationUpdate> mCallback;
RefPtr<WindowsLocationProvider> mProvider;
ULONG mCount;
};
STDMETHODIMP_(ULONG)
LocationEvent::AddRef() { return InterlockedIncrement(&mCount); }
STDMETHODIMP_(ULONG)
LocationEvent::Release() {
ULONG count = InterlockedDecrement(&mCount);
if (!count) {
delete this;
return 0;
}
return count;
}
STDMETHODIMP
LocationEvent::QueryInterface(REFIID iid, void** ppv) {
if (iid == IID_IUnknown) {
*ppv = static_cast<IUnknown*>(this);
} else if (iid == IID_ILocationEvents) {
*ppv = static_cast<ILocationEvents*>(this);
} else {
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
STDMETHODIMP
LocationEvent::OnStatusChanged(REFIID aReportType,
LOCATION_REPORT_STATUS aStatus) {
if (aReportType != IID_ILatLongReport) {
return S_OK;
}
// When registering event, REPORT_INITIALIZING is fired at first.
// Then, when the location is found, REPORT_RUNNING is fired.
if (aStatus == REPORT_RUNNING) {
// location is found by Windows Location provider, we use it.
mProvider->CancelMLSProvider();
return S_OK;
}
// Cannot get current location at this time. We use MLS instead until
// Location API returns RUNNING status.
if (NS_SUCCEEDED(mProvider->CreateAndWatchMLSProvider(mCallback))) {
return S_OK;
}
// Cannot watch location by MLS provider. We must return error by
// Location API.
uint16_t err;
switch (aStatus) {
case REPORT_ACCESS_DENIED:
err = GeolocationPositionError_Binding::PERMISSION_DENIED;
break;
case REPORT_NOT_SUPPORTED:
case REPORT_ERROR:
err = GeolocationPositionError_Binding::POSITION_UNAVAILABLE;
break;
default:
return S_OK;
}
nsCOMPtr<nsIGeolocationUpdate> callback(mCallback);
callback->NotifyError(err);
return S_OK;
}
STDMETHODIMP
LocationEvent::OnLocationChanged(REFIID aReportType, ILocationReport* aReport) {
if (aReportType != IID_ILatLongReport) {
return S_OK;
}
RefPtr<ILatLongReport> latLongReport;
if (FAILED(aReport->QueryInterface(IID_ILatLongReport,
getter_AddRefs(latLongReport)))) {
return E_FAIL;
}
DOUBLE latitude = 0.0;
latLongReport->GetLatitude(&latitude);
DOUBLE longitude = 0.0;
latLongReport->GetLongitude(&longitude);
DOUBLE alt = UnspecifiedNaN<double>();
latLongReport->GetAltitude(&alt);
DOUBLE herror = 0.0;
latLongReport->GetErrorRadius(&herror);
DOUBLE verror = UnspecifiedNaN<double>();
latLongReport->GetAltitudeError(&verror);
double heading = UnspecifiedNaN<double>();
double speed = UnspecifiedNaN<double>();
// nsGeoPositionCoords will convert NaNs to null for optional properties of
// the JavaScript Coordinates object.
RefPtr<nsGeoPosition> position =
new nsGeoPosition(latitude, longitude, alt, herror, verror, heading,
speed, PR_Now() / PR_USEC_PER_MSEC);
mCallback->Update(position);
Telemetry::Accumulate(Telemetry::GEOLOCATION_WIN8_SOURCE_IS_MLS, false);
return S_OK;
}
NS_IMPL_ISUPPORTS(WindowsLocationProvider, nsIGeolocationProvider) NS_IMPL_ISUPPORTS(WindowsLocationProvider, nsIGeolocationProvider)
WindowsLocationProvider::WindowsLocationProvider() { WindowsLocationProvider::WindowsLocationProvider() {
LOG("WindowsLocationProvider::WindowsLocationProvider(%p)", this); LOG("WindowsLocationProvider::WindowsLocationProvider(%p)\n", this);
MOZ_ASSERT(XRE_IsParentProcess());
MaybeCreateLocationActor();
} }
WindowsLocationProvider::~WindowsLocationProvider() { WindowsLocationProvider::~WindowsLocationProvider() {
LOG("WindowsLocationProvider::~WindowsLocationProvider(%p,%p,%p)", this, LOG("WindowsLocationProvider::~WindowsLocationProvider(%p, %p)\n", this,
mActor.get(), mActorPromise.get()); mLocation.get());
Send__delete__();
ReleaseUtilityProcess();
CancelMLSProvider();
}
void WindowsLocationProvider::MaybeCreateLocationActor() {
LOG("WindowsLocationProvider::MaybeCreateLocationActor(%p)", this);
if (mActor || mActorPromise) {
return;
}
auto utilityProc = mozilla::ipc::UtilityProcessManager::GetSingleton();
MOZ_ASSERT(utilityProc);
// Create a PWindowsLocation actor in the Windows utility process.
// This will attempt to launch the process if it doesn't already exist.
RefPtr<WindowsLocationProvider> self = this;
auto wuPromise = utilityProc->GetWindowsUtilsPromise();
mActorPromise = wuPromise->Then(
GetCurrentSerialEventTarget(), __func__,
[self](RefPtr<WindowsUtilsParent> wup) {
self->mActorPromise = nullptr;
auto actor = MakeRefPtr<WindowsLocationParent>(self);
if (!wup->SendPWindowsLocationConstructor(actor)) {
LOG("WindowsLocationProvider(%p) SendPWindowsLocationConstructor "
"failed",
self.get());
actor->DetachFromLocationProvider();
self->mActor = nullptr;
return WindowsLocationPromise::CreateAndReject(false, __func__);
}
LOG("WindowsLocationProvider connected to actor (%p,%p,%p)", self.get(),
self->mActor.get(), self->mActorPromise.get());
self->mActor = actor;
return WindowsLocationPromise::CreateAndResolve(self->mActor, __func__);
},
[self](nsresult aError) {
LOG("WindowsLocationProvider failed to connect to actor (%p,%p,%p)",
self.get(), self->mActor.get(), self->mActorPromise.get());
self->mActorPromise = nullptr;
return WindowsLocationPromise::CreateAndReject(false, __func__);
});
if (mActor) {
// Utility process already existed and mActorPromise was resolved
// immediately.
mActorPromise = nullptr;
}
}
void WindowsLocationProvider::ReleaseUtilityProcess() {
LOG("WindowsLocationProvider::ReleaseUtilityProcess(%p)", this);
auto utilityProc = mozilla::ipc::UtilityProcessManager::GetSingleton();
if (utilityProc) {
utilityProc->ReleaseWindowsUtils();
}
}
template <typename Fn>
bool WindowsLocationProvider::WhenActorIsReady(Fn&& fn) {
if (mActor) {
return fn(mActor);
}
if (mActorPromise) {
mActorPromise->Then(
GetCurrentSerialEventTarget(), __func__,
[fn](const RefPtr<WindowsLocationParent>& actor) {
Unused << fn(actor.get());
return actor;
},
[](bool) { return false; });
return true;
}
// The remote process failed to start.
return false;
}
bool WindowsLocationProvider::SendStartup() {
LOG("WindowsLocationProvider::SendStartup(%p)", this);
MaybeCreateLocationActor();
return WhenActorIsReady(
[](WindowsLocationParent* actor) { return actor->SendStartup(); });
}
bool WindowsLocationProvider::SendRegisterForReport(
nsIGeolocationUpdate* aCallback) {
LOG("WindowsLocationProvider::SendRegisterForReport(%p)", this);
RefPtr<WindowsLocationProvider> self = this;
RefPtr<nsIGeolocationUpdate> cb = aCallback;
return WhenActorIsReady([self, cb](WindowsLocationParent* actor) {
MOZ_ASSERT(!self->mCallback);
if (actor->SendRegisterForReport()) {
self->mCallback = cb;
return true;
}
return false;
});
}
bool WindowsLocationProvider::SendUnregisterForReport() {
LOG("WindowsLocationProvider::SendUnregisterForReport(%p)", this);
RefPtr<WindowsLocationProvider> self = this;
return WhenActorIsReady([self](WindowsLocationParent* actor) {
self->mCallback = nullptr;
if (actor->SendUnregisterForReport()) {
return true;
}
return false;
});
}
bool WindowsLocationProvider::SendSetHighAccuracy(bool aEnable) {
LOG("WindowsLocationProvider::SendSetHighAccuracy(%p)", this);
return WhenActorIsReady([aEnable](WindowsLocationParent* actor) {
return actor->SendSetHighAccuracy(aEnable);
});
}
bool WindowsLocationProvider::Send__delete__() {
LOG("WindowsLocationProvider::Send__delete__(%p)", this);
return WhenActorIsReady([self = RefPtr{this}](WindowsLocationParent*) {
if (WindowsLocationParent::Send__delete__(self->mActor)) {
if (self->mActor) {
self->mActor->DetachFromLocationProvider();
self->mActor = nullptr;
}
return true;
}
return false;
});
}
void WindowsLocationProvider::RecvUpdate(
RefPtr<nsIDOMGeoPosition> aGeoPosition) {
LOG("WindowsLocationProvider::RecvUpdate(%p)", this);
if (!mCallback) {
return;
}
mCallback->Update(aGeoPosition.get());
Telemetry::Accumulate(Telemetry::GEOLOCATION_WIN8_SOURCE_IS_MLS, false);
}
void WindowsLocationProvider::RecvFailed(uint16_t err) {
LOG("WindowsLocationProvider::RecvFailed(%p)", this);
// Cannot get current location at this time. We use MLS instead.
if (mMLSProvider || !mCallback) {
return;
}
if (NS_SUCCEEDED(CreateAndWatchMLSProvider(mCallback))) {
return;
}
// No ILocation and no MLS, so we have failed completely.
// We keep strong references to objects that we need to guarantee
// will live past the NotifyError callback.
RefPtr<WindowsLocationProvider> self = this;
nsCOMPtr<nsIGeolocationUpdate> callback = mCallback;
callback->NotifyError(err);
}
void WindowsLocationProvider::ActorStopped() {
// ActorDestroy has run. Make sure UtilityProcessHost no longer tries to use
// it.
ReleaseUtilityProcess();
if (mWatching) {
// Treat as remote geolocation error, which will cause it to fallback
// to MLS if it hasn't already.
mWatching = false;
RecvFailed(GeolocationPositionError_Binding::POSITION_UNAVAILABLE);
return;
}
MOZ_ASSERT(!mActorPromise);
if (mActor) {
mActor->DetachFromLocationProvider();
mActor = nullptr;
}
} }
NS_IMETHODIMP NS_IMETHODIMP
WindowsLocationProvider::Startup() { WindowsLocationProvider::Startup() {
LOG("WindowsLocationProvider::Startup(%p, %p, %p)", this, mActor.get(), LOG("WindowsLocationProvider::Startup(%p, %p)\n", this, mLocation.get());
mActorPromise.get()); if (mLocation) {
// If this fails, we will use the MLS fallback. return NS_OK;
SendStartup(); }
RefPtr<ILocation> location;
if (FAILED(::CoCreateInstance(CLSID_Location, nullptr, CLSCTX_INPROC_SERVER,
IID_ILocation, getter_AddRefs(location)))) {
// We will use MLS provider
return NS_OK;
}
IID reportTypes[] = {IID_ILatLongReport};
if (FAILED(location->RequestPermissions(nullptr, reportTypes, 1, FALSE))) {
// We will use MLS provider
return NS_OK;
}
mLocation = location;
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
WindowsLocationProvider::Watch(nsIGeolocationUpdate* aCallback) { WindowsLocationProvider::Watch(nsIGeolocationUpdate* aCallback) {
LOG("WindowsLocationProvider::Watch(%p, %p, %p, %p, %d)", this, mActor.get(), LOG("WindowsLocationProvider::Watch(%p, %p, %d)\n", this, mLocation.get(),
mActorPromise.get(), aCallback, mWatching); mWatching);
if (mWatching) { if (mLocation) {
return NS_OK; if (mWatching) {
return NS_OK;
}
RefPtr<LocationEvent> event = new LocationEvent(aCallback, this);
if (SUCCEEDED(mLocation->RegisterForReport(event, IID_ILatLongReport, 0))) {
mWatching = true;
return NS_OK;
}
} }
if (SendRegisterForReport(aCallback)) { // Cannot use Location API. We will use MLS instead.
mWatching = true; LOG(" > MLS fallback\n");
return NS_OK; mLocation = nullptr;
}
// Couldn't send request. We will use MLS instead.
return CreateAndWatchMLSProvider(aCallback); return CreateAndWatchMLSProvider(aCallback);
} }
NS_IMETHODIMP NS_IMETHODIMP
WindowsLocationProvider::Shutdown() { WindowsLocationProvider::Shutdown() {
LOG("WindowsLocationProvider::Shutdown(%p, %p, %p)", this, mActor.get(), LOG("WindowsLocationProvider::Shutdown(%p, %p)\n", this, mLocation.get());
mActorPromise.get()); if (mLocation) {
if (mWatching) {
if (mWatching) { mLocation->UnregisterForReport(IID_ILatLongReport);
SendUnregisterForReport(); }
mLocation = nullptr;
mWatching = false; mWatching = false;
} }
@@ -300,29 +255,26 @@ WindowsLocationProvider::Shutdown() {
NS_IMETHODIMP NS_IMETHODIMP
WindowsLocationProvider::SetHighAccuracy(bool enable) { WindowsLocationProvider::SetHighAccuracy(bool enable) {
LOG("WindowsLocationProvider::SetHighAccuracy(%p, %p, %p, %s)", this, if (!mLocation) {
mActor.get(), mActorPromise.get(), enable ? "true" : "false"); // MLS provider doesn't support HighAccuracy
if (mMLSProvider) {
// Ignored when running MLS fallback.
return NS_OK; return NS_OK;
} }
if (!SendSetHighAccuracy(enable)) { LOCATION_DESIRED_ACCURACY desiredAccuracy;
if (enable) {
desiredAccuracy = LOCATION_DESIRED_ACCURACY_HIGH;
} else {
desiredAccuracy = LOCATION_DESIRED_ACCURACY_DEFAULT;
}
if (FAILED(
mLocation->SetDesiredAccuracy(IID_ILatLongReport, desiredAccuracy))) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
// Since we SendSetHighAccuracy asynchronously, we cannot say for sure
// that it will succeed. If it does fail then we will get a
// RecvFailed IPC message, which will cause a fallback to MLS.
return NS_OK; return NS_OK;
} }
nsresult WindowsLocationProvider::CreateAndWatchMLSProvider( nsresult WindowsLocationProvider::CreateAndWatchMLSProvider(
nsIGeolocationUpdate* aCallback) { nsIGeolocationUpdate* aCallback) {
LOG("WindowsLocationProvider::CreateAndWatchMLSProvider"
"(%p, %p, %p, %p, %p)",
this, mMLSProvider.get(), mActor.get(), mActorPromise.get(), aCallback);
if (mMLSProvider) { if (mMLSProvider) {
return NS_OK; return NS_OK;
} }
@@ -332,11 +284,6 @@ nsresult WindowsLocationProvider::CreateAndWatchMLSProvider(
} }
void WindowsLocationProvider::CancelMLSProvider() { void WindowsLocationProvider::CancelMLSProvider() {
LOG("WindowsLocationProvider::CancelMLSProvider"
"(%p, %p, %p, %p, %p)",
this, mMLSProvider.get(), mActor.get(), mActorPromise.get(),
mCallback.get());
if (!mMLSProvider) { if (!mMLSProvider) {
return; return;
} }

View File

@@ -9,17 +9,13 @@
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsIGeolocationProvider.h" #include "nsIGeolocationProvider.h"
#include "mozilla/MozPromise.h"
#include <locationapi.h>
class MLSFallback; class MLSFallback;
namespace mozilla::dom { namespace mozilla::dom {
class WindowsLocationParent;
// Uses a PWindowsLocation actor to subscribe to geolocation updates from the
// Windows utility process and falls back to MLS when it is not available or
// fails.
class WindowsLocationProvider final : public nsIGeolocationProvider { class WindowsLocationProvider final : public nsIGeolocationProvider {
public: public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@@ -27,49 +23,25 @@ class WindowsLocationProvider final : public nsIGeolocationProvider {
WindowsLocationProvider(); WindowsLocationProvider();
private:
friend WindowsLocationParent;
~WindowsLocationProvider();
nsresult CreateAndWatchMLSProvider(nsIGeolocationUpdate* aCallback); nsresult CreateAndWatchMLSProvider(nsIGeolocationUpdate* aCallback);
void CancelMLSProvider(); void CancelMLSProvider();
void MaybeCreateLocationActor(); class MLSUpdate : public nsIGeolocationUpdate {
void ReleaseUtilityProcess(); public:
NS_DECL_ISUPPORTS
NS_DECL_NSIGEOLOCATIONUPDATE
explicit MLSUpdate(nsIGeolocationUpdate* aCallback);
// These methods either send the message on the existing actor or queue private:
// the messages to be sent (in order) once the actor exists. nsCOMPtr<nsIGeolocationUpdate> mCallback;
bool SendStartup(); virtual ~MLSUpdate() {}
bool SendRegisterForReport(nsIGeolocationUpdate* aCallback); };
bool SendUnregisterForReport();
bool SendSetHighAccuracy(bool aEnable);
bool Send__delete__();
void RecvUpdate(RefPtr<nsIDOMGeoPosition> aGeoPosition); private:
// See bug 1539864 for MOZ_CAN_RUN_SCRIPT_BOUNDARY justification. ~WindowsLocationProvider();
MOZ_CAN_RUN_SCRIPT_BOUNDARY void RecvFailed(uint16_t err);
// The utility process actor has ended its connection, either successfully
// or with an error.
void ActorStopped();
// Run fn once actor is ready to send messages, which may be immediately.
template <typename Fn>
bool WhenActorIsReady(Fn&& fn);
RefPtr<ILocation> mLocation;
RefPtr<MLSFallback> mMLSProvider; RefPtr<MLSFallback> mMLSProvider;
nsCOMPtr<nsIGeolocationUpdate> mCallback;
using WindowsLocationPromise =
MozPromise<RefPtr<WindowsLocationParent>, bool, false>;
// Before the utility process exists, we have a promise that we will get our
// location actor. mActor and mActorPromise are never both set.
RefPtr<WindowsLocationPromise> mActorPromise;
RefPtr<WindowsLocationParent> mActor;
bool mWatching = false; bool mWatching = false;
}; };

View File

@@ -1,30 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_WindowsUtilsChild_h__
#define mozilla_dom_WindowsUtilsChild_h__
#include "mozilla/dom/PWindowsUtilsChild.h"
#include "mozilla/dom/WindowsLocationChild.h"
namespace mozilla::dom {
// Manager for utilities in the WindowsUtils utility process.
class WindowsUtilsChild final : public PWindowsUtilsChild {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WindowsUtilsChild, override);
public:
already_AddRefed<PWindowsLocationChild> AllocPWindowsLocationChild() {
return MakeAndAddRef<WindowsLocationChild>();
}
protected:
~WindowsUtilsChild() = default;
};
} // namespace mozilla::dom
#endif // mozilla_dom_WindowsUtilsChild_h__

View File

@@ -1,52 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_WindowsUtilsParent_h__
#define mozilla_dom_WindowsUtilsParent_h__
#include "mozilla/dom/PWindowsUtilsParent.h"
#include "mozilla/ProcInfo.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/ipc/UtilityProcessParent.h"
namespace mozilla::dom {
// Main-process manager for utilities in the WindowsUtils utility process.
class WindowsUtilsParent final : public PWindowsUtilsParent {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WindowsUtilsParent, override);
nsresult BindToUtilityProcess(
RefPtr<mozilla::ipc::UtilityProcessParent> aUtilityParent) {
Endpoint<PWindowsUtilsParent> parentEnd;
Endpoint<PWindowsUtilsChild> childEnd;
nsresult rv = PWindowsUtils::CreateEndpoints(base::GetCurrentProcId(),
aUtilityParent->OtherPid(),
&parentEnd, &childEnd);
if (NS_FAILED(rv)) {
MOZ_ASSERT(false, "Protocol endpoints failure");
return NS_ERROR_FAILURE;
}
if (!aUtilityParent->SendStartWindowsUtilsService(std::move(childEnd))) {
MOZ_ASSERT(false, "SendStartWindowsUtilsService failed");
return NS_ERROR_FAILURE;
}
DebugOnly<bool> ok = parentEnd.Bind(this);
MOZ_ASSERT(ok);
return NS_OK;
}
UtilityActorName GetActorName() { return UtilityActorName::WindowsUtils; }
protected:
~WindowsUtilsParent() = default;
};
} // namespace mozilla::dom
#endif // mozilla_dom_WindowsUtilsParent_h__

View File

@@ -4,30 +4,8 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # 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/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.dom += [ SOURCES += ["nsHapticFeedback.cpp", "WindowsLocationProvider.cpp"]
"WindowsLocationChild.h",
"WindowsLocationParent.h",
"WindowsUtilsChild.h",
"WindowsUtilsParent.h",
]
UNIFIED_SOURCES += [
"nsHapticFeedback.cpp",
"WindowsLocationParent.cpp",
"WindowsLocationProvider.cpp",
]
SOURCES += [
"WindowsLocationChild.cpp", # includes locationapi.h
]
IPDL_SOURCES += [
"PWindowsLocation.ipdl",
"PWindowsUtils.ipdl",
]
LOCAL_INCLUDES += ["/dom/geolocation"] LOCAL_INCLUDES += ["/dom/geolocation"]
include("/ipc/chromium/chromium-config.mozbuild")
FINAL_LIBRARY = "xul" FINAL_LIBRARY = "xul"

View File

@@ -42,6 +42,10 @@ implementing the trivial example visible in `EmptyUtil
+ Add member within `enum WebIDLUtilityActorName in <https://searchfox.org/mozilla-central/rev/fb511723f821ceabeea23b123f1c50c9e93bde9d/dom/chrome-webidl/ChromeUtils.webidl#686-689>`_ + Add member within `enum WebIDLUtilityActorName in <https://searchfox.org/mozilla-central/rev/fb511723f821ceabeea23b123f1c50c9e93bde9d/dom/chrome-webidl/ChromeUtils.webidl#686-689>`_
+ Add member within `enum class UtilityActorName of <https://searchfox.org/mozilla-central/rev/fb511723f821ceabeea23b123f1c50c9e93bde9d/toolkit/components/processtools/ProcInfo.h#71-74>`_
+ Update mapping in `switch case <https://searchfox.org/mozilla-central/rev/fb511723f821ceabeea23b123f1c50c9e93bde9d/dom/base/ChromeUtils.cpp#916-919>`_ and update the `static assert <https://searchfox.org/mozilla-central/rev/fb511723f821ceabeea23b123f1c50c9e93bde9d/dom/base/ChromeUtils.cpp#910-911>`_
- Handle reception of ``StartEmptyUtilService`` on the child side of - Handle reception of ``StartEmptyUtilService`` on the child side of
``UtilityProcess`` within ``RecvStartEmptyUtilService()`` ``UtilityProcess`` within ``RecvStartEmptyUtilService()``

View File

@@ -10,10 +10,6 @@ include protocol PProfiler;
include protocol PUtilityAudioDecoder; include protocol PUtilityAudioDecoder;
include protocol PJSOracle; include protocol PJSOracle;
#if defined(XP_WIN)
include protocol PWindowsUtils;
#endif
#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS) #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
include protocol PSandboxTesting; include protocol PSandboxTesting;
#endif #endif
@@ -89,10 +85,6 @@ child:
async StartJSOracleService(Endpoint<PJSOracleChild> aEndpoint); async StartJSOracleService(Endpoint<PJSOracleChild> aEndpoint);
#if defined(XP_WIN)
async StartWindowsUtilsService(Endpoint<PWindowsUtilsChild> aEndpoint);
#endif
#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS) #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
async InitSandboxTesting(Endpoint<PSandboxTestingChild> aEndpoint); async InitSandboxTesting(Endpoint<PSandboxTestingChild> aEndpoint);
#endif #endif

View File

@@ -28,7 +28,6 @@
#if defined(XP_WIN) #if defined(XP_WIN)
# include "mozilla/WinDllServices.h" # include "mozilla/WinDllServices.h"
# include "mozilla/dom/WindowsUtilsChild.h"
#endif #endif
#include "nsDebugImpl.h" #include "nsDebugImpl.h"
@@ -250,20 +249,6 @@ mozilla::ipc::IPCResult UtilityProcessChild::RecvStartJSOracleService(
return IPC_OK(); return IPC_OK();
} }
#ifdef XP_WIN
mozilla::ipc::IPCResult UtilityProcessChild::RecvStartWindowsUtilsService(
Endpoint<dom::PWindowsUtilsChild>&& aEndpoint) {
mWindowsUtilsInstance = new dom::WindowsUtilsChild();
if (!mWindowsUtilsInstance) {
return IPC_FAIL(this, "Failed to create WindowsUtilsChild");
}
[[maybe_unused]] bool ok = std::move(aEndpoint).Bind(mWindowsUtilsInstance);
MOZ_ASSERT(ok);
return IPC_OK();
}
#endif
void UtilityProcessChild::ActorDestroy(ActorDestroyReason aWhy) { void UtilityProcessChild::ActorDestroy(ActorDestroyReason aWhy) {
if (AbnormalShutdown == aWhy) { if (AbnormalShutdown == aWhy) {
NS_WARNING("Shutting down Utility process early due to a crash!"); NS_WARNING("Shutting down Utility process early due to a crash!");

View File

@@ -63,11 +63,6 @@ class UtilityProcessChild final : public PUtilityProcessChild {
mozilla::ipc::IPCResult RecvStartJSOracleService( mozilla::ipc::IPCResult RecvStartJSOracleService(
Endpoint<dom::PJSOracleChild>&& aEndpoint); Endpoint<dom::PJSOracleChild>&& aEndpoint);
#ifdef XP_WIN
mozilla::ipc::IPCResult RecvStartWindowsUtilsService(
Endpoint<PWindowsUtilsChild>&& aEndpoint);
#endif
AsyncBlockers& AsyncShutdownService() { return mShutdownBlockers; } AsyncBlockers& AsyncShutdownService() { return mShutdownBlockers; }
void ActorDestroy(ActorDestroyReason aWhy) override; void ActorDestroy(ActorDestroyReason aWhy) override;
@@ -85,10 +80,6 @@ class UtilityProcessChild final : public PUtilityProcessChild {
RefPtr<ChildProfilerController> mProfilerController; RefPtr<ChildProfilerController> mProfilerController;
RefPtr<UtilityAudioDecoderParent> mUtilityAudioDecoderInstance{}; RefPtr<UtilityAudioDecoderParent> mUtilityAudioDecoderInstance{};
RefPtr<dom::JSOracleChild> mJSOracleInstance{}; RefPtr<dom::JSOracleChild> mJSOracleInstance{};
#ifdef XP_WIN
RefPtr<PWindowsUtilsChild> mWindowsUtilsInstance;
#endif
AsyncBlockers mShutdownBlockers; AsyncBlockers mShutdownBlockers;
}; };

View File

@@ -28,9 +28,6 @@
namespace mozilla::ipc { namespace mozilla::ipc {
LazyLogModule gUtilityProcessLog("utilityproc");
#define LOGD(...) MOZ_LOG(gUtilityProcessLog, LogLevel::Debug, (__VA_ARGS__))
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX) #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
bool UtilityProcessHost::sLaunchWithMacSandbox = false; bool UtilityProcessHost::sLaunchWithMacSandbox = false;
#endif #endif
@@ -41,9 +38,6 @@ UtilityProcessHost::UtilityProcessHost(SandboxingKind aSandbox,
mListener(std::move(aListener)), mListener(std::move(aListener)),
mLiveToken(new media::Refcountable<bool>(true)) { mLiveToken(new media::Refcountable<bool>(true)) {
MOZ_COUNT_CTOR(UtilityProcessHost); MOZ_COUNT_CTOR(UtilityProcessHost);
LOGD("[%p] UtilityProcessHost::UtilityProcessHost sandboxingKind=%" PRIu64,
this, aSandbox);
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX) #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
if (!sLaunchWithMacSandbox) { if (!sLaunchWithMacSandbox) {
sLaunchWithMacSandbox = sLaunchWithMacSandbox =
@@ -58,12 +52,6 @@ UtilityProcessHost::UtilityProcessHost(SandboxingKind aSandbox,
UtilityProcessHost::~UtilityProcessHost() { UtilityProcessHost::~UtilityProcessHost() {
MOZ_COUNT_DTOR(UtilityProcessHost); MOZ_COUNT_DTOR(UtilityProcessHost);
#if defined(MOZ_SANDBOX)
LOGD("[%p] UtilityProcessHost::~UtilityProcessHost sandboxingKind=%" PRIu64,
this, mSandbox);
#else
LOGD("[%p] UtilityProcessHost::~UtilityProcessHost", this);
#endif
} }
bool UtilityProcessHost::Launch(StringVector aExtraOpts) { bool UtilityProcessHost::Launch(StringVector aExtraOpts) {
@@ -72,8 +60,6 @@ bool UtilityProcessHost::Launch(StringVector aExtraOpts) {
MOZ_ASSERT(mLaunchPhase == LaunchPhase::Unlaunched); MOZ_ASSERT(mLaunchPhase == LaunchPhase::Unlaunched);
MOZ_ASSERT(!mUtilityProcessParent); MOZ_ASSERT(!mUtilityProcessParent);
LOGD("[%p] UtilityProcessHost::Launch", this);
mPrefSerializer = MakeUnique<ipc::SharedPreferenceSerializer>(); mPrefSerializer = MakeUnique<ipc::SharedPreferenceSerializer>();
if (!mPrefSerializer->SerializeToSharedMemory(GeckoProcessType_Utility, if (!mPrefSerializer->SerializeToSharedMemory(GeckoProcessType_Utility,
/* remoteType */ ""_ns)) { /* remoteType */ ""_ns)) {
@@ -121,7 +107,6 @@ bool UtilityProcessHost::Launch(StringVector aExtraOpts) {
mPrefSerializer = nullptr; mPrefSerializer = nullptr;
return false; return false;
} }
LOGD("[%p] UtilityProcessHost::Launch launching async", this);
return true; return true;
} }
@@ -158,7 +143,6 @@ RefPtr<GenericNonExclusivePromise> UtilityProcessHost::LaunchPromise() {
void UtilityProcessHost::OnChannelConnected(base::ProcessId peer_pid) { void UtilityProcessHost::OnChannelConnected(base::ProcessId peer_pid) {
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!NS_IsMainThread());
LOGD("[%p] UtilityProcessHost::OnChannelConnected", this);
GeckoChildProcessHost::OnChannelConnected(peer_pid); GeckoChildProcessHost::OnChannelConnected(peer_pid);
@@ -173,7 +157,6 @@ void UtilityProcessHost::OnChannelConnected(base::ProcessId peer_pid) {
void UtilityProcessHost::OnChannelError() { void UtilityProcessHost::OnChannelError() {
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!NS_IsMainThread());
LOGD("[%p] UtilityProcessHost::OnChannelError", this);
GeckoChildProcessHost::OnChannelError(); GeckoChildProcessHost::OnChannelError();
@@ -238,8 +221,6 @@ void UtilityProcessHost::InitAfterConnect(bool aSucceeded) {
Unused << GetActor()->SendInitProfiler( Unused << GetActor()->SendInitProfiler(
ProfilerParent::CreateForProcess(GetActor()->OtherPid())); ProfilerParent::CreateForProcess(GetActor()->OtherPid()));
LOGD("[%p] UtilityProcessHost::InitAfterConnect succeeded", this);
// Promise will be resolved later, from UtilityProcessParent when the child // Promise will be resolved later, from UtilityProcessParent when the child
// will send the InitCompleted message. // will send the InitCompleted message.
} }
@@ -247,14 +228,10 @@ void UtilityProcessHost::InitAfterConnect(bool aSucceeded) {
void UtilityProcessHost::Shutdown() { void UtilityProcessHost::Shutdown() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mShutdownRequested); MOZ_ASSERT(!mShutdownRequested);
LOGD("[%p] UtilityProcessHost::Shutdown", this);
RejectPromise(); RejectPromise();
if (mUtilityProcessParent) { if (mUtilityProcessParent) {
LOGD("[%p] UtilityProcessHost::Shutdown not destroying utility process.",
this);
// OnChannelClosed uses this to check if the shutdown was expected or // OnChannelClosed uses this to check if the shutdown was expected or
// unexpected. // unexpected.
mShutdownRequested = true; mShutdownRequested = true;
@@ -284,7 +261,6 @@ void UtilityProcessHost::Shutdown() {
void UtilityProcessHost::OnChannelClosed() { void UtilityProcessHost::OnChannelClosed() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
LOGD("[%p] UtilityProcessHost::OnChannelClosed", this);
RejectPromise(); RejectPromise();
@@ -301,7 +277,6 @@ void UtilityProcessHost::OnChannelClosed() {
void UtilityProcessHost::KillHard(const char* aReason) { void UtilityProcessHost::KillHard(const char* aReason) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
LOGD("[%p] UtilityProcessHost::KillHard", this);
ProcessHandle handle = GetChildProcessHandle(); ProcessHandle handle = GetChildProcessHandle();
if (!base::KillProcess(handle, base::PROCESS_END_KILLED_BY_USER)) { if (!base::KillProcess(handle, base::PROCESS_END_KILLED_BY_USER)) {
@@ -313,8 +288,6 @@ void UtilityProcessHost::KillHard(const char* aReason) {
void UtilityProcessHost::DestroyProcess() { void UtilityProcessHost::DestroyProcess() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
LOGD("[%p] UtilityProcessHost::DestroyProcess", this);
RejectPromise(); RejectPromise();
// Any pending tasks will be cancelled from now on. // Any pending tasks will be cancelled from now on.
@@ -326,7 +299,6 @@ void UtilityProcessHost::DestroyProcess() {
void UtilityProcessHost::ResolvePromise() { void UtilityProcessHost::ResolvePromise() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
LOGD("[%p] UtilityProcessHost connected - resolving launch promise", this);
if (!mLaunchPromiseSettled) { if (!mLaunchPromiseSettled) {
mLaunchPromise->Resolve(true, __func__); mLaunchPromise->Resolve(true, __func__);
@@ -339,8 +311,6 @@ void UtilityProcessHost::ResolvePromise() {
void UtilityProcessHost::RejectPromise() { void UtilityProcessHost::RejectPromise() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
LOGD("[%p] UtilityProcessHost connection failed - rejecting launch promise",
this);
if (!mLaunchPromiseSettled) { if (!mLaunchPromiseSettled) {
mLaunchPromise->Reject(NS_ERROR_FAILURE, __func__); mLaunchPromise->Reject(NS_ERROR_FAILURE, __func__);

View File

@@ -21,17 +21,10 @@
#include "nsAppRunner.h" #include "nsAppRunner.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#ifdef XP_WIN
# include "mozilla/dom/WindowsUtilsParent.h"
#endif
#include "mozilla/GeckoArgs.h" #include "mozilla/GeckoArgs.h"
namespace mozilla::ipc { namespace mozilla::ipc {
extern LazyLogModule gUtilityProcessLog;
#define LOGD(...) MOZ_LOG(gUtilityProcessLog, LogLevel::Debug, (__VA_ARGS__))
static StaticRefPtr<UtilityProcessManager> sSingleton; static StaticRefPtr<UtilityProcessManager> sSingleton;
static bool sXPCOMShutdown = false; static bool sXPCOMShutdown = false;
@@ -57,8 +50,6 @@ RefPtr<UtilityProcessManager> UtilityProcessManager::GetIfExists() {
} }
UtilityProcessManager::UtilityProcessManager() : mObserver(new Observer(this)) { UtilityProcessManager::UtilityProcessManager() : mObserver(new Observer(this)) {
LOGD("[%p] UtilityProcessManager::UtilityProcessManager", this);
// Start listening for pref changes so we can // Start listening for pref changes so we can
// forward them to the process once it is running. // forward them to the process once it is running.
nsContentUtils::RegisterShutdownObserver(mObserver); nsContentUtils::RegisterShutdownObserver(mObserver);
@@ -66,8 +57,6 @@ UtilityProcessManager::UtilityProcessManager() : mObserver(new Observer(this)) {
} }
UtilityProcessManager::~UtilityProcessManager() { UtilityProcessManager::~UtilityProcessManager() {
LOGD("[%p] UtilityProcessManager::~UtilityProcessManager", this);
// The Utility process should ALL have already been shut down. // The Utility process should ALL have already been shut down.
MOZ_ASSERT(NoMoreProcesses()); MOZ_ASSERT(NoMoreProcesses());
} }
@@ -91,8 +80,6 @@ UtilityProcessManager::Observer::Observe(nsISupports* aSubject,
} }
void UtilityProcessManager::OnXPCOMShutdown() { void UtilityProcessManager::OnXPCOMShutdown() {
LOGD("[%p] UtilityProcessManager::OnXPCOMShutdown", this);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
sXPCOMShutdown = true; sXPCOMShutdown = true;
nsContentUtils::UnregisterShutdownObserver(mObserver); nsContentUtils::UnregisterShutdownObserver(mObserver);
@@ -137,9 +124,6 @@ RefPtr<UtilityProcessManager::ProcessFields> UtilityProcessManager::GetProcess(
RefPtr<GenericNonExclusivePromise> UtilityProcessManager::LaunchProcess( RefPtr<GenericNonExclusivePromise> UtilityProcessManager::LaunchProcess(
SandboxingKind aSandbox) { SandboxingKind aSandbox) {
LOGD("[%p] UtilityProcessManager::LaunchProcess SandboxingKind=%" PRIu64,
this, aSandbox);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (IsShutdown()) { if (IsShutdown()) {
@@ -229,11 +213,6 @@ RefPtr<GenericNonExclusivePromise> UtilityProcessManager::LaunchProcess(
template <typename Actor> template <typename Actor>
RefPtr<GenericNonExclusivePromise> UtilityProcessManager::StartUtility( RefPtr<GenericNonExclusivePromise> UtilityProcessManager::StartUtility(
RefPtr<Actor> aActor, SandboxingKind aSandbox) { RefPtr<Actor> aActor, SandboxingKind aSandbox) {
LOGD(
"[%p] UtilityProcessManager::StartUtility actor=%p "
"SandboxingKind=%" PRIu64,
this, aActor.get(), aSandbox);
if (!aActor) { if (!aActor) {
MOZ_ASSERT(false, "Actor singleton failure"); MOZ_ASSERT(false, "Actor singleton failure");
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE, return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
@@ -377,41 +356,6 @@ UtilityProcessManager::StartJSOracle(dom::JSOracleParent* aParent) {
return StartUtility(RefPtr{aParent}, SandboxingKind::GENERIC_UTILITY); return StartUtility(RefPtr{aParent}, SandboxingKind::GENERIC_UTILITY);
} }
#ifdef XP_WIN
// Windows Utils
RefPtr<UtilityProcessManager::WindowsUtilsPromise>
UtilityProcessManager::GetWindowsUtilsPromise() {
RefPtr<UtilityProcessManager> self = this;
if (!mWindowsUtils) {
mWindowsUtils = new dom::WindowsUtilsParent();
}
RefPtr<dom::WindowsUtilsParent> wup = mWindowsUtils;
MOZ_ASSERT(wup, "Unable to get a singleton for WindowsUtils");
return StartUtility(wup, SandboxingKind::WINDOWS_UTILS)
->Then(
GetMainThreadSerialEventTarget(), __func__,
[self, wup]() {
if (!wup->CanSend()) {
MOZ_ASSERT(false, "WindowsUtilsParent can't send");
return WindowsUtilsPromise::CreateAndReject(NS_ERROR_FAILURE,
__func__);
}
return WindowsUtilsPromise::CreateAndResolve(wup, __func__);
},
[](nsresult aError) {
MOZ_ASSERT_UNREACHABLE(
"PWindowsUtils: failure when starting actor");
return WindowsUtilsPromise::CreateAndReject(aError, __func__);
});
}
void UtilityProcessManager::ReleaseWindowsUtils() { mWindowsUtils = nullptr; }
#endif // XP_WIN
bool UtilityProcessManager::IsProcessLaunching(SandboxingKind aSandbox) { bool UtilityProcessManager::IsProcessLaunching(SandboxingKind aSandbox) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
@@ -452,8 +396,6 @@ void UtilityProcessManager::OnProcessUnexpectedShutdown(
} }
void UtilityProcessManager::CleanShutdownAllProcesses() { void UtilityProcessManager::CleanShutdownAllProcesses() {
LOGD("[%p] UtilityProcessManager::CleanShutdownAllProcesses", this);
for (auto& it : mProcesses) { for (auto& it : mProcesses) {
if (it) { if (it) {
DestroyProcess(it->mSandbox); DestroyProcess(it->mSandbox);
@@ -462,9 +404,6 @@ void UtilityProcessManager::CleanShutdownAllProcesses() {
} }
void UtilityProcessManager::CleanShutdown(SandboxingKind aSandbox) { void UtilityProcessManager::CleanShutdown(SandboxingKind aSandbox) {
LOGD("[%p] UtilityProcessManager::CleanShutdown SandboxingKind=%" PRIu64,
this, aSandbox);
DestroyProcess(aSandbox); DestroyProcess(aSandbox);
} }
@@ -481,9 +420,6 @@ uint16_t UtilityProcessManager::AliveProcesses() {
bool UtilityProcessManager::NoMoreProcesses() { return AliveProcesses() == 0; } bool UtilityProcessManager::NoMoreProcesses() { return AliveProcesses() == 0; }
void UtilityProcessManager::DestroyProcess(SandboxingKind aSandbox) { void UtilityProcessManager::DestroyProcess(SandboxingKind aSandbox) {
LOGD("[%p] UtilityProcessManager::DestroyProcess SandboxingKind=%" PRIu64,
this, aSandbox);
MOZ_RELEASE_ASSERT(NS_IsMainThread()); MOZ_RELEASE_ASSERT(NS_IsMainThread());
if (AliveProcesses() <= 1) { if (AliveProcesses() <= 1) {

View File

@@ -20,8 +20,7 @@ class MemoryReportingProcess;
namespace dom { namespace dom {
class JSOracleParent; class JSOracleParent;
class WindowsUtilsParent; }
} // namespace dom
namespace ipc { namespace ipc {
@@ -38,9 +37,6 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener {
MozPromise<Endpoint<PRemoteDecoderManagerChild>, nsresult, true>; MozPromise<Endpoint<PRemoteDecoderManagerChild>, nsresult, true>;
using JSOraclePromise = GenericNonExclusivePromise; using JSOraclePromise = GenericNonExclusivePromise;
using WindowsUtilsPromise =
MozPromise<RefPtr<dom::WindowsUtilsParent>, nsresult, true>;
static void Initialize(); static void Initialize();
static void Shutdown(); static void Shutdown();
@@ -60,15 +56,6 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener {
RefPtr<JSOraclePromise> StartJSOracle(mozilla::dom::JSOracleParent* aParent); RefPtr<JSOraclePromise> StartJSOracle(mozilla::dom::JSOracleParent* aParent);
#ifdef XP_WIN
// Get the (possibly already resolved) promise for the Windows utility
// process actor. Creates the process if it is not running.
RefPtr<WindowsUtilsPromise> GetWindowsUtilsPromise();
// Releases the WindowsUtils actor so that it can be destroyed.
// Subsequent attempts to use WindowsUtils will create a new process.
void ReleaseWindowsUtils();
#endif
void OnProcessUnexpectedShutdown(UtilityProcessHost* aHost); void OnProcessUnexpectedShutdown(UtilityProcessHost* aHost);
// Returns the platform pid for this utility sandbox process. // Returns the platform pid for this utility sandbox process.
@@ -137,14 +124,6 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener {
return {}; return {};
} }
Span<const UtilityActorName> GetActors(SandboxingKind aSbKind) {
auto proc = GetProcess(aSbKind);
if (!proc) {
return {};
}
return proc->mActors;
}
// Shutdown the Utility process for that sandbox. // Shutdown the Utility process for that sandbox.
void CleanShutdown(SandboxingKind aSandbox); void CleanShutdown(SandboxingKind aSandbox);
@@ -218,10 +197,6 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener {
RefPtr<ProcessFields> GetProcess(SandboxingKind); RefPtr<ProcessFields> GetProcess(SandboxingKind);
bool NoMoreProcesses(); bool NoMoreProcesses();
uint16_t AliveProcesses(); uint16_t AliveProcesses();
#ifdef XP_WIN
RefPtr<dom::WindowsUtilsParent> mWindowsUtils;
#endif // XP_WIN
}; };
} // namespace ipc } // namespace ipc

View File

@@ -27,10 +27,6 @@ enum SandboxingKind : uint64_t {
#ifdef MOZ_WMF_MEDIA_ENGINE #ifdef MOZ_WMF_MEDIA_ENGINE
MF_MEDIA_ENGINE_CDM, MF_MEDIA_ENGINE_CDM,
#endif #endif
#ifdef XP_WIN
WINDOWS_UTILS,
#endif
COUNT, COUNT,
}; };

View File

@@ -14,8 +14,6 @@ skip-if =
skip-if = skip-if =
!crashreporter !crashreporter
ccov ccov
[browser_utility_geolocation_crashed.js]
skip-if = !(os == 'win' && os_version == '10.0') # Geolocation is remoted only on Windows 8+
[browser_utility_hard_kill.js] [browser_utility_hard_kill.js]
[browser_utility_hard_kill_delayed.js] # bug 1754572: we really want hard_kill to be rust before hard_kill_delayed [browser_utility_hard_kill_delayed.js] # bug 1754572: we really want hard_kill to be rust before hard_kill_delayed
[browser_utility_memoryReport.js] [browser_utility_memoryReport.js]

View File

@@ -44,10 +44,10 @@ add_setup(async function setup() {
add_task(async function testKill() { add_task(async function testKill() {
await runTest("small-shot.ogg", "Utility Generic", "vorbis audio decoder"); await runTest("small-shot.ogg", "Utility Generic", "vorbis audio decoder");
await cleanUtilityProcessShutdown( const audioDecoderPid = await findGenericAudioDecoder();
"audioDecoder_Generic", ok(audioDecoderPid > 0, `Valid PID found: ${audioDecoderPid}`);
true /* preferKill */
); await cleanUtilityProcessShutdown(audioDecoderPid, /* preferKill */ true);
info("Waiting 15s to trigger mShutdownBlockers assertions"); info("Waiting 15s to trigger mShutdownBlockers assertions");
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
@@ -64,7 +64,7 @@ add_task(async function testShutdown() {
const audioDecoderPid = await findGenericAudioDecoder(); const audioDecoderPid = await findGenericAudioDecoder();
ok(audioDecoderPid > 0, `Valid PID found: ${audioDecoderPid}`); ok(audioDecoderPid > 0, `Valid PID found: ${audioDecoderPid}`);
await cleanUtilityProcessShutdown("audioDecoder_Generic"); await cleanUtilityProcessShutdown(audioDecoderPid);
info("Waiting 15s to trigger mShutdownBlockers assertions"); info("Waiting 15s to trigger mShutdownBlockers assertions");
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {

View File

@@ -3,16 +3,15 @@
"use strict"; "use strict";
async function startAndCrashUtility(numUnknownActors, actorsCheck) { async function startAndCrashUtility(actors, actorsCheck) {
const actors = Array(numUnknownActors).fill("unknown");
const utilityPid = await startUtilityProcess(actors); const utilityPid = await startUtilityProcess(actors);
await crashSomeUtility(utilityPid, actorsCheck); await crashSomeUtility(utilityPid, actorsCheck);
} }
// When running full suite, previous tests may have left some utility // When running full suite, previous audio decoding tests might have left some
// processes running and this might interfere with our testing. // running and this might interfere with our testing
add_setup(async function ensureNoExistingProcess() { add_setup(async function ensureNoExistingProcess() {
await killUtilityProcesses(); await killPendingUtilityProcess();
}); });
add_task(async function utilityNoActor() { add_task(async function utilityNoActor() {

View File

@@ -1,70 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
async function getGeolocation() {
info("Requesting geolocation");
let resolve;
let promise = new Promise((_resolve, _reject) => {
resolve = _resolve;
});
navigator.geolocation.getCurrentPosition(
() => {
ok(true, "geolocation succeeded");
resolve(undefined);
},
() => {
ok(false, "geolocation failed");
resolve(undefined);
}
);
return promise;
}
add_setup(async function() {
// Avoid the permission doorhanger and cache that would trigger instead
// of re-requesting location. Setting geo.timeout to 0 causes it to
// retry the system geolocation (incl. recreating the utility process)
// instead of reusing the MLS geolocation fallback it found the first time.
await SpecialPowers.pushPrefEnv({
set: [
["geo.prompt.testing", true],
["geo.prompt.testing.allow", true],
["geo.provider.network.debug.requestCache.enabled", false],
["geo.provider.testing", false],
["geo.timeout", 0],
],
});
});
add_task(async function testGeolocationProcessCrash() {
info("Start the Windows utility process");
await getGeolocation();
info("Crash the utility process");
await crashSomeUtilityActor("windowsUtils");
info("Restart the Windows utility process");
await getGeolocation();
info("Confirm the restarted process");
await checkUtilityExists("windowsUtils");
info("Kill the utility process");
await cleanUtilityProcessShutdown("windowsUtils", true);
info("Restart the Windows utility process again");
await getGeolocation();
info("Confirm the restarted process");
await checkUtilityExists("windowsUtils");
});
add_task(async function testCleanup() {
info("Clean up to avoid confusing future tests");
await cleanUtilityProcessShutdown("windowsUtils", true);
});

View File

@@ -4,10 +4,27 @@
"use strict"; "use strict";
add_task(async () => { add_task(async () => {
await startUtilityProcess(["unknown"]); const utilityPid = await startUtilityProcess();
SimpleTest.expectChildProcessCrash(); SimpleTest.expectChildProcessCrash();
const utilityProcessGone = TestUtils.topicObserved("ipc:utility-shutdown");
info("Hard kill Utility Process"); info("Hard kill Utility Process");
await cleanUtilityProcessShutdown("unknown", true /* preferKill */); const ProcessTools = Cc["@mozilla.org/processtools-service;1"].getService(
Ci.nsIProcessToolsService
);
ProcessTools.kill(utilityPid);
info(`Waiting for utility process ${utilityPid} to go away.`);
let [subject, data] = await utilityProcessGone;
ok(
subject instanceof Ci.nsIPropertyBag2,
"Subject needs to be a nsIPropertyBag2 to clean up properly"
);
is(
parseInt(data, 10),
utilityPid,
`Should match the crashed PID ${utilityPid} with ${data}`
);
}); });

View File

@@ -6,7 +6,7 @@
// When running full suite, previous audio decoding tests might have left some // When running full suite, previous audio decoding tests might have left some
// running and this might interfere with our testing // running and this might interfere with our testing
add_setup(async function ensureNoExistingProcess() { add_setup(async function ensureNoExistingProcess() {
await killUtilityProcesses(); await utilityProcessTest().stopProcess();
}); });
add_task(async () => { add_task(async () => {
@@ -72,5 +72,5 @@ add_task(async () => {
"Collected some explicit/ report" "Collected some explicit/ report"
); );
await cleanUtilityProcessShutdown(); await cleanUtilityProcessShutdown(utilityPid);
}); });

View File

@@ -10,10 +10,10 @@ Services.scriptloader.loadSubScript(
this this
); );
// When running full suite, previous tests may have left some utility // When running full suite, previous audio decoding tests might have left some
// processes running and this might interfere with our testing. // running and this might interfere with our testing
add_setup(async function ensureNoExistingProcess() { add_setup(async function ensureNoExistingProcess() {
await killUtilityProcesses(); await killPendingUtilityProcess();
}); });
add_task(async () => { add_task(async () => {
@@ -72,5 +72,5 @@ add_task(async () => {
Services.profiler.StopProfiler(); Services.profiler.StopProfiler();
await cleanUtilityProcessShutdown(); await cleanUtilityProcessShutdown(utilityPid);
}); });

View File

@@ -4,6 +4,6 @@
"use strict"; "use strict";
add_task(async () => { add_task(async () => {
await startUtilityProcess(); const pid = await startUtilityProcess();
await cleanUtilityProcessShutdown(); await cleanUtilityProcessShutdown(pid);
}); });

View File

@@ -12,51 +12,14 @@ const utilityProcessTest = () => {
const kGenericUtilitySandbox = 0; const kGenericUtilitySandbox = 0;
const kGenericUtilityActor = "unknown"; const kGenericUtilityActor = "unknown";
// Start a generic utility process with the given array of utility actor names async function startUtilityProcess(actors) {
// registered.
async function startUtilityProcess(actors = []) {
info("Start a UtilityProcess"); info("Start a UtilityProcess");
return utilityProcessTest().startProcess(actors); return utilityProcessTest().startProcess(actors);
} }
// Returns an array of process infos for utility processes of the given type async function cleanUtilityProcessShutdown(utilityPid, preferKill = false) {
// or all utility processes if actor is not defined. info(`CleanShutdown Utility Process ${utilityPid}`);
async function getUtilityProcesses(actor = undefined) { ok(utilityPid !== undefined, "Utility needs to be defined");
let procInfos = (await ChromeUtils.requestProcInfo()).children.filter(p => {
return (
p.type === "utility" &&
(actor == undefined ||
p.utilityActors.find(a => a.actorName.startsWith(actor)))
);
});
info(`Utility process infos = ${JSON.stringify(procInfos)}`);
return procInfos;
}
async function getUtilityPid(actor) {
let process = await getUtilityProcesses(actor);
is(process.length, 1, `exactly one ${actor} process exists`);
return process[0].pid;
}
async function checkUtilityExists(actor) {
info(`Looking for a running ${actor} utility process`);
const utilityPid = await getUtilityPid(actor);
ok(utilityPid > 0, `Found ${actor} utility process ${utilityPid}`);
return utilityPid;
}
// "Cleanly stop" a utility process. This will never leave a crash dump file.
// preferKill will "kill" the process (e.g. SIGABRT) instead of using the
// UtilityProcessManager.
// To "crash" -- i.e. shutdown and generate a crash dump -- use
// crashSomeUtility().
async function cleanUtilityProcessShutdown(actor, preferKill = false) {
info(`${preferKill ? "Kill" : "Clean shutdown"} Utility Process ${actor}`);
const utilityPid = await getUtilityPid(actor);
ok(utilityPid !== undefined, `Must have PID for ${actor} utility process`);
const utilityProcessGone = TestUtils.topicObserved( const utilityProcessGone = TestUtils.topicObserved(
"ipc:utility-shutdown", "ipc:utility-shutdown",
@@ -71,8 +34,7 @@ async function cleanUtilityProcessShutdown(actor, preferKill = false) {
); );
ProcessTools.kill(utilityPid); ProcessTools.kill(utilityPid);
} else { } else {
info(`Stopping Utility Process ${utilityPid}`); await utilityProcessTest().stopProcess();
await utilityProcessTest().stopProcess(actor);
} }
let [subject, data] = await utilityProcessGone; let [subject, data] = await utilityProcessGone;
@@ -89,13 +51,22 @@ async function cleanUtilityProcessShutdown(actor, preferKill = false) {
ok(!subject.hasKey("dumpID"), "There should be no dumpID"); ok(!subject.hasKey("dumpID"), "There should be no dumpID");
} }
async function killUtilityProcesses() { async function killPendingUtilityProcess() {
let utilityProcesses = await getUtilityProcesses(); let audioDecoderProcesses = (
for (const utilityProcess of utilityProcesses) { await ChromeUtils.requestProcInfo()
for (const actor of utilityProcess.utilityActors) { ).children.filter(p => {
info(`Stopping ${actor.actorName} utility process`); return (
await cleanUtilityProcessShutdown(actor.actorName, /* preferKill */ true); p.type === "utility" &&
} p.utilityActors.find(a => a.actorName.startsWith("audioDecoder_Generic"))
);
});
info(`audioDecoderProcesses=${JSON.stringify(audioDecoderProcesses)}`);
for (let audioDecoderProcess of audioDecoderProcesses) {
info(`Stopping audio decoder PID ${audioDecoderProcess.pid}`);
await cleanUtilityProcessShutdown(
audioDecoderProcess.pid,
/* preferKill */ true
);
} }
} }
@@ -395,22 +366,3 @@ async function crashSomeUtility(utilityPid, actorsCheck) {
extrafile.remove(false); extrafile.remove(false);
} }
} }
// Crash a utility process and generate a crash dump. To close a utility
// process (forcefully or not) without a generating a crash, use
// cleanUtilityProcessShutdown.
async function crashSomeUtilityActor(
actor,
actorsCheck = () => {
return true;
}
) {
// Get PID for utility type
const procInfos = await getUtilityProcesses(actor);
ok(
procInfos.length == 1,
`exactly one ${actor} utility process should be found`
);
const utilityPid = procInfos[0].pid;
return crashSomeUtility(utilityPid, actorsCheck);
}

View File

@@ -12,51 +12,8 @@
namespace mozilla::ipc { namespace mozilla::ipc {
static UtilityActorName UtilityActorNameFromString(
const nsACString& aStringName) {
using namespace mozilla::dom;
// We use WebIDLUtilityActorNames because UtilityActorNames is not designed
// for iteration.
for (size_t i = 0; i < WebIDLUtilityActorNameValues::Count; ++i) {
auto idlName = static_cast<UtilityActorName>(i);
const nsDependentCSubstring idlNameString(
WebIDLUtilityActorNameValues::GetString(idlName));
if (idlNameString.Equals(aStringName)) {
return idlName;
}
}
MOZ_CRASH("Unknown utility actor name");
}
// Find the utility process with the given actor or any utility process if
// the actor is UtilityActorName::EndGuard_.
static SandboxingKind FindUtilityProcessWithActor(UtilityActorName aActorName) {
RefPtr<UtilityProcessManager> utilityProc =
UtilityProcessManager::GetSingleton();
MOZ_ASSERT(utilityProc, "No UtilityprocessManager?");
for (size_t i = 0; i < SandboxingKind::COUNT; ++i) {
auto sbKind = static_cast<SandboxingKind>(i);
if (!utilityProc->Process(sbKind)) {
continue;
}
if (aActorName == UtilityActorName::EndGuard_) {
return sbKind;
}
for (auto actor : utilityProc->GetActors(sbKind)) {
if (actor == aActorName) {
return sbKind;
}
}
}
return SandboxingKind::COUNT;
}
NS_IMETHODIMP NS_IMETHODIMP
UtilityProcessTest::StartProcess(const nsTArray<nsCString>& aActorsToRegister, UtilityProcessTest::StartProcess(int32_t aUnknownActors, JSContext* aCx,
JSContext* aCx,
mozilla::dom::Promise** aOutPromise) { mozilla::dom::Promise** aOutPromise) {
NS_ENSURE_ARG(aOutPromise); NS_ENSURE_ARG(aOutPromise);
*aOutPromise = nullptr; *aOutPromise = nullptr;
@@ -75,19 +32,20 @@ UtilityProcessTest::StartProcess(const nsTArray<nsCString>& aActorsToRegister,
UtilityProcessManager::GetSingleton(); UtilityProcessManager::GetSingleton();
MOZ_ASSERT(utilityProc, "No UtilityprocessManager?"); MOZ_ASSERT(utilityProc, "No UtilityprocessManager?");
auto actors = aActorsToRegister.Clone();
utilityProc->LaunchProcess(SandboxingKind::GENERIC_UTILITY) utilityProc->LaunchProcess(SandboxingKind::GENERIC_UTILITY)
->Then( ->Then(
GetCurrentSerialEventTarget(), __func__, GetCurrentSerialEventTarget(), __func__,
[promise, utilityProc, actors = std::move(actors)] { [promise, utilityProc, aUnknownActors]() {
RefPtr<UtilityProcessParent> utilityParent =
utilityProc->GetProcessParent(SandboxingKind::GENERIC_UTILITY);
Maybe<int32_t> utilityPid = Maybe<int32_t> utilityPid =
utilityProc->ProcessPid(SandboxingKind::GENERIC_UTILITY); utilityProc->ProcessPid(SandboxingKind::GENERIC_UTILITY);
for (size_t i = 0; i < actors.Length(); ++i) { if (aUnknownActors > 0) {
auto uan = UtilityActorNameFromString(actors[i]); RefPtr<UtilityProcessParent> utilityParent =
utilityProc->RegisterActor(utilityParent, uan); utilityProc->GetProcessParent(
SandboxingKind::GENERIC_UTILITY);
for (int32_t i = 0; i < aUnknownActors; i++) {
utilityProc->RegisterActor(utilityParent,
UtilityActorName::Unknown);
}
} }
if (utilityPid.isSome()) { if (utilityPid.isSome()) {
promise->MaybeResolve(*utilityPid); promise->MaybeResolve(*utilityPid);
@@ -106,31 +64,14 @@ UtilityProcessTest::StartProcess(const nsTArray<nsCString>& aActorsToRegister,
} }
NS_IMETHODIMP NS_IMETHODIMP
UtilityProcessTest::StopProcess(const char* aActorName) { UtilityProcessTest::StopProcess() {
using namespace mozilla::dom;
SandboxingKind sbKind;
if (aActorName) {
const nsDependentCString actorStringName(aActorName);
UtilityActorName actorName = UtilityActorNameFromString(actorStringName);
sbKind = FindUtilityProcessWithActor(actorName);
} else {
sbKind = FindUtilityProcessWithActor(UtilityActorName::EndGuard_);
}
if (sbKind == SandboxingKind::COUNT) {
MOZ_ASSERT_UNREACHABLE(
"Attempted to stop process for actor when no "
"such process exists");
return NS_ERROR_FAILURE;
}
RefPtr<UtilityProcessManager> utilityProc = RefPtr<UtilityProcessManager> utilityProc =
UtilityProcessManager::GetSingleton(); UtilityProcessManager::GetSingleton();
MOZ_ASSERT(utilityProc, "No UtilityprocessManager?"); MOZ_ASSERT(utilityProc, "No UtilityprocessManager?");
utilityProc->CleanShutdown(sbKind); utilityProc->CleanShutdown(SandboxingKind::GENERIC_UTILITY);
Maybe<int32_t> utilityPid = utilityProc->ProcessPid(sbKind); Maybe<int32_t> utilityPid =
utilityProc->ProcessPid(SandboxingKind::GENERIC_UTILITY);
MOZ_RELEASE_ASSERT(utilityPid.isNothing(), MOZ_RELEASE_ASSERT(utilityPid.isNothing(),
"Should not have a utility process PID anymore"); "Should not have a utility process PID anymore");

View File

@@ -12,21 +12,16 @@ interface nsIUtilityProcessTest : nsISupports
* ** Test-only Method ** * ** Test-only Method **
* *
* Allowing to start Utility Process from JS code. * Allowing to start Utility Process from JS code.
*
* actorsToAdd: An array of actor names, taken from WebIDLUtilityActorName.
* Unlike normal utility processes, test processes launched this way do not
* have any associated actor names unless specified here. Empty by default.
*/ */
[implicit_jscontext] [implicit_jscontext]
Promise startProcess([optional] in Array<ACString> actorsToAdd); Promise startProcess([optional] in int32_t unknownActors);
/** /**
* ** Test-only Method ** * ** Test-only Method **
* *
* Allowing to stop Utility Process from JS code. * Allowing to stop Utility Process from JS code.
* Default behavior is to stop any utility process.
*/ */
void stopProcess([optional] in string utilityActorName); void stopProcess();
/** /**
* ** Test-only Method ** * ** Test-only Method **

View File

@@ -65,7 +65,6 @@ static LazyLogModule sSandboxBrokerLog("SandboxBroker");
#define LOG_E(...) MOZ_LOG(sSandboxBrokerLog, LogLevel::Error, (__VA_ARGS__)) #define LOG_E(...) MOZ_LOG(sSandboxBrokerLog, LogLevel::Error, (__VA_ARGS__))
#define LOG_W(...) MOZ_LOG(sSandboxBrokerLog, LogLevel::Warning, (__VA_ARGS__)) #define LOG_W(...) MOZ_LOG(sSandboxBrokerLog, LogLevel::Warning, (__VA_ARGS__))
#define LOG_D(...) MOZ_LOG(sSandboxBrokerLog, LogLevel::Debug, (__VA_ARGS__))
// Used to store whether we have accumulated an error combination for this // Used to store whether we have accumulated an error combination for this
// session. // session.
@@ -1258,233 +1257,174 @@ bool SandboxBroker::SetSecurityLevelForSocketProcess() {
return true; return true;
} }
// A strict base sandbox for utility sandboxes to adapt.
struct UtilitySandboxProps {
sandbox::JobLevel mJobLevel = sandbox::JOB_LOCKDOWN;
sandbox::TokenLevel mInitialTokenLevel = sandbox::USER_RESTRICTED_SAME_ACCESS;
sandbox::TokenLevel mDelayedTokenLevel = sandbox::USER_LOCKDOWN;
sandbox::IntegrityLevel mInitialIntegrityLevel = // before lockdown
sandbox::INTEGRITY_LEVEL_LOW;
sandbox::IntegrityLevel mDelayedIntegrityLevel = // after lockdown
sandbox::INTEGRITY_LEVEL_UNTRUSTED;
bool mUseAlternateWindowStation = true;
bool mUseWin32kLockdown = true;
bool mUseCig = true;
sandbox::MitigationFlags mInitialMitigations =
sandbox::MITIGATION_BOTTOM_UP_ASLR | sandbox::MITIGATION_HEAP_TERMINATE |
sandbox::MITIGATION_SEHOP | sandbox::MITIGATION_EXTENSION_POINT_DISABLE |
sandbox::MITIGATION_DEP_NO_ATL_THUNK | sandbox::MITIGATION_DEP |
sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32 |
sandbox::MITIGATION_CET_COMPAT_MODE;
sandbox::MitigationFlags mDelayedMitigations =
sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
sandbox::MITIGATION_DLL_SEARCH_ORDER |
sandbox::MITIGATION_DYNAMIC_CODE_DISABLE;
};
struct GenericUtilitySandboxProps : public UtilitySandboxProps {};
struct UtilityAudioDecodingWmfSandboxProps : public UtilitySandboxProps {
UtilityAudioDecodingWmfSandboxProps() {
mDelayedTokenLevel = sandbox::USER_LIMITED;
mDelayedMitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
sandbox::MITIGATION_DLL_SEARCH_ORDER;
#ifdef MOZ_WMF
if (StaticPrefs::security_sandbox_utility_wmf_acg_enabled()) {
mDelayedMitigations |= DynamicCodeFlagForSystemMediaLibraries();
}
#else
mDelayedMitigations |= sandbox::MITIGATION_DYNAMIC_CODE_DISABLE;
#endif // MOZ_WMF
}
};
#ifdef MOZ_WMF_MEDIA_ENGINE
struct UtilityMfMediaEngineCdmSandboxProps : public UtilitySandboxProps {
UtilityMfMediaEngineCdmSandboxProps() {
mJobLevel = sandbox::JOB_INTERACTIVE;
mDelayedTokenLevel = sandbox::USER_RESTRICTED_NON_ADMIN;
mUseAlternateWindowStation = false;
mDelayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
mUseWin32kLockdown = false;
mDelayedMitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
sandbox::MITIGATION_DLL_SEARCH_ORDER;
}
};
#endif
struct WindowsUtilitySandboxProps : public UtilitySandboxProps {
WindowsUtilitySandboxProps() {
mJobLevel = sandbox::JOB_INTERACTIVE;
mDelayedTokenLevel = sandbox::USER_RESTRICTED_SAME_ACCESS;
mUseAlternateWindowStation = false;
mInitialIntegrityLevel = sandbox::INTEGRITY_LEVEL_MEDIUM;
mDelayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_MEDIUM;
mUseWin32kLockdown = false;
mUseCig = false;
mDelayedMitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
sandbox::MITIGATION_DLL_SEARCH_ORDER;
}
};
void LogUtilitySandboxProps(const UtilitySandboxProps& us) {
if (!static_cast<LogModule*>(sSandboxBrokerLog)->ShouldLog(LogLevel::Debug)) {
return;
}
nsAutoCString logMsg;
logMsg.AppendPrintf("Building sandbox for utility process:\n");
logMsg.AppendPrintf("\tJob Level: %d\n", static_cast<int>(us.mJobLevel));
logMsg.AppendPrintf("\tInitial Token Level: %d\n",
static_cast<int>(us.mInitialTokenLevel));
logMsg.AppendPrintf("\tDelayed Token Level: %d\n",
static_cast<int>(us.mDelayedTokenLevel));
logMsg.AppendPrintf("\tInitial Integrity Level: %d\n",
static_cast<int>(us.mInitialIntegrityLevel));
logMsg.AppendPrintf("\tDelayed Integrity Level: %d\n",
static_cast<int>(us.mDelayedIntegrityLevel));
logMsg.AppendPrintf("\tUse Alternate Window Station: %s\n",
us.mUseAlternateWindowStation ? "yes" : "no");
logMsg.AppendPrintf("\tUse Win32k Lockdown: %s\n",
us.mUseWin32kLockdown ? "yes" : "no");
logMsg.AppendPrintf("\tUse CIG: %s\n", us.mUseCig ? "yes" : "no");
logMsg.AppendPrintf("\tInitial mitigations: %016llx\n",
static_cast<uint64_t>(us.mInitialMitigations));
logMsg.AppendPrintf("\tDelayed mitigations: %016llx\n",
static_cast<uint64_t>(us.mDelayedMitigations));
LOG_D("%s", logMsg.get());
}
bool BuildUtilitySandbox(sandbox::TargetPolicy* policy,
const UtilitySandboxProps& us) {
LogUtilitySandboxProps(us);
auto result = SetJobLevel(policy, us.mJobLevel, 0 /* ui_exceptions */);
SANDBOX_ENSURE_SUCCESS(
result,
"SetJobLevel should never fail with these arguments, what happened?");
result = policy->SetTokenLevel(us.mInitialTokenLevel, us.mDelayedTokenLevel);
SANDBOX_ENSURE_SUCCESS(
result,
"SetTokenLevel should never fail with these arguments, what happened?");
result = policy->SetAlternateDesktop(us.mUseAlternateWindowStation);
if (NS_WARN_IF(result != sandbox::SBOX_ALL_OK)) {
LOG_W("SetAlternateDesktop failed, result: %i, last error: %lx", result,
::GetLastError());
}
result = policy->SetIntegrityLevel(us.mInitialIntegrityLevel);
SANDBOX_ENSURE_SUCCESS(result,
"SetIntegrityLevel should never fail with these "
"arguments, what happened?");
result = policy->SetDelayedIntegrityLevel(us.mDelayedIntegrityLevel);
SANDBOX_ENSURE_SUCCESS(result,
"SetDelayedIntegrityLevel should never fail with "
"these arguments, what happened?");
policy->SetLockdownDefaultDacl();
policy->AddRestrictingRandomSid();
sandbox::MitigationFlags initialMitigations = us.mInitialMitigations;
sandbox::MitigationFlags delayedMitigations = us.mDelayedMitigations;
if (us.mUseCig) {
const Maybe<Vector<const wchar_t*>>& exceptionModules =
GetPrespawnCigExceptionModules();
if (exceptionModules.isSome()) {
initialMitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
} else {
delayedMitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
}
}
result = policy->SetProcessMitigations(initialMitigations);
SANDBOX_ENSURE_SUCCESS(result, "Invalid flags for SetProcessMitigations.");
// Win32k lockdown might not work on earlier versions
// Bug 1719212, 1769992
if (IsWin10FallCreatorsUpdateOrLater() && us.mUseWin32kLockdown) {
result = AddWin32kLockdownPolicy(policy, false);
SANDBOX_ENSURE_SUCCESS(result, "Failed to add the win32k lockdown policy");
}
if (us.mUseCig) {
const Maybe<Vector<const wchar_t*>>& exceptionModules =
GetPrespawnCigExceptionModules();
if (exceptionModules.isSome()) {
// This needs to be called after MITIGATION_FORCE_MS_SIGNED_BINS is set
// because of DCHECK in PolicyBase::AddRuleInternal.
result = InitSignedPolicyRulesToBypassCig(policy, exceptionModules.ref());
SANDBOX_ENSURE_SUCCESS(result,
"Failed to initialize signed policy rules.");
}
// Running audio decoder somehow fails on MSIX packages unless we do that
if (mozilla::HasPackageIdentity() && exceptionModules.isNothing()) {
const Vector<const wchar_t*> emptyVector;
result = InitSignedPolicyRulesToBypassCig(policy, emptyVector);
SANDBOX_ENSURE_SUCCESS(result,
"Failed to initialize signed policy rules.");
}
}
result = policy->SetDelayedProcessMitigations(delayedMitigations);
SANDBOX_ENSURE_SUCCESS(result,
"Invalid flags for SetDelayedProcessMitigations.");
// Add the policy for the client side of a pipe. It is just a file
// in the \pipe\ namespace. We restrict it to pipes that start with
// "chrome." so the sandboxed process cannot connect to system services.
result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\chrome.*");
SANDBOX_ENSURE_SUCCESS(
result,
"With these static arguments AddRule should never fail, what happened?");
// Add the policy for the client side of the crash server pipe.
result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\gecko-crash-server-pipe.*");
SANDBOX_ENSURE_SUCCESS(
result,
"With these static arguments AddRule should never fail, what happened?");
return true;
}
bool SandboxBroker::SetSecurityLevelForUtilityProcess( bool SandboxBroker::SetSecurityLevelForUtilityProcess(
mozilla::ipc::SandboxingKind aSandbox) { mozilla::ipc::SandboxingKind aSandbox) {
if (!mPolicy) { if (!mPolicy) {
return false; return false;
} }
auto jobLevel = sandbox::JOB_LOCKDOWN;
#ifdef MOZ_WMF_MEDIA_ENGINE
if (aSandbox == mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM) {
jobLevel = sandbox::JOB_INTERACTIVE;
}
#endif
auto result = SetJobLevel(mPolicy, jobLevel, 0 /* ui_exceptions */);
SANDBOX_ENSURE_SUCCESS(
result,
"SetJobLevel should never fail with these arguments, what happened?");
auto lockdownLevel = sandbox::USER_LOCKDOWN;
if (aSandbox == mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF) {
lockdownLevel = sandbox::USER_LIMITED;
}
#ifdef MOZ_WMF_MEDIA_ENGINE
if (aSandbox == mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM) {
lockdownLevel = sandbox::USER_RESTRICTED_NON_ADMIN;
}
#endif
result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
lockdownLevel);
SANDBOX_ENSURE_SUCCESS(
result,
"SetTokenLevel should never fail with these arguments, what happened?");
bool useAlternateWindowStation = true;
#ifdef MOZ_WMF_MEDIA_ENGINE
if (aSandbox == mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM) {
useAlternateWindowStation = false;
}
#endif
result = mPolicy->SetAlternateDesktop(useAlternateWindowStation);
if (NS_WARN_IF(result != sandbox::SBOX_ALL_OK)) {
LOG_W("SetAlternateDesktop failed, result: %i, last error: %lx", result,
::GetLastError());
}
result = mPolicy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
SANDBOX_ENSURE_SUCCESS(result,
"SetIntegrityLevel should never fail with these "
"arguments, what happened?");
auto integrityLevel = sandbox::INTEGRITY_LEVEL_UNTRUSTED;
#ifdef MOZ_WMF_MEDIA_ENGINE
if (aSandbox == mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM) {
integrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
}
#endif
result = mPolicy->SetDelayedIntegrityLevel(integrityLevel);
SANDBOX_ENSURE_SUCCESS(result,
"SetDelayedIntegrityLevel should never fail with "
"these arguments, what happened?");
mPolicy->SetLockdownDefaultDacl();
mPolicy->AddRestrictingRandomSid();
sandbox::MitigationFlags mitigations =
sandbox::MITIGATION_BOTTOM_UP_ASLR | sandbox::MITIGATION_HEAP_TERMINATE |
sandbox::MITIGATION_SEHOP | sandbox::MITIGATION_EXTENSION_POINT_DISABLE |
sandbox::MITIGATION_DEP_NO_ATL_THUNK | sandbox::MITIGATION_DEP |
sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32 |
sandbox::MITIGATION_CET_COMPAT_MODE;
const Maybe<Vector<const wchar_t*>>& exceptionModules =
GetPrespawnCigExceptionModules();
if (exceptionModules.isSome()) {
mitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
}
result = mPolicy->SetProcessMitigations(mitigations);
SANDBOX_ENSURE_SUCCESS(result, "Invalid flags for SetProcessMitigations.");
if (exceptionModules.isSome()) {
// This needs to be called after MITIGATION_FORCE_MS_SIGNED_BINS is set
// because of DCHECK in PolicyBase::AddRuleInternal.
result = InitSignedPolicyRulesToBypassCig(mPolicy, exceptionModules.ref());
SANDBOX_ENSURE_SUCCESS(result, "Failed to initialize signed policy rules.");
}
// Win32k lockdown might not work on earlier versions
// Bug 1719212, 1769992
if (IsWin10FallCreatorsUpdateOrLater()
#ifdef MOZ_WMF_MEDIA_ENGINE
&& aSandbox != mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM
#endif
) {
result = AddWin32kLockdownPolicy(mPolicy, false);
SANDBOX_ENSURE_SUCCESS(result, "Failed to add the win32k lockdown policy");
}
mitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
sandbox::MITIGATION_DLL_SEARCH_ORDER;
switch (aSandbox) {
#ifdef MOZ_WMF
// The audio decoder process depends on MsAudDecMFT.dll.
case mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF:
if (StaticPrefs::security_sandbox_utility_wmf_acg_enabled()) {
mitigations |= DynamicCodeFlagForSystemMediaLibraries();
}
break;
#endif // MOZ_WMF
#ifdef MOZ_WMF_MEDIA_ENGINE
// No ACG on CDM utility processes.
case mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM:
break;
#endif // MOZ_WMF_MEDIA_ENGINE
default:
mitigations |= sandbox::MITIGATION_DYNAMIC_CODE_DISABLE;
}
if (exceptionModules.isNothing()) {
mitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
}
result = mPolicy->SetDelayedProcessMitigations(mitigations);
SANDBOX_ENSURE_SUCCESS(result,
"Invalid flags for SetDelayedProcessMitigations.");
// Running audio decoder somehow fails on MSIX packages unless we do that
if (mozilla::HasPackageIdentity() && exceptionModules.isNothing()) {
const Vector<const wchar_t*> emptyVector;
result = InitSignedPolicyRulesToBypassCig(mPolicy, emptyVector);
SANDBOX_ENSURE_SUCCESS(result, "Failed to initialize signed policy rules.");
}
// Add the policy for the client side of a pipe. It is just a file
// in the \pipe\ namespace. We restrict it to pipes that start with
// "chrome." so the sandboxed process cannot connect to system services.
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\chrome.*");
SANDBOX_ENSURE_SUCCESS(
result,
"With these static arguments AddRule should never fail, what happened?");
// Add the policy for the client side of the crash server pipe.
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\gecko-crash-server-pipe.*");
SANDBOX_ENSURE_SUCCESS(
result,
"With these static arguments AddRule should never fail, what happened?");
switch (aSandbox) { switch (aSandbox) {
case mozilla::ipc::SandboxingKind::GENERIC_UTILITY: case mozilla::ipc::SandboxingKind::GENERIC_UTILITY:
return BuildUtilitySandbox(mPolicy, GenericUtilitySandboxProps());
case mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF: case mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF:
return BuildUtilitySandbox(mPolicy, #if MOZ_WMF_MEDIA_ENGINE
UtilityAudioDecodingWmfSandboxProps());
#ifdef MOZ_WMF_MEDIA_ENGINE
case mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM: case mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM:
return BuildUtilitySandbox(mPolicy,
UtilityMfMediaEngineCdmSandboxProps());
#endif #endif
case mozilla::ipc::SandboxingKind::WINDOWS_UTILS: // Nothing specific to perform yet?
return BuildUtilitySandbox(mPolicy, WindowsUtilitySandboxProps()); break;
default: default:
MOZ_ASSERT_UNREACHABLE("Unknown sandboxing value"); MOZ_ASSERT(false, "Invalid SandboxingKind");
return false; break;
} }
return true;
} }
bool SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel, bool SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel,

View File

@@ -68,7 +68,14 @@ enum class ProcType {
Max = Unknown, Max = Unknown,
}; };
using UtilityActorName = mozilla::dom::WebIDLUtilityActorName; enum class UtilityActorName {
Unknown,
AudioDecoder_Generic,
AudioDecoder_AppleMedia,
AudioDecoder_WMF,
MfMediaEngineCDM,
JSOracle,
};
// String that will be used e.g. to annotate crash reports // String that will be used e.g. to annotate crash reports
nsCString GetUtilityActorName(const UtilityActorName aActorName); nsCString GetUtilityActorName(const UtilityActorName aActorName);

View File

@@ -55,11 +55,8 @@ nsCString GetUtilityActorName(const UtilityActorName aActorName) {
return "mf-media-engine"_ns; return "mf-media-engine"_ns;
case UtilityActorName::JSOracle: case UtilityActorName::JSOracle:
return "js-oracle"_ns; return "js-oracle"_ns;
case UtilityActorName::WindowsUtils:
return "windows-utils"_ns;
default:
return "unknown"_ns;
} }
return "unknown"_ns;
} }
} // namespace mozilla } // namespace mozilla

View File

@@ -16,7 +16,6 @@
#include "mozilla/ChaosMode.h" #include "mozilla/ChaosMode.h"
#include "mozilla/CmdLineAndEnvUtils.h" #include "mozilla/CmdLineAndEnvUtils.h"
#include "mozilla/IOInterposer.h" #include "mozilla/IOInterposer.h"
#include "mozilla/ipc/UtilityProcessChild.h"
#include "mozilla/Likely.h" #include "mozilla/Likely.h"
#include "mozilla/MemoryChecking.h" #include "mozilla/MemoryChecking.h"
#include "mozilla/Poison.h" #include "mozilla/Poison.h"
@@ -5977,28 +5976,16 @@ bool XRE_IsE10sParentProcess() {
#undef GECKO_PROCESS_TYPE #undef GECKO_PROCESS_TYPE
bool XRE_UseNativeEventProcessing() { bool XRE_UseNativeEventProcessing() {
switch (XRE_GetProcessType()) {
#if defined(XP_MACOSX) || defined(XP_WIN) #if defined(XP_MACOSX) || defined(XP_WIN)
case GeckoProcessType_RDD: if (XRE_IsRDDProcess() || XRE_IsSocketProcess() || XRE_IsUtilityProcess()) {
case GeckoProcessType_Socket: return false;
return false;
case GeckoProcessType_Utility: {
# if defined(XP_WIN)
auto upc = mozilla::ipc::UtilityProcessChild::Get();
MOZ_ASSERT(upc);
// WindowsUtils is for Windows APIs, which typically require a Windows
// native event loop.
return upc->mSandbox == mozilla::ipc::SandboxingKind::WINDOWS_UTILS;
# else
return false;
# endif // defined(XP_WIN)
}
#endif // defined(XP_MACOSX) || defined(XP_WIN)
case GeckoProcessType_Content:
return StaticPrefs::dom_ipc_useNativeEventProcessing_content();
default:
return true;
} }
#endif
if (XRE_IsContentProcess()) {
return StaticPrefs::dom_ipc_useNativeEventProcessing_content();
}
return true;
} }
namespace mozilla { namespace mozilla {