Use SecurityOriginData more consistently in Service Worker code
[WebKit-https.git] / Source / WebKit / WebProcess / WebStorage / StorageNamespaceImpl.cpp
1 /*
2  * Copyright (C) 2013-2017 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 "StorageNamespaceImpl.h"
28
29 #include "StorageAreaImpl.h"
30 #include "StorageAreaMap.h"
31 #include "WebPage.h"
32 #include "WebPageGroupProxy.h"
33 #include "WebProcess.h"
34 #include <WebCore/Frame.h>
35 #include <WebCore/PageGroup.h>
36 #include <WebCore/SecurityOrigin.h>
37 #include <WebCore/Settings.h>
38 #include <WebCore/StorageType.h>
39
40 using namespace WebCore;
41
42 namespace WebKit {
43
44 RefPtr<StorageNamespaceImpl> StorageNamespaceImpl::createSessionStorageNamespace(uint64_t identifier, unsigned quotaInBytes)
45 {
46     return adoptRef(new StorageNamespaceImpl(StorageType::Session, identifier, nullptr, quotaInBytes));
47 }
48
49 RefPtr<StorageNamespaceImpl> StorageNamespaceImpl::createEphemeralLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes)
50 {
51     return adoptRef(new StorageNamespaceImpl(StorageType::EphemeralLocal, identifier, nullptr, quotaInBytes));
52 }
53
54 RefPtr<StorageNamespaceImpl> StorageNamespaceImpl::createLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes)
55 {
56     return adoptRef(new StorageNamespaceImpl(StorageType::Local, identifier, nullptr, quotaInBytes));
57 }
58
59 RefPtr<StorageNamespaceImpl> StorageNamespaceImpl::createTransientLocalStorageNamespace(uint64_t identifier, WebCore::SecurityOrigin& topLevelOrigin, uint64_t quotaInBytes)
60 {
61     return adoptRef(new StorageNamespaceImpl(StorageType::TransientLocal, identifier, &topLevelOrigin, quotaInBytes));
62 }
63
64 StorageNamespaceImpl::StorageNamespaceImpl(WebCore::StorageType storageType, uint64_t storageNamespaceID, WebCore::SecurityOrigin* topLevelOrigin, unsigned quotaInBytes)
65     : m_storageType(storageType)
66     , m_storageNamespaceID(storageNamespaceID)
67     , m_topLevelOrigin(topLevelOrigin)
68     , m_quotaInBytes(quotaInBytes)
69 {
70 }
71
72 StorageNamespaceImpl::~StorageNamespaceImpl()
73 {
74 }
75
76 void StorageNamespaceImpl::didDestroyStorageAreaMap(StorageAreaMap& map)
77 {
78     m_storageAreaMaps.remove(map.securityOrigin().data());
79 }
80
81 RefPtr<StorageArea> StorageNamespaceImpl::storageArea(const SecurityOriginData& securityOrigin)
82 {
83     if (m_storageType == StorageType::EphemeralLocal)
84         return ephemeralLocalStorageArea(securityOrigin);
85
86     RefPtr<StorageAreaMap> map;
87
88     auto& slot = m_storageAreaMaps.add(securityOrigin, nullptr).iterator->value;
89     if (!slot) {
90         map = StorageAreaMap::create(this, securityOrigin.securityOrigin());
91         slot = map.get();
92     } else
93         map = slot;
94
95     return StorageAreaImpl::create(map.releaseNonNull());
96 }
97
98 class StorageNamespaceImpl::EphemeralStorageArea final : public StorageArea {
99 public:
100     static Ref<EphemeralStorageArea> create(const SecurityOriginData& origin, unsigned quotaInBytes)
101     {
102         return adoptRef(*new EphemeralStorageArea(origin, quotaInBytes));
103     }
104
105     Ref<EphemeralStorageArea> copy()
106     {
107         return adoptRef(*new EphemeralStorageArea(*this));
108     }
109
110 private:
111     EphemeralStorageArea(const SecurityOriginData& origin, unsigned quotaInBytes)
112         : m_securityOriginData(origin)
113         , m_storageMap(StorageMap::create(quotaInBytes))
114     {
115     }
116
117     EphemeralStorageArea(EphemeralStorageArea& other)
118         : m_securityOriginData(other.m_securityOriginData)
119         , m_storageMap(other.m_storageMap)
120     {
121     }
122
123     // WebCore::StorageArea.
124     unsigned length()
125     {
126         return m_storageMap->length();
127     }
128
129     String key(unsigned index)
130     {
131         return m_storageMap->key(index);
132     }
133
134     String item(const String& key)
135     {
136         return m_storageMap->getItem(key);
137     }
138
139     void setItem(Frame*, const String& key, const String& value, bool& quotaException)
140     {
141         String oldValue;
142         if (auto newMap = m_storageMap->setItem(key, value, oldValue, quotaException))
143             m_storageMap = WTFMove(newMap);
144     }
145
146     void removeItem(Frame*, const String& key)
147     {
148         String oldValue;
149         if (auto newMap = m_storageMap->removeItem(key, oldValue))
150             m_storageMap = WTFMove(newMap);
151     }
152
153     void clear(Frame*)
154     {
155         if (!m_storageMap->length())
156             return;
157
158         m_storageMap = StorageMap::create(m_storageMap->quota());
159     }
160
161     bool contains(const String& key)
162     {
163         return m_storageMap->contains(key);
164     }
165
166     StorageType storageType() const
167     {
168         return StorageType::EphemeralLocal;
169     }
170
171     size_t memoryBytesUsedByCache()
172     {
173         return 0;
174     }
175
176     void incrementAccessCount() { }
177     void decrementAccessCount() { }
178     void closeDatabaseIfIdle() { }
179
180     const SecurityOriginData& securityOrigin() const
181     {
182         return m_securityOriginData;
183     }
184
185     SecurityOriginData m_securityOriginData;
186     RefPtr<StorageMap> m_storageMap;
187 };
188
189 RefPtr<StorageArea> StorageNamespaceImpl::ephemeralLocalStorageArea(const SecurityOriginData& securityOrigin)
190 {
191     auto& slot = m_ephemeralLocalStorageAreas.add(securityOrigin, nullptr).iterator->value;
192     if (!slot)
193         slot = StorageNamespaceImpl::EphemeralStorageArea::create(securityOrigin, m_quotaInBytes);
194
195     return slot.get();
196 }
197
198 RefPtr<StorageNamespace> StorageNamespaceImpl::copy(Page* newPage)
199 {
200     ASSERT(m_storageNamespaceID);
201
202     if (m_storageType == StorageType::Session)
203         return createSessionStorageNamespace(WebPage::fromCorePage(newPage)->pageID(), m_quotaInBytes);
204
205     ASSERT(m_storageType == StorageType::EphemeralLocal);
206     RefPtr<StorageNamespaceImpl> newNamespace = adoptRef(new StorageNamespaceImpl(m_storageType, m_storageNamespaceID, m_topLevelOrigin.get(), m_quotaInBytes));
207
208     for (auto& iter : m_ephemeralLocalStorageAreas)
209         newNamespace->m_ephemeralLocalStorageAreas.set(iter.key, iter.value->copy());
210
211     return newNamespace;
212 }
213
214 } // namespace WebKit