Need a method to close all idle localstorage databases immediately.
[WebKit-https.git] / Source / WebCore / 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 "config.h"
27 #include "StorageNamespaceImpl.h"
28
29 #include "SecurityOriginHash.h"
30 #include "StorageAreaImpl.h"
31 #include "StorageMap.h"
32 #include "StorageSyncManager.h"
33 #include "StorageTracker.h"
34 #include <wtf/MainThread.h>
35 #include <wtf/StdLibExtras.h>
36 #include <wtf/text/StringHash.h>
37
38 namespace WebCore {
39
40 typedef HashMap<String, StorageNamespace*> LocalStorageNamespaceMap;
41
42 static LocalStorageNamespaceMap& localStorageNamespaceMap()
43 {
44     DEFINE_STATIC_LOCAL(LocalStorageNamespaceMap, localStorageNamespaceMap, ());
45     return localStorageNamespaceMap;
46 }
47
48 PassRefPtr<StorageNamespace> StorageNamespaceImpl::localStorageNamespace(const String& path, unsigned quota)
49 {
50     const String lookupPath = path.isNull() ? emptyString() : path;
51     LocalStorageNamespaceMap::iterator it = localStorageNamespaceMap().find(lookupPath);
52     if (it == localStorageNamespaceMap().end()) {
53         RefPtr<StorageNamespace> storageNamespace = adoptRef(new StorageNamespaceImpl(LocalStorage, lookupPath, quota));
54         localStorageNamespaceMap().set(lookupPath, storageNamespace.get());
55         return storageNamespace.release();
56     }
57
58     return it->value;
59 }
60
61 PassRefPtr<StorageNamespace> StorageNamespaceImpl::sessionStorageNamespace(unsigned quota)
62 {
63     return adoptRef(new StorageNamespaceImpl(SessionStorage, String(), quota));
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 PassRefPtr<StorageNamespace> StorageNamespaceImpl::copy()
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.release();
102 }
103
104 PassRefPtr<StorageArea> StorageNamespaceImpl::storageArea(PassRefPtr<SecurityOrigin> prpOrigin)
105 {
106     ASSERT(isMainThread());
107     ASSERT(!m_isShutdown);
108
109     RefPtr<SecurityOrigin> origin = prpOrigin;
110     RefPtr<StorageAreaImpl> storageArea;
111     if ((storageArea = m_storageAreaMap.get(origin)))
112         return storageArea.release();
113
114     storageArea = StorageAreaImpl::create(m_storageType, origin, m_syncManager, m_quota);
115     m_storageAreaMap.set(origin.release(), storageArea);
116     return storageArea.release();
117 }
118
119 void StorageNamespaceImpl::close()
120 {
121     ASSERT(isMainThread());
122
123     if (m_isShutdown)
124         return;
125
126     // If we're session storage, we shouldn't need to do any work here.
127     if (m_storageType == SessionStorage) {
128         ASSERT(!m_syncManager);
129         return;
130     }
131
132     StorageAreaMap::iterator end = m_storageAreaMap.end();
133     for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
134         it->value->close();
135
136     if (m_syncManager)
137         m_syncManager->close();
138
139     m_isShutdown = true;
140 }
141
142 void StorageNamespaceImpl::clearOriginForDeletion(SecurityOrigin* origin)
143 {
144     ASSERT(isMainThread());
145
146     RefPtr<StorageAreaImpl> storageArea = m_storageAreaMap.get(origin);
147     if (storageArea)
148         storageArea->clearForOriginDeletion();
149 }
150
151 void StorageNamespaceImpl::clearAllOriginsForDeletion()
152 {
153     ASSERT(isMainThread());
154
155     StorageAreaMap::iterator end = m_storageAreaMap.end();
156     for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
157         it->value->clearForOriginDeletion();
158 }
159     
160 void StorageNamespaceImpl::sync()
161 {
162     ASSERT(isMainThread());
163     StorageAreaMap::iterator end = m_storageAreaMap.end();
164     for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
165         it->value->sync();
166 }
167
168 void StorageNamespaceImpl::closeIdleLocalStorageDatabases()
169 {
170     ASSERT(isMainThread());
171     StorageAreaMap::iterator end = m_storageAreaMap.end();
172     for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
173         it->value->closeDatabaseIfIdle();
174 }
175
176 } // namespace WebCore