Backed out 2 changesets (bug 1784590) for causing mochitest failures on test_privateBrowsing.html. CLOSED TREE

Backed out changeset cd284ba05fbb (bug 1784590)
Backed out changeset 2f714355a8c8 (bug 1784590)
This commit is contained in:
Marian-Vasile Laza
2022-08-23 01:26:37 +03:00
parent 558b8dfadd
commit 719e13cde2
22 changed files with 270 additions and 65 deletions

View File

@@ -1818,12 +1818,6 @@ network::Connection* Navigator::GetConnection(ErrorResult& aRv) {
already_AddRefed<ServiceWorkerContainer> Navigator::ServiceWorker() {
MOZ_ASSERT(mWindow);
if (mWindow->AsGlobal()->GetStorageAccess() ==
StorageAccess::ePrivateBrowsing) {
SetUseCounter(mWindow->AsGlobal()->GetGlobalJSObject(),
eUseCounter_custom_PrivateBrowsingNavigatorServiceWorker);
}
if (!mServiceWorkerContainer) {
mServiceWorkerContainer =
ServiceWorkerContainer::Create(mWindow->AsGlobal());

View File

@@ -404,15 +404,5 @@ method Element.setHTML
// Features that might be deprecated in the future
custom WindowOpenEmptyUrl calls window.open with an empty url argument
// Unsupported web APIs in Private Browsing Mode
custom PrivateBrowsingIDBFactoryOpen calls indexedDB.open in Private Browsing Mode
custom PrivateBrowsingIDBFactoryDeleteDatabase calls indexedDB.deleteDatabase in Private Browsing Mode
custom PrivateBrowsingCachesMatch calls caches.match in Private Browsing Mode
custom PrivateBrowsingCachesHas calls caches.has in Private Browsing Mode
custom PrivateBrowsingCachesOpen calls caches.open in Private Browsing Mode
custom PrivateBrowsingCachesDelete calls caches.delete in Private Browsing Mode
custom PrivateBrowsingCachesKeys calls caches.keys in Private Browsing Mode
custom PrivateBrowsingNavigatorServiceWorker accesses navigator.serviceWorker in Private Browsing Mode
// NOTE: Adding use counters requires data review, see
// https://wiki.mozilla.org/Data_Collection

View File

@@ -65,11 +65,3 @@ method console.timeStamp
method console.profile
method console.profileEnd
// Unsupported web APIs in Private Browsing Mode
custom PrivateBrowsingIDBFactoryOpen calls indexedDB.open in Private Browsing Mode
custom PrivateBrowsingIDBFactoryDeleteDatabase calls indexedDB.deleteDatabase in Private Browsing Mode
custom PrivateBrowsingCachesMatch calls caches.match in Private Browsing Mode
custom PrivateBrowsingCachesHas calls caches.has in Private Browsing Mode
custom PrivateBrowsingCachesOpen calls caches.open in Private Browsing Mode
custom PrivateBrowsingCachesDelete calls caches.delete in Private Browsing Mode
custom PrivateBrowsingCachesKeys calls caches.keys in Private Browsing Mode

View File

@@ -3290,6 +3290,14 @@ bool nsGlobalWindowInner::CachesEnabled(JSContext* aCx, JSObject*) {
if (!StaticPrefs::dom_caches_enabled()) {
return false;
}
if (StaticPrefs::dom_caches_hide_in_pbmode_enabled()) {
if (const nsCOMPtr<nsIGlobalObject> global =
xpc::CurrentNativeGlobal(aCx)) {
if (global->GetStorageAccess() == StorageAccess::ePrivateBrowsing) {
return false;
}
}
}
if (!JS::GetIsSecureContext(js::GetContextRealm(aCx))) {
return StaticPrefs::dom_caches_testing_enabled() ||
StaticPrefs::dom_serviceWorkers_testing_enabled();
@@ -5091,6 +5099,12 @@ Storage* nsGlobalWindowInner::GetLocalStorage(ErrorResult& aError) {
IDBFactory* nsGlobalWindowInner::GetIndexedDB(JSContext* aCx,
ErrorResult& aError) {
if (!IDBFactory::IsEnabled(aCx, AsGlobal()->GetGlobalJSObject())) {
// Let window.indexedDB be an attribute with a null value, to prevent
// undefined identifier error
return nullptr;
}
if (!mIndexedDB) {
// This may keep mIndexedDB null without setting an error.
auto res = IDBFactory::CreateForWindow(this);

View File

@@ -82,3 +82,6 @@ support-files = file_title.xhtml
[test_swapFrameLoaders.xhtml]
skip-if = os == 'mac' # bug 1674413
[test_bug1339722.html]
[test_hide_in_pbmode.html]
support-files =
file_hide_in_pbmode.js

View File

@@ -0,0 +1,112 @@
/* global importScripts */
const isWorker = typeof DedicatedWorkerGlobalScope === "function";
function checkAll(content, inPrivateBrowsing) {
function check(
item,
{ valueExpected, enumerationExpected, parent = "globalThis" }
) {
const exposed = valueExpected ? "is exposed" : "is not exposed";
const pbmode = inPrivateBrowsing ? "with pbmode" : "without pbmode";
const enumerated = enumerationExpected
? "is enumerated"
: "is not enumerated";
const worker = isWorker ? "in worker" : "in window";
is(
content.eval(`!!${parent}.${item}`),
valueExpected,
`${parent}.${item} ${exposed} ${pbmode} ${worker}`
);
is(
content.eval(`"${item}" in ${parent}`),
enumerationExpected,
`${parent}.${item} ${enumerated} ${pbmode} ${worker}`
);
}
function checkNotExposedInPBM(item, parent) {
check(item, {
valueExpected: !inPrivateBrowsing,
enumerationExpected: !inPrivateBrowsing,
parent,
});
}
function checkCaches() {
checkNotExposedInPBM("caches");
checkNotExposedInPBM("Cache");
checkNotExposedInPBM("CacheStorage");
}
function checkIDB() {
checkNotExposedInPBM("IDBFactory");
checkNotExposedInPBM("IDBKeyRange");
checkNotExposedInPBM("IDBOpenDBRequest");
checkNotExposedInPBM("IDBRequest");
checkNotExposedInPBM("IDBVersionChangeEvent");
// These are always accessed by jakearchibald/idb@v3 without existence checks.
// https://github.com/jakearchibald/idb/blob/e1c7c44dbba38415745afc782b8e247da8c833f2/lib/idb.mjs#L152
check("IDBCursor", {
valueExpected: true,
enumerationExpected: true,
});
check("IDBDatabase", {
valueExpected: true,
enumerationExpected: true,
});
check("IDBIndex", {
valueExpected: true,
enumerationExpected: true,
});
check("IDBObjectStore", {
valueExpected: true,
enumerationExpected: true,
});
check("IDBTransaction", {
valueExpected: true,
enumerationExpected: true,
});
// https://www.msn.com/feed accesses indexedDB as a global variable without existence check
// We need to always expose the attribute itself
check("indexedDB", {
valueExpected: !inPrivateBrowsing,
enumerationExpected: true,
});
}
function checkSW() {
if (isWorker) {
// Currently not supported. Bug 1131324
return;
}
checkNotExposedInPBM("serviceWorker", "navigator");
checkNotExposedInPBM("ServiceWorker");
checkNotExposedInPBM("ServiceWorkerContainer");
checkNotExposedInPBM("ServiceWorkerRegistration");
checkNotExposedInPBM("NavigationPreloadManager");
checkNotExposedInPBM("PushManager");
checkNotExposedInPBM("PushSubscription");
checkNotExposedInPBM("PushSubscriptionOptions");
}
checkCaches();
checkIDB();
checkSW();
}
if (isWorker) {
importScripts("/tests/SimpleTest/WorkerSimpleTest.js");
globalThis.onmessage = ev => {
const { inPrivateBrowsing } = ev.data;
checkAll(globalThis, inPrivateBrowsing);
postMessage({
kind: "info",
next: true,
description: "Worker test finished",
});
};
}

View File

@@ -0,0 +1,70 @@
<!DOCTYPE html>
<title>Test for hiding features in Private Browsing</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/WorkerHandler.js"></script>
<script src="file_hide_in_pbmode.js"></script>
<link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<script>
const { BrowserTestUtils } = ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
const contentPage = "https://example.org/chrome/dom/workers/test/empty.html";
function openBrowserWindow(url, { private }) {
return new Promise(resolve => {
const win = window.browsingContext.topChromeWindow.OpenBrowserWindow({ private });
win.addEventListener("load", () => {
const listener = () => {
if (win.content.location.href != contentPage) {
BrowserTestUtils.loadURI(win.gBrowser, contentPage);
return;
}
win.removeEventListener("DOMContentLoaded", listener);
resolve(win);
}
win.addEventListener("DOMContentLoaded", listener);
}, { once: true });
});
}
function runWorkerTest(content, inPrivateBrowsing) {
return new Promise((resolve, reject) => {
/** @type {Worker} */
const worker = content.eval("new Worker('/chrome/dom/base/test/chrome/file_hide_in_pbmode.js')");
worker.postMessage({ inPrivateBrowsing });
worker.onerror = reject;
listenForTests(worker);
worker.addEventListener("message", ev => {
if (ev.data.next) {
worker.terminate();
resolve();
}
});
});
}
async function runTest() {
// sanity check
let win = await openBrowserWindow(contentPage, { private: false });
checkAll(win.content, false);
await runWorkerTest(win.content, false);
win.close();
win = await openBrowserWindow(contentPage, { private: true });
checkAll(win.content, true);
await runWorkerTest(win.content, true);
win.close();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({
set: [
["dom.caches.hide_in_pbmode.enabled", true],
["dom.indexedDB.hide_in_pbmode.enabled", true],
["dom.serviceWorkers.hide_in_pbmode.enabled", true],
]
}, runTest);
</script>

View File

@@ -301,8 +301,7 @@ already_AddRefed<Promise> CacheStorage::Match(
const MultiCacheQueryOptions& aOptions, ErrorResult& aRv) {
NS_ASSERT_OWNINGTHREAD(CacheStorage);
if (!HasStorageAccess(eUseCounter_custom_PrivateBrowsingCachesMatch,
UseCounterWorker::Custom_PrivateBrowsingCachesMatch)) {
if (!HasStorageAccess()) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
@@ -340,8 +339,7 @@ already_AddRefed<Promise> CacheStorage::Has(const nsAString& aKey,
ErrorResult& aRv) {
NS_ASSERT_OWNINGTHREAD(CacheStorage);
if (!HasStorageAccess(eUseCounter_custom_PrivateBrowsingCachesHas,
UseCounterWorker::Custom_PrivateBrowsingCachesHas)) {
if (!HasStorageAccess()) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
@@ -369,8 +367,7 @@ already_AddRefed<Promise> CacheStorage::Open(const nsAString& aKey,
ErrorResult& aRv) {
NS_ASSERT_OWNINGTHREAD(CacheStorage);
if (!HasStorageAccess(eUseCounter_custom_PrivateBrowsingCachesOpen,
UseCounterWorker::Custom_PrivateBrowsingCachesOpen)) {
if (!HasStorageAccess()) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
@@ -398,8 +395,7 @@ already_AddRefed<Promise> CacheStorage::Delete(const nsAString& aKey,
ErrorResult& aRv) {
NS_ASSERT_OWNINGTHREAD(CacheStorage);
if (!HasStorageAccess(eUseCounter_custom_PrivateBrowsingCachesDelete,
UseCounterWorker::Custom_PrivateBrowsingCachesDelete)) {
if (!HasStorageAccess()) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
@@ -426,8 +422,7 @@ already_AddRefed<Promise> CacheStorage::Delete(const nsAString& aKey,
already_AddRefed<Promise> CacheStorage::Keys(ErrorResult& aRv) {
NS_ASSERT_OWNINGTHREAD(CacheStorage);
if (!HasStorageAccess(eUseCounter_custom_PrivateBrowsingCachesKeys,
UseCounterWorker::Custom_PrivateBrowsingCachesKeys)) {
if (!HasStorageAccess()) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
@@ -558,21 +553,13 @@ OpenMode CacheStorage::GetOpenMode() const {
return mNamespace == CHROME_ONLY_NAMESPACE ? OpenMode::Eager : OpenMode::Lazy;
}
bool CacheStorage::HasStorageAccess(UseCounter aLabel,
UseCounterWorker aLabelWorker) const {
bool CacheStorage::HasStorageAccess() const {
NS_ASSERT_OWNINGTHREAD(CacheStorage);
if (NS_WARN_IF(!mGlobal)) {
return false;
}
StorageAccess access = mGlobal->GetStorageAccess();
if (access == StorageAccess::ePrivateBrowsing) {
if (NS_IsMainThread()) {
SetUseCounter(mGlobal->GetGlobalJSObject(), aLabel);
} else {
SetUseCounter(aLabelWorker);
}
}
return access > StorageAccess::ePrivateBrowsing ||
(StaticPrefs::
privacy_partition_always_partition_third_party_non_cookie_storage() &&

View File

@@ -95,7 +95,7 @@ class CacheStorage final : public nsISupports,
OpenMode GetOpenMode() const;
bool HasStorageAccess(UseCounter aLabel, UseCounterWorker aLabelWorker) const;
bool HasStorageAccess() const;
const Namespace mNamespace;
nsCOMPtr<nsIGlobalObject> mGlobal;

View File

@@ -1 +1,5 @@
[DEFAULT]
prefs =
dom.caches.hide_in_pbmode.enabled=false
[browser_cache_pb_window.js]

View File

@@ -359,6 +359,21 @@ bool IDBFactory::AllowedForPrincipal(nsIPrincipal* aPrincipal,
return !aPrincipal->GetIsNullPrincipal();
}
bool IDBFactory::IsEnabled(JSContext* aCx, JSObject* aGlobal) {
if (StaticPrefs::dom_indexedDB_privateBrowsing_enabled()) {
return true;
}
if (StaticPrefs::dom_indexedDB_hide_in_pbmode_enabled()) {
if (const nsCOMPtr<nsIGlobalObject> global =
xpc::CurrentNativeGlobal(aCx)) {
if (global->GetStorageAccess() == StorageAccess::ePrivateBrowsing) {
return false;
}
}
}
return true;
}
void IDBFactory::UpdateActiveTransactionCount(int32_t aDelta) {
AssertIsOnOwningThread();
MOZ_DIAGNOSTIC_ASSERT(aDelta > 0 || (mActiveTransactionCount + aDelta) <
@@ -401,7 +416,6 @@ RefPtr<IDBOpenDBRequest> IDBFactory::Open(JSContext* aCx,
const IDBOpenDBOptions& aOptions,
CallerType aCallerType,
ErrorResult& aRv) {
// This overload is nonstandard, see bug 1275496.
// Ignore calls with empty options for telemetry of usage count.
// Unfortunately, we cannot distinguish between the use of the method with
// only a single argument (which actually is a standard overload we don't want
@@ -537,20 +551,6 @@ RefPtr<IDBOpenDBRequest> IDBFactory::OpenInternal(
return nullptr;
}
} else {
if (mGlobal->GetStorageAccess() == StorageAccess::ePrivateBrowsing) {
if (NS_IsMainThread()) {
SetUseCounter(
mGlobal->GetGlobalJSObject(),
aDeleting
? eUseCounter_custom_PrivateBrowsingIDBFactoryOpen
: eUseCounter_custom_PrivateBrowsingIDBFactoryDeleteDatabase);
} else {
SetUseCounter(
aDeleting ? UseCounterWorker::Custom_PrivateBrowsingIDBFactoryOpen
: UseCounterWorker::
Custom_PrivateBrowsingIDBFactoryDeleteDatabase);
}
}
principalInfo = *mPrincipalInfo;
}

View File

@@ -95,6 +95,8 @@ class IDBFactory final : public nsISupports, public nsWrapperCache {
static bool AllowedForPrincipal(nsIPrincipal* aPrincipal,
bool* aIsSystemPrincipal = nullptr);
static bool IsEnabled(JSContext* aCx, JSObject* aGlobal);
void AssertIsOnOwningThread() const { NS_ASSERT_OWNINGTHREAD(IDBFactory); }
nsISerialEventTarget* EventTarget() const {

View File

@@ -1,4 +1,6 @@
[DEFAULT]
prefs =
dom.indexedDB.hide_in_pbmode.enabled=false
skip-if = (buildapp != "browser")
support-files =
head.js

View File

@@ -53,6 +53,15 @@ bool ServiceWorkersEnabled(JSContext* aCx, JSObject* aGlobal) {
// xpc::CurrentNativeGlobal below requires rooting
JS::Rooted<JSObject*> global(aCx, aGlobal);
if (StaticPrefs::dom_serviceWorkers_hide_in_pbmode_enabled()) {
if (const nsCOMPtr<nsIGlobalObject> global =
xpc::CurrentNativeGlobal(aCx)) {
if (global->GetStorageAccess() == StorageAccess::ePrivateBrowsing) {
return false;
}
}
}
// Allow a webextension principal to register a service worker script with
// a moz-extension url only if 'extensions.service_worker_register.allowed'
// is true.
@@ -77,6 +86,8 @@ bool ServiceWorkerVisible(JSContext* aCx, JSObject* aGlobal) {
// navigator.serviceWorker is available. Currently it may not be available
// with some reasons:
// 1. navigator.serviceWorker is not supported in workers. (bug 1131324)
// 2. `dom.serviceWorkers.hide_in_pbmode.enabled` wants to hide it in
// private browsing mode.
return ServiceWorkersEnabled(aCx, aGlobal);
}

View File

@@ -38,7 +38,7 @@ interface IDBCursor {
[NewObject, Throws] IDBRequest delete();
};
[Exposed=(Window,Worker)]
[Exposed=(Window,Worker), Func="IDBFactory::IsEnabled"]
interface IDBCursorWithValue : IDBCursor {
[Pure, Throws] readonly attribute any value;
};

View File

@@ -22,7 +22,7 @@ dictionary IDBOpenDBOptions
* https://w3c.github.io/IndexedDB/#idbfactory
* for more information.
*/
[Exposed=(Window,Worker)]
[Exposed=(Window,Worker), Func="IDBFactory::IsEnabled"]
interface IDBFactory {
[NewObject, Throws, NeedsCallerType]
IDBOpenDBRequest

View File

@@ -9,7 +9,7 @@
* liability, trademark and document use rules apply.
*/
[Exposed=(Window,Worker)]
[Exposed=(Window,Worker), Func="IDBFactory::IsEnabled"]
interface IDBKeyRange {
[Throws]
readonly attribute any lower;

View File

@@ -7,7 +7,7 @@
* https://w3c.github.io/IndexedDB/#idbopendbrequest
*/
[Exposed=(Window,Worker)]
[Exposed=(Window,Worker), Func="IDBFactory::IsEnabled"]
interface IDBOpenDBRequest : IDBRequest {
attribute EventHandler onblocked;

View File

@@ -13,7 +13,7 @@ enum IDBRequestReadyState {
"done"
};
[Exposed=(Window,Worker)]
[Exposed=(Window,Worker), Func="IDBFactory::IsEnabled"]
interface IDBRequest : EventTarget {
[Throws]
readonly attribute any result;

View File

@@ -15,7 +15,7 @@ dictionary IDBVersionChangeEventInit : EventInit {
unsigned long long? newVersion = null;
};
[Exposed=(Window,Worker)]
[Exposed=(Window,Worker), Func="IDBFactory::IsEnabled"]
interface IDBVersionChangeEvent : Event {
constructor(DOMString type,
optional IDBVersionChangeEventInit eventInitDict = {});

View File

@@ -679,6 +679,12 @@ already_AddRefed<IDBFactory> WorkerGlobalScope::GetIndexedDB(
JSContext* aCx, ErrorResult& aErrorResult) {
AssertIsOnWorkerThread();
if (!IDBFactory::IsEnabled(aCx, GetGlobalJSObject())) {
// Let window.indexedDB be an attribute with a null value, to prevent
// undefined identifier error
return nullptr;
}
RefPtr<IDBFactory> indexedDB = mIndexedDB;
if (!indexedDB) {

View File

@@ -2139,6 +2139,12 @@
value: false
mirror: always
# Disable CacheStorage in private browsing mode.
- name: dom.caches.hide_in_pbmode.enabled
type: RelaxedAtomicBool
value: @IS_NIGHTLY_BUILD@
mirror: always
# Disable capture attribute for input elements; only supported on GeckoView.
- name: dom.capture.enabled
type: bool
@@ -2598,6 +2604,12 @@
value: false
mirror: always
# Disable IndexedDB in private browsing mode.
- name: dom.indexedDB.hide_in_pbmode.enabled
type: RelaxedAtomicBool
value: @IS_NIGHTLY_BUILD@
mirror: always
# Whether or not indexedDB test mode is enabled.
- name: dom.indexedDB.testing
type: RelaxedAtomicBool
@@ -3699,6 +3711,12 @@
value: false
mirror: always
# Disable ServiceWorker in private browsing mode.
- name: dom.serviceWorkers.hide_in_pbmode.enabled
type: RelaxedAtomicBool
value: true
mirror: always
- name: dom.workers.requestAnimationFrame
type: RelaxedAtomicBool
value: true