зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1778489 - Define window.indexedDB as null in Private Browsing Mode r=twisniewski,asuth
https://www.msn.com/ja-jp/feed accesses `indexedDB` as a global variable and thus it throws undefined identifier error when it's not defined. Returning null fixes the regression. Differential Revision: https://phabricator.services.mozilla.com/D151373
This commit is contained in:
Родитель
28609ba87e
Коммит
f4fcfcd045
|
@ -5047,7 +5047,14 @@ Storage* nsGlobalWindowInner::GetLocalStorage(ErrorResult& aError) {
|
||||||
return mLocalStorage;
|
return mLocalStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
IDBFactory* nsGlobalWindowInner::GetIndexedDB(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) {
|
if (!mIndexedDB) {
|
||||||
// This may keep mIndexedDB null without setting an error.
|
// This may keep mIndexedDB null without setting an error.
|
||||||
auto res = IDBFactory::CreateForWindow(this);
|
auto res = IDBFactory::CreateForWindow(this);
|
||||||
|
|
|
@ -744,7 +744,8 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
||||||
mozilla::dom::Storage* GetSessionStorage(mozilla::ErrorResult& aError);
|
mozilla::dom::Storage* GetSessionStorage(mozilla::ErrorResult& aError);
|
||||||
mozilla::dom::Storage* GetLocalStorage(mozilla::ErrorResult& aError);
|
mozilla::dom::Storage* GetLocalStorage(mozilla::ErrorResult& aError);
|
||||||
mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aError);
|
mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aError);
|
||||||
mozilla::dom::IDBFactory* GetIndexedDB(mozilla::ErrorResult& aError);
|
mozilla::dom::IDBFactory* GetIndexedDB(JSContext* aCx,
|
||||||
|
mozilla::ErrorResult& aError);
|
||||||
already_AddRefed<nsICSSDeclaration> GetComputedStyle(
|
already_AddRefed<nsICSSDeclaration> GetComputedStyle(
|
||||||
mozilla::dom::Element& aElt, const nsAString& aPseudoElt,
|
mozilla::dom::Element& aElt, const nsAString& aPseudoElt,
|
||||||
mozilla::ErrorResult& aError) override;
|
mozilla::ErrorResult& aError) override;
|
||||||
|
|
|
@ -2,66 +2,107 @@
|
||||||
|
|
||||||
const isWorker = typeof DedicatedWorkerGlobalScope === "function";
|
const isWorker = typeof DedicatedWorkerGlobalScope === "function";
|
||||||
|
|
||||||
function check(content, expected, item) {
|
function checkAll(content, inPrivateBrowsing) {
|
||||||
const exposed = expected ? "is exposed without" : "is not exposed with";
|
function check(
|
||||||
const worker = isWorker ? "in worker" : "in window";
|
item,
|
||||||
is(
|
{ valueExpected, enumerationExpected, parent = "globalThis" }
|
||||||
content.eval(`!!globalThis.${item}`),
|
) {
|
||||||
expected,
|
const exposed = valueExpected ? "is exposed" : "is not exposed";
|
||||||
`${item} ${exposed} pbmode ${worker}`
|
const pbmode = inPrivateBrowsing ? "with pbmode" : "without pbmode";
|
||||||
);
|
const enumerated = enumerationExpected
|
||||||
}
|
? "is enumerated"
|
||||||
|
: "is not enumerated";
|
||||||
function checkCaches(content, expected) {
|
const worker = isWorker ? "in worker" : "in window";
|
||||||
check(content, expected, "caches");
|
is(
|
||||||
check(content, expected, "Cache");
|
content.eval(`!!${parent}.${item}`),
|
||||||
check(content, expected, "CacheStorage");
|
valueExpected,
|
||||||
}
|
`${parent}.${item} ${exposed} ${pbmode} ${worker}`
|
||||||
|
);
|
||||||
function checkIDB(content, expected) {
|
is(
|
||||||
check(content, expected, "indexedDB");
|
content.eval(`"${item}" in ${parent}`),
|
||||||
check(content, expected, "IDBFactory");
|
enumerationExpected,
|
||||||
check(content, expected, "IDBKeyRange");
|
`${parent}.${item} ${enumerated} ${pbmode} ${worker}`
|
||||||
check(content, expected, "IDBOpenDBRequest");
|
);
|
||||||
check(content, expected, "IDBRequest");
|
|
||||||
check(content, expected, "IDBVersionChangeEvent");
|
|
||||||
|
|
||||||
// These are always accessed by jakearchibald/idb@v3 without existence checks.
|
|
||||||
// https://github.com/jakearchibald/idb/blob/e1c7c44dbba38415745afc782b8e247da8c833f2/lib/idb.mjs#L152
|
|
||||||
check(content, true, "IDBCursor");
|
|
||||||
check(content, true, "IDBDatabase");
|
|
||||||
check(content, true, "IDBIndex");
|
|
||||||
check(content, true, "IDBObjectStore");
|
|
||||||
check(content, true, "IDBTransaction");
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkSW(content, expected) {
|
|
||||||
if (isWorker) {
|
|
||||||
// Currently not supported. Bug 1131324
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
check(content, expected, "navigator.serviceWorker");
|
|
||||||
check(content, expected, "ServiceWorker");
|
|
||||||
check(content, expected, "ServiceWorkerContainer");
|
|
||||||
check(content, expected, "ServiceWorkerRegistration");
|
|
||||||
check(content, expected, "NavigationPreloadManager");
|
|
||||||
check(content, expected, "PushManager");
|
|
||||||
check(content, expected, "PushSubscription");
|
|
||||||
check(content, expected, "PushSubscriptionOptions");
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkAll(content, expected) {
|
function checkNotExposedInPBM(item, parent) {
|
||||||
checkCaches(content, expected);
|
check(item, {
|
||||||
checkIDB(content, expected);
|
valueExpected: !inPrivateBrowsing,
|
||||||
checkSW(content, expected);
|
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) {
|
if (isWorker) {
|
||||||
importScripts("/tests/SimpleTest/WorkerSimpleTest.js");
|
importScripts("/tests/SimpleTest/WorkerSimpleTest.js");
|
||||||
|
|
||||||
globalThis.onmessage = ev => {
|
globalThis.onmessage = ev => {
|
||||||
const { expected } = ev.data;
|
const { inPrivateBrowsing } = ev.data;
|
||||||
checkAll(globalThis, expected);
|
checkAll(globalThis, inPrivateBrowsing);
|
||||||
postMessage({
|
postMessage({
|
||||||
kind: "info",
|
kind: "info",
|
||||||
next: true,
|
next: true,
|
||||||
|
|
|
@ -27,11 +27,11 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function runWorkerTest(content, expected) {
|
function runWorkerTest(content, inPrivateBrowsing) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
/** @type {Worker} */
|
/** @type {Worker} */
|
||||||
const worker = content.eval("new Worker('/chrome/dom/base/test/chrome/file_hide_in_pbmode.js')");
|
const worker = content.eval("new Worker('/chrome/dom/base/test/chrome/file_hide_in_pbmode.js')");
|
||||||
worker.postMessage({ expected });
|
worker.postMessage({ inPrivateBrowsing });
|
||||||
worker.onerror = reject;
|
worker.onerror = reject;
|
||||||
listenForTests(worker);
|
listenForTests(worker);
|
||||||
worker.addEventListener("message", ev => {
|
worker.addEventListener("message", ev => {
|
||||||
|
@ -46,13 +46,13 @@
|
||||||
async function runTest() {
|
async function runTest() {
|
||||||
// sanity check
|
// sanity check
|
||||||
let win = await openBrowserWindow(contentPage, { private: false });
|
let win = await openBrowserWindow(contentPage, { private: false });
|
||||||
checkAll(win.content, true);
|
checkAll(win.content, false);
|
||||||
await runWorkerTest(win.content, true);
|
await runWorkerTest(win.content, false);
|
||||||
win.close();
|
win.close();
|
||||||
|
|
||||||
win = await openBrowserWindow(contentPage, { private: true });
|
win = await openBrowserWindow(contentPage, { private: true });
|
||||||
checkAll(win.content, false);
|
checkAll(win.content, true);
|
||||||
await runWorkerTest(win.content, false);
|
await runWorkerTest(win.content, true);
|
||||||
win.close();
|
win.close();
|
||||||
|
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
|
|
|
@ -1600,7 +1600,7 @@ DOMInterfaces = {
|
||||||
'nativeType': 'nsGlobalWindowInner',
|
'nativeType': 'nsGlobalWindowInner',
|
||||||
'headerFile': 'nsGlobalWindow.h',
|
'headerFile': 'nsGlobalWindow.h',
|
||||||
'implicitJSContext': [
|
'implicitJSContext': [
|
||||||
'requestIdleCallback'
|
'requestIdleCallback', 'indexedDB'
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1627,7 +1627,7 @@ DOMInterfaces = {
|
||||||
|
|
||||||
'WorkerGlobalScope': {
|
'WorkerGlobalScope': {
|
||||||
'headerFile': 'mozilla/dom/WorkerScope.h',
|
'headerFile': 'mozilla/dom/WorkerScope.h',
|
||||||
'implicitJSContext': [ 'importScripts' ],
|
'implicitJSContext': [ 'importScripts', 'indexedDB' ],
|
||||||
},
|
},
|
||||||
|
|
||||||
'Worklet': {
|
'Worklet': {
|
||||||
|
|
|
@ -70,7 +70,7 @@ partial interface mixin WindowOrWorkerGlobalScope {
|
||||||
// http://w3c.github.io/IndexedDB/#factory-interface
|
// http://w3c.github.io/IndexedDB/#factory-interface
|
||||||
partial interface mixin WindowOrWorkerGlobalScope {
|
partial interface mixin WindowOrWorkerGlobalScope {
|
||||||
// readonly attribute IDBFactory indexedDB; // bug 1776789
|
// readonly attribute IDBFactory indexedDB; // bug 1776789
|
||||||
[Throws, Func="IDBFactory::IsEnabled"]
|
[Throws]
|
||||||
readonly attribute IDBFactory? indexedDB;
|
readonly attribute IDBFactory? indexedDB;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -676,9 +676,15 @@ already_AddRefed<Promise> WorkerGlobalScope::Fetch(
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<IDBFactory> WorkerGlobalScope::GetIndexedDB(
|
already_AddRefed<IDBFactory> WorkerGlobalScope::GetIndexedDB(
|
||||||
ErrorResult& aErrorResult) {
|
JSContext* aCx, ErrorResult& aErrorResult) {
|
||||||
AssertIsOnWorkerThread();
|
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;
|
RefPtr<IDBFactory> indexedDB = mIndexedDB;
|
||||||
|
|
||||||
if (!indexedDB) {
|
if (!indexedDB) {
|
||||||
|
|
|
@ -312,7 +312,8 @@ class WorkerGlobalScope : public WorkerGlobalScopeBase {
|
||||||
|
|
||||||
bool IsSecureContext() const;
|
bool IsSecureContext() const;
|
||||||
|
|
||||||
already_AddRefed<IDBFactory> GetIndexedDB(ErrorResult& aErrorResult);
|
already_AddRefed<IDBFactory> GetIndexedDB(JSContext* aCx,
|
||||||
|
ErrorResult& aErrorResult);
|
||||||
|
|
||||||
already_AddRefed<cache::CacheStorage> GetCaches(ErrorResult& aRv);
|
already_AddRefed<cache::CacheStorage> GetCaches(ErrorResult& aRv);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче