Initial refactoring of database functionality into the manager and server.
[WebKit-https.git] / Source / WebCore / Modules / webdatabase / DatabaseManager.cpp
1 /*
2  * Copyright (C) 2012 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 "DatabaseManager.h"
28
29 #if ENABLE(SQL_DATABASE)
30
31 #include "AbstractDatabase.h"
32 #include "Database.h"
33 #include "DatabaseCallback.h"
34 #include "DatabaseContext.h"
35 #include "DatabaseSync.h"
36 #include "InspectorDatabaseInstrumentation.h"
37 #include "Logging.h"
38 #include "ScriptExecutionContext.h"
39 #include "SecurityOrigin.h"
40
41 #if USE(PLATFORM_STRATEGIES)
42 #include "DatabaseStrategy.h"
43 #include "PlatformStrategies.h"
44 #else
45 #include "DBBackendServer.h"
46 #endif
47
48 namespace WebCore {
49
50 DatabaseManager& DatabaseManager::manager()
51 {
52     static DatabaseManager* dbManager = 0;
53     if (!dbManager)
54         dbManager = new DatabaseManager();
55
56     return *dbManager;
57 }
58
59 DatabaseManager::DatabaseManager()
60     : m_client(0)
61     , m_databaseIsAvailable(true)
62 {
63 #if USE(PLATFORM_STRATEGIES)
64     m_server = platformStrategies()->databaseStrategy()->getDatabaseServer();
65 #else
66     m_server = new DBBackend::Server;
67 #endif
68     ASSERT(m_server); // We should always have a server to work with.
69 }
70
71 void DatabaseManager::initialize(const String& databasePath)
72 {
73     m_server->initialize(databasePath);
74 }
75
76 void DatabaseManager::setClient(DatabaseManagerClient* client)
77 {
78     m_client = client;
79     m_server->setClient(client);
80 }
81
82 String DatabaseManager::databaseDirectoryPath() const
83 {
84     return m_server->databaseDirectoryPath();
85 }
86
87 void DatabaseManager::setDatabaseDirectoryPath(const String& path)
88 {
89     m_server->setDatabaseDirectoryPath(path);
90 }
91
92 bool DatabaseManager::isAvailable()
93 {
94     return m_databaseIsAvailable;
95 }
96
97 void DatabaseManager::setIsAvailable(bool available)
98 {
99     m_databaseIsAvailable = available;
100 }
101
102 class DatabaseCreationCallbackTask : public ScriptExecutionContext::Task {
103 public:
104     static PassOwnPtr<DatabaseCreationCallbackTask> create(PassRefPtr<Database> database, PassRefPtr<DatabaseCallback> creationCallback)
105     {
106         return adoptPtr(new DatabaseCreationCallbackTask(database, creationCallback));
107     }
108
109     virtual void performTask(ScriptExecutionContext*)
110     {
111         m_creationCallback->handleEvent(m_database.get());
112     }
113
114 private:
115     DatabaseCreationCallbackTask(PassRefPtr<Database> database, PassRefPtr<DatabaseCallback> callback)
116         : m_database(database)
117         , m_creationCallback(callback)
118     {
119     }
120
121     RefPtr<Database> m_database;
122     RefPtr<DatabaseCallback> m_creationCallback;
123 };
124
125 PassRefPtr<Database> DatabaseManager::openDatabase(ScriptExecutionContext* context,
126     const String& name, const String& expectedVersion, const String& displayName,
127     unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, ExceptionCode& e)
128 {
129     if (!canEstablishDatabase(context, name, displayName, estimatedSize)) {
130         LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.ascii().data(), context->securityOrigin()->toString().ascii().data());
131         return 0;
132     }
133
134     RefPtr<Database> database = adoptRef(new Database(context, name, expectedVersion, displayName, estimatedSize));
135
136     String errorMessage;
137     if (!database->openAndVerifyVersion(!creationCallback, e, errorMessage)) {
138         database->logErrorMessage(errorMessage);
139         DatabaseManager::manager().removeOpenDatabase(database.get());
140         return 0;
141     }
142
143     DatabaseManager::manager().setDatabaseDetails(context->securityOrigin(), name, displayName, estimatedSize);
144     DatabaseManager::manager().setHasOpenDatabases(context);
145
146     InspectorInstrumentation::didOpenDatabase(context, database, context->securityOrigin()->host(), name, expectedVersion);
147
148     if (database->isNew() && creationCallback.get()) {
149         LOG(StorageAPI, "Scheduling DatabaseCreationCallbackTask for database %p\n", database.get());
150         database->m_scriptExecutionContext->postTask(DatabaseCreationCallbackTask::create(database, creationCallback));
151     }
152
153     return database;
154 }
155
156 PassRefPtr<DatabaseSync> DatabaseManager::openDatabaseSync(ScriptExecutionContext* context,
157     const String& name, const String& expectedVersion, const String& displayName,
158     unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, ExceptionCode& ec)
159 {
160     ASSERT(context->isContextThread());
161
162     if (!canEstablishDatabase(context, name, displayName, estimatedSize)) {
163         LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.ascii().data(), context->securityOrigin()->toString().ascii().data());
164         return 0;
165     }
166
167     RefPtr<DatabaseSync> database = adoptRef(new DatabaseSync(context, name, expectedVersion, displayName, estimatedSize));
168
169     String errorMessage;
170     if (!database->performOpenAndVerify(!creationCallback, ec, errorMessage)) {
171         database->logErrorMessage(errorMessage);
172         DatabaseManager::manager().removeOpenDatabase(database.get());
173         return 0;
174     }
175
176     DatabaseManager::manager().setDatabaseDetails(context->securityOrigin(), name, displayName, estimatedSize);
177
178     if (database->isNew() && creationCallback.get()) {
179         LOG(StorageAPI, "Invoking the creation callback for database %p\n", database.get());
180         creationCallback->handleEvent(database.get());
181     }
182
183     return database;
184 }
185
186 bool DatabaseManager::hasOpenDatabases(ScriptExecutionContext* context)
187 {
188     return DatabaseContext::hasOpenDatabases(context);
189 }
190
191 void DatabaseManager::setHasOpenDatabases(ScriptExecutionContext* context)
192 {
193     DatabaseContext::from(context)->setHasOpenDatabases();
194 }
195
196 void DatabaseManager::stopDatabases(ScriptExecutionContext* context, DatabaseTaskSynchronizer* synchronizer)
197 {
198     DatabaseContext::stopDatabases(context, synchronizer);
199 }
200
201 String DatabaseManager::fullPathForDatabase(SecurityOrigin* origin, const String& name, bool createIfDoesNotExist)
202 {
203     return m_server->fullPathForDatabase(origin, name, createIfDoesNotExist);
204 }
205
206 #if !PLATFORM(CHROMIUM)
207 bool DatabaseManager::hasEntryForOrigin(SecurityOrigin* origin)
208 {
209     return m_server->hasEntryForOrigin(origin);
210 }
211
212 void DatabaseManager::origins(Vector<RefPtr<SecurityOrigin> >& result)
213 {
214     m_server->origins(result);
215 }
216
217 bool DatabaseManager::databaseNamesForOrigin(SecurityOrigin* origin, Vector<String>& result)
218 {
219     return m_server->databaseNamesForOrigin(origin, result);
220 }
221
222 DatabaseDetails DatabaseManager::detailsForNameAndOrigin(const String& name, SecurityOrigin* origin)
223 {
224     return m_server->detailsForNameAndOrigin(name, origin);
225 }
226
227 unsigned long long DatabaseManager::usageForOrigin(SecurityOrigin* origin)
228 {
229     return m_server->usageForOrigin(origin);
230 }
231
232 unsigned long long DatabaseManager::quotaForOrigin(SecurityOrigin* origin)
233 {
234     return m_server->quotaForOrigin(origin);
235 }
236
237 void DatabaseManager::setQuota(SecurityOrigin* origin, unsigned long long quotaSize)
238 {
239     m_server->setQuota(origin, quotaSize);
240 }
241
242 void DatabaseManager::deleteAllDatabases()
243 {
244     m_server->deleteAllDatabases();
245 }
246
247 bool DatabaseManager::deleteOrigin(SecurityOrigin* origin)
248 {
249     return m_server->deleteOrigin(origin);
250 }
251
252 bool DatabaseManager::deleteDatabase(SecurityOrigin* origin, const String& name)
253 {
254     return m_server->deleteDatabase(origin, name);
255 }
256
257 // From a secondary thread, must be thread safe with its data
258 void DatabaseManager::scheduleNotifyDatabaseChanged(SecurityOrigin* origin, const String& name)
259 {
260     m_server->scheduleNotifyDatabaseChanged(origin, name);
261 }
262
263 void DatabaseManager::databaseChanged(AbstractDatabase* database)
264 {
265     m_server->databaseChanged(database);
266 }
267
268 #else // PLATFORM(CHROMIUM)
269 void DatabaseManager::closeDatabasesImmediately(const String& originIdentifier, const String& name)
270 {
271     m_server->closeDatabasesImmediately(originIdentifier, name);
272 }
273 #endif // PLATFORM(CHROMIUM)
274
275 void DatabaseManager::interruptAllDatabasesForContext(const ScriptExecutionContext* context)
276 {
277     m_server->interruptAllDatabasesForContext(context);
278 }
279
280 bool DatabaseManager::canEstablishDatabase(ScriptExecutionContext* context, const String& name, const String& displayName, unsigned long estimatedSize)
281 {
282     return m_server->canEstablishDatabase(context, name, displayName, estimatedSize);
283 }
284
285 void DatabaseManager::addOpenDatabase(AbstractDatabase* database)
286 {
287     m_server->addOpenDatabase(database);
288 }
289
290 void DatabaseManager::removeOpenDatabase(AbstractDatabase* database)
291 {
292     m_server->removeOpenDatabase(database);
293 }
294
295 void DatabaseManager::setDatabaseDetails(SecurityOrigin* origin, const String& name, const String& displayName, unsigned long estimatedSize)
296 {
297     m_server->setDatabaseDetails(origin, name, displayName, estimatedSize);
298 }
299
300 unsigned long long DatabaseManager::getMaxSizeForDatabase(const AbstractDatabase* database)
301 {
302     return m_server->getMaxSizeForDatabase(database);
303 }
304
305 } // namespace WebCore
306
307 #endif // ENABLE(SQL_DATABASE)