Diff
Modified: trunk/LayoutTests/ChangeLog (215314 => 215315)
--- trunk/LayoutTests/ChangeLog 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/LayoutTests/ChangeLog 2017-04-13 06:38:19 UTC (rev 215315)
@@ -1,3 +1,20 @@
+2017-04-12 Brady Eidson <beid...@apple.com>
+
+ QuotaExceededError when saving to localStorage in private mode.
+ https://bugs.webkit.org/show_bug.cgi?id=157010
+
+ Reviewed by Alex Christensen.
+
+ * platform/mac-wk2/TestExpectations:
+ * storage/domstorage/localstorage/private-browsing-affects-storage-expected.txt:
+ * storage/domstorage/localstorage/private-browsing-affects-storage.html:
+ * storage/domstorage/localstorage/resources/private-browsing-1.html: Added.
+ * storage/domstorage/localstorage/resources/private-browsing-2.html: Added.
+ * storage/domstorage/localstorage/resources/private-browsing-3.html: Added.
+ * storage/domstorage/localstorage/resources/private-browsing-storage-2.html: Added.
+ * storage/domstorage/sessionstorage/private-browsing-affects-storage-expected.txt: Removed.
+ * storage/domstorage/sessionstorage/private-browsing-affects-storage.html: Removed.
+
2017-04-12 Joseph Pecoraro <pecor...@apple.com>
test262: test262/test/built-ins/NativeErrors/EvalError/proto.js
Modified: trunk/LayoutTests/platform/mac-wk2/TestExpectations (215314 => 215315)
--- trunk/LayoutTests/platform/mac-wk2/TestExpectations 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/LayoutTests/platform/mac-wk2/TestExpectations 2017-04-13 06:38:19 UTC (rev 215315)
@@ -424,8 +424,6 @@
http/tests/security/storage-blocking-strengthened-private-browsing-plugin.html [ Skip ]
plugins/private-browsing-mode-2.html [ Skip ]
plugins/private-browsing-mode.html [ Skip ]
-storage/domstorage/localstorage/private-browsing-affects-storage.html [ Skip ]
-storage/domstorage/sessionstorage/private-browsing-affects-storage.html [ Skip ]
storage/websql/private-browsing-noread-nowrite.html [ Skip ]
# There is no network load scheduling or prioritization with NetworkProcess.
Modified: trunk/LayoutTests/storage/domstorage/localstorage/private-browsing-affects-storage-expected.txt (215314 => 215315)
--- trunk/LayoutTests/storage/domstorage/localstorage/private-browsing-affects-storage-expected.txt 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/LayoutTests/storage/domstorage/localstorage/private-browsing-affects-storage-expected.txt 2017-04-13 06:38:19 UTC (rev 215315)
@@ -1,7 +1,14 @@
-This is a test to make sure that when private browsing is on any attempt to change the localStorage area fail.
-Initial value of testItem is: null
-Caught exception trying to change item: QuotaExceededError (DOM Exception 22): The quota has been exceeded.
-After change attempt, testItem is: null
-After remove attempt, testItem is: null
-After clear attempt, testItem is: null
+ALERT: Persistent localStorage testItem is: Persistent item!
+ALERT: Start of private browsing test, testItem is: null
+ALERT: localStorage's length is: 0
+ALERT: After set attempt, testItem is: FirstValue
+ALERT: After second set attempt, testItem is: ChangedValue
+ALERT: Opening window...
+ALERT: localStorage's length is: 1
+ALERT: The item in new window starts out as: ChangedValue
+ALERT: The item in new window is now: NewWindowValue
+ALERT: Back in parent window, localStorage's length is: 1
+ALERT: Back in parent window, testItem is: ChangedValue
+ALERT: Final window, localStorage's length is: 1
+ALERT: Final window, item is: Persistent item!
Modified: trunk/LayoutTests/storage/domstorage/localstorage/private-browsing-affects-storage.html (215314 => 215315)
--- trunk/LayoutTests/storage/domstorage/localstorage/private-browsing-affects-storage.html 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/LayoutTests/storage/domstorage/localstorage/private-browsing-affects-storage.html 2017-04-13 06:38:19 UTC (rev 215315)
@@ -2,49 +2,36 @@
<head>
<script>
-if (window.testRunner)
+if (window.testRunner) {
testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
function log(a)
{
- document.getElementById("logger").innerHTML += a + "<br>";
+ alert(a + "");
}
function runTest()
{
- if (!window.localStorage) {
- log("window.localStorage DOES NOT exist");
- return;
- }
if (!window.testRunner) {
- log("Test only designed to be run under DumpRenderTree");
+ log("Test only designed to be run under DumpRenderTree or WebKitTestRunner");
return;
}
- localStorage.clear();
+
+ localStorage.setItem("testItem", "Persistent item!");
+ log("Persistent localStorage testItem is: " + localStorage.getItem("testItem"));
- localStorage.setItem("testItem", "InitialValue");
testRunner.setPrivateBrowsingEnabled(true);
- log("Initial value of testItem is: " + localStorage.getItem("testItem"));
-
- try {
- localStorage.setItem("testItem", "ChangedValue");
- } catch(e) {
- log("Caught exception trying to change item: " + e);
- }
-
- log("After change attempt, testItem is: " + localStorage.getItem("testItem"));
+ testRunner.setCanOpenWindows();
- localStorage.removeItem("testItem");
- log("After remove attempt, testItem is: " + localStorage.getItem("testItem"));
-
- localStorage.clear();
- log("After clear attempt, testItem is: " + localStorage.getItem("testItem"));
+ window.location.href = ""
}
</script>
</head>
<body _onload_="runTest();">
-This is a test to make sure that when private browsing is on any attempt to change the localStorage area fail.
+This is a test to make sure that when private browsing is on changes to local storage are not persistent.
<div id="logger"></div>
</body>
</html>
Added: trunk/LayoutTests/storage/domstorage/localstorage/resources/private-browsing-1.html (0 => 215315)
--- trunk/LayoutTests/storage/domstorage/localstorage/resources/private-browsing-1.html (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/resources/private-browsing-1.html 2017-04-13 06:38:19 UTC (rev 215315)
@@ -0,0 +1,56 @@
+<html>
+<head>
+<script>
+
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+
+function log(a)
+{
+ alert(a + "");
+}
+
+function runTest()
+{
+ window.logger = log;
+ window.allDone = function() {
+ log("Back in parent window, localStorage's length is: " + localStorage.length);
+ log("Back in parent window, testItem is: " + localStorage.getItem("testItem"));
+
+ testRunner.setPrivateBrowsingEnabled(false);
+
+ window.location.href = ""
+ }
+
+ log("Start of private browsing test, testItem is: " + localStorage.getItem("testItem"));
+ log("localStorage's length is: " + localStorage.length);
+
+ try {
+ localStorage.setItem("testItem", "FirstValue");
+ } catch(e) {
+ log("Caught exception trying to change item: " + e);
+ }
+
+ log("After set attempt, testItem is: " + localStorage.getItem("testItem"));
+
+ try {
+ localStorage.setItem("testItem", "ChangedValue");
+ } catch(e) {
+ log("Caught exception trying to change item: " + e);
+ }
+
+ log("After second set attempt, testItem is: " + localStorage.getItem("testItem"));
+ log("Opening window...");
+
+ window.open("private-browsing-2.html", "_blank");
+}
+
+</script>
+</head>
+<body _onload_="runTest();">
+This is a test to make sure that when private browsing is on changes to local storage are not persistent.
+<div id="logger"></div>
+</body>
+</html>
Added: trunk/LayoutTests/storage/domstorage/localstorage/resources/private-browsing-2.html (0 => 215315)
--- trunk/LayoutTests/storage/domstorage/localstorage/resources/private-browsing-2.html (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/resources/private-browsing-2.html 2017-04-13 06:38:19 UTC (rev 215315)
@@ -0,0 +1,31 @@
+<html>
+<head>
+<script>
+
+function log(a)
+{
+ opener.logger(a);
+}
+
+function runTest()
+{
+ if (!window.testRunner) {
+ log("Test only designed to be run under DumpRenderTree or WebKitTestRunner");
+ return;
+ }
+
+ testRunner.setPrivateBrowsingEnabled(true);
+
+ log("localStorage's length is: " + localStorage.length);
+ log("The item in new window starts out as: " + localStorage.getItem("testItem"));
+ localStorage.setItem("testItem", "NewWindowValue");
+ log("The item in new window is now: " + localStorage.getItem("testItem"));
+
+ opener.allDone();
+}
+
+</script>
+</head>
+<body _onload_="runTest();">
+</body>
+</html>
Added: trunk/LayoutTests/storage/domstorage/localstorage/resources/private-browsing-3.html (0 => 215315)
--- trunk/LayoutTests/storage/domstorage/localstorage/resources/private-browsing-3.html (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/resources/private-browsing-3.html 2017-04-13 06:38:19 UTC (rev 215315)
@@ -0,0 +1,23 @@
+<html>
+<head>
+<script>
+
+function log(a)
+{
+ alert(a + "");
+}
+
+function runTest()
+{
+ log("Final window, localStorage's length is: " + localStorage.length);
+ log("Final window, item is: " + localStorage.getItem("testItem"));
+
+ if (testRunner)
+ testRunner.notifyDone();
+}
+
+</script>
+</head>
+<body _onload_="runTest();">
+</body>
+</html>
Added: trunk/LayoutTests/storage/domstorage/localstorage/resources/private-browsing-storage-2.html (0 => 215315)
--- trunk/LayoutTests/storage/domstorage/localstorage/resources/private-browsing-storage-2.html (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/resources/private-browsing-storage-2.html 2017-04-13 06:38:19 UTC (rev 215315)
@@ -0,0 +1,29 @@
+<html>
+<head>
+<script>
+
+function log(a)
+{
+ opener.logger(a);
+}
+
+function runTest()
+{
+ if (!window.testRunner) {
+ log("Test only designed to be run under DumpRenderTree or WebKitTestRunner");
+ return;
+ }
+
+ log("localStorage's length is: " + localStorage.length);
+ log("The item in new window starts out as: " + localStorage.getItem("testItem"));
+ localStorage.setItem("testItem", "NewWindowValue");
+ log("The item in new window is now: " + localStorage.getItem("testItem"));
+
+ opener.allDone();
+}
+
+</script>
+</head>
+<body _onload_="runTest();">
+</body>
+</html>
Deleted: trunk/LayoutTests/storage/domstorage/sessionstorage/private-browsing-affects-storage-expected.txt (215314 => 215315)
--- trunk/LayoutTests/storage/domstorage/sessionstorage/private-browsing-affects-storage-expected.txt 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/LayoutTests/storage/domstorage/sessionstorage/private-browsing-affects-storage-expected.txt 2017-04-13 06:38:19 UTC (rev 215315)
@@ -1,7 +0,0 @@
-This is a test to make sure that when private browsing is on any attempt to change the sessionStorage area fail.
-Initial value of testItem is: null
-Caught exception trying to change item: QuotaExceededError (DOM Exception 22): The quota has been exceeded.
-After change attempt, testItem is: null
-After remove attempt, testItem is: null
-After clear attempt, testItem is: null
-
Deleted: trunk/LayoutTests/storage/domstorage/sessionstorage/private-browsing-affects-storage.html (215314 => 215315)
--- trunk/LayoutTests/storage/domstorage/sessionstorage/private-browsing-affects-storage.html 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/LayoutTests/storage/domstorage/sessionstorage/private-browsing-affects-storage.html 2017-04-13 06:38:19 UTC (rev 215315)
@@ -1,50 +0,0 @@
-<html>
-<head>
-<script src=""
-<script>
-
-if (window.testRunner)
- testRunner.dumpAsText();
-
-function log(a)
-{
- document.getElementById("logger").innerHTML += a + "<br>";
-}
-
-function runTest()
-{
- if (!window.sessionStorage) {
- log("window.sessionStorage DOES NOT exist");
- return;
- }
- if (!window.testRunner) {
- log("Test only designed to be run under DumpRenderTree");
- return;
- }
-
- sessionStorage.setItem("testItem", "InitialValue");
- testRunner.setPrivateBrowsingEnabled(true);
- log("Initial value of testItem is: " + sessionStorage.getItem("testItem"));
-
- try {
- sessionStorage.setItem("testItem", "ChangedValue");
- } catch(e) {
- log("Caught exception trying to change item: " + e);
- }
-
- log("After change attempt, testItem is: " + sessionStorage.getItem("testItem"));
-
- sessionStorage.removeItem("testItem");
- log("After remove attempt, testItem is: " + sessionStorage.getItem("testItem"));
-
- sessionStorage.clear();
- log("After clear attempt, testItem is: " + sessionStorage.getItem("testItem"));
-}
-
-</script>
-</head>
-<body _onload_="runTest();">
-This is a test to make sure that when private browsing is on any attempt to change the sessionStorage area fail.
-<div id="logger"></div>
-</body>
-</html>
Modified: trunk/Source/WebCore/ChangeLog (215314 => 215315)
--- trunk/Source/WebCore/ChangeLog 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebCore/ChangeLog 2017-04-13 06:38:19 UTC (rev 215315)
@@ -1,3 +1,48 @@
+2017-04-12 Brady Eidson <beid...@apple.com>
+
+ QuotaExceededError when saving to localStorage in private mode.
+ https://bugs.webkit.org/show_bug.cgi?id=157010
+
+ Reviewed by Alex Christensen.
+
+ No new tests (Covered by changes to existing test).
+
+ LocalStorage in private browsing is now effectively SessionStorage.
+ It's ephemeral, per-tab, and copied over to tabs window.open()'ed from the current.
+
+ * loader/EmptyClients.cpp:
+ (WebCore::EmptyStorageNamespaceProvider::createEphemeralLocalStorageNamespace):
+
+ * page/Chrome.cpp:
+ (WebCore::Chrome::createWindow):
+
+ * page/Page.cpp:
+ (WebCore::Page::ephemeralLocalStorage):
+ (WebCore::Page::setEphemeralLocalStorage):
+ * page/Page.h:
+
+ * page/SecurityOriginData.h:
+
+ * storage/Storage.cpp:
+ (WebCore::Storage::length):
+ (WebCore::Storage::key):
+ (WebCore::Storage::getItem):
+ (WebCore::Storage::setItem):
+ (WebCore::Storage::removeItem):
+ (WebCore::Storage::clear):
+ (WebCore::Storage::contains):
+ (WebCore::Storage::isDisabledByPrivateBrowsing): Deleted.
+
+ * storage/StorageMap.h:
+
+ * storage/StorageNamespaceProvider.cpp:
+ (WebCore::StorageNamespaceProvider::localStorageArea):
+ * storage/StorageNamespaceProvider.h:
+
+ * storage/StorageType.h:
+ (WebCore::isLocalStorage):
+ (WebCore::isPersistentLocalStorage):
+
2017-04-12 Myles C. Maxfield <mmaxfi...@apple.com>
[Cocoa] Suppress font download dialog in new matching algorithm
Modified: trunk/Source/WebCore/loader/EmptyClients.cpp (215314 => 215315)
--- trunk/Source/WebCore/loader/EmptyClients.cpp 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebCore/loader/EmptyClients.cpp 2017-04-13 06:38:19 UTC (rev 215315)
@@ -562,6 +562,7 @@
RefPtr<StorageNamespace> createSessionStorageNamespace(Page&, unsigned) final;
RefPtr<StorageNamespace> createLocalStorageNamespace(unsigned) final;
+ RefPtr<StorageNamespace> createEphemeralLocalStorageNamespace(Page&, unsigned) final;
RefPtr<StorageNamespace> createTransientLocalStorageNamespace(SecurityOrigin&, unsigned) final;
};
@@ -676,6 +677,11 @@
return adoptRef(*new EmptyStorageNamespace);
}
+RefPtr<StorageNamespace> EmptyStorageNamespaceProvider::createEphemeralLocalStorageNamespace(Page&, unsigned)
+{
+ return adoptRef(*new EmptyStorageNamespace);
+}
+
RefPtr<StorageNamespace> EmptyStorageNamespaceProvider::createTransientLocalStorageNamespace(SecurityOrigin&, unsigned)
{
return adoptRef(*new EmptyStorageNamespace);
Modified: trunk/Source/WebCore/page/Chrome.cpp (215314 => 215315)
--- trunk/Source/WebCore/page/Chrome.cpp 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebCore/page/Chrome.cpp 2017-04-13 06:38:19 UTC (rev 215315)
@@ -192,8 +192,12 @@
Page* newPage = m_client.createWindow(frame, request, features, action);
if (!newPage)
return nullptr;
+
if (auto* oldSessionStorage = m_page.sessionStorage(false))
newPage->setSessionStorage(oldSessionStorage->copy(newPage));
+ if (auto* oldEphemeralLocalStorage = m_page.ephemeralLocalStorage(false))
+ newPage->setEphemeralLocalStorage(oldEphemeralLocalStorage->copy(newPage));
+
return newPage;
}
Modified: trunk/Source/WebCore/page/Page.cpp (215314 => 215315)
--- trunk/Source/WebCore/page/Page.cpp 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebCore/page/Page.cpp 2017-04-13 06:38:19 UTC (rev 215315)
@@ -1311,6 +1311,19 @@
m_sessionStorage = WTFMove(newStorage);
}
+StorageNamespace* Page::ephemeralLocalStorage(bool optionalCreate)
+{
+ if (!m_ephemeralLocalStorage && optionalCreate)
+ m_ephemeralLocalStorage = m_storageNamespaceProvider->createEphemeralLocalStorageNamespace(*this, m_settings->sessionStorageQuota());
+
+ return m_ephemeralLocalStorage.get();
+}
+
+void Page::setEphemeralLocalStorage(RefPtr<StorageNamespace>&& newStorage)
+{
+ m_ephemeralLocalStorage = WTFMove(newStorage);
+}
+
bool Page::hasCustomHTMLTokenizerTimeDelay() const
{
return m_settings->maxParseDuration() != -1;
Modified: trunk/Source/WebCore/page/Page.h (215314 => 215315)
--- trunk/Source/WebCore/page/Page.h 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebCore/page/Page.h 2017-04-13 06:38:19 UTC (rev 215315)
@@ -414,6 +414,9 @@
StorageNamespace* sessionStorage(bool optionalCreate = true);
void setSessionStorage(RefPtr<StorageNamespace>&&);
+ StorageNamespace* ephemeralLocalStorage(bool optionalCreate = true);
+ void setEphemeralLocalStorage(RefPtr<StorageNamespace>&&);
+
bool hasCustomHTMLTokenizerTimeDelay() const;
double customHTMLTokenizerTimeDelay() const;
@@ -716,6 +719,7 @@
bool m_canStartMedia;
RefPtr<StorageNamespace> m_sessionStorage;
+ RefPtr<StorageNamespace> m_ephemeralLocalStorage;
#if ENABLE(VIEW_MODE_CSS_MEDIA)
ViewMode m_viewMode;
Modified: trunk/Source/WebCore/page/SecurityOriginData.h (215314 => 215315)
--- trunk/Source/WebCore/page/SecurityOriginData.h 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebCore/page/SecurityOriginData.h 2017-04-13 06:38:19 UTC (rev 215315)
@@ -78,7 +78,7 @@
}
#if !LOG_DISABLED
- String debugString() const;
+ WEBCORE_EXPORT String debugString() const;
#endif
};
Modified: trunk/Source/WebCore/storage/Storage.cpp (215314 => 215315)
--- trunk/Source/WebCore/storage/Storage.cpp 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebCore/storage/Storage.cpp 2017-04-13 06:38:19 UTC (rev 215315)
@@ -63,9 +63,6 @@
if (!m_storageArea->canAccessStorage(m_frame))
return Exception { SECURITY_ERR };
- if (isDisabledByPrivateBrowsing())
- return 0;
-
return m_storageArea->length();
}
@@ -74,9 +71,6 @@
if (!m_storageArea->canAccessStorage(m_frame))
return Exception { SECURITY_ERR };
- if (isDisabledByPrivateBrowsing())
- return String();
-
return m_storageArea->key(index);
}
@@ -85,9 +79,6 @@
if (!m_storageArea->canAccessStorage(m_frame))
return Exception { SECURITY_ERR };
- if (isDisabledByPrivateBrowsing())
- return String();
-
return m_storageArea->item(key);
}
@@ -96,9 +87,6 @@
if (!m_storageArea->canAccessStorage(m_frame))
return Exception { SECURITY_ERR };
- if (isDisabledByPrivateBrowsing())
- return Exception { QUOTA_EXCEEDED_ERR };
-
bool quotaException = false;
m_storageArea->setItem(m_frame, key, value, quotaException);
if (quotaException)
@@ -111,9 +99,6 @@
if (!m_storageArea->canAccessStorage(m_frame))
return Exception { SECURITY_ERR };
- if (isDisabledByPrivateBrowsing())
- return { };
-
m_storageArea->removeItem(m_frame, key);
return { };
}
@@ -123,9 +108,6 @@
if (!m_storageArea->canAccessStorage(m_frame))
return Exception { SECURITY_ERR };
- if (isDisabledByPrivateBrowsing())
- return { };
-
m_storageArea->clear(m_frame);
return { };
}
@@ -135,23 +117,7 @@
if (!m_storageArea->canAccessStorage(m_frame))
return Exception { SECURITY_ERR };
- if (isDisabledByPrivateBrowsing())
- return false;
-
return m_storageArea->contains(key);
}
-bool Storage::isDisabledByPrivateBrowsing() const
-{
- if (!m_frame->page()->usesEphemeralSession())
- return false;
-
- if (isLocalStorage(m_storageArea->storageType())) {
- if (SchemeRegistry::allowsLocalStorageAccessInPrivateBrowsing(m_frame->document()->securityOrigin().protocol()))
- return false;
- }
-
- return true;
-}
-
} // namespace WebCore
Modified: trunk/Source/WebCore/storage/StorageMap.h (215314 => 215315)
--- trunk/Source/WebCore/storage/StorageMap.h 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebCore/storage/StorageMap.h 2017-04-13 06:38:19 UTC (rev 215315)
@@ -51,11 +51,12 @@
unsigned quota() const { return m_quotaSize; }
+ WEBCORE_EXPORT Ref<StorageMap> copy();
+
static const constexpr unsigned noQuota = UINT_MAX;
private:
explicit StorageMap(unsigned quota);
- Ref<StorageMap> copy();
void invalidateIterator();
void setIteratorToIndex(unsigned);
Modified: trunk/Source/WebCore/storage/StorageNamespaceProvider.cpp (215314 => 215315)
--- trunk/Source/WebCore/storage/StorageNamespaceProvider.cpp 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebCore/storage/StorageNamespaceProvider.cpp 2017-04-13 06:38:19 UTC (rev 215315)
@@ -27,6 +27,7 @@
#include "StorageNamespaceProvider.h"
#include "Document.h"
+#include "Page.h"
#include "SecurityOriginData.h"
#include "StorageArea.h"
#include "StorageNamespace.h"
@@ -61,9 +62,23 @@
RefPtr<StorageArea> StorageNamespaceProvider::localStorageArea(Document& document)
{
- auto& storageNamespace = document.securityOrigin().canAccessLocalStorage(&document.topOrigin()) ? localStorageNamespace() : transientLocalStorageNamespace(document.topOrigin());
+ // This StorageNamespaceProvider was retrieved from the Document's Page,
+ // so the Document had better still actually have a Page.
+ ASSERT(document.page());
- return storageNamespace.storageArea(SecurityOriginData::fromSecurityOrigin(document.securityOrigin()));
+ bool ephemeral = document.page()->usesEphemeralSession();
+ bool transient = !document.securityOrigin().canAccessLocalStorage(&document.topOrigin());
+
+ RefPtr<StorageNamespace> storageNamespace;
+
+ if (transient)
+ storageNamespace = &transientLocalStorageNamespace(document.topOrigin());
+ else if (ephemeral)
+ storageNamespace = document.page()->ephemeralLocalStorage();
+ else
+ storageNamespace = &localStorageNamespace();
+
+ return storageNamespace->storageArea(SecurityOriginData::fromSecurityOrigin(document.securityOrigin()));
}
StorageNamespace& StorageNamespaceProvider::localStorageNamespace()
Modified: trunk/Source/WebCore/storage/StorageNamespaceProvider.h (215314 => 215315)
--- trunk/Source/WebCore/storage/StorageNamespaceProvider.h 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebCore/storage/StorageNamespaceProvider.h 2017-04-13 06:38:19 UTC (rev 215315)
@@ -45,6 +45,8 @@
WEBCORE_EXPORT virtual ~StorageNamespaceProvider();
virtual RefPtr<StorageNamespace> createSessionStorageNamespace(Page&, unsigned quota) = 0;
+ virtual RefPtr<StorageNamespace> createEphemeralLocalStorageNamespace(Page&, unsigned quota) = 0;
+
RefPtr<StorageArea> localStorageArea(Document&);
void addPage(Page&);
Modified: trunk/Source/WebCore/storage/StorageType.h (215314 => 215315)
--- trunk/Source/WebCore/storage/StorageType.h 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebCore/storage/StorageType.h 2017-04-13 06:38:19 UTC (rev 215315)
@@ -30,11 +30,17 @@
enum class StorageType {
Session,
Local,
+ EphemeralLocal,
TransientLocal,
};
inline bool isLocalStorage(StorageType storageType)
{
+ return storageType == StorageType::Local || storageType == StorageType::TransientLocal || storageType == StorageType::EphemeralLocal;
+}
+
+inline bool isPersistentLocalStorage(StorageType storageType)
+{
return storageType == StorageType::Local || storageType == StorageType::TransientLocal;
}
Modified: trunk/Source/WebKit/ChangeLog (215314 => 215315)
--- trunk/Source/WebKit/ChangeLog 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebKit/ChangeLog 2017-04-13 06:38:19 UTC (rev 215315)
@@ -1,3 +1,22 @@
+2017-04-12 Brady Eidson <beid...@apple.com>
+
+ QuotaExceededError when saving to localStorage in private mode.
+ https://bugs.webkit.org/show_bug.cgi?id=157010
+
+ Reviewed by Alex Christensen.
+
+ * Storage/StorageNamespaceImpl.cpp:
+ (WebKit::StorageNamespaceImpl::createEphemeralLocalStorageNamespace):
+ (WebKit::StorageNamespaceImpl::StorageNamespaceImpl):
+ (WebKit::StorageNamespaceImpl::~StorageNamespaceImpl):
+ (WebKit::StorageNamespaceImpl::copy):
+ (WebKit::StorageNamespaceImpl::close):
+ * Storage/StorageNamespaceImpl.h:
+
+ * Storage/WebStorageNamespaceProvider.cpp:
+ (WebKit::WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace):
+ * Storage/WebStorageNamespaceProvider.h:
+
2017-04-12 Yusuke Suzuki <utatane....@gmail.com>
[WTF] Introduce Thread class and use RefPtr<Thread> and align Windows Threading implementation semantics to Pthread one
Modified: trunk/Source/WebKit/Storage/StorageNamespaceImpl.cpp (215314 => 215315)
--- trunk/Source/WebKit/Storage/StorageNamespaceImpl.cpp 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebKit/Storage/StorageNamespaceImpl.cpp 2017-04-13 06:38:19 UTC (rev 215315)
@@ -50,6 +50,11 @@
return adoptRef(*new StorageNamespaceImpl(StorageType::Session, String(), quota));
}
+Ref<StorageNamespaceImpl> StorageNamespaceImpl::createEphemeralLocalStorageNamespace(unsigned quota)
+{
+ return adoptRef(*new StorageNamespaceImpl(StorageType::EphemeralLocal, String(), quota));
+}
+
Ref<StorageNamespaceImpl> StorageNamespaceImpl::getOrCreateLocalStorageNamespace(const String& databasePath, unsigned quota)
{
ASSERT(!databasePath.isNull());
@@ -71,7 +76,7 @@
, m_quota(quota)
, m_isShutdown(false)
{
- if (isLocalStorage(m_storageType) && !m_path.isEmpty())
+ if (isPersistentLocalStorage(m_storageType) && !m_path.isEmpty())
m_syncManager = StorageSyncManager::create(m_path);
}
@@ -79,7 +84,7 @@
{
ASSERT(isMainThread());
- if (isLocalStorage(m_storageType)) {
+ if (isPersistentLocalStorage(m_storageType)) {
ASSERT(localStorageNamespaceMap().get(m_path) == this);
localStorageNamespaceMap().remove(m_path);
}
@@ -92,13 +97,12 @@
{
ASSERT(isMainThread());
ASSERT(!m_isShutdown);
- ASSERT(m_storageType == StorageType::Session);
+ ASSERT(m_storageType == StorageType::Session || m_storageType == StorageType::EphemeralLocal);
RefPtr<StorageNamespaceImpl> newNamespace = adoptRef(new StorageNamespaceImpl(m_storageType, m_path, m_quota));
+ for (auto& iter : m_storageAreaMap)
+ newNamespace->m_storageAreaMap.set(iter.key, iter.value->copy());
- StorageAreaMap::iterator end = m_storageAreaMap.end();
- for (StorageAreaMap::iterator i = m_storageAreaMap.begin(); i != end; ++i)
- newNamespace->m_storageAreaMap.set(i->key, i->value->copy());
return newNamespace;
}
@@ -123,8 +127,8 @@
if (m_isShutdown)
return;
- // If we're session storage, we shouldn't need to do any work here.
- if (m_storageType == StorageType::Session) {
+ // If we're not a persistent storage, we shouldn't need to do any work here.
+ if (m_storageType == StorageType::Session || m_storageType == StorageType::EphemeralLocal) {
ASSERT(!m_syncManager);
return;
}
Modified: trunk/Source/WebKit/Storage/StorageNamespaceImpl.h (215314 => 215315)
--- trunk/Source/WebKit/Storage/StorageNamespaceImpl.h 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebKit/Storage/StorageNamespaceImpl.h 2017-04-13 06:38:19 UTC (rev 215315)
@@ -39,6 +39,7 @@
class StorageNamespaceImpl : public WebCore::StorageNamespace {
public:
static Ref<StorageNamespaceImpl> createSessionStorageNamespace(unsigned quota);
+ static Ref<StorageNamespaceImpl> createEphemeralLocalStorageNamespace(unsigned quota);
static Ref<StorageNamespaceImpl> getOrCreateLocalStorageNamespace(const String& databasePath, unsigned quota);
virtual ~StorageNamespaceImpl();
Modified: trunk/Source/WebKit/Storage/WebStorageNamespaceProvider.cpp (215314 => 215315)
--- trunk/Source/WebKit/Storage/WebStorageNamespaceProvider.cpp 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebKit/Storage/WebStorageNamespaceProvider.cpp 2017-04-13 06:38:19 UTC (rev 215315)
@@ -101,6 +101,11 @@
return StorageNamespaceImpl::createSessionStorageNamespace(quota);
}
+RefPtr<StorageNamespace> WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace(Page&, unsigned quota)
+{
+ return StorageNamespaceImpl::createEphemeralLocalStorageNamespace(quota);
+}
+
RefPtr<StorageNamespace> WebStorageNamespaceProvider::createLocalStorageNamespace(unsigned quota)
{
return StorageNamespaceImpl::getOrCreateLocalStorageNamespace(m_localStorageDatabasePath, quota);
Modified: trunk/Source/WebKit/Storage/WebStorageNamespaceProvider.h (215314 => 215315)
--- trunk/Source/WebKit/Storage/WebStorageNamespaceProvider.h 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebKit/Storage/WebStorageNamespaceProvider.h 2017-04-13 06:38:19 UTC (rev 215315)
@@ -50,6 +50,7 @@
explicit WebStorageNamespaceProvider(const String& localStorageDatabasePath);
RefPtr<WebCore::StorageNamespace> createSessionStorageNamespace(WebCore::Page&, unsigned quota) override;
+ RefPtr<WebCore::StorageNamespace> createEphemeralLocalStorageNamespace(WebCore::Page&, unsigned quota) override;
RefPtr<WebCore::StorageNamespace> createLocalStorageNamespace(unsigned quota) override;
RefPtr<WebCore::StorageNamespace> createTransientLocalStorageNamespace(WebCore::SecurityOrigin&, unsigned quota) override;
Modified: trunk/Source/WebKit2/ChangeLog (215314 => 215315)
--- trunk/Source/WebKit2/ChangeLog 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebKit2/ChangeLog 2017-04-13 06:38:19 UTC (rev 215315)
@@ -1,3 +1,25 @@
+2017-04-12 Brady Eidson <beid...@apple.com>
+
+ QuotaExceededError when saving to localStorage in private mode.
+ https://bugs.webkit.org/show_bug.cgi?id=157010
+
+ Reviewed by Alex Christensen.
+
+ * WebProcess/Storage/StorageAreaMap.cpp:
+ (WebKit::StorageAreaMap::StorageAreaMap):
+ (WebKit::StorageAreaMap::~StorageAreaMap):
+
+ * WebProcess/Storage/StorageNamespaceImpl.cpp:
+ (WebKit::StorageNamespaceImpl::createEphemeralLocalStorageNamespace):
+ (WebKit::StorageNamespaceImpl::storageArea):
+ (WebKit::StorageNamespaceImpl::ephemeralLocalStorageArea):
+ (WebKit::StorageNamespaceImpl::copy):
+ * WebProcess/Storage/StorageNamespaceImpl.h:
+
+ * WebProcess/Storage/WebStorageNamespaceProvider.cpp:
+ (WebKit::WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace):
+ * WebProcess/Storage/WebStorageNamespaceProvider.h:
+
2017-04-12 Yusuke Suzuki <utatane....@gmail.com>
Unreviewed, fix build failure on Ubuntu LTS GTK bot
Modified: trunk/Source/WebKit2/WebProcess/Storage/StorageAreaMap.cpp (215314 => 215315)
--- trunk/Source/WebKit2/WebProcess/Storage/StorageAreaMap.cpp 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebKit2/WebProcess/Storage/StorageAreaMap.cpp 2017-04-13 06:38:19 UTC (rev 215315)
@@ -83,6 +83,10 @@
case StorageType::Session:
WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::CreateSessionStorageMap(m_storageMapID, storageNamespace->storageNamespaceID(), SecurityOriginData::fromSecurityOrigin(m_securityOrigin)), 0);
break;
+
+ case StorageType::EphemeralLocal:
+ // The UI process is not involved for EphemeralLocal storages.
+ return;
}
WebProcess::singleton().addMessageReceiver(Messages::StorageAreaMap::messageReceiverName(), m_storageMapID, *this);
@@ -90,8 +94,10 @@
StorageAreaMap::~StorageAreaMap()
{
- WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::DestroyStorageMap(m_storageMapID), 0);
- WebProcess::singleton().removeMessageReceiver(Messages::StorageAreaMap::messageReceiverName(), m_storageMapID);
+ if (m_storageType != StorageType::EphemeralLocal) {
+ WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::DestroyStorageMap(m_storageMapID), 0);
+ WebProcess::singleton().removeMessageReceiver(Messages::StorageAreaMap::messageReceiverName(), m_storageMapID);
+ }
m_storageNamespace->didDestroyStorageAreaMap(*this);
}
Modified: trunk/Source/WebKit2/WebProcess/Storage/StorageNamespaceImpl.cpp (215314 => 215315)
--- trunk/Source/WebKit2/WebProcess/Storage/StorageNamespaceImpl.cpp 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebKit2/WebProcess/Storage/StorageNamespaceImpl.cpp 2017-04-13 06:38:19 UTC (rev 215315)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,6 +31,7 @@
#include "WebPage.h"
#include "WebPageGroupProxy.h"
#include "WebProcess.h"
+#include <WebCore/Frame.h>
#include <WebCore/PageGroup.h>
#include <WebCore/SecurityOrigin.h>
#include <WebCore/Settings.h>
@@ -45,6 +46,11 @@
return adoptRef(new StorageNamespaceImpl(StorageType::Session, identifier, nullptr, quotaInBytes));
}
+RefPtr<StorageNamespaceImpl> StorageNamespaceImpl::createEphemeralLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes)
+{
+ return adoptRef(new StorageNamespaceImpl(StorageType::EphemeralLocal, identifier, nullptr, quotaInBytes));
+}
+
RefPtr<StorageNamespaceImpl> StorageNamespaceImpl::createLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes)
{
return adoptRef(new StorageNamespaceImpl(StorageType::Local, identifier, nullptr, quotaInBytes));
@@ -74,6 +80,9 @@
RefPtr<StorageArea> StorageNamespaceImpl::storageArea(const SecurityOriginData& securityOrigin)
{
+ if (m_storageType == StorageType::EphemeralLocal)
+ return ephemeralLocalStorageArea(securityOrigin);
+
RefPtr<StorageAreaMap> map;
auto& slot = m_storageAreaMaps.add(securityOrigin, nullptr).iterator->value;
@@ -86,11 +95,125 @@
return StorageAreaImpl::create(map.releaseNonNull());
}
+class StorageNamespaceImpl::EphemeralStorageArea final : public StorageArea {
+public:
+ static Ref<EphemeralStorageArea> create(const SecurityOriginData& origin, unsigned quotaInBytes)
+ {
+ return adoptRef(*new EphemeralStorageArea(origin, quotaInBytes));
+ }
+
+ Ref<EphemeralStorageArea> copy()
+ {
+ return adoptRef(*new EphemeralStorageArea(*this));
+ }
+
+private:
+ EphemeralStorageArea(const SecurityOriginData& origin, unsigned quotaInBytes)
+ : m_securityOriginData(origin)
+ , m_storageMap(StorageMap::create(quotaInBytes))
+ {
+ }
+
+ EphemeralStorageArea(EphemeralStorageArea& other)
+ : m_securityOriginData(other.m_securityOriginData)
+ , m_storageMap(other.m_storageMap)
+ {
+ }
+
+ // WebCore::StorageArea.
+ unsigned length()
+ {
+ return m_storageMap->length();
+ }
+
+ String key(unsigned index)
+ {
+ return m_storageMap->key(index);
+ }
+
+ String item(const String& key)
+ {
+ return m_storageMap->getItem(key);
+ }
+
+ void setItem(Frame*, const String& key, const String& value, bool& quotaException)
+ {
+ String oldValue;
+ if (auto newMap = m_storageMap->setItem(key, value, oldValue, quotaException))
+ m_storageMap = WTFMove(newMap);
+ }
+
+ void removeItem(Frame*, const String& key)
+ {
+ String oldValue;
+ if (auto newMap = m_storageMap->removeItem(key, oldValue))
+ m_storageMap = WTFMove(newMap);
+ }
+
+ void clear(Frame*)
+ {
+ if (!m_storageMap->length())
+ return;
+
+ m_storageMap = StorageMap::create(m_storageMap->quota());
+ }
+
+ bool contains(const String& key)
+ {
+ return m_storageMap->contains(key);
+ }
+
+ bool canAccessStorage(Frame* frame)
+ {
+ return frame && frame->page();
+ }
+
+ StorageType storageType() const
+ {
+ return StorageType::EphemeralLocal;
+ }
+
+ size_t memoryBytesUsedByCache()
+ {
+ return 0;
+ }
+
+ void incrementAccessCount() { }
+ void decrementAccessCount() { }
+ void closeDatabaseIfIdle() { }
+
+ SecurityOriginData securityOrigin() const
+ {
+ return m_securityOriginData;
+ }
+
+ SecurityOriginData m_securityOriginData;
+ RefPtr<StorageMap> m_storageMap;
+};
+
+RefPtr<StorageArea> StorageNamespaceImpl::ephemeralLocalStorageArea(const SecurityOriginData& securityOrigin)
+{
+ auto& slot = m_ephemeralLocalStorageAreas.add(securityOrigin, nullptr).iterator->value;
+ if (!slot)
+ slot = StorageNamespaceImpl::EphemeralStorageArea::create(securityOrigin, m_quotaInBytes);
+
+ return slot.get();
+}
+
RefPtr<StorageNamespace> StorageNamespaceImpl::copy(Page* newPage)
{
ASSERT(m_storageNamespaceID);
- return createSessionStorageNamespace(WebPage::fromCorePage(newPage)->pageID(), m_quotaInBytes);
+ if (m_storageType == StorageType::Session)
+ return createSessionStorageNamespace(WebPage::fromCorePage(newPage)->pageID(), m_quotaInBytes);
+
+ ASSERT(m_storageType == StorageType::EphemeralLocal);
+ RefPtr<StorageNamespaceImpl> newNamespace = adoptRef(new StorageNamespaceImpl(m_storageType, m_storageNamespaceID, m_topLevelOrigin.get(), m_quotaInBytes));
+
+ for (auto& iter : m_ephemeralLocalStorageAreas)
+ newNamespace->m_ephemeralLocalStorageAreas.set(iter.key, iter.value->copy());
+
+ return newNamespace;
}
} // namespace WebKit
Modified: trunk/Source/WebKit2/WebProcess/Storage/StorageNamespaceImpl.h (215314 => 215315)
--- trunk/Source/WebKit2/WebProcess/Storage/StorageNamespaceImpl.h 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebKit2/WebProcess/Storage/StorageNamespaceImpl.h 2017-04-13 06:38:19 UTC (rev 215315)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,6 +28,7 @@
#include <WebCore/SecurityOriginData.h>
#include <WebCore/SecurityOriginHash.h>
#include <WebCore/StorageArea.h>
+#include <WebCore/StorageMap.h>
#include <WebCore/StorageNamespace.h>
#include <wtf/HashMap.h>
@@ -39,6 +40,7 @@
class StorageNamespaceImpl : public WebCore::StorageNamespace {
public:
static RefPtr<StorageNamespaceImpl> createSessionStorageNamespace(uint64_t identifier, unsigned quotaInBytes);
+ static RefPtr<StorageNamespaceImpl> createEphemeralLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes);
static RefPtr<StorageNamespaceImpl> createLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes);
static RefPtr<StorageNamespaceImpl> createTransientLocalStorageNamespace(uint64_t identifier, WebCore::SecurityOrigin& topLevelOrigin, uint64_t quotaInBytes);
@@ -57,6 +59,8 @@
RefPtr<WebCore::StorageArea> storageArea(const WebCore::SecurityOriginData&) override;
RefPtr<WebCore::StorageNamespace> copy(WebCore::Page*) override;
+ RefPtr<WebCore::StorageArea> ephemeralLocalStorageArea(const WebCore::SecurityOriginData&);
+
const WebCore::StorageType m_storageType;
const uint64_t m_storageNamespaceID;
@@ -66,6 +70,9 @@
const unsigned m_quotaInBytes;
HashMap<WebCore::SecurityOriginData, StorageAreaMap*> m_storageAreaMaps;
+
+ class EphemeralStorageArea;
+ HashMap<WebCore::SecurityOriginData, RefPtr<EphemeralStorageArea>> m_ephemeralLocalStorageAreas;
};
} // namespace WebKit
Modified: trunk/Source/WebKit2/WebProcess/Storage/WebStorageNamespaceProvider.cpp (215314 => 215315)
--- trunk/Source/WebKit2/WebProcess/Storage/WebStorageNamespaceProvider.cpp 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebKit2/WebProcess/Storage/WebStorageNamespaceProvider.cpp 2017-04-13 06:38:19 UTC (rev 215315)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -71,6 +71,11 @@
return StorageNamespaceImpl::createSessionStorageNamespace(WebPage::fromCorePage(&page)->pageID(), quota);
}
+RefPtr<WebCore::StorageNamespace> WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace(Page& page, unsigned quota)
+{
+ return StorageNamespaceImpl::createEphemeralLocalStorageNamespace(WebPage::fromCorePage(&page)->pageID(), quota);
+}
+
RefPtr<WebCore::StorageNamespace> WebStorageNamespaceProvider::createLocalStorageNamespace(unsigned quota)
{
return StorageNamespaceImpl::createLocalStorageNamespace(m_identifier, quota);
Modified: trunk/Source/WebKit2/WebProcess/Storage/WebStorageNamespaceProvider.h (215314 => 215315)
--- trunk/Source/WebKit2/WebProcess/Storage/WebStorageNamespaceProvider.h 2017-04-13 05:49:14 UTC (rev 215314)
+++ trunk/Source/WebKit2/WebProcess/Storage/WebStorageNamespaceProvider.h 2017-04-13 06:38:19 UTC (rev 215315)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -39,6 +39,7 @@
explicit WebStorageNamespaceProvider(uint64_t identifier);
RefPtr<WebCore::StorageNamespace> createSessionStorageNamespace(WebCore::Page&, unsigned quota) override;
+ RefPtr<WebCore::StorageNamespace> createEphemeralLocalStorageNamespace(WebCore::Page&, unsigned quota) override;
RefPtr<WebCore::StorageNamespace> createLocalStorageNamespace(unsigned quota) override;
RefPtr<WebCore::StorageNamespace> createTransientLocalStorageNamespace(WebCore::SecurityOrigin&, unsigned quota) override;