Implement Same-Site cookies
[WebKit-https.git] / Source / WebKit / NetworkProcess / cache / NetworkCacheSubresourcesEntry.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
28 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
29 #include "NetworkCacheSubresourcesEntry.h"
30
31 #include "Logging.h"
32 #include "NetworkCacheCoders.h"
33
34 namespace WebKit {
35 namespace NetworkCache {
36
37 void SubresourceInfo::encode(WTF::Persistence::Encoder& encoder) const
38 {
39     encoder << m_key;
40     encoder << m_lastSeen;
41     encoder << m_firstSeen;
42     encoder << m_isTransient;
43
44     // Do not bother serializing other data members of transient resources as they are empty.
45     if (m_isTransient)
46         return;
47
48     encoder << m_isSameSite;
49     encoder << m_firstPartyForCookies;
50     encoder << m_requestHeaders;
51     encoder.encodeEnum(m_priority);
52 }
53
54 bool SubresourceInfo::decode(WTF::Persistence::Decoder& decoder, SubresourceInfo& info)
55 {
56     if (!decoder.decode(info.m_key))
57         return false;
58     if (!decoder.decode(info.m_lastSeen))
59         return false;
60     if (!decoder.decode(info.m_firstSeen))
61         return false;
62     
63     if (!decoder.decode(info.m_isTransient))
64         return false;
65     
66     if (info.m_isTransient)
67         return true;
68
69     if (!decoder.decode(info.m_isSameSite))
70         return false;
71
72     if (!decoder.decode(info.m_firstPartyForCookies))
73         return false;
74
75     if (!decoder.decode(info.m_requestHeaders))
76         return false;
77
78     if (!decoder.decodeEnum(info.m_priority))
79         return false;
80     
81     return true;
82 }
83
84 Storage::Record SubresourcesEntry::encodeAsStorageRecord() const
85 {
86     WTF::Persistence::Encoder encoder;
87     encoder << m_subresources;
88
89     encoder.encodeChecksum();
90
91     return { m_key, m_timeStamp, { encoder.buffer(), encoder.bufferSize() }, { }, { }};
92 }
93
94 std::unique_ptr<SubresourcesEntry> SubresourcesEntry::decodeStorageRecord(const Storage::Record& storageEntry)
95 {
96     auto entry = std::make_unique<SubresourcesEntry>(storageEntry);
97
98     WTF::Persistence::Decoder decoder(storageEntry.header.data(), storageEntry.header.size());
99     if (!decoder.decode(entry->m_subresources))
100         return nullptr;
101
102     if (!decoder.verifyChecksum()) {
103         LOG(NetworkCache, "(NetworkProcess) checksum verification failure\n");
104         return nullptr;
105     }
106
107     return entry;
108 }
109
110 SubresourcesEntry::SubresourcesEntry(const Storage::Record& storageEntry)
111     : m_key(storageEntry.key)
112     , m_timeStamp(storageEntry.timeStamp)
113 {
114     ASSERT(m_key.type() == "SubResources");
115 }
116
117 SubresourceInfo::SubresourceInfo(const Key& key, const WebCore::ResourceRequest& request, const SubresourceInfo* previousInfo)
118     : m_key(key)
119     , m_lastSeen(WallTime::now())
120     , m_firstSeen(previousInfo ? previousInfo->firstSeen() : m_lastSeen)
121     , m_isTransient(!previousInfo)
122     , m_isSameSite(request.isSameSite())
123     , m_firstPartyForCookies(request.firstPartyForCookies())
124     , m_requestHeaders(request.httpHeaderFields())
125     , m_priority(request.priority())
126 {
127 }
128
129 static Vector<SubresourceInfo> makeSubresourceInfoVector(const Vector<std::unique_ptr<SubresourceLoad>>& subresourceLoads, Vector<SubresourceInfo>* previousSubresources)
130 {
131     Vector<SubresourceInfo> result;
132     result.reserveInitialCapacity(subresourceLoads.size());
133     
134     HashMap<Key, unsigned> previousMap;
135     if (previousSubresources) {
136         for (unsigned i = 0; i < previousSubresources->size(); ++i)
137             previousMap.add(previousSubresources->at(i).key(), i);
138     }
139
140     HashSet<Key> deduplicationSet;
141     for (auto& load : subresourceLoads) {
142         if (!deduplicationSet.add(load->key).isNewEntry)
143             continue;
144         
145         SubresourceInfo* previousInfo = nullptr;
146         if (previousSubresources) {
147             auto it = previousMap.find(load->key);
148             if (it != previousMap.end())
149                 previousInfo = &(*previousSubresources)[it->value];
150         }
151         
152         result.uncheckedAppend({ load->key, load->request, previousInfo });
153         
154         // FIXME: We should really consider all resources seen for the first time transient.
155         if (!previousSubresources)
156             result.last().setNonTransient();
157     }
158
159     return result;
160 }
161
162 SubresourcesEntry::SubresourcesEntry(Key&& key, const Vector<std::unique_ptr<SubresourceLoad>>& subresourceLoads)
163     : m_key(WTFMove(key))
164     , m_timeStamp(WallTime::now())
165     , m_subresources(makeSubresourceInfoVector(subresourceLoads, nullptr))
166 {
167     ASSERT(m_key.type() == "SubResources");
168 }
169     
170 void SubresourcesEntry::updateSubresourceLoads(const Vector<std::unique_ptr<SubresourceLoad>>& subresourceLoads)
171 {
172     m_subresources = makeSubresourceInfoVector(subresourceLoads, &m_subresources);
173 }
174
175 } // namespace WebKit
176 } // namespace NetworkCache
177
178 #endif // ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)