This pref gated the availability of GPC as a whole, acting as a third "undecided" state that left navigator.globalPrivacyControl undefined and suppressed the Sec-GPC header. It has been set to true in firefox.js since GPC shipped, so remove it and assume it to be true everywhere. Removed from StaticPrefList.yaml, from every line that set it (firefox.js, GeckoRuntimeSettings, the about:preferences settings config, and the test pref environments), and from every use: the three C++ conjunctions in nsHttpChannel/Navigator/WorkerNavigator, the [Pref=] annotation on the GlobalPrivacyControl WebIDL mixin, the StartupTelemetry check and its observer, and the visibility gate on the gpcEnabled setting. This is a no-op for desktop Firefox and for Fenix/Focus, which reach setGlobalPrivacyControl() at startup and committed the pref to true there. The one observable change is for GeckoView embedders that never call setGlobalPrivacyControl(): navigator.globalPrivacyControl becomes false rather than undefined. No Sec-GPC header is sent either way, since both privacy.globalprivacycontrol.enabled and .pbmode.enabled default to false. There is no GeckoView API change: the removed Pref field is package-private and api.txt is untouched. The browser_privacy_gpc.js task asserting the section is hidden when the feature pref is disabled is removed rather than rewritten, since its premise no longer exists; nonTechnicalPrivacyGroup is now unconditionally visible, which matches its behaviour with the pref set to true. Differential Revision: https://phabricator.services.mozilla.com/D317979
348 lines
10 KiB
C++
348 lines
10 KiB
C++
/* 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 "mozilla/dom/WorkerNavigator.h"
|
|
|
|
#include "ErrorList.h"
|
|
#include "MainThreadUtils.h"
|
|
#include "RuntimeService.h"
|
|
#include "WorkerRunnable.h"
|
|
#include "WorkerScope.h"
|
|
#include "mozilla/dom/LockManager.h"
|
|
#include "mozilla/dom/MediaCapabilities.h"
|
|
#include "mozilla/dom/Navigator.h"
|
|
#include "mozilla/dom/Permissions.h"
|
|
#include "mozilla/dom/Serial.h"
|
|
#include "mozilla/dom/ServiceWorkerContainer.h"
|
|
#include "mozilla/dom/StorageManager.h"
|
|
#include "mozilla/dom/WorkerCommon.h"
|
|
#include "mozilla/dom/WorkerNavigatorBinding.h"
|
|
#include "mozilla/dom/WorkerStatus.h"
|
|
#include "mozilla/dom/network/Connection.h"
|
|
#include "mozilla/webgpu/Instance.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsDebug.h"
|
|
#include "nsError.h"
|
|
#include "nsIGlobalObject.h"
|
|
#include "nsLiteralString.h"
|
|
#include "nsPIDOMWindow.h"
|
|
#include "nsRFPService.h"
|
|
#include "nsString.h"
|
|
|
|
class JSObject;
|
|
struct JSContext;
|
|
|
|
namespace mozilla::dom {
|
|
|
|
using namespace workerinternals;
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(WorkerNavigator)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WorkerNavigator)
|
|
tmp->Invalidate();
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WorkerNavigator)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaCapabilities)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebGpu)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocks)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSerial)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
WorkerNavigator::WorkerNavigator(const NavigatorProperties& aProperties,
|
|
bool aOnline)
|
|
: mProperties(aProperties), mOnline(aOnline) {}
|
|
|
|
WorkerNavigator::~WorkerNavigator() { Invalidate(); }
|
|
|
|
/* static */
|
|
already_AddRefed<WorkerNavigator> WorkerNavigator::Create(bool aOnLine) {
|
|
RuntimeService* rts = RuntimeService::GetService();
|
|
MOZ_ASSERT(rts);
|
|
|
|
RuntimeService::NavigatorProperties properties =
|
|
rts->GetNavigatorProperties();
|
|
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
if (workerPrivate && !workerPrivate->GetLanguageOverride().IsEmpty()) {
|
|
properties.mLanguages = workerPrivate->GetLanguageOverride().Clone();
|
|
}
|
|
|
|
RefPtr<WorkerNavigator> navigator = new WorkerNavigator(properties, aOnLine);
|
|
|
|
return navigator.forget();
|
|
}
|
|
|
|
void WorkerNavigator::Invalidate() {
|
|
if (mStorageManager) {
|
|
mStorageManager->Shutdown();
|
|
mStorageManager = nullptr;
|
|
}
|
|
|
|
mConnection = nullptr;
|
|
|
|
mMediaCapabilities = nullptr;
|
|
|
|
mWebGpu = nullptr;
|
|
|
|
if (mLocks) {
|
|
mLocks->Shutdown();
|
|
mLocks = nullptr;
|
|
}
|
|
|
|
mPermissions = nullptr;
|
|
|
|
mServiceWorkerContainer = nullptr;
|
|
|
|
if (mSerial) {
|
|
mSerial->Shutdown();
|
|
mSerial = nullptr;
|
|
}
|
|
}
|
|
|
|
JSObject* WorkerNavigator::WrapObject(JSContext* aCx,
|
|
JS::Handle<JSObject*> aGivenProto) {
|
|
return WorkerNavigator_Binding::Wrap(aCx, this, aGivenProto);
|
|
}
|
|
|
|
bool WorkerNavigator::GlobalPrivacyControl() const {
|
|
bool gpcStatus = StaticPrefs::privacy_globalprivacycontrol_enabled();
|
|
if (!gpcStatus) {
|
|
JSObject* jso = GetWrapper();
|
|
if (const nsCOMPtr<nsIGlobalObject> global = xpc::NativeGlobal(jso)) {
|
|
if (const nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull()) {
|
|
gpcStatus = principal->GetIsInPrivateBrowsing() &&
|
|
StaticPrefs::privacy_globalprivacycontrol_pbmode_enabled();
|
|
}
|
|
}
|
|
}
|
|
return gpcStatus;
|
|
}
|
|
|
|
void WorkerNavigator::SetLanguages(const nsTArray<nsString>& aLanguages) {
|
|
WorkerNavigator_Binding::ClearCachedLanguageValue(this);
|
|
WorkerNavigator_Binding::ClearCachedLanguagesValue(this);
|
|
mProperties.mLanguages = aLanguages.Clone();
|
|
}
|
|
|
|
void WorkerNavigator::GetAppVersion(nsString& aAppVersion,
|
|
CallerType aCallerType,
|
|
ErrorResult& aRv) const {
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
if (aCallerType != CallerType::System) {
|
|
if (workerPrivate->ShouldResistFingerprinting(
|
|
RFPTarget::NavigatorAppVersion)) {
|
|
// See nsRFPService.h for spoofed value.
|
|
aAppVersion.AssignLiteral(SPOOFED_APPVERSION);
|
|
return;
|
|
}
|
|
|
|
if (!mProperties.mAppVersionOverridden.IsEmpty()) {
|
|
aAppVersion = mProperties.mAppVersionOverridden;
|
|
return;
|
|
}
|
|
}
|
|
|
|
aAppVersion = mProperties.mAppVersion;
|
|
}
|
|
|
|
void WorkerNavigator::GetPlatform(nsString& aPlatform, CallerType aCallerType,
|
|
ErrorResult& aRv) const {
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
// navigator.platform is the same for default and spoofed values. The
|
|
// "general.platform.override" pref should override the default platform,
|
|
// but the spoofed platform should override the pref.
|
|
if (aCallerType == CallerType::System ||
|
|
workerPrivate->ShouldResistFingerprinting(RFPTarget::NavigatorPlatform) ||
|
|
mProperties.mPlatformOverridden.IsEmpty()) {
|
|
aPlatform = mProperties.mPlatform;
|
|
} else {
|
|
// from "general.platform.override" pref.
|
|
aPlatform = mProperties.mPlatformOverridden;
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* This Worker Runnable needs to check RFP; but our standard way of doing so
|
|
* relies on accessing GlobalScope() - which can only be accessed on the worker
|
|
* thread. So we need to pass it in.
|
|
*/
|
|
class GetUserAgentRunnable final : public WorkerMainThreadRunnable {
|
|
nsString& mUA;
|
|
bool mShouldResistFingerprinting;
|
|
|
|
public:
|
|
GetUserAgentRunnable(WorkerPrivate* aWorkerPrivate, nsString& aUA,
|
|
bool aShouldResistFingerprinting)
|
|
: WorkerMainThreadRunnable(aWorkerPrivate, "UserAgent getter"_ns),
|
|
mUA(aUA),
|
|
mShouldResistFingerprinting(aShouldResistFingerprinting) {
|
|
MOZ_ASSERT(aWorkerPrivate);
|
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
|
}
|
|
|
|
virtual bool MainThreadRun() override {
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(mWorkerRef);
|
|
|
|
WorkerPrivate* workerPrivate = mWorkerRef->Private();
|
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window = workerPrivate->GetWindow();
|
|
|
|
nsresult rv =
|
|
dom::Navigator::GetUserAgent(window, workerPrivate->GetDocument(),
|
|
Some(mShouldResistFingerprinting), mUA);
|
|
if (NS_FAILED(rv)) {
|
|
NS_WARNING("Failed to retrieve user-agent from the worker thread.");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
void WorkerNavigator::GetUserAgent(nsString& aUserAgent, CallerType aCallerType,
|
|
ErrorResult& aRv) const {
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
RefPtr<GetUserAgentRunnable> runnable = new GetUserAgentRunnable(
|
|
workerPrivate, aUserAgent,
|
|
workerPrivate->ShouldResistFingerprinting(RFPTarget::NavigatorUserAgent));
|
|
|
|
runnable->Dispatch(workerPrivate, Canceling, aRv);
|
|
}
|
|
|
|
uint64_t WorkerNavigator::HardwareConcurrency() const {
|
|
RuntimeService* rts = RuntimeService::GetService();
|
|
MOZ_ASSERT(rts);
|
|
|
|
WorkerPrivate* aWorkerPrivate = GetCurrentThreadWorkerPrivate();
|
|
|
|
return rts->ClampedHardwareConcurrency(
|
|
aWorkerPrivate->ShouldResistFingerprinting(
|
|
RFPTarget::NavigatorHWConcurrency),
|
|
aWorkerPrivate->ShouldResistFingerprinting(
|
|
RFPTarget::NavigatorHWConcurrencyTiered));
|
|
}
|
|
|
|
StorageManager* WorkerNavigator::Storage() {
|
|
if (!mStorageManager) {
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
RefPtr<nsIGlobalObject> global = workerPrivate->GlobalScope();
|
|
MOZ_ASSERT(global);
|
|
|
|
mStorageManager = new StorageManager(global);
|
|
}
|
|
|
|
return mStorageManager;
|
|
}
|
|
|
|
network::Connection* WorkerNavigator::GetConnection(ErrorResult& aRv) {
|
|
if (!mConnection) {
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
mConnection = network::Connection::CreateForWorker(workerPrivate, aRv);
|
|
}
|
|
|
|
return mConnection;
|
|
}
|
|
|
|
dom::MediaCapabilities* WorkerNavigator::MediaCapabilities() {
|
|
if (!mMediaCapabilities) {
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
nsIGlobalObject* global = workerPrivate->GlobalScope();
|
|
MOZ_ASSERT(global);
|
|
|
|
mMediaCapabilities = new dom::MediaCapabilities(global);
|
|
}
|
|
return mMediaCapabilities;
|
|
}
|
|
|
|
webgpu::Instance* WorkerNavigator::Gpu() {
|
|
if (!mWebGpu) {
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
nsIGlobalObject* global = workerPrivate->GlobalScope();
|
|
MOZ_ASSERT(global);
|
|
|
|
mWebGpu = webgpu::Instance::Create(global);
|
|
}
|
|
return mWebGpu;
|
|
}
|
|
|
|
dom::LockManager* WorkerNavigator::Locks() {
|
|
if (!mLocks) {
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
nsIGlobalObject* global = workerPrivate->GlobalScope();
|
|
MOZ_ASSERT(global);
|
|
|
|
mLocks = dom::LockManager::Create(*global);
|
|
}
|
|
return mLocks;
|
|
}
|
|
|
|
dom::Permissions* WorkerNavigator::Permissions() {
|
|
if (!mPermissions) {
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
nsIGlobalObject* global = workerPrivate->GlobalScope();
|
|
MOZ_ASSERT(global);
|
|
mPermissions = new dom::Permissions(global);
|
|
}
|
|
|
|
return mPermissions;
|
|
}
|
|
|
|
already_AddRefed<ServiceWorkerContainer> WorkerNavigator::ServiceWorker() {
|
|
if (!mServiceWorkerContainer) {
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
nsIGlobalObject* global = workerPrivate->GlobalScope();
|
|
MOZ_ASSERT(global);
|
|
|
|
mServiceWorkerContainer = ServiceWorkerContainer::Create(global);
|
|
}
|
|
|
|
RefPtr<ServiceWorkerContainer> ref = mServiceWorkerContainer;
|
|
return ref.forget();
|
|
}
|
|
|
|
dom::Serial* WorkerNavigator::Serial() {
|
|
if (!mSerial) {
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
nsIGlobalObject* global = workerPrivate->GlobalScope();
|
|
MOZ_ASSERT(global);
|
|
|
|
mSerial = MakeRefPtr<dom::Serial>(global);
|
|
}
|
|
|
|
return mSerial;
|
|
}
|
|
|
|
} // namespace mozilla::dom
|