Implement Cache API partitioning based on ClientOrigin
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Jan 2018 08:49:12 +0000 (08:49 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Jan 2018 08:49:12 +0000 (08:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=181240

Patch by Youenn Fablet <youenn@apple.com> on 2018-01-04
Reviewed by Alex Christensen.

Source/WebCore:

Covered by updated tests.

Previously, cache storage was partitioned according the origin of the client, represented as a String.
We now partition according both client and top origins, represented as a ClientOrigin

Minor refactoring to use more makePendingActivity.
Added support for IPC serialization of ClientOrigin.
Added SecurityOriginData::toString which is used by WebKit2 Cache Storage implementation.

* Modules/cache/CacheStorageConnection.cpp:
(WebCore::CacheStorageConnection::open):
(WebCore::CacheStorageConnection::retrieveCaches):
* Modules/cache/CacheStorageConnection.h:
(WebCore::CacheStorageConnection::clearMemoryRepresentation):
(WebCore::CacheStorageConnection::doOpen):
(WebCore::CacheStorageConnection::doRetrieveCaches):
* Modules/cache/DOMCacheStorage.cpp:
(WebCore::DOMCacheStorage::origin const):
(WebCore::DOMCacheStorage::retrieveCaches):
(WebCore::DOMCacheStorage::open):
(WebCore::DOMCacheStorage::remove):
* Modules/cache/DOMCacheStorage.h:
* Modules/cache/WorkerCacheStorageConnection.cpp:
(WebCore::WorkerCacheStorageConnection::doOpen):
(WebCore::WorkerCacheStorageConnection::doRetrieveCaches):
* Modules/cache/WorkerCacheStorageConnection.h:
* page/ClientOrigin.h:
(WebCore::ClientOrigin::isolatedCopy const):
(WebCore::ClientOrigin::encode const):
(WebCore::ClientOrigin::decode):
* page/SecurityOriginData.cpp:
(WebCore::SecurityOriginData::toString const):
(WebCore::SecurityOriginData::debugString const): Deleted.
* page/SecurityOriginData.h:
(WebCore::SecurityOriginData::debugString const):
* testing/Internals.cpp:
(WebCore::Internals::clearCacheStorageMemoryRepresentation):

Source/WebKit:

open and retrieveCaches now take a ClientOrigin instead of a String.
Updated cache filesystem path computation to take both client origin and top origin.

When clearing an origin, caches whose client origin or top origin matches the origin are cleared.
Caches are added to the web site data of their client origin with their corresponding cache size.
Caches are added to the web site data of their top origin with a size equal to 0.

Updated memory representation dumping used for test to include both top and client origins.

* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
* NetworkProcess/cache/CacheStorageEngine.cpp:
(WebKit::CacheStorage::Engine::cachesRootPath):
(WebKit::CacheStorage::Engine::open):
(WebKit::CacheStorage::Engine::remove):
(WebKit::CacheStorage::Engine::retrieveCaches):
(WebKit::CacheStorage::Engine::readCachesFromDisk):
(WebKit::CacheStorage::Engine::removeCaches):
(WebKit::CacheStorage::Engine::fetchEntries):
(WebKit::CacheStorage::Engine::clearCachesForOrigin):
(WebKit::CacheStorage::Engine::clearMemoryRepresentation):
(WebKit::CacheStorage::Engine::representation):
* NetworkProcess/cache/CacheStorageEngine.h:
* NetworkProcess/cache/CacheStorageEngineCache.cpp:
(WebKit::CacheStorage::Cache::Cache):
* NetworkProcess/cache/CacheStorageEngineCaches.cpp:
(WebKit::CacheStorage::Caches::retrieveOriginFromDirectory):
(WebKit::CacheStorage::Caches::Caches):
(WebKit::CacheStorage::Caches::storeOrigin):
(WebKit::CacheStorage::Caches::readOrigin):
(WebKit::CacheStorage::Caches::open):
* NetworkProcess/cache/CacheStorageEngineCaches.h:
(WebKit::CacheStorage::Caches::create):
(WebKit::CacheStorage::Caches::origin const):
* NetworkProcess/cache/CacheStorageEngineConnection.cpp:
(WebKit::CacheStorageEngineConnection::open):
(WebKit::CacheStorageEngineConnection::caches):
(WebKit::CacheStorageEngineConnection::clearMemoryRepresentation):
* NetworkProcess/cache/CacheStorageEngineConnection.h:
* NetworkProcess/cache/CacheStorageEngineConnection.messages.in:
* WebProcess/Cache/WebCacheStorageConnection.cpp:
(WebKit::WebCacheStorageConnection::doOpen):
(WebKit::WebCacheStorageConnection::doRetrieveCaches):
(WebKit::WebCacheStorageConnection::clearMemoryRepresentation):
* WebProcess/Cache/WebCacheStorageConnection.h:

LayoutTests:

Beefing up test to ensure that client and top origins are taken into consideration.

* http/tests/cache-storage/cache-origins.https-expected.txt:
* http/tests/cache-storage/cache-origins.https.html:
* http/tests/cache-storage/cache-clearing-origin.https-expected.txt:
* http/tests/cache-storage/cache-clearing-origin.https.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@226401 268f45cc-cd09-0410-ab3c-d52691b4dbfc

27 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/cache-storage/cache-clearing-origin.https-expected.txt
LayoutTests/http/tests/cache-storage/cache-clearing-origin.https.html
LayoutTests/http/tests/cache-storage/cache-origins.https-expected.txt
LayoutTests/http/tests/cache-storage/cache-origins.https.html
Source/WebCore/ChangeLog
Source/WebCore/Modules/cache/CacheStorageConnection.cpp
Source/WebCore/Modules/cache/CacheStorageConnection.h
Source/WebCore/Modules/cache/DOMCacheStorage.cpp
Source/WebCore/Modules/cache/DOMCacheStorage.h
Source/WebCore/Modules/cache/WorkerCacheStorageConnection.cpp
Source/WebCore/Modules/cache/WorkerCacheStorageConnection.h
Source/WebCore/page/ClientOrigin.h
Source/WebCore/page/SecurityOriginData.cpp
Source/WebCore/page/SecurityOriginData.h
Source/WebCore/testing/Internals.cpp
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/NetworkProcess.cpp
Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp
Source/WebKit/NetworkProcess/cache/CacheStorageEngine.h
Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp
Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.h
Source/WebKit/NetworkProcess/cache/CacheStorageEngineConnection.cpp
Source/WebKit/NetworkProcess/cache/CacheStorageEngineConnection.h
Source/WebKit/NetworkProcess/cache/CacheStorageEngineConnection.messages.in
Source/WebKit/WebProcess/Cache/WebCacheStorageConnection.cpp
Source/WebKit/WebProcess/Cache/WebCacheStorageConnection.h

index e68adc1..ace1e0a 100644 (file)
@@ -1,3 +1,17 @@
+2018-01-04  Youenn Fablet  <youenn@apple.com>
+
+        Implement Cache API partitioning based on ClientOrigin
+        https://bugs.webkit.org/show_bug.cgi?id=181240
+
+        Reviewed by Alex Christensen.
+
+        Beefing up test to ensure that client and top origins are taken into consideration.
+
+        * http/tests/cache-storage/cache-origins.https-expected.txt:
+        * http/tests/cache-storage/cache-origins.https.html:
+        * http/tests/cache-storage/cache-clearing-origin.https-expected.txt:
+        * http/tests/cache-storage/cache-clearing-origin.https.html:
+
 2018-01-03  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         [Attachment Support] Add plumbing for starting a drag with promised blob data
index 2785511..33587ac 100644 (file)
@@ -1,4 +1,5 @@
 
-PASS Cleaning existing caches 
+
+PASS Create a cache storage from localhost and clear it 
 PASS Clearing disk cache of a given origin 
 
index 1296670..8712922 100644 (file)
@@ -8,13 +8,27 @@
 <body>
     <script>
 promise_test(test => {
-    return self.caches.keys().then(keys => {
-        var pending = [];
-        for (key of keys)
-            pending.push(self.caches.delete(keys[0]));
-        return Promise.all(pending);
-    });
-}, "Cleaning existing caches");
+    if (!window.internals || !window.testRunner)
+        return Promise.reject("Test requires internals and test runner");
+
+    return new Promise((resolve, reject) => {
+        var counter = 0;
+        window.addEventListener("message", test.step_func(async (event) => {
+            var representation = JSON.parse(await internals.cacheStorageEngineRepresentation());
+            assert_equals(representation[0].origin.topOrigin, "https://127.0.0.1:8443", "top origin of cache 1");
+            assert_equals(representation[0].origin.clientOrigin, "https://localhost:8443", "client origin of cache 1");
+            assert_array_equals(representation[0].caches.persistent, ["cache1"]);
+
+            testRunner.clearDOMCache('https://localhost:8443');
+            var representation = JSON.parse(await internals.cacheStorageEngineRepresentation());
+            assert_equals(representation[0].origin.topOrigin, "https://127.0.0.1:8443", "top origin of cache 1");
+            assert_equals(representation[0].origin.clientOrigin, "https://localhost:8443", "client origin of cache 1");
+            assert_array_equals(representation[0].caches.persistent, []);
+
+            resolve();
+        }));
+    })
+}, "Create a cache storage from localhost and clear it");
 
 promise_test(async test => {
     var cache = await self.caches.open("test-cache-records-persistency");
@@ -44,5 +58,6 @@ promise_test(async test => {
     assert_equals(keys.length, 0, "records should be empty");
 }, 'Clearing disk cache of a given origin');
     </script>
+    <iframe src="https://localhost:8443/cache-storage/resources/cache-persistency-iframe.html#name=cache1"></iframe>
 </body>
 </html>
index 36707dd..3787db3 100644 (file)
@@ -1,5 +1,7 @@
   
 
 PASS Create a cache storage and look at the representation 
-PASS Caches from different origins should not mix 
+PASS Verifying that two caches are created on two different client origins 
+PASS Verifying that caches are clustered per client origin. 
+PASS Verifying that clearing caches for an origin will clear both top origin and client origin caches. 
 
index f29b9b1..7731f1c 100644 (file)
@@ -8,28 +8,54 @@
 <body>
     <script>
 
-    function checkCaches(name) {
-        promise_test(() => {
-            return self.caches.keys().then(keys => {
-                assert_true(keys.indexOf("cache1") !== -1, "Should have cache1");
-                assert_true(keys.indexOf("cache2") === -1, "Should not have cache1");
-            });
-        }, name);
+    async function checkCachesAfterClearingMemoryRepresentation(name) {
+        await internals.clearCacheStorageMemoryRepresentation();
+        var keys = await self.caches.keys();
+        test(() => {
+            assert_true(keys.indexOf("cache1") !== -1, "Should have cache1");
+            assert_true(keys.indexOf("cache2") === -1, "Should not have cache2");
+        }, "Verifying that caches are clustered per client origin.");
+    }
+
+    async function checkCachesAfterClearingOrigins() {
+        testRunner.clearDOMCache('https://127.0.0.1:8443');
+        var representation = JSON.parse(await internals.cacheStorageEngineRepresentation());
+        test(() => {
+            assert_equals(representation[0].origin.topOrigin, "https://127.0.0.1:8443", "top origin of cache 1");
+            assert_equals(representation[1].origin.topOrigin, "https://127.0.0.1:8443", "top origin of cache 2");
+            assert_equals(representation[0].origin.clientOrigin, "https://127.0.0.1:8443", "client origin of cache 1");
+            assert_equals(representation[1].origin.clientOrigin, "https://localhost:8443", "client origin of cache 2");
+            assert_array_equals(representation[0].caches.persistent, []);
+            assert_array_equals(representation[1].caches.persistent, []);
+        }, "Verifying that clearing caches for an origin will clear both top origin and client origin caches.");
+    }
+
+    async function checkCacheRepresentation() {
+        var representation = JSON.parse(await internals.cacheStorageEngineRepresentation());
+        test(() => {
+            assert_equals(representation[0].origin.topOrigin, "https://127.0.0.1:8443", "top origin of cache 1");
+            assert_equals(representation[1].origin.topOrigin, "https://127.0.0.1:8443", "top origin of cache 2");
+            assert_equals(representation[0].origin.clientOrigin, "https://127.0.0.1:8443", "client origin of cache 1");
+            assert_equals(representation[1].origin.clientOrigin, "https://localhost:8443", "client origin of cache 2");
+            assert_array_equals(representation[0].caches.persistent, ["cache1"]);
+            assert_array_equals(representation[1].caches.persistent, ["cache2"]);
+        }, "Verifying that two caches are created on two different client origins");
     }
 
     promise_test(test => {
-        if (!window.internals)
-            return Promise.reject("Test requires internals");
+        if (!window.internals || !window.testRunner)
+            return Promise.reject("Test requires internals and test runner");
 
         return new Promise((resolve, reject) => {
             var counter = 0;
-            window.addEventListener("message", test.step_func((event) => {
+            window.addEventListener("message", test.step_func(async (event) => {
                 if (++counter <= 1)
                     return;
-                internals.clearCacheStorageMemoryRepresentation().then(() => {
-                    checkCaches("Caches from different origins should not mix");
-                    resolve();
-                });
+
+                await checkCacheRepresentation();
+                await checkCachesAfterClearingMemoryRepresentation();
+                await checkCachesAfterClearingOrigins();
+                resolve();
             }));
         })
     }, "Create a cache storage and look at the representation");
@@ -40,4 +66,3 @@
     </div>
 </body>
 </html>
-
index 128d6e5..465896a 100644 (file)
@@ -1,5 +1,50 @@
 2018-01-04  Youenn Fablet  <youenn@apple.com>
 
+        Implement Cache API partitioning based on ClientOrigin
+        https://bugs.webkit.org/show_bug.cgi?id=181240
+
+        Reviewed by Alex Christensen.
+
+        Covered by updated tests.
+
+        Previously, cache storage was partitioned according the origin of the client, represented as a String.
+        We now partition according both client and top origins, represented as a ClientOrigin
+
+        Minor refactoring to use more makePendingActivity.
+        Added support for IPC serialization of ClientOrigin.
+        Added SecurityOriginData::toString which is used by WebKit2 Cache Storage implementation.
+
+        * Modules/cache/CacheStorageConnection.cpp:
+        (WebCore::CacheStorageConnection::open):
+        (WebCore::CacheStorageConnection::retrieveCaches):
+        * Modules/cache/CacheStorageConnection.h:
+        (WebCore::CacheStorageConnection::clearMemoryRepresentation):
+        (WebCore::CacheStorageConnection::doOpen):
+        (WebCore::CacheStorageConnection::doRetrieveCaches):
+        * Modules/cache/DOMCacheStorage.cpp:
+        (WebCore::DOMCacheStorage::origin const):
+        (WebCore::DOMCacheStorage::retrieveCaches):
+        (WebCore::DOMCacheStorage::open):
+        (WebCore::DOMCacheStorage::remove):
+        * Modules/cache/DOMCacheStorage.h:
+        * Modules/cache/WorkerCacheStorageConnection.cpp:
+        (WebCore::WorkerCacheStorageConnection::doOpen):
+        (WebCore::WorkerCacheStorageConnection::doRetrieveCaches):
+        * Modules/cache/WorkerCacheStorageConnection.h:
+        * page/ClientOrigin.h:
+        (WebCore::ClientOrigin::isolatedCopy const):
+        (WebCore::ClientOrigin::encode const):
+        (WebCore::ClientOrigin::decode):
+        * page/SecurityOriginData.cpp:
+        (WebCore::SecurityOriginData::toString const):
+        (WebCore::SecurityOriginData::debugString const): Deleted.
+        * page/SecurityOriginData.h:
+        (WebCore::SecurityOriginData::debugString const):
+        * testing/Internals.cpp:
+        (WebCore::Internals::clearCacheStorageMemoryRepresentation):
+
+2018-01-04  Youenn Fablet  <youenn@apple.com>
+
         Service Worker should expose redirect mode for navigation loads as manual
         https://bugs.webkit.org/show_bug.cgi?id=181067
 
index 20522f0..fe0dfa6 100644 (file)
@@ -33,7 +33,7 @@
 namespace WebCore {
 using namespace WebCore::DOMCacheEngine;
 
-void CacheStorageConnection::open(const String& origin, const String& cacheName, CacheIdentifierCallback&& callback)
+void CacheStorageConnection::open(const ClientOrigin& origin, const String& cacheName, CacheIdentifierCallback&& callback)
 {
     uint64_t requestIdentifier = ++m_lastRequestIdentifier;
     m_openAndRemoveCachePendingRequests.add(requestIdentifier, WTFMove(callback));
@@ -49,7 +49,7 @@ void CacheStorageConnection::remove(uint64_t cacheIdentifier, CacheIdentifierCal
     doRemove(requestIdentifier, cacheIdentifier);
 }
 
-void CacheStorageConnection::retrieveCaches(const String& origin, uint64_t updateCounter, CacheInfosCallback&& callback)
+void CacheStorageConnection::retrieveCaches(const ClientOrigin& origin, uint64_t updateCounter, CacheInfosCallback&& callback)
 {
     uint64_t requestIdentifier = ++m_lastRequestIdentifier;
     m_retrieveCachesPendingRequests.add(requestIdentifier, WTFMove(callback));
index 6ca7bfb..4daa344 100644 (file)
@@ -32,6 +32,7 @@
 
 namespace WebCore {
 
+struct ClientOrigin;
 class FetchResponse;
 
 class CacheStorageConnection : public ThreadSafeRefCounted<CacheStorageConnection> {
@@ -39,9 +40,9 @@ public:
     static Ref<CacheStorageConnection> create() { return adoptRef(*new CacheStorageConnection()); }
     virtual ~CacheStorageConnection() = default;
 
-    void open(const String& origin, const String& cacheName, DOMCacheEngine::CacheIdentifierCallback&&);
+    void open(const ClientOrigin&, const String& cacheName, DOMCacheEngine::CacheIdentifierCallback&&);
     void remove(uint64_t cacheIdentifier, DOMCacheEngine::CacheIdentifierCallback&&);
-    void retrieveCaches(const String& origin, uint64_t updateCounter, DOMCacheEngine::CacheInfosCallback&&);
+    void retrieveCaches(const ClientOrigin&, uint64_t updateCounter, DOMCacheEngine::CacheInfosCallback&&);
 
     void retrieveRecords(uint64_t cacheIdentifier, const URL&, DOMCacheEngine::RecordsCallback&&);
     void batchDeleteOperation(uint64_t cacheIdentifier, const ResourceRequest&, CacheQueryOptions&&, DOMCacheEngine::RecordIdentifiersCallback&&);
@@ -52,7 +53,7 @@ public:
     virtual void dereference(uint64_t /* cacheIdentifier */) { }
 
     // Used only for testing purposes.
-    virtual void clearMemoryRepresentation(const String& /* origin */, DOMCacheEngine::CompletionCallback&& callback) { callback(DOMCacheEngine::Error::NotImplemented); }
+    virtual void clearMemoryRepresentation(const ClientOrigin&, DOMCacheEngine::CompletionCallback&& callback) { callback(DOMCacheEngine::Error::NotImplemented); }
     virtual void engineRepresentation(WTF::Function<void(const String&)>&& callback) { callback(String { }); }
 
 protected:
@@ -67,9 +68,9 @@ protected:
     WEBCORE_EXPORT void putRecordsCompleted(uint64_t requestIdentifier, DOMCacheEngine::RecordIdentifiersOrError&&);
 
 private:
-    virtual void doOpen(uint64_t requestIdentifier, const String& /* origin */, const String& /* cacheName */) { openCompleted(requestIdentifier, makeUnexpected(DOMCacheEngine::Error::NotImplemented)); }
+    virtual void doOpen(uint64_t requestIdentifier, const ClientOrigin&, const String& /* cacheName */) { openCompleted(requestIdentifier, makeUnexpected(DOMCacheEngine::Error::NotImplemented)); }
     virtual void doRemove(uint64_t requestIdentifier, uint64_t /* cacheIdentifier */) { removeCompleted(requestIdentifier, makeUnexpected(DOMCacheEngine::Error::NotImplemented)); }
-    virtual void doRetrieveCaches(uint64_t requestIdentifier, const String& /* origin */, uint64_t /* updateCounter */) { updateCaches(requestIdentifier, { }); }
+    virtual void doRetrieveCaches(uint64_t requestIdentifier, const ClientOrigin&, uint64_t /* updateCounter */) { updateCaches(requestIdentifier, { }); }
 
     virtual void doRetrieveRecords(uint64_t requestIdentifier, uint64_t /* cacheIdentifier */, const URL& /* url */) { updateRecords(requestIdentifier, { }); }
     virtual void doBatchDeleteOperation(uint64_t requestIdentifier, uint64_t /* cacheIdentifier */, const ResourceRequest&, CacheQueryOptions&&) { deleteRecordsCompleted(requestIdentifier, makeUnexpected(DOMCacheEngine::Error::NotImplemented)); }
index 8599589..5cfb36c 100644 (file)
@@ -27,6 +27,7 @@
 #include "DOMCacheStorage.h"
 
 #include "CacheQueryOptions.h"
+#include "ClientOrigin.h"
 #include "JSDOMCache.h"
 #include "JSFetchResponse.h"
 #include "ScriptExecutionContext.h"
@@ -42,11 +43,13 @@ DOMCacheStorage::DOMCacheStorage(ScriptExecutionContext& context, Ref<CacheStora
     suspendIfNeeded();
 }
 
-String DOMCacheStorage::origin() const
+std::optional<ClientOrigin> DOMCacheStorage::origin() const
 {
-    // FIXME: Do we really need to check for origin being null?
     auto* origin = scriptExecutionContext() ? scriptExecutionContext()->securityOrigin() : nullptr;
-    return origin ? origin->toString() : String();
+    if (!origin)
+        return std::nullopt;
+
+    return ClientOrigin { SecurityOriginData::fromSecurityOrigin(scriptExecutionContext()->topOrigin()), SecurityOriginData::fromSecurityOrigin(*origin) };
 }
 
 static void doSequentialMatch(size_t index, Vector<Ref<DOMCache>>&& caches, DOMCache::RequestInfo&& info, CacheQueryOptions&& options, DOMCache::MatchCallback&& completionHandler)
@@ -135,12 +138,11 @@ Ref<DOMCache> DOMCacheStorage::findCacheOrCreate(CacheInfo&& info)
 
 void DOMCacheStorage::retrieveCaches(WTF::Function<void(std::optional<Exception>&&)>&& callback)
 {
-    String origin = this->origin();
-    if (origin.isNull())
+    auto origin = this->origin();
+    if (!origin)
         return;
 
-    setPendingActivity(this);
-    m_connection->retrieveCaches(origin, m_updateCounter, [this, callback = WTFMove(callback)](CacheInfosOrError&& result) mutable {
+    m_connection->retrieveCaches(*origin, m_updateCounter, [this, callback = WTFMove(callback), pendingActivity = makePendingActivity(*this)](CacheInfosOrError&& result) mutable {
         if (!m_isStopped) {
             if (!result.has_value()) {
                 callback(DOMCacheEngine::errorToException(result.error()));
@@ -158,7 +160,6 @@ void DOMCacheStorage::retrieveCaches(WTF::Function<void(std::optional<Exception>
             }
             callback(std::nullopt);
         }
-        unsetPendingActivity(this);
     });
 }
 
@@ -177,33 +178,32 @@ void DOMCacheStorage::open(const String& name, DOMPromiseDeferred<IDLInterface<D
             promise.reject(WTFMove(exception.value()));
             return;
         }
+        doOpen(name, WTFMove(promise));
+    });
+}
 
-        auto position = m_caches.findMatching([&](auto& item) { return item->name() == name; });
-        if (position != notFound) {
-            auto& cache = m_caches[position];
-            promise.resolve(DOMCache::create(*scriptExecutionContext(), String { cache->name() }, cache->identifier(), m_connection.copyRef()));
-            return;
-        }
-
-        String origin = this->origin();
-        ASSERT(!origin.isNull());
+void DOMCacheStorage::doOpen(const String& name, DOMPromiseDeferred<IDLInterface<DOMCache>>&& promise)
+{
+    auto position = m_caches.findMatching([&](auto& item) { return item->name() == name; });
+    if (position != notFound) {
+        auto& cache = m_caches[position];
+        promise.resolve(DOMCache::create(*scriptExecutionContext(), String { cache->name() }, cache->identifier(), m_connection.copyRef()));
+        return;
+    }
 
-        setPendingActivity(this);
-        m_connection->open(origin, name, [this, name, promise = WTFMove(promise)](const CacheIdentifierOrError& result) mutable {
-            if (!m_isStopped) {
-                if (!result.has_value())
-                    promise.reject(DOMCacheEngine::errorToException(result.error()));
-                else {
-                    if (result.value().hadStorageError)
-                        logConsolePersistencyError(scriptExecutionContext(), name);
-
-                    auto cache = DOMCache::create(*scriptExecutionContext(), String { name }, result.value().identifier, m_connection.copyRef());
-                    promise.resolve(cache);
-                    m_caches.append(WTFMove(cache));
-                }
+    m_connection->open(*origin(), name, [this, name, promise = WTFMove(promise), pendingActivity = makePendingActivity(*this)](const CacheIdentifierOrError& result) mutable {
+        if (!m_isStopped) {
+            if (!result.has_value())
+                promise.reject(DOMCacheEngine::errorToException(result.error()));
+            else {
+                if (result.value().hadStorageError)
+                    logConsolePersistencyError(scriptExecutionContext(), name);
+
+                auto cache = DOMCache::create(*scriptExecutionContext(), String { name }, result.value().identifier, m_connection.copyRef());
+                promise.resolve(cache);
+                m_caches.append(WTFMove(cache));
             }
-            unsetPendingActivity(this);
-        });
+        }
     });
 }
 
@@ -214,31 +214,30 @@ void DOMCacheStorage::remove(const String& name, DOMPromiseDeferred<IDLBoolean>&
             promise.reject(WTFMove(exception.value()));
             return;
         }
+        doRemove(name, WTFMove(promise));
+    });
+}
 
-        auto position = m_caches.findMatching([&](auto& item) { return item->name() == name; });
-        if (position == notFound) {
-            promise.resolve(false);
-            return;
-        }
-
-        String origin = this->origin();
-        ASSERT(!origin.isNull());
+void DOMCacheStorage::doRemove(const String& name, DOMPromiseDeferred<IDLBoolean>&& promise)
+{
+    auto position = m_caches.findMatching([&](auto& item) { return item->name() == name; });
+    if (position == notFound) {
+        promise.resolve(false);
+        return;
+    }
 
-        setPendingActivity(this);
-        m_connection->remove(m_caches[position]->identifier(), [this, name, promise = WTFMove(promise)](const CacheIdentifierOrError& result) mutable {
-            if (!m_isStopped) {
-                if (!result.has_value())
-                    promise.reject(DOMCacheEngine::errorToException(result.error()));
-                else {
-                    if (result.value().hadStorageError)
-                        logConsolePersistencyError(scriptExecutionContext(), name);
-                    promise.resolve(true);
-                }
+    m_connection->remove(m_caches[position]->identifier(), [this, name, promise = WTFMove(promise), pendingActivity = makePendingActivity(*this)](const CacheIdentifierOrError& result) mutable {
+        if (!m_isStopped) {
+            if (!result.has_value())
+                promise.reject(DOMCacheEngine::errorToException(result.error()));
+            else {
+                if (result.value().hadStorageError)
+                    logConsolePersistencyError(scriptExecutionContext(), name);
+                promise.resolve(true);
             }
-            unsetPendingActivity(this);
-        });
-        m_caches.remove(position);
+        }
     });
+    m_caches.remove(position);
 }
 
 void DOMCacheStorage::keys(KeysPromise&& promise)
index 93a82fb..f30fd3d 100644 (file)
@@ -52,9 +52,11 @@ private:
     const char* activeDOMObjectName() const final;
     bool canSuspendForDocumentSuspension() const final;
 
+    void doOpen(const String& name, DOMPromiseDeferred<IDLInterface<DOMCache>>&&);
+    void doRemove(const String&, DOMPromiseDeferred<IDLBoolean>&&);
     void retrieveCaches(WTF::Function<void(std::optional<Exception>&&)>&&);
     Ref<DOMCache> findCacheOrCreate(DOMCacheEngine::CacheInfo&&);
-    String origin() const;
+    std::optional<ClientOrigin> origin() const;
 
     Vector<Ref<DOMCache>> m_caches;
     uint64_t m_updateCounter { 0 };
index f9e5471..c5437b6 100644 (file)
@@ -109,7 +109,7 @@ WorkerCacheStorageConnection::~WorkerCacheStorageConnection()
         callOnMainThread([mainThreadConnection = WTFMove(m_mainThreadConnection)]() mutable { });
 }
 
-void WorkerCacheStorageConnection::doOpen(uint64_t requestIdentifier, const String& origin, const String& cacheName)
+void WorkerCacheStorageConnection::doOpen(uint64_t requestIdentifier, const ClientOrigin& origin, const String& cacheName)
 {
     callOnMainThread([workerThread = makeRef(m_scope.thread()), mainThreadConnection = m_mainThreadConnection, requestIdentifier, origin = origin.isolatedCopy(), cacheName = cacheName.isolatedCopy()] () mutable {
         mainThreadConnection->open(origin, cacheName, [workerThread = WTFMove(workerThread), requestIdentifier] (const CacheIdentifierOrError& result) mutable {
@@ -132,7 +132,7 @@ void WorkerCacheStorageConnection::doRemove(uint64_t requestIdentifier, uint64_t
     });
 }
 
-void WorkerCacheStorageConnection::doRetrieveCaches(uint64_t requestIdentifier, const String& origin, uint64_t updateCounter)
+void WorkerCacheStorageConnection::doRetrieveCaches(uint64_t requestIdentifier, const ClientOrigin& origin, uint64_t updateCounter)
 {
     callOnMainThread([workerThread = makeRef(m_scope.thread()), mainThreadConnection = m_mainThreadConnection, requestIdentifier, origin = origin.isolatedCopy(), updateCounter] () mutable {
         mainThreadConnection->retrieveCaches(origin, updateCounter, [workerThread = WTFMove(workerThread), requestIdentifier] (CacheInfosOrError&& result) mutable {
index 276a57a..7aa05ad 100644 (file)
@@ -42,9 +42,9 @@ private:
     explicit WorkerCacheStorageConnection(WorkerGlobalScope&);
 
     // WebCore::CacheStorageConnection.
-    void doOpen(uint64_t requestIdentifier, const String& origin, const String& cacheName) final;
+    void doOpen(uint64_t requestIdentifier, const ClientOrigin&, const String& cacheName) final;
     void doRemove(uint64_t requestIdentifier, uint64_t cacheIdentifier) final;
-    void doRetrieveCaches(uint64_t requestIdentifier, const String& origin, uint64_t updateCounter) final;
+    void doRetrieveCaches(uint64_t requestIdentifier, const ClientOrigin&, uint64_t updateCounter) final;
 
     void doRetrieveRecords(uint64_t requestIdentifier, uint64_t cacheIdentifier, const URL&) final;
 
index 20e2838..af7ca92 100644 (file)
@@ -36,6 +36,11 @@ struct ClientOrigin {
     unsigned hash() const;
     bool operator==(const ClientOrigin&) const;
 
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static std::optional<ClientOrigin> decode(Decoder&);
+
+    ClientOrigin isolatedCopy() const;
+
     SecurityOriginData topOrigin;
     SecurityOriginData clientOrigin;
 };
@@ -54,6 +59,31 @@ inline bool ClientOrigin::operator==(const ClientOrigin& other) const
     return topOrigin == other.topOrigin && clientOrigin == other.clientOrigin;
 }
 
+inline ClientOrigin ClientOrigin::isolatedCopy() const
+{
+    return { topOrigin.isolatedCopy(), clientOrigin.isolatedCopy() };
+}
+
+template<class Encoder> inline void ClientOrigin::encode(Encoder& encoder) const
+{
+    encoder << topOrigin;
+    encoder << clientOrigin;
+}
+
+template<class Decoder> inline std::optional<ClientOrigin> ClientOrigin::decode(Decoder& decoder)
+{
+    std::optional<SecurityOriginData> topOrigin;
+    std::optional<SecurityOriginData> clientOrigin;
+    decoder >> topOrigin;
+    if (!topOrigin)
+        return std::nullopt;
+    decoder >> clientOrigin;
+    if (!clientOrigin)
+        return std::nullopt;
+
+    return ClientOrigin { WTFMove(*topOrigin), WTFMove(*clientOrigin) };
+}
+
 } // namespace WebCore
 
 namespace WTF {
index ada1f41..e90ab82 100644 (file)
@@ -48,12 +48,10 @@ SecurityOriginData SecurityOriginData::fromSecurityOrigin(const SecurityOrigin&
     return securityOriginData;
 }
 
-#if !LOG_DISABLED
-String SecurityOriginData::debugString() const
+String SecurityOriginData::toString() const
 {
     return makeString(protocol, "://", host, ":", String::number(port.value_or(0)));
 }
-#endif
 
 SecurityOriginData SecurityOriginData::fromFrame(Frame* frame)
 {
index 0effa64..5f55f94 100644 (file)
@@ -77,8 +77,10 @@ struct SecurityOriginData {
         return protocol.isHashTableDeletedValue();
     }
     
+    WEBCORE_EXPORT String toString() const;
+
 #if !LOG_DISABLED
-    WEBCORE_EXPORT String debugString() const;
+    String debugString() const { return toString(); }
 #endif
 };
 
index 1fb61ce..665da19 100644 (file)
@@ -45,6 +45,7 @@
 #include "CachedImage.h"
 #include "CachedResourceLoader.h"
 #include "Chrome.h"
+#include "ClientOrigin.h"
 #include "ComposedTreeIterator.h"
 #include "Cursor.h"
 #include "DOMRect.h"
@@ -4248,7 +4249,7 @@ void Internals::clearCacheStorageMemoryRepresentation(DOMPromiseDeferred<void>&&
         if (!m_cacheStorageConnection)
             return;
     }
-    m_cacheStorageConnection->clearMemoryRepresentation(document->securityOrigin().toString(), [promise = WTFMove(promise)](std::optional<DOMCacheEngine::Error>&& result) mutable {
+    m_cacheStorageConnection->clearMemoryRepresentation(ClientOrigin { SecurityOriginData::fromSecurityOrigin(document->topOrigin()), SecurityOriginData::fromSecurityOrigin(document->securityOrigin()) }, [promise = WTFMove(promise)] (auto && result) mutable {
         ASSERT_UNUSED(result, !result);
         promise.resolve();
     });
index bb28e5b..9829b77 100644 (file)
@@ -1,5 +1,58 @@
 2018-01-04  Youenn Fablet  <youenn@apple.com>
 
+        Implement Cache API partitioning based on ClientOrigin
+        https://bugs.webkit.org/show_bug.cgi?id=181240
+
+        Reviewed by Alex Christensen.
+
+        open and retrieveCaches now take a ClientOrigin instead of a String.
+        Updated cache filesystem path computation to take both client origin and top origin.
+
+        When clearing an origin, caches whose client origin or top origin matches the origin are cleared.
+        Caches are added to the web site data of their client origin with their corresponding cache size.
+        Caches are added to the web site data of their top origin with a size equal to 0.
+
+        Updated memory representation dumping used for test to include both top and client origins.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
+        * NetworkProcess/cache/CacheStorageEngine.cpp:
+        (WebKit::CacheStorage::Engine::cachesRootPath):
+        (WebKit::CacheStorage::Engine::open):
+        (WebKit::CacheStorage::Engine::remove):
+        (WebKit::CacheStorage::Engine::retrieveCaches):
+        (WebKit::CacheStorage::Engine::readCachesFromDisk):
+        (WebKit::CacheStorage::Engine::removeCaches):
+        (WebKit::CacheStorage::Engine::fetchEntries):
+        (WebKit::CacheStorage::Engine::clearCachesForOrigin):
+        (WebKit::CacheStorage::Engine::clearMemoryRepresentation):
+        (WebKit::CacheStorage::Engine::representation):
+        * NetworkProcess/cache/CacheStorageEngine.h:
+        * NetworkProcess/cache/CacheStorageEngineCache.cpp:
+        (WebKit::CacheStorage::Cache::Cache):
+        * NetworkProcess/cache/CacheStorageEngineCaches.cpp:
+        (WebKit::CacheStorage::Caches::retrieveOriginFromDirectory):
+        (WebKit::CacheStorage::Caches::Caches):
+        (WebKit::CacheStorage::Caches::storeOrigin):
+        (WebKit::CacheStorage::Caches::readOrigin):
+        (WebKit::CacheStorage::Caches::open):
+        * NetworkProcess/cache/CacheStorageEngineCaches.h:
+        (WebKit::CacheStorage::Caches::create):
+        (WebKit::CacheStorage::Caches::origin const):
+        * NetworkProcess/cache/CacheStorageEngineConnection.cpp:
+        (WebKit::CacheStorageEngineConnection::open):
+        (WebKit::CacheStorageEngineConnection::caches):
+        (WebKit::CacheStorageEngineConnection::clearMemoryRepresentation):
+        * NetworkProcess/cache/CacheStorageEngineConnection.h:
+        * NetworkProcess/cache/CacheStorageEngineConnection.messages.in:
+        * WebProcess/Cache/WebCacheStorageConnection.cpp:
+        (WebKit::WebCacheStorageConnection::doOpen):
+        (WebKit::WebCacheStorageConnection::doRetrieveCaches):
+        (WebKit::WebCacheStorageConnection::clearMemoryRepresentation):
+        * WebProcess/Cache/WebCacheStorageConnection.h:
+
+2018-01-04  Youenn Fablet  <youenn@apple.com>
+
         Service Worker should expose redirect mode for navigation loads as manual
         https://bugs.webkit.org/show_bug.cgi?id=181067
 
index 5a1b3ac..d0cbf08 100644 (file)
@@ -515,10 +515,8 @@ void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, Optio
     });
 
     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
-        for (auto& originData : originDatas) {
-            auto origin = originData.securityOrigin()->toString();
-            CacheStorage::Engine::from(sessionID).clearCachesForOrigin(origin, clearTasksHandler);
-        }
+        for (auto& originData : originDatas)
+            CacheStorage::Engine::from(sessionID).clearCachesForOrigin(originData, clearTasksHandler);
     }
 
     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
index 84c4ffe..ba72703 100644 (file)
@@ -52,13 +52,13 @@ static HashMap<PAL::SessionID, RefPtr<Engine>>& globalEngineMap()
     return map;
 }
 
-String Engine::cachesRootPath(const String& origin)
+String Engine::cachesRootPath(const WebCore::ClientOrigin& origin)
 {
     if (!shouldPersist())
         return { };
 
-    Key key(origin, { }, { }, { }, salt());
-    return WebCore::FileSystem::pathByAppendingComponent(rootPath(), key.partitionHashAsString());
+    Key key(origin.topOrigin.toString(), origin.clientOrigin.toString(), { }, { }, salt());
+    return WebCore::FileSystem::pathByAppendingComponent(rootPath(), key.hashAsString());
 }
 
 Engine::~Engine()
@@ -100,7 +100,7 @@ Engine::Engine(String&& rootPath)
         m_ioQueue = WorkQueue::create("com.apple.WebKit.CacheStorageEngine.serialBackground", WorkQueue::Type::Serial, WorkQueue::QOS::Background);
 }
 
-void Engine::open(const String& origin, const String& cacheName, CacheIdentifierCallback&& callback)
+void Engine::open(const WebCore::ClientOrigin& origin, const String& cacheName, CacheIdentifierCallback&& callback)
 {
     readCachesFromDisk(origin, [cacheName, callback = WTFMove(callback)](CachesOrError&& cachesOrError) mutable {
         if (!cachesOrError.has_value()) {
@@ -118,7 +118,7 @@ void Engine::remove(uint64_t cacheIdentifier, CacheIdentifierCallback&& callback
     for (auto& caches : m_caches.values()) {
         auto* cacheToRemove = caches->find(cacheIdentifier);
         if (cacheToRemove) {
-            cachesToModify = caches.ptr();
+            cachesToModify = caches.get();
             break;
         }
     }
@@ -130,7 +130,7 @@ void Engine::remove(uint64_t cacheIdentifier, CacheIdentifierCallback&& callback
     cachesToModify->remove(cacheIdentifier, WTFMove(callback));
 }
 
-void Engine::retrieveCaches(const String& origin, uint64_t updateCounter, CacheInfosCallback&& callback)
+void Engine::retrieveCaches(const WebCore::ClientOrigin& origin, uint64_t updateCounter, CacheInfosCallback&& callback)
 {
     readCachesFromDisk(origin, [updateCounter, callback = WTFMove(callback)](CachesOrError&& cachesOrError) mutable {
         if (!cachesOrError.has_value()) {
@@ -203,15 +203,16 @@ void Engine::initialize(Function<void(std::optional<Error>&&)>&& callback)
     });
 }
 
-void Engine::readCachesFromDisk(const String& origin, CachesCallback&& callback)
+void Engine::readCachesFromDisk(const WebCore::ClientOrigin& origin, CachesCallback&& callback)
 {
     initialize([this, origin, callback = WTFMove(callback)](std::optional<Error>&& error) mutable {
         auto& caches = m_caches.ensure(origin, [&origin, this] {
-            return Caches::create(*this, String { origin }, cachesRootPath(origin), NetworkProcess::singleton().cacheStoragePerOriginQuota());
+            auto path = cachesRootPath(origin);
+            return Caches::create(*this, WebCore::ClientOrigin { origin }, WTFMove(path), NetworkProcess::singleton().cacheStoragePerOriginQuota());
         }).iterator->value;
 
         if (caches->isInitialized()) {
-            callback(std::reference_wrapper<Caches> { caches.get() });
+            callback(std::reference_wrapper<Caches> { *caches });
             return;
         }
 
@@ -226,7 +227,7 @@ void Engine::readCachesFromDisk(const String& origin, CachesCallback&& callback)
                 return;
             }
 
-            callback(std::reference_wrapper<Caches> { caches.get() });
+            callback(std::reference_wrapper<Caches> { *caches });
         });
     });
 }
@@ -322,12 +323,6 @@ void Engine::removeFile(const String& filename)
     });
 }
 
-void Engine::removeCaches(const String& origin)
-{
-    ASSERT(m_caches.contains(origin));
-    m_caches.remove(origin);
-}
-
 class ReadOriginsTaskCounter : public RefCounted<ReadOriginsTaskCounter> {
 public:
     static Ref<ReadOriginsTaskCounter> create(WTF::CompletionHandler<void(Vector<WebsiteData::Entry>)>&& callback)
@@ -359,7 +354,7 @@ void Engine::fetchEntries(bool shouldComputeSize, WTF::CompletionHandler<void(Ve
 {
     if (!shouldPersist()) {
         auto entries = WTF::map(m_caches, [] (auto& pair) {
-            return WebsiteData::Entry { pair.value->origin(), WebsiteDataType::DOMCache, 0 };
+            return WebsiteData::Entry { pair.value->origin().clientOrigin, WebsiteDataType::DOMCache, 0 };
         });
         completionHandler(WTFMove(entries));
         return;
@@ -369,22 +364,22 @@ void Engine::fetchEntries(bool shouldComputeSize, WTF::CompletionHandler<void(Ve
     for (auto& folderPath : WebCore::FileSystem::listDirectory(m_rootPath, "*")) {
         if (!WebCore::FileSystem::fileIsDirectory(folderPath, WebCore::FileSystem::ShouldFollowSymbolicLinks::No))
             continue;
-        Caches::retrieveOriginFromDirectory(folderPath, *m_ioQueue, [protectedThis = makeRef(*this), shouldComputeSize, taskCounter = taskCounter.copyRef()] (std::optional<WebCore::SecurityOriginData>&& origin) mutable {
+        Caches::retrieveOriginFromDirectory(folderPath, *m_ioQueue, [protectedThis = makeRef(*this), shouldComputeSize, taskCounter = taskCounter.copyRef()] (auto&& origin) mutable {
             ASSERT(RunLoop::isMain());
             if (!origin)
                 return;
 
             if (!shouldComputeSize) {
-                taskCounter->addOrigin(WTFMove(origin.value()), 0);
+                taskCounter->addOrigin(WTFMove(origin->topOrigin), 0);
+                taskCounter->addOrigin(WTFMove(origin->clientOrigin), 0);
                 return;
             }
 
-            auto cacheOrigin = origin->securityOrigin()->toString();
-            protectedThis->readCachesFromDisk(cacheOrigin, [origin = WTFMove(origin.value()), taskCounter = WTFMove(taskCounter)] (CachesOrError&& result) mutable {
+            protectedThis->readCachesFromDisk(origin.value(), [origin = origin.value(), taskCounter = WTFMove(taskCounter)] (CachesOrError&& result) mutable {
                 if (!result.has_value())
                     return;
-                taskCounter->addOrigin(WTFMove(origin), result.value().get().storageSize());
-
+                taskCounter->addOrigin(WTFMove(origin.topOrigin), 0);
+                taskCounter->addOrigin(WTFMove(origin.clientOrigin), result.value().get().storageSize());
             });
         });
     }
@@ -406,22 +401,33 @@ void Engine::clearAllCaches(CallbackAggregator& taskHandler)
     });
 }
 
-void Engine::clearCachesForOrigin(const String& origin, CallbackAggregator& taskHandler)
+void Engine::clearCachesForOrigin(const WebCore::SecurityOriginData& origin, CallbackAggregator& taskHandler)
 {
-    if (auto caches = m_caches.get(origin)) {
-        caches->clear([taskHandler = makeRef(taskHandler)] { });
-        return;
+    for (auto& keyValue : m_caches) {
+        if (keyValue.key.topOrigin == origin || keyValue.key.clientOrigin == origin)
+            keyValue.value->clear([taskHandler = makeRef(taskHandler)] { });
     }
 
     if (!shouldPersist())
         return;
 
-    m_ioQueue->dispatch([filename = cachesRootPath(origin), taskHandler = makeRef(taskHandler)] {
-        deleteDirectoryRecursively(filename);
-    });
+    for (auto& folderPath : WebCore::FileSystem::listDirectory(m_rootPath, "*")) {
+        if (!WebCore::FileSystem::fileIsDirectory(folderPath, WebCore::FileSystem::ShouldFollowSymbolicLinks::No))
+            continue;
+        Caches::retrieveOriginFromDirectory(folderPath, *m_ioQueue, [this, protectedThis = makeRef(*this), origin, taskHandler = makeRef(taskHandler)] (std::optional<WebCore::ClientOrigin>&& folderOrigin) mutable {
+            if (!folderOrigin)
+                return;
+            if (folderOrigin->topOrigin != origin && folderOrigin->clientOrigin != origin)
+                return;
+
+            m_ioQueue->dispatch([path = cachesRootPath(*folderOrigin), taskHandler = WTFMove(taskHandler)] {
+                deleteDirectoryRecursively(path);
+            });
+        });
+    }
 }
 
-void Engine::clearMemoryRepresentation(const String& origin, WebCore::DOMCacheEngine::CompletionCallback&& callback)
+void Engine::clearMemoryRepresentation(const WebCore::ClientOrigin& origin, WebCore::DOMCacheEngine::CompletionCallback&& callback)
 {
     readCachesFromDisk(origin, [callback = WTFMove(callback)](CachesOrError&& result) {
         if (!result.has_value()) {
@@ -469,9 +475,11 @@ String Engine::representation()
             builder.append(",");
         isFirst = false;
 
-        builder.append("\n{ \"origin\" : \"");
-        builder.append(keyValue.key);
-        builder.append("\", \"caches\" : ");
+        builder.append("\n{ \"origin\" : { \"topOrigin\" : \"");
+        builder.append(keyValue.key.topOrigin.toString());
+        builder.append("\", \"clientOrigin\": \"");
+        builder.append(keyValue.key.clientOrigin.toString());
+        builder.append("\" }, \"caches\" : ");
         keyValue.value->appendRepresentation(builder);
         builder.append("}");
     }
index 8aea8f1..075eee5 100644 (file)
@@ -28,6 +28,7 @@
 #include "CacheStorageEngineCaches.h"
 #include "NetworkCacheData.h"
 #include "WebsiteData.h"
+#include <WebCore/ClientOrigin.h>
 #include <wtf/HashMap.h>
 #include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/WorkQueue.h>
@@ -63,9 +64,9 @@ public:
 
     bool shouldPersist() const { return !!m_ioQueue;}
 
-    void open(const String& origin, const String& cacheName, WebCore::DOMCacheEngine::CacheIdentifierCallback&&);
+    void open(const WebCore::ClientOrigin&, const String& cacheName, WebCore::DOMCacheEngine::CacheIdentifierCallback&&);
     void remove(uint64_t cacheIdentifier, WebCore::DOMCacheEngine::CacheIdentifierCallback&&);
-    void retrieveCaches(const String& origin, uint64_t updateCounter, WebCore::DOMCacheEngine::CacheInfosCallback&&);
+    void retrieveCaches(const WebCore::ClientOrigin&, uint64_t updateCounter, WebCore::DOMCacheEngine::CacheInfosCallback&&);
 
     void retrieveRecords(uint64_t cacheIdentifier, WebCore::URL&&, WebCore::DOMCacheEngine::RecordsCallback&&);
     void putRecords(uint64_t cacheIdentifier, Vector<WebCore::DOMCacheEngine::Record>&&, WebCore::DOMCacheEngine::RecordIdentifiersCallback&&);
@@ -82,19 +83,17 @@ public:
     const NetworkCache::Salt& salt() const { return m_salt.value(); }
     uint64_t nextCacheIdentifier() { return ++m_nextCacheIdentifier; }
 
-    void removeCaches(const String& origin);
-
-    void clearMemoryRepresentation(const String& origin, WebCore::DOMCacheEngine::CompletionCallback&&);
+    void clearMemoryRepresentation(const WebCore::ClientOrigin&, WebCore::DOMCacheEngine::CompletionCallback&&);
     String representation();
 
     void clearAllCaches(WTF::CallbackAggregator&);
-    void clearCachesForOrigin(const String& origin, WTF::CallbackAggregator&);
+    void clearCachesForOrigin(const WebCore::SecurityOriginData&, WTF::CallbackAggregator&);
 
 private:
     static Engine& defaultEngine();
     explicit Engine(String&& rootPath);
 
-    String cachesRootPath(const String& origin);
+    String cachesRootPath(const WebCore::ClientOrigin&);
 
     void fetchEntries(bool /* shouldComputeSize */, WTF::CompletionHandler<void(Vector<WebsiteData::Entry>)>&&);
 
@@ -102,7 +101,7 @@ private:
 
     using CachesOrError = Expected<std::reference_wrapper<Caches>, WebCore::DOMCacheEngine::Error>;
     using CachesCallback = WTF::Function<void(CachesOrError&&)>;
-    void readCachesFromDisk(const String& origin, CachesCallback&&);
+    void readCachesFromDisk(const WebCore::ClientOrigin&, CachesCallback&&);
 
     using CacheOrError = Expected<std::reference_wrapper<Cache>, WebCore::DOMCacheEngine::Error>;
     using CacheCallback = WTF::Function<void(CacheOrError&&)>;
@@ -110,7 +109,7 @@ private:
 
     Cache* cache(uint64_t cacheIdentifier);
 
-    HashMap<String, Ref<Caches>> m_caches;
+    HashMap<WebCore::ClientOrigin, RefPtr<Caches>> m_caches;
     uint64_t m_nextCacheIdentifier { 0 };
     String m_rootPath;
     RefPtr<WorkQueue> m_ioQueue;
index a2f1970..353531f 100644 (file)
@@ -50,7 +50,7 @@ static inline String cachesOriginFilename(const String& cachesRootPath)
     return WebCore::FileSystem::pathByAppendingComponent(cachesRootPath, ASCIILiteral("origin"));
 }
 
-void Caches::retrieveOriginFromDirectory(const String& folderPath, WorkQueue& queue, WTF::CompletionHandler<void(std::optional<WebCore::SecurityOriginData>&&)>&& completionHandler)
+void Caches::retrieveOriginFromDirectory(const String& folderPath, WorkQueue& queue, WTF::CompletionHandler<void(std::optional<WebCore::ClientOrigin>&&)>&& completionHandler)
 {
     queue.dispatch([completionHandler = WTFMove(completionHandler), folderPath = folderPath.isolatedCopy()]() mutable {
         if (!WebCore::FileSystem::fileExists(cachesListFilename(folderPath))) {
@@ -72,9 +72,9 @@ void Caches::retrieveOriginFromDirectory(const String& folderPath, WorkQueue& qu
     });
 }
 
-Caches::Caches(Engine& engine, String&& origin, String&& rootPath, uint64_t quota)
+Caches::Caches(Engine& engine, WebCore::ClientOrigin&& origin, String&& rootPath, uint64_t quota)
     : m_engine(&engine)
-    , m_origin(WebCore::SecurityOriginData::fromSecurityOrigin(WebCore::SecurityOrigin::createFromString(origin)))
+    , m_origin(WTFMove(origin))
     , m_rootPath(WTFMove(rootPath))
     , m_quota(quota)
 {
@@ -83,27 +83,36 @@ Caches::Caches(Engine& engine, String&& origin, String&& rootPath, uint64_t quot
 void Caches::storeOrigin(CompletionCallback&& completionHandler)
 {
     WTF::Persistence::Encoder encoder;
-    encoder << m_origin.protocol;
-    encoder << m_origin.host;
-    encoder << m_origin.port;
+    encoder << m_origin.topOrigin.protocol;
+    encoder << m_origin.topOrigin.host;
+    encoder << m_origin.topOrigin.port;
+    encoder << m_origin.clientOrigin.protocol;
+    encoder << m_origin.clientOrigin.host;
+    encoder << m_origin.clientOrigin.port;
     m_engine->writeFile(cachesOriginFilename(m_rootPath), Data { encoder.buffer(), encoder.bufferSize() }, [protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (std::optional<Error>&& error) mutable {
         completionHandler(WTFMove(error));
     });
 }
 
-std::optional<WebCore::SecurityOriginData> Caches::readOrigin(const Data& data)
+std::optional<WebCore::ClientOrigin> Caches::readOrigin(const Data& data)
 {
     // FIXME: We should be able to use modern decoders for persistent data.
-    WebCore::SecurityOriginData origin;
+    WebCore::SecurityOriginData topOrigin, clientOrigin;
     WTF::Persistence::Decoder decoder(data.data(), data.size());
 
-    if (!decoder.decode(origin.protocol))
+    if (!decoder.decode(topOrigin.protocol))
         return std::nullopt;
-    if (!decoder.decode(origin.host))
+    if (!decoder.decode(topOrigin.host))
         return std::nullopt;
-    if (!decoder.decode(origin.port))
+    if (!decoder.decode(topOrigin.port))
         return std::nullopt;
-    return WTFMove(origin);
+    if (!decoder.decode(clientOrigin.protocol))
+        return std::nullopt;
+    if (!decoder.decode(clientOrigin.host))
+        return std::nullopt;
+    if (!decoder.decode(clientOrigin.port))
+        return std::nullopt;
+    return WebCore::ClientOrigin { WTFMove(topOrigin), WTFMove(clientOrigin) };
 }
 
 void Caches::initialize(WebCore::DOMCacheEngine::CompletionCallback&& callback)
index ec08e23..aa823f2 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "CacheStorageEngineCache.h"
 #include "NetworkCacheStorage.h"
-#include <WebCore/SecurityOriginData.h>
+#include <WebCore/ClientOrigin.h>
 #include <wtf/CompletionHandler.h>
 
 namespace WebKit {
@@ -38,9 +38,9 @@ class Engine;
 
 class Caches : public RefCounted<Caches> {
 public:
-    static Ref<Caches> create(Engine& engine, String&& origin, String&& rootPath, uint64_t quota) { return adoptRef(*new Caches { engine, WTFMove(origin), WTFMove(rootPath), quota }); }
+    static Ref<Caches> create(Engine& engine, WebCore::ClientOrigin&& origin, String&& rootPath, uint64_t quota) { return adoptRef(*new Caches { engine, WTFMove(origin), WTFMove(rootPath), quota }); }
 
-    static void retrieveOriginFromDirectory(const String& folderPath, WorkQueue&, WTF::CompletionHandler<void(std::optional<WebCore::SecurityOriginData>&&)>&&);
+    static void retrieveOriginFromDirectory(const String& folderPath, WorkQueue&, WTF::CompletionHandler<void(std::optional<WebCore::ClientOrigin>&&)>&&);
 
     void initialize(WebCore::DOMCacheEngine::CompletionCallback&&);
     void open(const String& name, WebCore::DOMCacheEngine::CacheIdentifierCallback&&);
@@ -66,7 +66,7 @@ public:
     void removeRecord(const RecordInformation&);
 
     const NetworkCache::Salt& salt() const;
-    const WebCore::SecurityOriginData& origin() const { return m_origin; }
+    const WebCore::ClientOrigin& origin() const { return m_origin; }
 
     bool shouldPersist() const { return !m_rootPath.isNull(); }
 
@@ -76,14 +76,14 @@ public:
     uint64_t storageSize() const;
 
 private:
-    Caches(Engine&, String&& origin, String&& rootPath, uint64_t quota);
+    Caches(Engine&, WebCore::ClientOrigin&&, String&& rootPath, uint64_t quota);
 
     void initializeSize(WebCore::DOMCacheEngine::CompletionCallback&&);
     void readCachesFromDisk(WTF::Function<void(Expected<Vector<Cache>, WebCore::DOMCacheEngine::Error>&&)>&&);
     void writeCachesToDisk(WebCore::DOMCacheEngine::CompletionCallback&&);
 
     void storeOrigin(WebCore::DOMCacheEngine::CompletionCallback&&);
-    static std::optional<WebCore::SecurityOriginData> readOrigin(const NetworkCache::Data&);
+    static std::optional<WebCore::ClientOrigin> readOrigin(const NetworkCache::Data&);
 
     Cache* find(const String& name);
 
@@ -93,7 +93,7 @@ private:
     bool m_isInitialized { false };
     Engine* m_engine { nullptr };
     uint64_t m_updateCounter { 0 };
-    WebCore::SecurityOriginData m_origin;
+    WebCore::ClientOrigin m_origin;
     String m_rootPath;
     uint64_t m_quota { 0 };
     uint64_t m_size { 0 };
index b000689..589c5e9 100644 (file)
@@ -53,7 +53,7 @@ CacheStorageEngineConnection::~CacheStorageEngineConnection()
     }
 }
 
-void CacheStorageEngineConnection::open(PAL::SessionID sessionID, uint64_t requestIdentifier, const String& origin, const String& cacheName)
+void CacheStorageEngineConnection::open(PAL::SessionID sessionID, uint64_t requestIdentifier, const WebCore::ClientOrigin& origin, const String& cacheName)
 {
     Engine::from(sessionID).open(origin, cacheName, [connection = makeRef(m_connection.connection()), sessionID, requestIdentifier](const CacheIdentifierOrError& result) {
         connection->send(Messages::WebCacheStorageConnection::OpenCompleted(requestIdentifier, result), sessionID.sessionID());
@@ -67,7 +67,7 @@ void CacheStorageEngineConnection::remove(PAL::SessionID sessionID, uint64_t req
     });
 }
 
-void CacheStorageEngineConnection::caches(PAL::SessionID sessionID, uint64_t requestIdentifier, const String& origin, uint64_t updateCounter)
+void CacheStorageEngineConnection::caches(PAL::SessionID sessionID, uint64_t requestIdentifier, const WebCore::ClientOrigin& origin, uint64_t updateCounter)
 {
     Engine::from(sessionID).retrieveCaches(origin, updateCounter, [connection = makeRef(m_connection.connection()), sessionID, origin, requestIdentifier](CacheInfosOrError&& result) {
         connection->send(Messages::WebCacheStorageConnection::UpdateCaches(requestIdentifier, result), sessionID.sessionID());
@@ -127,7 +127,7 @@ void CacheStorageEngineConnection::dereference(PAL::SessionID sessionID, uint64_
     references.remove(referenceResult);
 }
 
-void CacheStorageEngineConnection::clearMemoryRepresentation(PAL::SessionID sessionID, uint64_t requestIdentifier, const String& origin)
+void CacheStorageEngineConnection::clearMemoryRepresentation(PAL::SessionID sessionID, uint64_t requestIdentifier, const WebCore::ClientOrigin& origin)
 {
     Engine::from(sessionID).clearMemoryRepresentation(origin, [connection = makeRef(m_connection.connection()), sessionID, requestIdentifier] (std::optional<Error>&& error) {
         connection->send(Messages::WebCacheStorageConnection::ClearMemoryRepresentationCompleted(requestIdentifier, error), sessionID.sessionID());
index 9afff68..e57c5e3 100644 (file)
@@ -50,9 +50,9 @@ public:
 private:
     explicit CacheStorageEngineConnection(NetworkConnectionToWebProcess&);
 
-    void open(PAL::SessionID, uint64_t openRequestIdentifier, const String& origin, const String& cacheName);
+    void open(PAL::SessionID, uint64_t openRequestIdentifier, const WebCore::ClientOrigin&, const String& cacheName);
     void remove(PAL::SessionID, uint64_t removeRequestIdentifier, uint64_t cacheIdentifier);
-    void caches(PAL::SessionID, uint64_t retrieveCachesIdentifier, const String& origin, uint64_t updateCounter);
+    void caches(PAL::SessionID, uint64_t retrieveCachesIdentifier, const WebCore::ClientOrigin&, uint64_t updateCounter);
 
     void retrieveRecords(PAL::SessionID, uint64_t requestIdentifier, uint64_t cacheIdentifier, WebCore::URL&&);
     void deleteMatchingRecords(PAL::SessionID, uint64_t requestIdentifier, uint64_t cacheIdentifier, WebCore::ResourceRequest&&, WebCore::CacheQueryOptions&&);
@@ -61,7 +61,7 @@ private:
     void reference(PAL::SessionID, uint64_t cacheIdentifier);
     void dereference(PAL::SessionID, uint64_t cacheIdentifier);
 
-    void clearMemoryRepresentation(PAL::SessionID, uint64_t requestIdentifier, const String& origin);
+    void clearMemoryRepresentation(PAL::SessionID, uint64_t requestIdentifier, const WebCore::ClientOrigin&);
     void engineRepresentation(PAL::SessionID, uint64_t requestIdentifier);
 
     NetworkConnectionToWebProcess& m_connection;
index d6e3ce5..e3107e2 100644 (file)
@@ -24,11 +24,11 @@ messages -> CacheStorageEngineConnection {
     Reference(PAL::SessionID sessionID, uint64_t cacheIdentifier);
     Dereference(PAL::SessionID sessionID, uint64_t cacheIdentifier);
 
-    Open(PAL::SessionID sessionID, uint64_t requestIdentifier, String origin, String cacheName);
+    Open(PAL::SessionID sessionID, uint64_t requestIdentifier, struct WebCore::ClientOrigin origin, String cacheName);
     Remove(PAL::SessionID sessionID, uint64_t requestIdentifier, uint64_t cacheIdentifier);
-    Caches(PAL::SessionID sessionID, uint64_t requestIdentifier, String origin, uint64_t updateCounter);
+    Caches(PAL::SessionID sessionID, uint64_t requestIdentifier, struct WebCore::ClientOrigin origin, uint64_t updateCounter);
 
-    ClearMemoryRepresentation(PAL::SessionID sessionID, uint64_t requestIdentifier, String origin);
+    ClearMemoryRepresentation(PAL::SessionID sessionID, uint64_t requestIdentifier, struct WebCore::ClientOrigin origin);
     EngineRepresentation(PAL::SessionID sessionID, uint64_t requestIdentifier);
 
     RetrieveRecords(PAL::SessionID sessionID, uint64_t requestIdentifier, uint64_t cacheIdentifier, WebCore::URL url);
index f3188fd..3f27123 100644 (file)
@@ -56,7 +56,7 @@ IPC::Connection& WebCacheStorageConnection::connection()
     return WebProcess::singleton().ensureNetworkProcessConnection().connection();
 }
 
-void WebCacheStorageConnection::doOpen(uint64_t requestIdentifier, const String& origin, const String& cacheName)
+void WebCacheStorageConnection::doOpen(uint64_t requestIdentifier, const WebCore::ClientOrigin& origin, const String& cacheName)
 {
     connection().send(Messages::CacheStorageEngineConnection::Open(m_sessionID, requestIdentifier, origin, cacheName), 0);
 }
@@ -66,7 +66,7 @@ void WebCacheStorageConnection::doRemove(uint64_t requestIdentifier, uint64_t ca
     connection().send(Messages::CacheStorageEngineConnection::Remove(m_sessionID, requestIdentifier, cacheIdentifier), 0);
 }
 
-void WebCacheStorageConnection::doRetrieveCaches(uint64_t requestIdentifier, const String& origin, uint64_t updateCounter)
+void WebCacheStorageConnection::doRetrieveCaches(uint64_t requestIdentifier, const WebCore::ClientOrigin& origin, uint64_t updateCounter)
 {
     connection().send(Messages::CacheStorageEngineConnection::Caches(m_sessionID, requestIdentifier, origin, updateCounter), 0);
 }
@@ -126,7 +126,7 @@ void WebCacheStorageConnection::putRecordsCompleted(uint64_t requestIdentifier,
     CacheStorageConnection::putRecordsCompleted(requestIdentifier, WTFMove(result));
 }
 
-void WebCacheStorageConnection::clearMemoryRepresentation(const String& origin, CompletionCallback&& callback)
+void WebCacheStorageConnection::clearMemoryRepresentation(const WebCore::ClientOrigin& origin, CompletionCallback&& callback)
 {
     uint64_t requestIdentifier = ++m_engineRepresentationNextIdentifier;
     m_clearRepresentationCallbacks.set(requestIdentifier, WTFMove(callback));
index 0b24e2a..480eddd 100644 (file)
@@ -52,9 +52,9 @@ private:
     IPC::Connection& connection();
 
     // WebCore::CacheStorageConnection
-    void doOpen(uint64_t requestIdentifier, const String& origin, const String& cacheName) final;
+    void doOpen(uint64_t requestIdentifier, const WebCore::ClientOrigin&, const String& cacheName) final;
     void doRemove(uint64_t requestIdentifier, uint64_t cacheIdentifier) final;
-    void doRetrieveCaches(uint64_t requestIdentifier, const String& origin, uint64_t updateCounter) final;
+    void doRetrieveCaches(uint64_t requestIdentifier, const WebCore::ClientOrigin&, uint64_t updateCounter) final;
 
     void doRetrieveRecords(uint64_t requestIdentifier, uint64_t cacheIdentifier, const WebCore::URL&) final;
     void doBatchDeleteOperation(uint64_t requestIdentifier, uint64_t cacheIdentifier, const WebCore::ResourceRequest&, WebCore::CacheQueryOptions&&) final;
@@ -63,7 +63,7 @@ private:
     void reference(uint64_t cacheIdentifier) final;
     void dereference(uint64_t cacheIdentifier) final;
 
-    void clearMemoryRepresentation(const String& origin, WebCore::DOMCacheEngine::CompletionCallback&&) final;
+    void clearMemoryRepresentation(const WebCore::ClientOrigin&, WebCore::DOMCacheEngine::CompletionCallback&&) final;
     void engineRepresentation(WTF::Function<void(const String&)>&&) final;
 
     void openCompleted(uint64_t requestIdentifier, const WebCore::DOMCacheEngine::CacheIdentifierOrError&);