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