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:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -728,7 +728,6 @@ enum WebIDLUtilityActorName {
|
|||||||
"audioDecoder_WMF",
|
"audioDecoder_WMF",
|
||||||
"mfMediaEngineCDM",
|
"mfMediaEngineCDM",
|
||||||
"jSOracle",
|
"jSOracle",
|
||||||
"windowsUtils",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
dictionary UtilityActorsDictionary {
|
dictionary UtilityActorsDictionary {
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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__
|
|
||||||
@@ -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
|
|
||||||
@@ -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__
|
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
|
||||||
@@ -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__
|
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -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()``
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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!");
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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__);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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);
|
|
||||||
});
|
|
||||||
@@ -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}`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|
||||||
|
|||||||
@@ -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 **
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user