Title: [221942] trunk/Source
Revision
221942
Author
[email protected]
Date
2017-09-12 16:13:17 -0700 (Tue, 12 Sep 2017)

Log Message

Introduce a RecordData for Cache to efficiently check whether it matches a corresponding request or not
https://bugs.webkit.org/show_bug.cgi?id=176579

Patch by Youenn Fablet <[email protected]> on 2017-09-12
Reviewed by Alex Christensen.

Source/WebCore:

No change of behavior.

Introducing another version of queryCacheMatch used for the NetworkProcess implementation of the Cache.
Exporting the copy of a response body to be used also there.

* Modules/cache/DOMCacheEngine.cpp:
(WebCore::DOMCacheEngine::matchURLs):
(WebCore::DOMCacheEngine::queryCacheMatch):
(WebCore::DOMCacheEngine::copyResponseBody):
* Modules/cache/DOMCacheEngine.h:

Source/WebKit:

Introducing RecordData that splits its stored data in mandatory data,
used to check a record with a request and optional data that is
necessary to build a CacheStorageEngine::Record used by WebProcess.

The mandatory data contains the URL, Vary header information and identifiers.
Adding routines to go from a Record to RecordData and vice versa.
Storing in CacheStorage::Cache RecordData instead of Record.

* NetworkProcess/cache/CacheStorageEngineCache.cpp:
(WebKit::CacheStorage::queryCache):
(WebKit::CacheStorage::updateVaryInformation):
(WebKit::CacheStorage::toRecord):
(WebKit::CacheStorage::toRecordData):
(WebKit::CacheStorage::Cache::retrieveRecords const):
(WebKit::CacheStorage::Cache::addRecord):
(WebKit::CacheStorage::Cache::recordsFromURL):
(WebKit::CacheStorage::Cache::recordsFromURL const):
(WebKit::CacheStorage::Cache::put):
(WebKit::CacheStorage::Cache::writeRecordToDisk):
(WebKit::CacheStorage::Cache::removeRecordFromDisk):
* NetworkProcess/cache/CacheStorageEngineCache.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (221941 => 221942)


--- trunk/Source/WebCore/ChangeLog	2017-09-12 22:09:47 UTC (rev 221941)
+++ trunk/Source/WebCore/ChangeLog	2017-09-12 23:13:17 UTC (rev 221942)
@@ -1,3 +1,21 @@
+2017-09-12  Youenn Fablet  <[email protected]>
+
+        Introduce a RecordData for Cache to efficiently check whether it matches a corresponding request or not
+        https://bugs.webkit.org/show_bug.cgi?id=176579
+
+        Reviewed by Alex Christensen.
+
+        No change of behavior.
+
+        Introducing another version of queryCacheMatch used for the NetworkProcess implementation of the Cache.
+        Exporting the copy of a response body to be used also there.
+
+        * Modules/cache/DOMCacheEngine.cpp:
+        (WebCore::DOMCacheEngine::matchURLs):
+        (WebCore::DOMCacheEngine::queryCacheMatch):
+        (WebCore::DOMCacheEngine::copyResponseBody):
+        * Modules/cache/DOMCacheEngine.h:
+
 2017-09-12  Antti Koivisto  <[email protected]>
 
         AnimationBase should point to Element instead of RenderElement

Modified: trunk/Source/WebCore/Modules/cache/DOMCacheEngine.cpp (221941 => 221942)


--- trunk/Source/WebCore/Modules/cache/DOMCacheEngine.cpp	2017-09-12 22:09:47 UTC (rev 221941)
+++ trunk/Source/WebCore/Modules/cache/DOMCacheEngine.cpp	2017-09-12 23:13:17 UTC (rev 221942)
@@ -49,18 +49,25 @@
     }
 }
 
-bool queryCacheMatch(const ResourceRequest& request, const ResourceRequest& cachedRequest, const ResourceResponse& cachedResponse, const CacheQueryOptions& options)
+static inline bool matchURLs(const ResourceRequest& request, const URL& cachedURL, const CacheQueryOptions& options)
 {
     ASSERT(options.ignoreMethod || request.httpMethod() == "GET");
 
     URL requestURL = request.url();
-    URL cachedRequestURL = cachedRequest.url();
+    URL cachedRequestURL = cachedURL;
 
     if (options.ignoreSearch) {
-        requestURL.setQuery({ });
-        cachedRequestURL.setQuery({ });
+        if (requestURL.hasQuery())
+            requestURL.setQuery({ });
+        if (cachedRequestURL.hasQuery())
+            cachedRequestURL.setQuery({ });
     }
-    if (!equalIgnoringFragmentIdentifier(requestURL, cachedRequestURL))
+    return equalIgnoringFragmentIdentifier(requestURL, cachedRequestURL);
+}
+
+bool queryCacheMatch(const ResourceRequest& request, const ResourceRequest& cachedRequest, const ResourceResponse& cachedResponse, const CacheQueryOptions& options)
+{
+    if (!matchURLs(request, cachedRequest.url(), options))
         return false;
 
     if (options.ignoreVary)
@@ -70,14 +77,36 @@
     if (varyValue.isNull())
         return true;
 
-    // FIXME: This is inefficient, we should be able to split and trim whitespaces at the same time.
-    Vector<String> varyHeaderNames;
-    varyValue.split(',', false, varyHeaderNames);
-    for (auto& name : varyHeaderNames) {
-        if (stripLeadingAndTrailingHTTPSpaces(name) == "*")
+    bool isVarying = false;
+    varyValue.split(',', false, [&](StringView view) {
+        if (isVarying)
+            return;
+        auto nameView = stripLeadingAndTrailingHTTPSpaces(view);
+        if (nameView == "*") {
+            isVarying = true;
+            return;
+        }
+        auto name = nameView.toString();
+        isVarying = cachedRequest.httpHeaderField(name) != request.httpHeaderField(name);
+    });
+
+    return !isVarying;
+}
+
+bool queryCacheMatch(const ResourceRequest& request, const URL& url, bool hasVaryStar, const HashMap<String, String>& varyHeaders, const CacheQueryOptions& options)
+{
+    if (!matchURLs(request, url, options))
+        return false;
+
+    if (options.ignoreVary)
+        return true;
+
+    if (hasVaryStar)
+        return false;
+
+    for (const auto& pair : varyHeaders) {
+        if (pair.value != request.httpHeaderField(pair.key))
             return false;
-        if (cachedRequest.httpHeaderField(name) != request.httpHeaderField(name))
-            return false;
     }
     return true;
 }
@@ -93,7 +122,7 @@
     });
 }
 
-static inline ResponseBody copyResponseBody(const DOMCacheEngine::ResponseBody& body)
+ResponseBody copyResponseBody(const ResponseBody& body)
 {
     return WTF::switchOn(body, [](const Ref<FormData>& formData) {
         return formData.copyRef();

Modified: trunk/Source/WebCore/Modules/cache/DOMCacheEngine.h (221941 => 221942)


--- trunk/Source/WebCore/Modules/cache/DOMCacheEngine.h	2017-09-12 22:09:47 UTC (rev 221941)
+++ trunk/Source/WebCore/Modules/cache/DOMCacheEngine.h	2017-09-12 23:13:17 UTC (rev 221942)
@@ -48,9 +48,11 @@
 Exception errorToException(Error);
 
 WEBCORE_EXPORT bool queryCacheMatch(const ResourceRequest& request, const ResourceRequest& cachedRequest, const ResourceResponse&, const CacheQueryOptions&);
+WEBCORE_EXPORT bool queryCacheMatch(const ResourceRequest& request, const URL& url, bool hasVaryStar, const HashMap<String, String>& varyHeaders, const CacheQueryOptions&);
 
 using ResponseBody = Variant<std::nullptr_t, Ref<FormData>, Ref<SharedBuffer>>;
 ResponseBody isolatedResponseBody(const ResponseBody&);
+WEBCORE_EXPORT ResponseBody copyResponseBody(const ResponseBody&);
 
 struct Record {
     WEBCORE_EXPORT Record copy() const;

Modified: trunk/Source/WebKit/ChangeLog (221941 => 221942)


--- trunk/Source/WebKit/ChangeLog	2017-09-12 22:09:47 UTC (rev 221941)
+++ trunk/Source/WebKit/ChangeLog	2017-09-12 23:13:17 UTC (rev 221942)
@@ -1,3 +1,32 @@
+2017-09-12  Youenn Fablet  <[email protected]>
+
+        Introduce a RecordData for Cache to efficiently check whether it matches a corresponding request or not
+        https://bugs.webkit.org/show_bug.cgi?id=176579
+
+        Reviewed by Alex Christensen.
+
+        Introducing RecordData that splits its stored data in mandatory data,
+        used to check a record with a request and optional data that is
+        necessary to build a CacheStorageEngine::Record used by WebProcess.
+
+        The mandatory data contains the URL, Vary header information and identifiers.
+        Adding routines to go from a Record to RecordData and vice versa.
+        Storing in CacheStorage::Cache RecordData instead of Record.
+
+        * NetworkProcess/cache/CacheStorageEngineCache.cpp:
+        (WebKit::CacheStorage::queryCache):
+        (WebKit::CacheStorage::updateVaryInformation):
+        (WebKit::CacheStorage::toRecord):
+        (WebKit::CacheStorage::toRecordData):
+        (WebKit::CacheStorage::Cache::retrieveRecords const):
+        (WebKit::CacheStorage::Cache::addRecord):
+        (WebKit::CacheStorage::Cache::recordsFromURL):
+        (WebKit::CacheStorage::Cache::recordsFromURL const):
+        (WebKit::CacheStorage::Cache::put):
+        (WebKit::CacheStorage::Cache::writeRecordToDisk):
+        (WebKit::CacheStorage::Cache::removeRecordFromDisk):
+        * NetworkProcess/cache/CacheStorageEngineCache.h:
+
 2017-09-12  Dan Bernstein  <[email protected]>
 
         Tried to fix the iOS 10 build after r221930.

Modified: trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.cpp (221941 => 221942)


--- trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.cpp	2017-09-12 22:09:47 UTC (rev 221941)
+++ trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.cpp	2017-09-12 23:13:17 UTC (rev 221942)
@@ -31,6 +31,7 @@
 #include "NetworkCacheKey.h"
 #include "NetworkProcess.h"
 #include <WebCore/CacheQueryOptions.h>
+#include <WebCore/HTTPParsers.h>
 #include <pal/SessionID.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/MainThread.h>
@@ -50,7 +51,7 @@
 
 namespace CacheStorage {
 
-static inline Vector<uint64_t> queryCache(const Vector<Record>* records, const ResourceRequest& request, const CacheQueryOptions& options)
+static inline Vector<uint64_t> queryCache(const Vector<RecordData>* records, const ResourceRequest& request, const CacheQueryOptions& options)
 {
     if (!records)
         return { };
@@ -60,12 +61,48 @@
 
     Vector<uint64_t> results;
     for (const auto& record : *records) {
-        if (WebCore::DOMCacheEngine::queryCacheMatch(request, record.request, record.response, options))
+        if (WebCore::DOMCacheEngine::queryCacheMatch(request, record.url, record.hasVaryStar, record.varyHeaders, options))
             results.append(record.identifier);
     }
     return results;
 }
 
+static inline void updateVaryInformation(RecordData& recordData)
+{
+    auto varyValue = recordData.data->response.httpHeaderField(WebCore::HTTPHeaderName::Vary);
+    if (varyValue.isNull()) {
+        recordData.hasVaryStar = false;
+        recordData.varyHeaders = { };
+        return;
+    }
+
+    varyValue.split(',', false, [&](StringView view) {
+        if (!recordData.hasVaryStar && stripLeadingAndTrailingHTTPSpaces(view) == "*")
+            recordData.hasVaryStar = true;
+        String headerName = view.toString();
+        recordData.varyHeaders.add(headerName, recordData.data->request.httpHeaderField(headerName));
+    });
+
+    if (recordData.hasVaryStar)
+        recordData.varyHeaders = { };
+}
+
+static inline Record toRecord(const RecordData& record)
+{
+    return { record.identifier, record.updateResponseCounter, record.data->requestHeadersGuard, record.data->request, record.data->options, record.data->referrer, record.data->responseHeadersGuard, record.data->response, copyResponseBody(record.data->responseBody) };
+}
+
+static inline RecordData toRecordData(Record&& record)
+{
+    auto url = ""
+    RecordData::Data data = { record.requestHeadersGuard, WTFMove(record.request), WTFMove(record.options), WTFMove(record.referrer), WTFMove(record.responseHeadersGuard), WTFMove(record.response), WTFMove(record.responseBody) };
+    RecordData recordData = { { }, monotonicallyIncreasingTimeMS(), record.identifier, 0, url, false, { }, WTFMove(data) };
+
+    updateVaryInformation(recordData);
+
+    return recordData;
+}
+
 Cache::Cache(Caches& caches, uint64_t identifier, State state, String&& name)
     : m_caches(caches)
     , m_state(state)
@@ -131,7 +168,7 @@
         Vector<Record> result;
         for (auto& records : m_records.values()) {
             for (auto& record : records)
-                result.append(record.copy());
+                result.append(toRecord(record));
         }
         std::sort(result.begin(), result.end(), [](const auto& a, const auto& b) {
             return a.identifier < b.identifier;
@@ -146,7 +183,7 @@
     Vector<Record> result;
     result.reserveInitialCapacity(records->size());
     for (auto& record : *records)
-        result.uncheckedAppend(record.copy());
+        result.append(toRecord(record));
     return result;
 }
 
@@ -159,18 +196,18 @@
     return keyURL;
 }
 
-Record& Cache::addNewURLRecord(Record&& record)
+RecordData& Cache::addRecord(Vector<RecordData>* records, Record&& record)
 {
-    auto key = computeKeyURL(record.request.url());
-    ASSERT(!m_records.contains(key));
-
-    Vector<Record> newRecords;
-    newRecords.reserveInitialCapacity(1);
-    newRecords.uncheckedAppend(WTFMove(record));
-    return m_records.set(key, WTFMove(newRecords)).iterator->value.last();
+    if (!records) {
+        auto key = computeKeyURL(record.request.url());
+        ASSERT(!m_records.contains(key));
+        records = &m_records.set(key, Vector<RecordData> { }).iterator->value;
+    }
+    records->append(toRecordData(WTFMove(record)));
+    return records->last();
 }
 
-Vector<Record>* Cache::recordsFromURL(const URL& url)
+Vector<RecordData>* Cache::recordsFromURL(const URL& url)
 {
     auto iterator = m_records.find(computeKeyURL(url));
     if (iterator == m_records.end())
@@ -178,7 +215,7 @@
     return &iterator->value;
 }
 
-const Vector<Record>* Cache::recordsFromURL(const URL& url) const
+const Vector<RecordData>* Cache::recordsFromURL(const URL& url) const
 {
     auto iterator = m_records.find(computeKeyURL(url));
     if (iterator == m_records.end())
@@ -201,13 +238,8 @@
             recordIdentifiers.uncheckedAppend(record.identifier);
 
             shouldWriteRecordList = true;
-            if (!sameURLRecords) {
-                auto& recordToWrite = addNewURLRecord(WTFMove(record));
-                writeRecordToDisk(recordToWrite);
-            } else {
-                sameURLRecords->append(WTFMove(record));
-                writeRecordToDisk(sameURLRecords->last());
-            }
+            auto& recordToWrite = addRecord(sameURLRecords, WTFMove(record));
+            writeRecordToDisk(recordToWrite);
         } else {
             auto identifier = matchingRecords[0];
             auto position = sameURLRecords->findMatching([&](const auto& item) { return item.identifier == identifier; });
@@ -215,11 +247,14 @@
             if (position != notFound) {
                 auto& existingRecord = (*sameURLRecords)[position];
                 recordIdentifiers.uncheckedAppend(identifier);
-                existingRecord.responseHeadersGuard = record.responseHeadersGuard;
-                existingRecord.response = WTFMove(record.response);
-                existingRecord.responseBody = WTFMove(record.responseBody);
                 ++existingRecord.updateResponseCounter;
 
+                // FIXME: Handle the case where data is null.
+                ASSERT(existingRecord.data);
+                existingRecord.data->responseHeadersGuard = record.responseHeadersGuard;
+                existingRecord.data->response = WTFMove(record.response);
+                existingRecord.data->responseBody = WTFMove(record.responseBody);
+                updateVaryInformation(existingRecord);
                 writeRecordToDisk(existingRecord);
             }
         }
@@ -275,12 +310,12 @@
     callback(std::nullopt);
 }
 
-void Cache::writeRecordToDisk(Record& record)
+void Cache::writeRecordToDisk(RecordData&)
 {
     // FIXME: Implement this.
 }
 
-void Cache::removeRecordFromDisk(Record& record)
+void Cache::removeRecordFromDisk(RecordData&)
 {
     // FIXME: Implement this.
 }

Modified: trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.h (221941 => 221942)


--- trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.h	2017-09-12 22:09:47 UTC (rev 221941)
+++ trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.h	2017-09-12 23:13:17 UTC (rev 221942)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "NetworkCacheKey.h"
 #include <WebCore/DOMCacheEngine.h>
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
@@ -35,6 +36,31 @@
 
 class Caches;
 
+struct RecordData {
+    NetworkCache::Key key;
+    double insertionTime { 0 };
+
+    uint64_t identifier { 0 };
+    uint64_t updateResponseCounter { 0 };
+
+    WebCore::URL url;
+    bool hasVaryStar { false };
+    HashMap<String, String> varyHeaders;
+
+    struct Data {
+        WebCore::FetchHeaders::Guard requestHeadersGuard;
+        WebCore::ResourceRequest request;
+        WebCore::FetchOptions options;
+        String referrer;
+
+        WebCore::FetchHeaders::Guard responseHeadersGuard;
+        WebCore::ResourceResponse response;
+        WebCore::DOMCacheEngine::ResponseBody responseBody;
+    };
+
+    std::optional<Data> data;
+};
+
 class Cache {
 public:
     enum class State { Uninitialized, Opening, Open };
@@ -56,22 +82,22 @@
     void clearMemoryRepresentation();
  
 private:
-    Vector<WebCore::DOMCacheEngine::Record>* recordsFromURL(const WebCore::URL&);
-    const Vector<WebCore::DOMCacheEngine::Record>* recordsFromURL(const WebCore::URL&) const;
-    WebCore::DOMCacheEngine::Record& addNewURLRecord(WebCore::DOMCacheEngine::Record&&);
+    Vector<RecordData>* recordsFromURL(const WebCore::URL&);
+    const Vector<RecordData>* recordsFromURL(const WebCore::URL&) const;
+    RecordData& addRecord(Vector<RecordData>*, WebCore::DOMCacheEngine::Record&&);
 
     void finishOpening(WebCore::DOMCacheEngine::CompletionCallback&&, std::optional<WebCore::DOMCacheEngine::Error>&&);
 
     void readRecordsList(WebCore::DOMCacheEngine::CompletionCallback&&);
     void writeRecordsList(WebCore::DOMCacheEngine::CompletionCallback&&);
-    void writeRecordToDisk(WebCore::DOMCacheEngine::Record&);
-    void removeRecordFromDisk(WebCore::DOMCacheEngine::Record&);
+    void writeRecordToDisk(RecordData&);
+    void removeRecordFromDisk(RecordData&);
 
     Caches& m_caches;
     State m_state;
     uint64_t m_identifier { 0 };
     String m_name;
-    HashMap<String, Vector<WebCore::DOMCacheEngine::Record>> m_records;
+    HashMap<String, Vector<RecordData>> m_records;
     uint64_t m_nextRecordIdentifier { 0 };
     Vector<WebCore::DOMCacheEngine::CompletionCallback> m_pendingOpeningCallbacks;
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to