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

Backed out changeset 36d36e75930f (bug 1784590)
Backed out changeset 35dbbd6dbb70 (bug 1784590)
This commit is contained in:
Marian-Vasile Laza 2022-08-22 22:50:41 +03:00
Родитель 41e03a66c8
Коммит b92a6b8396
22 изменённых файлов: 270 добавлений и 65 удалений

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

@ -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());

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

@ -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

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

@ -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

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

@ -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);

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

@ -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

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

@ -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",
});
};
}

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

@ -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>

25
dom/cache/CacheStorage.cpp поставляемый
Просмотреть файл

@ -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() &&

2
dom/cache/CacheStorage.h поставляемый
Просмотреть файл

@ -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;

4
dom/cache/test/browser/browser.ini поставляемый
Просмотреть файл

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

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

@ -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;
}

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

@ -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 {

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

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

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

@ -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);
}

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

@ -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;
};

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

@ -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

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

@ -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;

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

@ -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;

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

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

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

@ -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 = {});

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

@ -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) {

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

@ -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
@ -3692,6 +3704,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