OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011 Google 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 are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 #include "config.h" | |
32 #include "modules/webdatabase/DatabaseTracker.h" | |
33 | |
34 #include "core/dom/ScriptExecutionContext.h" | |
35 #include "core/platform/sql/SQLiteFileSystem.h" | |
36 #include "modules/webdatabase/DatabaseBackendBase.h" | |
37 #include "modules/webdatabase/DatabaseBackendContext.h" | |
38 #include "modules/webdatabase/chromium/DatabaseObserver.h" | |
39 #include "modules/webdatabase/chromium/QuotaTracker.h" | |
40 #include "weborigin/DatabaseIdentifier.h" | |
41 #include "weborigin/SecurityOrigin.h" | |
42 #include "weborigin/SecurityOriginHash.h" | |
43 #include "wtf/Assertions.h" | |
44 #include "wtf/StdLibExtras.h" | |
45 #include "wtf/text/WTFString.h" | |
46 | |
47 namespace WebCore { | |
48 | |
49 DatabaseTracker& DatabaseTracker::tracker() | |
50 { | |
51 AtomicallyInitializedStatic(DatabaseTracker&, tracker = *new DatabaseTracker
()); | |
52 return tracker; | |
53 } | |
54 | |
55 DatabaseTracker::DatabaseTracker() | |
56 { | |
57 SQLiteFileSystem::registerSQLiteVFS(); | |
58 } | |
59 | |
60 bool DatabaseTracker::canEstablishDatabase(DatabaseBackendContext* databaseConte
xt, const String& name, const String& displayName, unsigned long estimatedSize,
DatabaseError& error) | |
61 { | |
62 ScriptExecutionContext* scriptExecutionContext = databaseContext->scriptExec
utionContext(); | |
63 bool success = DatabaseObserver::canEstablishDatabase(scriptExecutionContext
, name, displayName, estimatedSize); | |
64 if (!success) | |
65 error = DatabaseError::GenericSecurityError; | |
66 return success; | |
67 } | |
68 | |
69 String DatabaseTracker::fullPathForDatabase(SecurityOrigin* origin, const String
& name, bool) | |
70 { | |
71 return createDatabaseIdentifierFromSecurityOrigin(origin) + "/" + name + "#"
; | |
72 } | |
73 | |
74 void DatabaseTracker::addOpenDatabase(DatabaseBackendBase* database) | |
75 { | |
76 MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); | |
77 if (!m_openDatabaseMap) | |
78 m_openDatabaseMap = adoptPtr(new DatabaseOriginMap); | |
79 | |
80 String originIdentifier = createDatabaseIdentifierFromSecurityOrigin(databas
e->securityOrigin()); | |
81 DatabaseNameMap* nameMap = m_openDatabaseMap->get(originIdentifier); | |
82 if (!nameMap) { | |
83 nameMap = new DatabaseNameMap(); | |
84 m_openDatabaseMap->set(originIdentifier, nameMap); | |
85 } | |
86 | |
87 String name(database->stringIdentifier()); | |
88 DatabaseSet* databaseSet = nameMap->get(name); | |
89 if (!databaseSet) { | |
90 databaseSet = new DatabaseSet(); | |
91 nameMap->set(name, databaseSet); | |
92 } | |
93 | |
94 databaseSet->add(database); | |
95 } | |
96 | |
97 class NotifyDatabaseObserverOnCloseTask : public ScriptExecutionContext::Task { | |
98 public: | |
99 static PassOwnPtr<NotifyDatabaseObserverOnCloseTask> create(PassRefPtr<Datab
aseBackendBase> database) | |
100 { | |
101 return adoptPtr(new NotifyDatabaseObserverOnCloseTask(database)); | |
102 } | |
103 | |
104 virtual void performTask(ScriptExecutionContext* context) | |
105 { | |
106 DatabaseObserver::databaseClosed(m_database.get()); | |
107 } | |
108 | |
109 virtual bool isCleanupTask() const | |
110 { | |
111 return true; | |
112 } | |
113 | |
114 private: | |
115 NotifyDatabaseObserverOnCloseTask(PassRefPtr<DatabaseBackendBase> database) | |
116 : m_database(database) | |
117 { | |
118 } | |
119 | |
120 RefPtr<DatabaseBackendBase> m_database; | |
121 }; | |
122 | |
123 void DatabaseTracker::removeOpenDatabase(DatabaseBackendBase* database) | |
124 { | |
125 String originIdentifier = createDatabaseIdentifierFromSecurityOrigin(databas
e->securityOrigin()); | |
126 MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); | |
127 ASSERT(m_openDatabaseMap); | |
128 DatabaseNameMap* nameMap = m_openDatabaseMap->get(originIdentifier); | |
129 if (!nameMap) | |
130 return; | |
131 | |
132 String name(database->stringIdentifier()); | |
133 DatabaseSet* databaseSet = nameMap->get(name); | |
134 if (!databaseSet) | |
135 return; | |
136 | |
137 DatabaseSet::iterator found = databaseSet->find(database); | |
138 if (found == databaseSet->end()) | |
139 return; | |
140 | |
141 databaseSet->remove(found); | |
142 if (databaseSet->isEmpty()) { | |
143 nameMap->remove(name); | |
144 delete databaseSet; | |
145 if (nameMap->isEmpty()) { | |
146 m_openDatabaseMap->remove(originIdentifier); | |
147 delete nameMap; | |
148 } | |
149 } | |
150 | |
151 ScriptExecutionContext* scriptExecutionContext = database->databaseContext()
->scriptExecutionContext(); | |
152 if (!scriptExecutionContext->isContextThread()) | |
153 scriptExecutionContext->postTask(NotifyDatabaseObserverOnCloseTask::crea
te(database)); | |
154 else | |
155 DatabaseObserver::databaseClosed(database); | |
156 } | |
157 | |
158 void DatabaseTracker::prepareToOpenDatabase(DatabaseBackendBase* database) | |
159 { | |
160 ASSERT(database->databaseContext()->scriptExecutionContext()->isContextThrea
d()); | |
161 DatabaseObserver::databaseOpened(database); | |
162 } | |
163 | |
164 void DatabaseTracker::failedToOpenDatabase(DatabaseBackendBase* database) | |
165 { | |
166 ScriptExecutionContext* scriptExecutionContext = database->databaseContext()
->scriptExecutionContext(); | |
167 if (!scriptExecutionContext->isContextThread()) | |
168 scriptExecutionContext->postTask(NotifyDatabaseObserverOnCloseTask::crea
te(database)); | |
169 else | |
170 DatabaseObserver::databaseClosed(database); | |
171 } | |
172 | |
173 unsigned long long DatabaseTracker::getMaxSizeForDatabase(const DatabaseBackendB
ase* database) | |
174 { | |
175 unsigned long long spaceAvailable = 0; | |
176 unsigned long long databaseSize = 0; | |
177 QuotaTracker::instance().getDatabaseSizeAndSpaceAvailableToOrigin( | |
178 createDatabaseIdentifierFromSecurityOrigin(database->securityOrigin()), | |
179 database->stringIdentifier(), &databaseSize, &spaceAvailable); | |
180 return databaseSize + spaceAvailable; | |
181 } | |
182 | |
183 void DatabaseTracker::interruptAllDatabasesForContext(const DatabaseBackendConte
xt* context) | |
184 { | |
185 MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); | |
186 | |
187 if (!m_openDatabaseMap) | |
188 return; | |
189 | |
190 DatabaseNameMap* nameMap = m_openDatabaseMap->get(createDatabaseIdentifierFr
omSecurityOrigin(context->securityOrigin())); | |
191 if (!nameMap) | |
192 return; | |
193 | |
194 DatabaseNameMap::const_iterator dbNameMapEndIt = nameMap->end(); | |
195 for (DatabaseNameMap::const_iterator dbNameMapIt = nameMap->begin(); dbNameM
apIt != dbNameMapEndIt; ++dbNameMapIt) { | |
196 DatabaseSet* databaseSet = dbNameMapIt->value; | |
197 DatabaseSet::const_iterator end = databaseSet->end(); | |
198 for (DatabaseSet::const_iterator it = databaseSet->begin(); it != end; +
+it) { | |
199 if ((*it)->databaseContext() == context) | |
200 (*it)->interrupt(); | |
201 } | |
202 } | |
203 } | |
204 | |
205 class DatabaseTracker::CloseOneDatabaseImmediatelyTask : public ScriptExecutionC
ontext::Task { | |
206 public: | |
207 static PassOwnPtr<CloseOneDatabaseImmediatelyTask> create(const String& orig
inIdentifier, const String& name, DatabaseBackendBase* database) | |
208 { | |
209 return adoptPtr(new CloseOneDatabaseImmediatelyTask(originIdentifier, na
me, database)); | |
210 } | |
211 | |
212 virtual void performTask(ScriptExecutionContext* context) | |
213 { | |
214 DatabaseTracker::tracker().closeOneDatabaseImmediately(m_originIdentifie
r, m_name, m_database); | |
215 } | |
216 | |
217 private: | |
218 CloseOneDatabaseImmediatelyTask(const String& originIdentifier, const String
& name, DatabaseBackendBase* database) | |
219 : m_originIdentifier(originIdentifier.isolatedCopy()) | |
220 , m_name(name.isolatedCopy()) | |
221 , m_database(database) | |
222 { | |
223 } | |
224 | |
225 String m_originIdentifier; | |
226 String m_name; | |
227 DatabaseBackendBase* m_database; // Intentionally a raw pointer. | |
228 }; | |
229 | |
230 void DatabaseTracker::closeDatabasesImmediately(const String& originIdentifier,
const String& name) { | |
231 MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); | |
232 if (!m_openDatabaseMap) | |
233 return; | |
234 | |
235 DatabaseNameMap* nameMap = m_openDatabaseMap->get(originIdentifier); | |
236 if (!nameMap) | |
237 return; | |
238 | |
239 DatabaseSet* databaseSet = nameMap->get(name); | |
240 if (!databaseSet) | |
241 return; | |
242 | |
243 // We have to call closeImmediately() on the context thread and we cannot sa
fely add a reference to | |
244 // the database in our collection when not on the context thread (which is a
lways the case given | |
245 // current usage). | |
246 for (DatabaseSet::iterator it = databaseSet->begin(); it != databaseSet->end
(); ++it) | |
247 (*it)->databaseContext()->scriptExecutionContext()->postTask(CloseOneDat
abaseImmediatelyTask::create(originIdentifier, name, *it)); | |
248 } | |
249 | |
250 void DatabaseTracker::closeOneDatabaseImmediately(const String& originIdentifier
, const String& name, DatabaseBackendBase* database) | |
251 { | |
252 // First we have to confirm the 'database' is still in our collection. | |
253 { | |
254 MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); | |
255 if (!m_openDatabaseMap) | |
256 return; | |
257 | |
258 DatabaseNameMap* nameMap = m_openDatabaseMap->get(originIdentifier); | |
259 if (!nameMap) | |
260 return; | |
261 | |
262 DatabaseSet* databaseSet = nameMap->get(name); | |
263 if (!databaseSet) | |
264 return; | |
265 | |
266 DatabaseSet::iterator found = databaseSet->find(database); | |
267 if (found == databaseSet->end()) | |
268 return; | |
269 } | |
270 | |
271 // And we have to call closeImmediately() without our collection lock being
held. | |
272 database->closeImmediately(); | |
273 } | |
274 | |
275 } | |
OLD | NEW |