Changeset 142030 in webkit
- Timestamp:
- Feb 6, 2013 1:51:58 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r142029 r142030 1 2013-02-06 Mark Lam <mark.lam@apple.com> 2 3 Split openDatabase() between front and back end work. 4 https://bugs.webkit.org/show_bug.cgi?id=107475. 5 6 Reviewed by Anders Carlsson. 7 8 The main work of splitting DatabaseManager::openDatabase() is in 9 refactoring how DatabaseTracker::canEstablishDatabase() works. It used 10 to check for adequate space quota, and if the check fails, it would call 11 back into the client from inside canEstablishDatabase(). The call back 12 allows the client to update the quota (if appropriate). Thereafter, 13 canEstablishDatabase() will retry its quota check. 14 15 In a webkit2 world, we'll want to minimize the traffic between the 16 client (script side) and the server (sqlite db side), and ideally, we 17 don't want the server to call back to the client. Note: the 18 DatabaseTracker belongs on the server side. 19 20 To achieve this, we split canEstablishDatabase() into 2 parts: the 21 checks before the call back to the client, and the checks after. 22 The first part will retain the name canEstablishDatabase(), and the 23 second part will be named retryCanEstablishDatabase(). 24 We also added a DatabaseServer::openDatabase() function that can be 25 called with a retry flag. 26 27 The client side DatabaseManager::openDatabase() will call 28 DatabaseServer::openDatabase(), which then calls canEstablishDatabase() 29 to do its quota check. If there is enough quota, 30 DatabaseServer::openDatabase() will proceed to open the backend database 31 without return to the client first. The opened database will be returned 32 to the client. 33 34 If DatabaseServer::openDatabase() finds inadequate quota the first time, 35 it will return with a DatabaseSizeExceededQuota error. The DatabaseManager 36 (on the client side) will check for this error and call back to its client 37 for an opportunity to increase the quota. Thereafter, the DatabaseManager 38 will call DatabaseServer::openDatabase() again. This time, 39 DatabaseServer::openDatabase() will call retryCanEstablishDatabase() to 40 check the quota, and then open the backend database if there is enough 41 quota. 42 43 No new tests. 44 45 * Modules/webdatabase/AbstractDatabaseServer.h: 46 * Modules/webdatabase/DOMWindowWebDatabase.cpp: 47 (WebCore::DOMWindowWebDatabase::openDatabase): 48 * Modules/webdatabase/Database.cpp: 49 (WebCore::Database::create): 50 * Modules/webdatabase/Database.h: 51 (Database): 52 * Modules/webdatabase/DatabaseBackend.cpp: 53 (WebCore::DatabaseBackend::performOpenAndVerify): 54 * Modules/webdatabase/DatabaseBackend.h: 55 (DatabaseBackend): 56 * Modules/webdatabase/DatabaseBackendAsync.cpp: 57 (WebCore::DatabaseBackendAsync::openAndVerifyVersion): 58 (WebCore::DatabaseBackendAsync::performOpenAndVerify): 59 * Modules/webdatabase/DatabaseBackendAsync.h: 60 (DatabaseBackendAsync): 61 * Modules/webdatabase/DatabaseBackendSync.cpp: 62 (WebCore::DatabaseBackendSync::openAndVerifyVersion): 63 * Modules/webdatabase/DatabaseBackendSync.h: 64 (DatabaseBackendSync): 65 * Modules/webdatabase/DatabaseError.h: 66 (WebCore::ENUM_CLASS): 67 * Modules/webdatabase/DatabaseManager.cpp: 68 (WebCore::DatabaseManager::exceptionCodeForDatabaseError): 69 (WebCore::DatabaseManager::openDatabaseBackend): 70 (WebCore::DatabaseManager::openDatabase): 71 (WebCore::DatabaseManager::openDatabaseSync): 72 * Modules/webdatabase/DatabaseManager.h: 73 (DatabaseManager): 74 * Modules/webdatabase/DatabaseServer.cpp: 75 (WebCore::DatabaseServer::openDatabase): 76 (WebCore::DatabaseServer::createDatabase): 77 * Modules/webdatabase/DatabaseServer.h: 78 * Modules/webdatabase/DatabaseSync.cpp: 79 (WebCore::DatabaseSync::create): 80 * Modules/webdatabase/DatabaseSync.h: 81 (DatabaseSync): 82 * Modules/webdatabase/DatabaseTracker.cpp: 83 (WebCore::DatabaseTracker::hasAdequateQuotaForOrigin): 84 (WebCore::DatabaseTracker::canEstablishDatabase): 85 (WebCore::DatabaseTracker::retryCanEstablishDatabase): 86 * Modules/webdatabase/DatabaseTracker.h: 87 (DatabaseTracker): 88 * Modules/webdatabase/WorkerContextWebDatabase.cpp: 89 (WebCore::WorkerContextWebDatabase::openDatabase): 90 (WebCore::WorkerContextWebDatabase::openDatabaseSync): 91 * Modules/webdatabase/chromium/DatabaseTrackerChromium.cpp: 92 (WebCore::DatabaseTracker::canEstablishDatabase): 93 (WebCore::DatabaseTracker::retryCanEstablishDatabase): 94 1 95 2013-02-06 Tony Gentilcore <tonyg@chromium.org> 2 96 -
trunk/Source/WebCore/Modules/webdatabase/AbstractDatabaseServer.h
r141928 r142030 29 29 #if ENABLE(SQL_DATABASE) 30 30 31 #include "DatabaseBasicTypes.h" 31 32 #include "DatabaseDetails.h" 33 #include "DatabaseError.h" 32 34 #include <wtf/RefPtr.h> 33 35 #include <wtf/Vector.h> … … 37 39 38 40 class DatabaseBackend; 39 class DatabaseBackendAsync;40 41 class DatabaseBackendContext; 41 class DatabaseBackendSync;42 42 class DatabaseManagerClient; 43 43 class SecurityOrigin; … … 52 52 53 53 virtual String fullPathForDatabase(SecurityOrigin*, const String& name, bool createIfDoesNotExist = true) = 0; 54 55 enum OpenAttempt { 56 FirstTryToOpenDatabase, 57 RetryOpenDatabase 58 }; 59 60 virtual PassRefPtr<DatabaseBackend> openDatabase(RefPtr<DatabaseBackendContext>&, DatabaseType, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError&, String& errorMessage, OpenAttempt = FirstTryToOpenDatabase) = 0; 54 61 55 62 #if !PLATFORM(CHROMIUM) … … 78 85 virtual void interruptAllDatabasesForContext(const DatabaseBackendContext*) = 0; 79 86 80 virtual bool canEstablishDatabase(DatabaseBackendContext*, const String& name, const String& displayName, unsigned long estimatedSize) = 0;81 82 virtual void setDatabaseDetails(SecurityOrigin*, const String& name, const String& displayName, unsigned long estimatedSize) = 0;83 87 virtual unsigned long long getMaxSizeForDatabase(const DatabaseBackend*) = 0; 84 88 -
trunk/Source/WebCore/Modules/webdatabase/DOMWindowWebDatabase.cpp
r141668 r142030 49 49 DatabaseManager& dbManager = DatabaseManager::manager(); 50 50 DatabaseError error = DatabaseError::None; 51 if (dbManager.isAvailable() && window->document()->securityOrigin()->canAccessDatabase(window->document()->topOrigin())) 51 if (dbManager.isAvailable() && window->document()->securityOrigin()->canAccessDatabase(window->document()->topOrigin())) { 52 52 database = dbManager.openDatabase(window->document(), name, version, displayName, estimatedSize, creationCallback, error); 53 54 ASSERT(error == DatabaseError::None || error == DatabaseError::CannotOpenDatabase); 55 if (error == DatabaseError::CannotOpenDatabase) 56 ec = INVALID_STATE_ERR; 57 if (!database && !ec) 53 ASSERT(database || error != DatabaseError::None); 54 ec = DatabaseManager::exceptionCodeForDatabaseError(error); 55 } else 58 56 ec = SECURITY_ERR; 59 57 -
trunk/Source/WebCore/Modules/webdatabase/Database.cpp
r141956 r142030 67 67 namespace WebCore { 68 68 69 PassRefPtr<Database> Database::create(ScriptExecutionContext*, PassRefPtr<DatabaseBackend> backend) 70 { 71 return static_cast<Database*>(backend.get()); 72 } 73 69 74 Database::Database(PassRefPtr<DatabaseBackendContext> databaseContext, 70 75 const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize) … … 134 139 } 135 140 136 bool Database::openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage)137 {138 DatabaseTaskSynchronizer synchronizer;139 if (!databaseContext()->databaseThread() || databaseContext()->databaseThread()->terminationRequested(&synchronizer))140 return false;141 142 #if PLATFORM(CHROMIUM)143 DatabaseTracker::tracker().prepareToOpenDatabase(this);144 #endif145 bool success = false;146 OwnPtr<DatabaseOpenTask> task = DatabaseOpenTask::create(this, setVersionInNewDatabase, &synchronizer, error, errorMessage, success);147 databaseContext()->databaseThread()->scheduleImmediateTask(task.release());148 synchronizer.waitForTaskCompletion();149 150 return success;151 }152 153 141 void Database::markAsDeletedAndClose() 154 142 { … … 203 191 { 204 192 return DatabaseManager::manager().getMaxSizeForDatabase(this); 205 }206 207 bool Database::performOpenAndVerify(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage)208 {209 if (DatabaseBackend::performOpenAndVerify(setVersionInNewDatabase, error, errorMessage)) {210 if (databaseContext()->databaseThread())211 databaseContext()->databaseThread()->recordDatabaseOpen(this);212 213 return true;214 }215 216 return false;217 193 } 218 194 -
trunk/Source/WebCore/Modules/webdatabase/Database.h
r141956 r142030 89 89 const String& expectedVersion, const String& displayName, unsigned long estimatedSize); 90 90 PassRefPtr<DatabaseBackendAsync> backend(); 91 static PassRefPtr<Database> create(ScriptExecutionContext*, PassRefPtr<DatabaseBackend>); 91 92 92 93 void runTransaction(PassRefPtr<SQLTransactionCallback>, PassRefPtr<SQLTransactionErrorCallback>, 93 94 PassRefPtr<VoidCallback> successCallback, PassRefPtr<SQLTransactionWrapper>, bool readOnly); 94 95 bool openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage);96 virtual bool performOpenAndVerify(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage);97 95 98 96 void inProgressTransactionCompleted(); … … 111 109 112 110 friend class DatabaseManager; 111 friend class DatabaseServer; // FIXME: remove this when the backend has been split out. 113 112 friend class DatabaseBackendAsync; // FIXME: remove this when the backend has been split out. 114 113 }; -
trunk/Source/WebCore/Modules/webdatabase/DatabaseBackend.cpp
r141950 r142030 315 315 ASSERT(errorMessage.isEmpty()); 316 316 ASSERT(error == DatabaseError::None); // Better not have any errors already. 317 error = DatabaseError:: CannotOpenDatabase; // Presumed failure. We'll clear it if we succeed below.317 error = DatabaseError::InvalidDatabaseState; // Presumed failure. We'll clear it if we succeed below. 318 318 319 319 const int maxSqliteBusyWaitTime = 30000; -
trunk/Source/WebCore/Modules/webdatabase/DatabaseBackend.h
r141956 r142030 104 104 void closeDatabase(); 105 105 106 virtual bool openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage) = 0; 106 107 virtual bool performOpenAndVerify(bool shouldSetVersionInNewDatabase, DatabaseError&, String& errorMessage); 107 108 -
trunk/Source/WebCore/Modules/webdatabase/DatabaseBackendAsync.cpp
r141950 r142030 30 30 31 31 #include "DatabaseBackendContext.h" 32 #include "DatabaseTask.h" 33 #include "DatabaseThread.h" 34 #include "DatabaseTracker.h" 32 35 33 36 namespace WebCore { … … 38 41 } 39 42 43 bool DatabaseBackendAsync::openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage) 44 { 45 DatabaseTaskSynchronizer synchronizer; 46 if (!databaseContext()->databaseThread() || databaseContext()->databaseThread()->terminationRequested(&synchronizer)) 47 return false; 48 49 #if PLATFORM(CHROMIUM) 50 DatabaseTracker::tracker().prepareToOpenDatabase(this); 51 #endif 52 bool success = false; 53 OwnPtr<DatabaseOpenTask> task = DatabaseOpenTask::create(this, setVersionInNewDatabase, &synchronizer, error, errorMessage, success); 54 databaseContext()->databaseThread()->scheduleImmediateTask(task.release()); 55 synchronizer.waitForTaskCompletion(); 56 57 return success; 58 } 59 60 bool DatabaseBackendAsync::performOpenAndVerify(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage) 61 { 62 if (DatabaseBackend::performOpenAndVerify(setVersionInNewDatabase, error, errorMessage)) { 63 if (databaseContext()->databaseThread()) 64 databaseContext()->databaseThread()->recordDatabaseOpen(this); 65 66 return true; 67 } 68 69 return false; 70 } 40 71 41 72 } // namespace WebCore -
trunk/Source/WebCore/Modules/webdatabase/DatabaseBackendAsync.h
r141956 r142030 44 44 45 45 class DatabaseBackendAsync : public DatabaseBackend { 46 p rotected:46 public: 47 47 DatabaseBackendAsync(PassRefPtr<DatabaseBackendContext>, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize); 48 48 49 friend class DatabaseManager; // FIXME: remove this once we have isolated this to the backend.50 friend class DatabaseServer;49 virtual bool openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); 50 virtual bool performOpenAndVerify(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); 51 51 52 52 private: -
trunk/Source/WebCore/Modules/webdatabase/DatabaseBackendSync.cpp
r141950 r142030 30 30 31 31 #include "DatabaseBackendContext.h" 32 #include "DatabaseTracker.h" 32 33 33 34 namespace WebCore { … … 52 53 } 53 54 55 bool DatabaseBackendSync::openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage) 56 { 57 #if PLATFORM(CHROMIUM) 58 DatabaseTracker::tracker().prepareToOpenDatabase(this); 59 #endif 60 return performOpenAndVerify(setVersionInNewDatabase, error, errorMessage); 61 } 62 54 63 } // namespace WebCore 55 64 -
trunk/Source/WebCore/Modules/webdatabase/DatabaseBackendSync.h
r141928 r142030 46 46 virtual ~DatabaseBackendSync(); 47 47 48 virtual bool openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); 49 48 50 protected: 49 51 DatabaseBackendSync(PassRefPtr<DatabaseBackendContext>, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize); 50 52 51 friend class DatabaseManager; // FIXME: remove this once we have isolated this to the backend.52 53 friend class DatabaseServer; 53 54 }; -
trunk/Source/WebCore/Modules/webdatabase/DatabaseError.h
r141950 r142030 35 35 ENUM_CLASS(DatabaseError) { 36 36 None = 0, 37 CannotOpenDatabase,38 37 DatabaseIsBeingDeleted, 39 38 DatabaseSizeExceededQuota, 40 DatabaseSizeOverflowed 39 DatabaseSizeOverflowed, 40 GenericSecurityError, 41 InvalidDatabaseState 41 42 } ENUM_CLASS_END(DatabaseError); 42 43 -
trunk/Source/WebCore/Modules/webdatabase/DatabaseManager.cpp
r141928 r142030 29 29 #if ENABLE(SQL_DATABASE) 30 30 31 #include "AbstractDatabaseServer.h" 31 32 #include "Database.h" 32 33 #include "DatabaseBackend.h" … … 201 202 #endif 202 203 204 ExceptionCode DatabaseManager::exceptionCodeForDatabaseError(DatabaseError error) 205 { 206 switch (error) { 207 case DatabaseError::None: 208 return 0; 209 case DatabaseError::DatabaseIsBeingDeleted: 210 case DatabaseError::DatabaseSizeExceededQuota: 211 case DatabaseError::DatabaseSizeOverflowed: 212 case DatabaseError::GenericSecurityError: 213 return SECURITY_ERR; 214 case DatabaseError::InvalidDatabaseState: 215 return INVALID_STATE_ERR; 216 } 217 ASSERT_NOT_REACHED(); 218 return 0; // Make some older compilers happy. 219 } 220 221 static void logOpenDatabaseError(ScriptExecutionContext* context, const String& name) 222 { 223 LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.ascii().data(), 224 context->securityOrigin()->toString().ascii().data()); 225 } 226 227 PassRefPtr<DatabaseBackend> DatabaseManager::openDatabaseBackend(ScriptExecutionContext* context, 228 DatabaseType type, const String& name, const String& expectedVersion, const String& displayName, 229 unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage) 230 { 231 ASSERT(error == DatabaseError::None); 232 233 RefPtr<DatabaseContext> databaseContext = databaseContextFor(context); 234 RefPtr<DatabaseBackendContext> backendContext = databaseContext->backend(); 235 236 RefPtr<DatabaseBackend> backend = m_server->openDatabase(backendContext, type, name, expectedVersion, 237 displayName, estimatedSize, setVersionInNewDatabase, error, errorMessage); 238 239 if (!backend) { 240 ASSERT(error != DatabaseError::None); 241 242 switch (error) { 243 case DatabaseError::DatabaseIsBeingDeleted: 244 case DatabaseError::DatabaseSizeOverflowed: 245 case DatabaseError::GenericSecurityError: 246 logOpenDatabaseError(context, name); 247 return 0; 248 249 case DatabaseError::InvalidDatabaseState: 250 logErrorMessage(context, errorMessage); 251 return 0; 252 253 case DatabaseError::DatabaseSizeExceededQuota: 254 // Notify the client that we've exceeded the database quota. 255 // The client may want to increase the quota, and we'll give it 256 // one more try after if that is the case. 257 databaseContext->databaseExceededQuota(name, 258 DatabaseDetails(name.isolatedCopy(), displayName.isolatedCopy(), estimatedSize, 0)); 259 260 error = DatabaseError::None; 261 262 backend = m_server->openDatabase(backendContext, type, name, expectedVersion, 263 displayName, estimatedSize, setVersionInNewDatabase, error, errorMessage, 264 AbstractDatabaseServer::RetryOpenDatabase); 265 break; 266 267 default: 268 ASSERT_NOT_REACHED(); 269 } 270 271 if (!backend) { 272 ASSERT(error != DatabaseError::None); 273 274 if (error == DatabaseError::InvalidDatabaseState) { 275 logErrorMessage(context, errorMessage); 276 return 0; 277 } 278 279 logOpenDatabaseError(context, name); 280 return 0; 281 } 282 } 283 284 return backend.release(); 285 } 286 203 287 PassRefPtr<Database> DatabaseManager::openDatabase(ScriptExecutionContext* context, 204 288 const String& name, const String& expectedVersion, const String& displayName, … … 207 291 { 208 292 ScriptController::initializeThreading(); 293 ASSERT(error == DatabaseError::None); 294 295 bool setVersionInNewDatabase = !creationCallback; 296 String errorMessage; 297 RefPtr<DatabaseBackend> backend = openDatabaseBackend(context, DatabaseType::Async, name, 298 expectedVersion, displayName, estimatedSize, setVersionInNewDatabase, error, errorMessage); 299 if (!backend) 300 return 0; 301 302 RefPtr<Database> database = Database::create(context, backend); 303 209 304 RefPtr<DatabaseContext> databaseContext = databaseContextFor(context); 210 RefPtr<DatabaseBackendContext> backendContext = databaseContext->backend();211 ASSERT(error == DatabaseError::None);212 213 if (!m_server->canEstablishDatabase(backendContext.get(), name, displayName, estimatedSize)) {214 LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.ascii().data(), context->securityOrigin()->toString().ascii().data());215 return 0;216 }217 218 String errorMessage;219 RefPtr<Database> database = adoptRef(new Database(backendContext, name, expectedVersion, displayName, estimatedSize));220 221 if (!database->openAndVerifyVersion(!creationCallback, error, errorMessage)) {222 logErrorMessage(context, errorMessage);223 return 0;224 }225 226 m_server->setDatabaseDetails(context->securityOrigin(), name, displayName, estimatedSize);227 305 databaseContext->setHasOpenDatabases(); 228 229 306 InspectorInstrumentation::didOpenDatabase(context, database, context->securityOrigin()->host(), name, expectedVersion); 230 307 231 if ( database->isNew() && creationCallback.get()) {308 if (backend->isNew() && creationCallback.get()) { 232 309 LOG(StorageAPI, "Scheduling DatabaseCreationCallbackTask for database %p\n", database.get()); 233 310 database->m_scriptExecutionContext->postTask(DatabaseCreationCallbackTask::create(database, creationCallback)); 234 311 } 235 312 313 ASSERT(database); 236 314 return database.release(); 237 315 } … … 241 319 unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, DatabaseError& error) 242 320 { 243 RefPtr<DatabaseContext> databaseContext = databaseContextFor(context);244 RefPtr<DatabaseBackendContext> backendContext = databaseContext->backend();245 321 ASSERT(context->isContextThread()); 246 322 ASSERT(error == DatabaseError::None); 247 323 248 if (!m_server->canEstablishDatabase(backendContext.get(), name, displayName, estimatedSize)) { 249 LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.ascii().data(), context->securityOrigin()->toString().ascii().data()); 324 bool setVersionInNewDatabase = !creationCallback; 325 String errorMessage; 326 RefPtr<DatabaseBackend> backend = openDatabaseBackend(context, DatabaseType::Sync, name, 327 expectedVersion, displayName, estimatedSize, setVersionInNewDatabase, error, errorMessage); 328 if (!backend) 250 329 return 0; 251 } 252 253 String errorMessage; 254 RefPtr<DatabaseSync> database = adoptRef(new DatabaseSync(backendContext, name, expectedVersion, displayName, estimatedSize)); 255 256 if (!database->openAndVerifyVersion(!creationCallback, error, errorMessage)) { 257 logErrorMessage(context, errorMessage); 258 return 0; 259 } 260 261 m_server->setDatabaseDetails(context->securityOrigin(), name, displayName, estimatedSize); 262 263 if (database->isNew() && creationCallback.get()) { 330 331 RefPtr<DatabaseSync> database = DatabaseSync::create(context, backend); 332 333 if (backend->isNew() && creationCallback.get()) { 264 334 LOG(StorageAPI, "Invoking the creation callback for database %p\n", database.get()); 265 335 creationCallback->handleEvent(database.get()); 266 336 } 267 337 338 ASSERT(database); 268 339 return database.release(); 269 340 } -
trunk/Source/WebCore/Modules/webdatabase/DatabaseManager.h
r141928 r142030 29 29 #if ENABLE(SQL_DATABASE) 30 30 31 #include "AbstractDatabaseServer.h"32 31 #include "DatabaseBasicTypes.h" 33 32 #include "DatabaseDetails.h" … … 81 80 #endif 82 81 82 static ExceptionCode exceptionCodeForDatabaseError(DatabaseError); 83 83 84 PassRefPtr<Database> openDatabase(ScriptExecutionContext*, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback>, DatabaseError&); 84 85 PassRefPtr<DatabaseSync> openDatabaseSync(ScriptExecutionContext*, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback>, DatabaseError&); … … 125 126 PassRefPtr<DatabaseContext> existingDatabaseContextFor(ScriptExecutionContext*); 126 127 128 PassRefPtr<DatabaseBackend> openDatabaseBackend(ScriptExecutionContext*, 129 DatabaseType, const String& name, const String& expectedVersion, const String& displayName, 130 unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); 131 127 132 static void logErrorMessage(ScriptExecutionContext*, const String& message); 128 133 -
trunk/Source/WebCore/Modules/webdatabase/DatabaseServer.cpp
r141928 r142030 29 29 #if ENABLE(SQL_DATABASE) 30 30 31 #include "Database.h" 31 32 #include "DatabaseBackendAsync.h" 32 33 #include "DatabaseBackendContext.h" 33 34 #include "DatabaseBackendSync.h" 35 #include "DatabaseSync.h" 34 36 #include "DatabaseTracker.h" 35 37 #include <wtf/UnusedParam.h> … … 150 152 } 151 153 152 bool DatabaseServer::canEstablishDatabase(DatabaseBackendContext* backendContext, const String& name, const String& displayName, unsigned long estimatedSize) 153 { 154 return DatabaseTracker::tracker().canEstablishDatabase(backendContext, name, displayName, estimatedSize); 155 } 156 157 void DatabaseServer::setDatabaseDetails(SecurityOrigin* origin, const String& name, const String& displayName, unsigned long estimatedSize) 158 { 159 DatabaseTracker::tracker().setDatabaseDetails(origin, name, displayName, estimatedSize); 154 PassRefPtr<DatabaseBackend> DatabaseServer::openDatabase(RefPtr<DatabaseBackendContext>& backendContext, 155 DatabaseType type, const String& name, const String& expectedVersion, const String& displayName, 156 unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError &error, String& errorMessage, 157 OpenAttempt attempt) 158 { 159 RefPtr<DatabaseBackend> database; 160 bool success = false; // Make some older compilers happy. 161 162 switch (attempt) { 163 case FirstTryToOpenDatabase: 164 success = DatabaseTracker::tracker().canEstablishDatabase(backendContext.get(), name, displayName, estimatedSize, error); 165 break; 166 case RetryOpenDatabase: 167 success = DatabaseTracker::tracker().retryCanEstablishDatabase(backendContext.get(), name, displayName, estimatedSize, error); 168 } 169 170 if (success) 171 database = createDatabase(backendContext, type, name, expectedVersion, displayName, estimatedSize, setVersionInNewDatabase, error, errorMessage); 172 return database.release(); 173 } 174 175 PassRefPtr<DatabaseBackend> DatabaseServer::createDatabase(RefPtr<DatabaseBackendContext>& backendContext, 176 DatabaseType type, const String& name, const String& expectedVersion, const String& displayName, 177 unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage) 178 { 179 RefPtr<DatabaseBackend> database; 180 switch (type) { 181 case DatabaseType::Async: 182 database = adoptRef(new Database(backendContext, name, expectedVersion, displayName, estimatedSize)); 183 break; 184 case DatabaseType::Sync: 185 database = adoptRef(new DatabaseSync(backendContext, name, expectedVersion, displayName, estimatedSize)); 186 } 187 188 if (!database->openAndVerifyVersion(setVersionInNewDatabase, error, errorMessage)) 189 return 0; 190 191 DatabaseTracker::tracker().setDatabaseDetails(backendContext->securityOrigin(), name, displayName, estimatedSize); 192 return database.release(); 160 193 } 161 194 -
trunk/Source/WebCore/Modules/webdatabase/DatabaseServer.h
r141928 r142030 46 46 virtual String fullPathForDatabase(SecurityOrigin*, const String& name, bool createIfDoesNotExist); 47 47 48 virtual PassRefPtr<DatabaseBackend> openDatabase(RefPtr<DatabaseBackendContext>&, DatabaseType, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError&, String& errorMessage, OpenAttempt); 49 48 50 #if !PLATFORM(CHROMIUM) 49 51 virtual bool hasEntryForOrigin(SecurityOrigin*); … … 71 73 virtual void interruptAllDatabasesForContext(const DatabaseBackendContext*); 72 74 73 virtual bool canEstablishDatabase(DatabaseBackendContext*, const String& name, const String& displayName, unsigned long estimatedSize);75 virtual unsigned long long getMaxSizeForDatabase(const DatabaseBackend*); 74 76 75 virtual void setDatabaseDetails(SecurityOrigin*, const String& name, const String& displayName, unsigned long estimatedSize); 76 virtual unsigned long long getMaxSizeForDatabase(const DatabaseBackend*);77 protected: 78 virtual PassRefPtr<DatabaseBackend> createDatabase(RefPtr<DatabaseBackendContext>&, DatabaseType, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); 77 79 }; 78 80 -
trunk/Source/WebCore/Modules/webdatabase/DatabaseSync.cpp
r141928 r142030 52 52 namespace WebCore { 53 53 54 PassRefPtr<DatabaseSync> DatabaseSync::create(ScriptExecutionContext*, PassRefPtr<DatabaseBackend> backend) 55 { 56 return static_cast<DatabaseSync*>(backend.get()); 57 } 58 54 59 DatabaseSync::DatabaseSync(PassRefPtr<DatabaseBackendContext> databaseContext, 55 60 const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize) … … 155 160 } 156 161 157 bool DatabaseSync::openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage)158 {159 #if PLATFORM(CHROMIUM)160 DatabaseTracker::tracker().prepareToOpenDatabase(this);161 #endif162 return performOpenAndVerify(setVersionInNewDatabase, error, errorMessage);163 }164 165 162 void DatabaseSync::markAsDeletedAndClose() 166 163 { -
trunk/Source/WebCore/Modules/webdatabase/DatabaseSync.h
r141928 r142030 78 78 const String& expectedVersion, const String& displayName, unsigned long estimatedSize); 79 79 PassRefPtr<DatabaseBackendSync> backend(); 80 static PassRefPtr<DatabaseSync> create(ScriptExecutionContext*, PassRefPtr<DatabaseBackend>); 80 81 81 82 void runTransaction(PassRefPtr<SQLTransactionSyncCallback>, bool readOnly, ExceptionCode&); 82 83 bool openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage);84 83 85 84 String m_lastErrorMessage; 86 85 87 86 friend class DatabaseManager; 88 friend class Database BackendSync; // FIXME: remove this when the backend has been split out.87 friend class DatabaseServer; // FIXME: remove this when the backend has been split out. 89 88 }; 90 89 -
trunk/Source/WebCore/Modules/webdatabase/DatabaseTracker.cpp
r141928 r142030 143 143 } 144 144 145 bool DatabaseTracker::canEstablishDatabase(DatabaseBackendContext* context, const String& name, const String& displayName, unsigned long estimatedSize) 146 { 147 SecurityOrigin* origin = context->securityOrigin(); 148 unsigned long long requirement; 149 { 150 MutexLocker lockDatabase(m_databaseGuard); 151 Locker<OriginQuotaManager> quotaManagerLocker(originQuotaManager()); 152 153 if (isDeletingDatabaseOrOriginFor(origin, name)) 154 return false; 155 156 recordCreatingDatabase(origin, name); 157 158 // Since we're imminently opening a database within this context's origin, make sure this origin is being tracked by the QuotaTracker 159 // by fetching its current usage now. 160 unsigned long long usage = usageForOriginNoLock(origin); 161 162 // If a database already exists, ignore the passed-in estimated size and say it's OK. 163 if (hasEntryForDatabase(origin, name)) 164 return true; 165 166 // If the database will fit, allow its creation. 167 requirement = usage + max(1UL, estimatedSize); 168 if (requirement < usage) { 169 doneCreatingDatabase(origin, name); 170 return false; // If the estimated size is so big it causes an overflow, don't allow creation. 171 } 172 if (requirement <= quotaForOriginNoLock(origin)) 173 return true; 174 } 175 176 // Give the chrome client a chance to increase the quota. 177 // Drop all locks before calling out; we don't know what they'll do. 178 context->databaseExceededQuota(name, DatabaseDetails(name.isolatedCopy(), displayName.isolatedCopy(), estimatedSize, 0)); 179 180 MutexLocker lockDatabase(m_databaseGuard); 181 182 // If the database will fit now, allow its creation. 145 bool DatabaseTracker::hasAdequateQuotaForOrigin(SecurityOrigin* origin, unsigned long estimatedSize, DatabaseError& err) 146 { 147 // Since we're imminently opening a database within this context's origin, 148 // make sure this origin is being tracked by the OriginQuotaManager 149 // by fetching its current usage now. Calling usageForOrigin() has the side 150 // effect of initiating tracking by the OriginQuotaManager if the origin is 151 // not already tracked. 152 unsigned long long usage = usageForOriginNoLock(origin); 153 154 // If the database will fit, allow its creation. 155 unsigned long long requirement = usage + max(1UL, estimatedSize); 156 if (requirement < usage) { 157 // The estimated size is so big it causes an overflow; don't allow creation. 158 err = DatabaseError::DatabaseSizeOverflowed; 159 return false; 160 } 183 161 if (requirement <= quotaForOriginNoLock(origin)) 184 162 return true; 185 163 164 err = DatabaseError::DatabaseSizeExceededQuota; 165 return false; 166 } 167 168 bool DatabaseTracker::canEstablishDatabase(DatabaseBackendContext* context, const String& name, const String& displayName, unsigned long estimatedSize, DatabaseError& error) 169 { 170 UNUSED_PARAM(displayName); // Chromium needs the displayName but we don't. 171 error = DatabaseError::None; 172 173 MutexLocker lockDatabase(m_databaseGuard); 174 Locker<OriginQuotaManager> quotaManagerLocker(originQuotaManager()); 175 SecurityOrigin* origin = context->securityOrigin(); 176 177 if (isDeletingDatabaseOrOriginFor(origin, name)) { 178 error = DatabaseError::DatabaseIsBeingDeleted; 179 return false; 180 } 181 182 recordCreatingDatabase(origin, name); 183 184 // If a database already exists, ignore the passed-in estimated size and say it's OK. 185 if (hasEntryForDatabase(origin, name)) 186 return true; 187 188 if (hasAdequateQuotaForOrigin(origin, estimatedSize, error)) { 189 ASSERT(error == DatabaseError::None); 190 return true; 191 } 192 193 // If we get here, then we do not have enough quota for one of the 194 // following reasons as indicated by the set error: 195 // 196 // If the error is DatabaseSizeOverflowed, then this means the requested 197 // estimatedSize if so unreasonably large that it can cause an overflow in 198 // the usage budget computation. In that case, there's nothing more we can 199 // do, and there's no need for a retry. Hence, we should indicate that 200 // we're done with our attempt to create the database. 201 // 202 // If the error is DatabaseSizeExceededQuota, then we'll give the client 203 // a chance to update the quota and call retryCanEstablishDatabase() to try 204 // again. Hence, we don't call doneCreatingDatabase() yet in that case. 205 206 if (error == DatabaseError::DatabaseSizeOverflowed) 207 doneCreatingDatabase(origin, name); 208 else 209 ASSERT(error == DatabaseError::DatabaseSizeExceededQuota); 210 211 return false; 212 } 213 214 // Note: a thought about performance: hasAdequateQuotaForOrigin() was also 215 // called in canEstablishDatabase(), and hence, we're repeating some work within 216 // hasAdequateQuotaForOrigin(). However, retryCanEstablishDatabase() should only 217 // be called in the rare even if canEstablishDatabase() fails. Since it is rare, 218 // we should not bother optimizing it. It is more beneficial to keep 219 // hasAdequateQuotaForOrigin() simple and correct (i.e. bug free), and just 220 // re-use it. Also note that the path for opening a database involves IO, and 221 // hence should not be a performance critical path anyway. 222 bool DatabaseTracker::retryCanEstablishDatabase(DatabaseBackendContext* context, const String& name, const String& displayName, unsigned long estimatedSize, DatabaseError& error) 223 { 224 // Chromium needs the displayName in canEstablishDatabase(), but we don't. 225 // Though Chromium does not use retryCanEstablishDatabase(), we should 226 // keep the prototypes for canEstablishDatabase() and its retry function 227 // the same. Hence, we also have an unneeded displayName arg here. 228 UNUSED_PARAM(displayName); 229 error = DatabaseError::None; 230 231 MutexLocker lockDatabase(m_databaseGuard); 232 Locker<OriginQuotaManager> quotaManagerLocker(originQuotaManager()); 233 SecurityOrigin* origin = context->securityOrigin(); 234 235 // We have already eliminated other types of errors in canEstablishDatabase(). 236 // The only reason we're in retryCanEstablishDatabase() is because we gave 237 // the client a chance to update the quota and are rechecking it here. 238 // If we fail this check, the only possible reason this time should be due 239 // to inadequate quota. 240 if (hasAdequateQuotaForOrigin(origin, estimatedSize, error)) { 241 ASSERT(error == DatabaseError::None); 242 return true; 243 } 244 245 ASSERT(error == DatabaseError::DatabaseSizeExceededQuota); 186 246 doneCreatingDatabase(origin, name); 187 247 -
trunk/Source/WebCore/Modules/webdatabase/DatabaseTracker.h
r141928 r142030 32 32 #if ENABLE(SQL_DATABASE) 33 33 34 #include "DatabaseError.h" 34 35 #include <wtf/HashMap.h> 35 36 #include <wtf/HashSet.h> … … 71 72 // notificationMutex() is currently independent of the other locks. 72 73 73 bool canEstablishDatabase(DatabaseBackendContext*, const String& name, const String& displayName, unsigned long estimatedSize); 74 bool canEstablishDatabase(DatabaseBackendContext*, const String& name, const String& displayName, unsigned long estimatedSize, DatabaseError&); 75 bool retryCanEstablishDatabase(DatabaseBackendContext*, const String& name, const String& displayName, unsigned long estimatedSize, DatabaseError&); 76 74 77 void setDatabaseDetails(SecurityOrigin*, const String& name, const String& displayName, unsigned long estimatedSize); 75 78 String fullPathForDatabase(SecurityOrigin*, const String& name, bool createIfDoesNotExist = true); … … 86 89 private: 87 90 explicit DatabaseTracker(const String& databasePath); 91 92 bool hasAdequateQuotaForOrigin(SecurityOrigin*, unsigned long estimatedSize, DatabaseError&); 88 93 89 94 #if !PLATFORM(CHROMIUM) -
trunk/Source/WebCore/Modules/webdatabase/WorkerContextWebDatabase.cpp
r141668 r142030 46 46 RefPtr<Database> database; 47 47 DatabaseError error = DatabaseError::None; 48 if (dbManager.isAvailable() && context->securityOrigin()->canAccessDatabase(context->topOrigin())) 48 if (dbManager.isAvailable() && context->securityOrigin()->canAccessDatabase(context->topOrigin())) { 49 49 database = dbManager.openDatabase(context, name, version, displayName, estimatedSize, creationCallback, error); 50 51 ASSERT(error == DatabaseError::None || error == DatabaseError::CannotOpenDatabase); 52 if (error == DatabaseError::CannotOpenDatabase) 53 ec = INVALID_STATE_ERR; 54 if (!database && !ec) 50 ASSERT(database || error != DatabaseError::None); 51 ec = DatabaseManager::exceptionCodeForDatabaseError(error); 52 } else 55 53 ec = SECURITY_ERR; 56 54 … … 63 61 RefPtr<DatabaseSync> database; 64 62 DatabaseError error = DatabaseError::None; 65 if (dbManager.isAvailable() && context->securityOrigin()->canAccessDatabase(context->topOrigin())) 63 if (dbManager.isAvailable() && context->securityOrigin()->canAccessDatabase(context->topOrigin())) { 66 64 database = dbManager.openDatabaseSync(context, name, version, displayName, estimatedSize, creationCallback, error); 67 65 68 ASSERT(error == DatabaseError::None || error == DatabaseError::CannotOpenDatabase); 69 if (error == DatabaseError::CannotOpenDatabase) 70 ec = INVALID_STATE_ERR; 71 if (!database && !ec) 66 ASSERT(database || error != DatabaseError::None); 67 ec = DatabaseManager::exceptionCodeForDatabaseError(error); 68 } else 72 69 ec = SECURITY_ERR; 73 70 -
trunk/Source/WebCore/Modules/webdatabase/chromium/DatabaseTrackerChromium.cpp
r141928 r142030 42 42 #include "SecurityOriginHash.h" 43 43 #include "SQLiteFileSystem.h" 44 #include <wtf/Assertions.h> 44 45 #include <wtf/StdLibExtras.h> 45 46 #include <wtf/text/WTFString.h> … … 58 59 } 59 60 60 bool DatabaseTracker::canEstablishDatabase(DatabaseBackendContext* databaseContext, const String& name, const String& displayName, unsigned long estimatedSize )61 bool DatabaseTracker::canEstablishDatabase(DatabaseBackendContext* databaseContext, const String& name, const String& displayName, unsigned long estimatedSize, DatabaseError& error) 61 62 { 62 63 ScriptExecutionContext* scriptExecutionContext = databaseContext->scriptExecutionContext(); 63 return DatabaseObserver::canEstablishDatabase(scriptExecutionContext, name, displayName, estimatedSize); 64 bool success = DatabaseObserver::canEstablishDatabase(scriptExecutionContext, name, displayName, estimatedSize); 65 if (!success) 66 error = DatabaseError::GenericSecurityError; 67 return success; 68 } 69 70 bool DatabaseTracker::retryCanEstablishDatabase(DatabaseBackendContext*, const String&, const String&, unsigned long, DatabaseError&) 71 { 72 ASSERT_NOT_REACHED(); 73 return false; 64 74 } 65 75
Note: See TracChangeset
for help on using the changeset viewer.