Stop using PassRefPtr in ShareableResource
[WebKit-https.git] / Source / WebKit2 / NetworkProcess / cache / NetworkCacheEntry.cpp
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "NetworkCache.h"
28
29 #include "Logging.h"
30 #include "NetworkCacheCoders.h"
31 #include "NetworkCacheDecoder.h"
32 #include "NetworkCacheEncoder.h"
33 #include <WebCore/ResourceRequest.h>
34 #include <WebCore/SharedBuffer.h>
35 #include <wtf/text/StringBuilder.h>
36
37 #if ENABLE(NETWORK_CACHE)
38
39 namespace WebKit {
40 namespace NetworkCache {
41
42 Entry::Entry(const Key& key, const WebCore::ResourceResponse& response, RefPtr<WebCore::SharedBuffer>&& buffer, const Vector<std::pair<String, String>>& varyingRequestHeaders)
43     : m_key(key)
44     , m_timeStamp(std::chrono::system_clock::now())
45     , m_response(response)
46     , m_varyingRequestHeaders(varyingRequestHeaders)
47     , m_buffer(WTFMove(buffer))
48 {
49     ASSERT(m_key.type() == "Resource");
50 }
51
52 Entry::Entry(const Key& key, const WebCore::ResourceResponse& response, const WebCore::ResourceRequest& redirectRequest, const Vector<std::pair<String, String>>& varyingRequestHeaders)
53     : m_key(key)
54     , m_timeStamp(std::chrono::system_clock::now())
55     , m_response(response)
56     , m_varyingRequestHeaders(varyingRequestHeaders)
57 {
58     ASSERT(m_key.type() == "Resource");
59     // Redirect body is not needed even if exists.
60
61     m_redirectRequest = std::make_unique<WebCore::ResourceRequest>();
62     m_redirectRequest->setAsIsolatedCopy(redirectRequest);
63     m_redirectRequest->setHTTPBody(nullptr);
64 }
65
66 Entry::Entry(const Entry& other)
67     : m_key(other.m_key)
68     , m_timeStamp(other.m_timeStamp)
69     , m_response(other.m_response)
70     , m_varyingRequestHeaders(other.m_varyingRequestHeaders)
71     , m_buffer(other.m_buffer)
72     , m_sourceStorageRecord(other.m_sourceStorageRecord)
73 {
74 }
75
76 Entry::Entry(const Storage::Record& storageEntry)
77     : m_key(storageEntry.key)
78     , m_timeStamp(storageEntry.timeStamp)
79     , m_sourceStorageRecord(storageEntry)
80 {
81     ASSERT(m_key.type() == "Resource");
82 }
83
84 Storage::Record Entry::encodeAsStorageRecord() const
85 {
86     Encoder encoder;
87     encoder << m_response;
88
89     bool hasVaryingRequestHeaders = !m_varyingRequestHeaders.isEmpty();
90     encoder << hasVaryingRequestHeaders;
91     if (hasVaryingRequestHeaders)
92         encoder << m_varyingRequestHeaders;
93
94     bool isRedirect = !!m_redirectRequest;
95     encoder << isRedirect;
96     if (isRedirect)
97         m_redirectRequest->encodeWithoutPlatformData(encoder);
98
99     encoder.encodeChecksum();
100
101     Data header(encoder.buffer(), encoder.bufferSize());
102     Data body;
103     if (m_buffer)
104         body = { reinterpret_cast<const uint8_t*>(m_buffer->data()), m_buffer->size() };
105
106     return { m_key, m_timeStamp, header, body };
107 }
108
109 std::unique_ptr<Entry> Entry::decodeStorageRecord(const Storage::Record& storageEntry)
110 {
111     auto entry = std::make_unique<Entry>(storageEntry);
112
113     Decoder decoder(storageEntry.header.data(), storageEntry.header.size());
114     if (!decoder.decode(entry->m_response))
115         return nullptr;
116     entry->m_response.setSource(WebCore::ResourceResponse::Source::DiskCache);
117
118     bool hasVaryingRequestHeaders;
119     if (!decoder.decode(hasVaryingRequestHeaders))
120         return nullptr;
121
122     if (hasVaryingRequestHeaders) {
123         if (!decoder.decode(entry->m_varyingRequestHeaders))
124             return nullptr;
125     }
126
127     bool isRedirect;
128     if (!decoder.decode(isRedirect))
129         return nullptr;
130
131     if (isRedirect) {
132         entry->m_redirectRequest = std::make_unique<WebCore::ResourceRequest>();
133         if (!entry->m_redirectRequest->decodeWithoutPlatformData(decoder))
134             return nullptr;
135     }
136
137     if (!decoder.verifyChecksum()) {
138         LOG(NetworkCache, "(NetworkProcess) checksum verification failure\n");
139         return nullptr;
140     }
141
142     return entry;
143 }
144
145 #if ENABLE(SHAREABLE_RESOURCE)
146 void Entry::initializeShareableResourceHandleFromStorageRecord() const
147 {
148     auto sharedMemory = m_sourceStorageRecord.body.tryCreateSharedMemory();
149     if (!sharedMemory)
150         return;
151
152     auto shareableResource = ShareableResource::create(sharedMemory.releaseNonNull(), 0, m_sourceStorageRecord.body.size());
153     shareableResource->createHandle(m_shareableResourceHandle);
154 }
155 #endif
156
157 void Entry::initializeBufferFromStorageRecord() const
158 {
159 #if ENABLE(SHAREABLE_RESOURCE)
160     if (!shareableResourceHandle().isNull()) {
161         m_buffer = m_shareableResourceHandle.tryWrapInSharedBuffer();
162         if (m_buffer)
163             return;
164     }
165 #endif
166     m_buffer = WebCore::SharedBuffer::create(m_sourceStorageRecord.body.data(), m_sourceStorageRecord.body.size());
167 }
168
169 WebCore::SharedBuffer* Entry::buffer() const
170 {
171     if (!m_buffer)
172         initializeBufferFromStorageRecord();
173
174     return m_buffer.get();
175 }
176
177 #if ENABLE(SHAREABLE_RESOURCE)
178 ShareableResource::Handle& Entry::shareableResourceHandle() const
179 {
180     if (m_shareableResourceHandle.isNull())
181         initializeShareableResourceHandleFromStorageRecord();
182
183     return m_shareableResourceHandle;
184 }
185 #endif
186
187 bool Entry::needsValidation() const
188 {
189     return m_response.source() == WebCore::ResourceResponse::Source::DiskCacheAfterValidation;
190 }
191
192 void Entry::setNeedsValidation(bool value)
193 {
194     m_response.setSource(value ? WebCore::ResourceResponse::Source::DiskCacheAfterValidation : WebCore::ResourceResponse::Source::DiskCache);
195 }
196
197 void Entry::asJSON(StringBuilder& json, const Storage::RecordInfo& info) const
198 {
199     json.appendLiteral("{\n");
200     json.appendLiteral("\"hash\": ");
201     json.appendQuotedJSONString(m_key.hashAsString());
202     json.appendLiteral(",\n");
203     json.appendLiteral("\"bodySize\": ");
204     json.appendNumber(info.bodySize);
205     json.appendLiteral(",\n");
206     json.appendLiteral("\"worth\": ");
207     json.appendNumber(info.worth);
208     json.appendLiteral(",\n");
209     json.appendLiteral("\"partition\": ");
210     json.appendQuotedJSONString(m_key.partition());
211     json.appendLiteral(",\n");
212     json.appendLiteral("\"timestamp\": ");
213     json.appendNumber(std::chrono::duration_cast<std::chrono::milliseconds>(m_timeStamp.time_since_epoch()).count());
214     json.appendLiteral(",\n");
215     json.appendLiteral("\"URL\": ");
216     json.appendQuotedJSONString(m_response.url().string());
217     json.appendLiteral(",\n");
218     json.appendLiteral("\"bodyHash\": ");
219     json.appendQuotedJSONString(info.bodyHash);
220     json.appendLiteral(",\n");
221     json.appendLiteral("\"bodyShareCount\": ");
222     json.appendNumber(info.bodyShareCount);
223     json.appendLiteral(",\n");
224     json.appendLiteral("\"headers\": {\n");
225     bool firstHeader = true;
226     for (auto& header : m_response.httpHeaderFields()) {
227         if (!firstHeader)
228             json.appendLiteral(",\n");
229         firstHeader = false;
230         json.appendLiteral("    ");
231         json.appendQuotedJSONString(header.key);
232         json.appendLiteral(": ");
233         json.appendQuotedJSONString(header.value);
234     }
235     json.appendLiteral("\n}\n");
236     json.appendLiteral("}");
237 }
238
239 }
240 }
241
242 #endif