Clean up Storage code
[WebKit-https.git] / Source / WebKit / Storage / StorageNamespaceImpl.cpp
1 /*
2  * Copyright (C) 2008 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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "StorageNamespaceImpl.h"
27
28 #include "StorageAreaImpl.h"
29 #include "StorageSyncManager.h"
30 #include "StorageTracker.h"
31 #include <WebCore/StorageMap.h>
32 #include <wtf/MainThread.h>
33 #include <wtf/NeverDestroyed.h>
34 #include <wtf/text/StringHash.h>
35
36 using namespace WebCore;
37
38 namespace WebKit {
39
40 static HashMap<String, StorageNamespaceImpl*>& localStorageNamespaceMap()
41 {
42     static NeverDestroyed<HashMap<String, StorageNamespaceImpl*>> localStorageNamespaceMap;
43
44     return localStorageNamespaceMap;
45 }
46
47 Ref<StorageNamespaceImpl> StorageNamespaceImpl::createSessionStorageNamespace(unsigned quota)
48 {
49     return adoptRef(*new StorageNamespaceImpl(SessionStorage, String(), quota));
50 }
51
52 Ref<StorageNamespaceImpl> StorageNamespaceImpl::getOrCreateLocalStorageNamespace(const String& databasePath, unsigned quota)
53 {
54     ASSERT(!databasePath.isNull());
55
56     auto& slot = localStorageNamespaceMap().add(databasePath, nullptr).iterator->value;
57     if (slot)
58         return *slot;
59
60     Ref<StorageNamespaceImpl> storageNamespace = adoptRef(*new StorageNamespaceImpl(LocalStorage, databasePath, quota));
61     slot = storageNamespace.ptr();
62
63     return storageNamespace;
64 }
65
66 StorageNamespaceImpl::StorageNamespaceImpl(StorageType storageType, const String& path, unsigned quota)
67     : m_storageType(storageType)
68     , m_path(path.isolatedCopy())
69     , m_syncManager(0)
70     , m_quota(quota)
71     , m_isShutdown(false)
72 {
73     if (m_storageType == LocalStorage && !m_path.isEmpty())
74         m_syncManager = StorageSyncManager::create(m_path);
75 }
76
77 StorageNamespaceImpl::~StorageNamespaceImpl()
78 {
79     ASSERT(isMainThread());
80
81     if (m_storageType == LocalStorage) {
82         ASSERT(localStorageNamespaceMap().get(m_path) == this);
83         localStorageNamespaceMap().remove(m_path);
84     }
85
86     if (!m_isShutdown)
87         close();
88 }
89
90 RefPtr<StorageNamespace> StorageNamespaceImpl::copy(Page*)
91 {
92     ASSERT(isMainThread());
93     ASSERT(!m_isShutdown);
94     ASSERT(m_storageType == SessionStorage);
95
96     RefPtr<StorageNamespaceImpl> newNamespace = adoptRef(new StorageNamespaceImpl(m_storageType, m_path, m_quota));
97
98     StorageAreaMap::iterator end = m_storageAreaMap.end();
99     for (StorageAreaMap::iterator i = m_storageAreaMap.begin(); i != end; ++i)
100         newNamespace->m_storageAreaMap.set(i->key, i->value->copy());
101     return newNamespace;
102 }
103
104 RefPtr<StorageArea> StorageNamespaceImpl::storageArea(RefPtr<SecurityOrigin>&& origin)
105 {
106     ASSERT(isMainThread());
107     ASSERT(!m_isShutdown);
108
109     RefPtr<StorageAreaImpl> storageArea;
110     if ((storageArea = m_storageAreaMap.get(origin.get())))
111         return storageArea;
112
113     storageArea = StorageAreaImpl::create(m_storageType, origin.get(), m_syncManager.get(), m_quota);
114     m_storageAreaMap.set(origin, storageArea.get());
115     return storageArea;
116 }
117
118 void StorageNamespaceImpl::close()
119 {
120     ASSERT(isMainThread());
121
122     if (m_isShutdown)
123         return;
124
125     // If we're session storage, we shouldn't need to do any work here.
126     if (m_storageType == SessionStorage) {
127         ASSERT(!m_syncManager);
128         return;
129     }
130
131     StorageAreaMap::iterator end = m_storageAreaMap.end();
132     for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
133         it->value->close();
134
135     if (m_syncManager)
136         m_syncManager->close();
137
138     m_isShutdown = true;
139 }
140
141 void StorageNamespaceImpl::clearOriginForDeletion(SecurityOrigin* origin)
142 {
143     ASSERT(isMainThread());
144
145     RefPtr<StorageAreaImpl> storageArea = m_storageAreaMap.get(origin);
146     if (storageArea)
147         storageArea->clearForOriginDeletion();
148 }
149
150 void StorageNamespaceImpl::clearAllOriginsForDeletion()
151 {
152     ASSERT(isMainThread());
153
154     StorageAreaMap::iterator end = m_storageAreaMap.end();
155     for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
156         it->value->clearForOriginDeletion();
157 }
158     
159 void StorageNamespaceImpl::sync()
160 {
161     ASSERT(isMainThread());
162     StorageAreaMap::iterator end = m_storageAreaMap.end();
163     for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
164         it->value->sync();
165 }
166
167 void StorageNamespaceImpl::closeIdleLocalStorageDatabases()
168 {
169     ASSERT(isMainThread());
170     StorageAreaMap::iterator end = m_storageAreaMap.end();
171     for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
172         it->value->closeDatabaseIfIdle();
173 }
174
175 } // namespace WebCore