Changeset 53595 in webkit
- Timestamp:
- Jan 20, 2010 7:49:51 PM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r53592 r53595 1 2010-01-20 Eric Uhrhane <ericu@chromium.org> 2 3 Reviewed by Dmitry Titov. 4 5 Refactoring and plumbing to get the HTML5 SQL Database API accessible to 6 web workers. No new functionality is exposed yet; this just gets the 7 infrastructure in place. It touches a lot of files in small ways; here 8 are the main changes: 9 10 1) Database members and methods move from Document up to 11 ScriptExecutionContext. Each of Document and WorkerContext must 12 implement a few virtual methods where the Database code requires 13 differentiation. 14 2) Worker thread shutdown got changed a bunch to handle Database cleanup 15 and thread synchronization issues. Database cleanup tasks need to post 16 some cleanup tasks to the JavaScript thread. However, since database 17 cleanup may happen due to the destruction of the WorkerThread, I added a 18 handshake [involving WorkerThreadShutdownStartTask, 19 WorkerThreadShutdownFinishTask, and a DatabaseTaskSynchronizer] between 20 the Database thread and WorkerThread that cleans up all the Database 21 stuff before the WorkerThread's runLoop can exit. 22 3) The runtime enabler for the Database moved to a static variable 23 accessible through Database::isAvailable, following the model used by 24 WebSocket. 25 4) Worker threads don't run their JavaScript on the Main thread, so 26 Database code that differentiated between the Main thread and the 27 Database thread now need to deal with a third possibility. 28 5) Most of the other changes have to do with having a 29 ScriptExecutionContext pointer instead of a Document pointer when 30 dealing with a Database. In many cases it's just a string replacement, 31 but in some it required the creation of a new virtual function [e.g. 32 databaseExceededQuota, isDatabaseReadOnly] 33 34 https://bugs.webkit.org/show_bug.cgi?id=22725 35 36 No new tests; in a future patch I'll add JSC and V8 bindings and new 37 layout tests to exercise them. 38 39 * bindings/v8/custom/V8DOMWindowCustom.cpp: 40 (WebCore::V8DOMWindow::OpenDatabaseEnabled): 41 * dom/Document.cpp: 42 (WebCore::Document::Document): 43 (WebCore::Document::~Document): 44 (WebCore::Document::isDatabaseReadOnly): 45 (WebCore::Document::databaseExceededQuota): 46 (WebCore::Document::isContextThread): 47 * dom/Document.h: 48 * dom/ScriptExecutionContext.cpp: 49 (WebCore::ScriptExecutionContext::ScriptExecutionContext): 50 (WebCore::ScriptExecutionContext::~ScriptExecutionContext): 51 (WebCore::ScriptExecutionContext::databaseThread): 52 (WebCore::ScriptExecutionContext::addOpenDatabase): 53 (WebCore::ScriptExecutionContext::removeOpenDatabase): 54 (WebCore::ScriptExecutionContext::stopDatabases): 55 * dom/ScriptExecutionContext.h: 56 (WebCore::ScriptExecutionContext::setHasOpenDatabases): 57 (WebCore::ScriptExecutionContext::hasOpenDatabases): 58 (WebCore::ScriptExecutionContext::Task::isCleanupTask): 59 * loader/FrameLoader.cpp: 60 (WebCore::FrameLoader::stopLoading): 61 * storage/Database.cpp: 62 (WebCore::Database::setIsAvailable): 63 (WebCore::Database::isAvailable): 64 (WebCore::Database::openDatabase): 65 (WebCore::Database::Database): 66 (WebCore::DerefContextTask::create): 67 (WebCore::DerefContextTask::performTask): 68 (WebCore::DerefContextTask::isCleanupTask): 69 (WebCore::Database::~Database): 70 (WebCore::Database::openAndVerifyVersion): 71 (WebCore::Database::markAsDeletedAndClose): 72 (WebCore::ContextRemoveOpenDatabaseTask::create): 73 (WebCore::ContextRemoveOpenDatabaseTask::performTask): 74 (WebCore::ContextRemoveOpenDatabaseTask::isCleanupTask): 75 (WebCore::ContextRemoveOpenDatabaseTask::ContextRemoveOpenDatabaseTask): 76 (WebCore::Database::close): 77 (WebCore::Database::performOpenAndVerify): 78 (WebCore::Database::scheduleTransaction): 79 (WebCore::Database::scheduleTransactionStep): 80 (WebCore::DeliverPendingCallbackTask::create): 81 (WebCore::DeliverPendingCallbackTask::performTask): 82 (WebCore::DeliverPendingCallbackTask::DeliverPendingCallbackTask): 83 (WebCore::Database::scheduleTransactionCallback): 84 (WebCore::Database::transactionClient): 85 (WebCore::Database::transactionCoordinator): 86 (WebCore::Database::tableNames): 87 (WebCore::Database::securityOrigin): 88 * storage/Database.h: 89 (WebCore::Database::scriptExecutionContext): 90 * storage/DatabaseTask.h: 91 * storage/DatabaseThread.cpp: 92 (WebCore::DatabaseThread::DatabaseThread): 93 (WebCore::DatabaseThread::~DatabaseThread): 94 (WebCore::DatabaseThread::requestTermination): 95 (WebCore::DatabaseThread::databaseThread): 96 (WebCore::DatabaseThread::unscheduleDatabaseTasks): 97 * storage/DatabaseThread.h: 98 * storage/DatabaseTracker.cpp: 99 (WebCore::DatabaseTracker::canEstablishDatabase): 100 (WebCore::DatabaseTracker::getMaxSizeForDatabase): 101 * storage/DatabaseTracker.h: 102 * storage/SQLTransaction.cpp: 103 (WebCore::SQLTransaction::executeSQL): 104 * storage/SQLTransactionClient.cpp: 105 (WebCore::SQLTransactionClient::didCommitTransaction): 106 (WebCore::SQLTransactionClient::didExecuteStatement): 107 (WebCore::SQLTransactionClient::didExceedQuota): 108 * storage/chromium/DatabaseTrackerChromium.cpp: 109 (WebCore::DatabaseTracker::canEstablishDatabase): 110 (WebCore::DatabaseTracker::addOpenDatabase): 111 (WebCore::TrackerRemoveOpenDatabaseTask::create): 112 (WebCore::TrackerRemoveOpenDatabaseTask::performTask): 113 (WebCore::TrackerRemoveOpenDatabaseTask::TrackerRemoveOpenDatabaseTask): 114 (WebCore::DatabaseTracker::removeOpenDatabase): 115 (WebCore::DatabaseTracker::getMaxSizeForDatabase): 116 * storage/chromium/SQLTransactionClientChromium.cpp: 117 (WebCore::NotifyDatabaseChangedTask::create): 118 (WebCore::NotifyDatabaseChangedTask::performTask): 119 (WebCore::NotifyDatabaseChangedTask::NotifyDatabaseChangedTask): 120 (WebCore::SQLTransactionClient::didCommitTransaction): 121 (WebCore::SQLTransactionClient::didExecuteStatement): 122 (WebCore::SQLTransactionClient::didExceedQuota): 123 * workers/WorkerContext.cpp: 124 (WebCore::WorkerContext::openDatabase): 125 (WebCore::WorkerContext::isContextThread): 126 * workers/WorkerContext.h: 127 (WebCore::WorkerContext::clearScript): 128 (WebCore::WorkerContext::thread): 129 (WebCore::WorkerContext::isDatabaseReadOnly): 130 (WebCore::WorkerContext::databaseExceededQuota): 131 * workers/WorkerRunLoop.cpp: 132 (WebCore::WorkerRunLoop::runInMode): 133 (WebCore::WorkerRunLoop::Task::performTask): 134 * workers/WorkerThread.cpp: 135 (WebCore::WorkerThread::workerThread): 136 (WebCore::WorkerThreadShutdownFinishTask::create): 137 (WebCore::WorkerThreadShutdownFinishTask::performTask): 138 (WebCore::WorkerThreadShutdownFinishTask::isCleanupTask): 139 (WebCore::WorkerThreadShutdownStartTask::create): 140 (WebCore::WorkerThreadShutdownStartTask::performTask): 141 (WebCore::WorkerThreadShutdownStartTask::isCleanupTask): 142 (WebCore::WorkerThread::stop): 143 1 144 2010-01-20 Fumitoshi Ukai <ukai@chromium.org> 2 145 -
trunk/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp
r53586 r53595 34 34 #include "Base64.h" 35 35 #include "Chrome.h" 36 #include "Database.h" 36 37 #include "DOMTimer.h" 37 38 #include "DOMWindow.h" … … 297 298 bool V8DOMWindow::OpenDatabaseEnabled() 298 299 { 299 return WebCore::RuntimeEnabledFeatures::databaseEnabled();300 return Database::isAvailable(); 300 301 } 301 302 #endif -
trunk/WebCore/dom/Document.cpp
r53563 r53595 38 38 #include "CachedCSSStyleSheet.h" 39 39 #include "Chrome.h" 40 #include "ChromeClient.h" 40 41 #include "Comment.h" 41 42 #include "Console.h" … … 139 140 #include <wtf/StdLibExtras.h> 140 141 141 #if ENABLE(DATABASE)142 #include "Database.h"143 #include "DatabaseThread.h"144 #endif145 146 142 #if ENABLE(SHARED_WORKERS) 147 143 #include "SharedWorkerRepository.h" … … 392 388 , m_normalWorldWrapperCache(0) 393 389 #endif 394 #if ENABLE(DATABASE)395 , m_hasOpenDatabases(false)396 #endif397 390 , m_usingGeolocation(false) 398 391 #if ENABLE(WML) … … 539 532 for (unsigned i = 0; i < count; i++) 540 533 deleteAllValues(m_nameCollectionInfo[i]); 541 542 #if ENABLE(DATABASE)543 if (m_databaseThread) {544 ASSERT(m_databaseThread->terminationRequested());545 m_databaseThread = 0;546 }547 #endif548 534 549 535 if (m_styleSheets) … … 4444 4430 } 4445 4431 4432 #if ENABLE(DATABASE) 4433 4434 bool Document::isDatabaseReadOnly() const 4435 { 4436 if (!page() || page()->settings()->privateBrowsingEnabled()) 4437 return true; 4438 return false; 4439 } 4440 4441 void Document::databaseExceededQuota(const String& name) 4442 { 4443 Page* currentPage = page(); 4444 if (currentPage) 4445 currentPage->chrome()->client()->exceededDatabaseQuota(document()->frame(), name); 4446 } 4447 4448 #endif 4449 4450 bool Document::isContextThread() const 4451 { 4452 return isMainThread(); 4453 } 4454 4446 4455 void Document::updateURLForPushOrReplaceState(const KURL& url) 4447 4456 { … … 4543 4552 return frame() ? frame()->domWindow()->getSelection() : 0; 4544 4553 } 4545 4546 #if ENABLE(DATABASE)4547 4548 void Document::addOpenDatabase(Database* database)4549 {4550 if (!m_openDatabaseSet)4551 m_openDatabaseSet.set(new DatabaseSet);4552 4553 ASSERT(!m_openDatabaseSet->contains(database));4554 m_openDatabaseSet->add(database);4555 }4556 4557 void Document::removeOpenDatabase(Database* database)4558 {4559 ASSERT(m_openDatabaseSet && m_openDatabaseSet->contains(database));4560 if (!m_openDatabaseSet)4561 return;4562 4563 m_openDatabaseSet->remove(database);4564 }4565 4566 DatabaseThread* Document::databaseThread()4567 {4568 if (!m_databaseThread && !m_hasOpenDatabases) {4569 // Create the database thread on first request - but not if at least one database was already opened,4570 // because in that case we already had a database thread and terminated it and should not create another.4571 m_databaseThread = DatabaseThread::create();4572 if (!m_databaseThread->start())4573 m_databaseThread = 0;4574 }4575 4576 return m_databaseThread.get();4577 }4578 4579 void Document::stopDatabases()4580 {4581 if (m_openDatabaseSet) {4582 DatabaseSet::iterator i = m_openDatabaseSet->begin();4583 DatabaseSet::iterator end = m_openDatabaseSet->end();4584 for (; i != end; ++i) {4585 (*i)->stop();4586 if (m_databaseThread)4587 m_databaseThread->unscheduleDatabaseTasks(*i);4588 }4589 }4590 4591 if (m_databaseThread)4592 m_databaseThread->requestTermination();4593 }4594 4595 #endif4596 4554 4597 4555 #if ENABLE(WML) -
trunk/WebCore/dom/Document.h
r53563 r53595 913 913 914 914 #if ENABLE(DATABASE) 915 void addOpenDatabase(Database*); 916 void removeOpenDatabase(Database*); 917 DatabaseThread* databaseThread(); // Creates the thread as needed, but not if it has been already terminated. 918 void setHasOpenDatabases() { m_hasOpenDatabases = true; } 919 bool hasOpenDatabases() { return m_hasOpenDatabases; } 920 void stopDatabases(); 921 #endif 915 virtual bool isDatabaseReadOnly() const; 916 virtual void databaseExceededQuota(const String& name); 917 #endif 918 919 virtual bool isContextThread() const; 922 920 923 921 void setUsingGeolocation(bool f) { m_usingGeolocation = f; } … … 1184 1182 #endif 1185 1183 1186 #if ENABLE(DATABASE)1187 RefPtr<DatabaseThread> m_databaseThread;1188 bool m_hasOpenDatabases; // This never changes back to false, even as the database thread is closed.1189 typedef HashSet<Database*> DatabaseSet;1190 OwnPtr<DatabaseSet> m_openDatabaseSet;1191 #endif1192 1193 1184 bool m_usingGeolocation; 1194 1185 -
trunk/WebCore/dom/ScriptExecutionContext.cpp
r51127 r53595 29 29 30 30 #include "ActiveDOMObject.h" 31 #include "Document.h" 31 #include "DatabaseTask.h" 32 #include "DatabaseThread.h" 32 33 #include "MessagePort.h" 33 34 #include "SecurityOrigin.h" … … 57 58 58 59 ScriptExecutionContext::ScriptExecutionContext() 60 #if ENABLE(DATABASE) 61 : m_hasOpenDatabases(false) 62 #endif 59 63 { 60 64 } … … 73 77 (*iter)->contextDestroyed(); 74 78 } 75 } 79 if (m_databaseThread) { 80 ASSERT(m_databaseThread->terminationRequested()); 81 m_databaseThread = 0; 82 } 83 } 84 85 #if ENABLE(DATABASE) 86 87 DatabaseThread* ScriptExecutionContext::databaseThread() 88 { 89 if (!m_databaseThread && !m_hasOpenDatabases) { 90 // Create the database thread on first request - but not if at least one database was already opened, 91 // because in that case we already had a database thread and terminated it and should not create another. 92 m_databaseThread = DatabaseThread::create(); 93 if (!m_databaseThread->start()) 94 m_databaseThread = 0; 95 } 96 97 return m_databaseThread.get(); 98 } 99 100 void ScriptExecutionContext::addOpenDatabase(Database* database) 101 { 102 ASSERT(isContextThread()); 103 if (!m_openDatabaseSet) 104 m_openDatabaseSet.set(new DatabaseSet()); 105 106 ASSERT(!m_openDatabaseSet->contains(database)); 107 m_openDatabaseSet->add(database); 108 } 109 110 void ScriptExecutionContext::removeOpenDatabase(Database* database) 111 { 112 ASSERT(isContextThread()); 113 ASSERT(m_openDatabaseSet && m_openDatabaseSet->contains(database)); 114 if (!m_openDatabaseSet) 115 return; 116 m_openDatabaseSet->remove(database); 117 } 118 119 void ScriptExecutionContext::stopDatabases(DatabaseTaskSynchronizer* cleanupSync) 120 { 121 ASSERT(isContextThread()); 122 if (m_openDatabaseSet) { 123 DatabaseSet::iterator i = m_openDatabaseSet->begin(); 124 DatabaseSet::iterator end = m_openDatabaseSet->end(); 125 for (; i != end; ++i) { 126 (*i)->stop(); 127 if (m_databaseThread) 128 m_databaseThread->unscheduleDatabaseTasks(*i); 129 } 130 } 131 132 if (m_databaseThread) 133 m_databaseThread->requestTermination(cleanupSync); 134 else if (cleanupSync) 135 cleanupSync->taskCompleted(); 136 } 137 138 #endif 76 139 77 140 void ScriptExecutionContext::processMessagePortMessagesSoon() -
trunk/WebCore/dom/ScriptExecutionContext.h
r51793 r53595 34 34 #include <wtf/PassOwnPtr.h> 35 35 #include <wtf/PassRefPtr.h> 36 #include <wtf/RefPtr.h> 36 37 #include <wtf/Threading.h> 37 38 … … 39 40 40 41 class ActiveDOMObject; 42 #if ENABLE(DATABASE) 43 class Database; 44 class DatabaseTaskSynchronizer; 45 class DatabaseThread; 46 #endif 41 47 class DOMTimer; 42 48 class MessagePort; … … 59 65 virtual bool isDocument() const { return false; } 60 66 virtual bool isWorkerContext() const { return false; } 67 68 #if ENABLE(DATABASE) 69 virtual bool isDatabaseReadOnly() const = 0; 70 virtual void databaseExceededQuota(const String& name) = 0; 71 DatabaseThread* databaseThread(); 72 void setHasOpenDatabases() { m_hasOpenDatabases = true; } 73 bool hasOpenDatabases() const { return m_hasOpenDatabases; } 74 void addOpenDatabase(Database*); 75 void removeOpenDatabase(Database*); 76 // When the database cleanup is done, cleanupSync will be signalled. 77 void stopDatabases(DatabaseTaskSynchronizer*); 78 #endif 79 virtual bool isContextThread() const = 0; 61 80 62 81 const KURL& url() const { return virtualURL(); } … … 98 117 virtual ~Task(); 99 118 virtual void performTask(ScriptExecutionContext*) = 0; 119 // Certain tasks get marked specially so that they aren't discarded, and are executed, when the context is shutting down its message queue. 120 virtual bool isCleanupTask() const { return false; } 100 121 }; 101 122 … … 130 151 virtual void refScriptExecutionContext() = 0; 131 152 virtual void derefScriptExecutionContext() = 0; 153 154 #if ENABLE(DATABASE) 155 RefPtr<DatabaseThread> m_databaseThread; 156 bool m_hasOpenDatabases; // This never changes back to false, even after the database thread is closed. 157 typedef HashSet<Database* > DatabaseSet; 158 OwnPtr<DatabaseSet> m_openDatabaseSet; 159 #endif 132 160 }; 133 161 -
trunk/WebCore/loader/FrameLoader.cpp
r53590 r53595 567 567 #if ENABLE(DATABASE) 568 568 if (databasePolicy == DatabasePolicyStop) 569 doc->stopDatabases( );569 doc->stopDatabases(0); 570 570 #else 571 571 UNUSED_PARAM(databasePolicy); -
trunk/WebCore/storage/Database.cpp
r52631 r53595 54 54 #include "SQLTransactionClient.h" 55 55 #include "SQLTransactionCoordinator.h" 56 #include <wtf/MainThread.h> 57 #endif 56 57 #endif // ENABLE(DATABASE) 58 58 59 59 #if USE(JSC) … … 73 73 74 74 #if ENABLE(DATABASE) 75 76 static bool isDatabaseAvailable = false; 77 78 void Database::setIsAvailable(bool available) 79 { 80 isDatabaseAvailable = available; 81 } 82 83 bool Database::isAvailable() 84 { 85 return isDatabaseAvailable; 86 } 75 87 76 88 static Mutex& guidMutex() … … 121 133 static int guidForOriginAndName(const String& origin, const String& name); 122 134 123 PassRefPtr<Database> Database::openDatabase( Document* document, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, ExceptionCode& e)124 { 125 if (!DatabaseTracker::tracker().canEstablishDatabase( document, name, displayName, estimatedSize)) {135 PassRefPtr<Database> Database::openDatabase(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, ExceptionCode& e) 136 { 137 if (!DatabaseTracker::tracker().canEstablishDatabase(context, name, displayName, estimatedSize)) { 126 138 // FIXME: There should be an exception raised here in addition to returning a null Database object. The question has been raised with the WHATWG. 127 LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.ascii().data(), document->securityOrigin()->toString().ascii().data());139 LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.ascii().data(), context->securityOrigin()->toString().ascii().data()); 128 140 return 0; 129 141 } 130 142 131 RefPtr<Database> database = adoptRef(new Database( document, name, expectedVersion, displayName, estimatedSize));143 RefPtr<Database> database = adoptRef(new Database(context, name, expectedVersion, displayName, estimatedSize)); 132 144 133 145 if (!database->openAndVerifyVersion(e)) { 134 146 LOG(StorageAPI, "Failed to open and verify version (expected %s) of database %s", expectedVersion.ascii().data(), database->databaseDebugName().ascii().data()); 135 document->removeOpenDatabase(database.get());147 context->removeOpenDatabase(database.get()); 136 148 DatabaseTracker::tracker().removeOpenDatabase(database.get()); 137 149 return 0; 138 150 } 139 151 140 DatabaseTracker::tracker().setDatabaseDetails(document->securityOrigin(), name, displayName, estimatedSize); 141 142 document->setHasOpenDatabases(); 143 152 DatabaseTracker::tracker().setDatabaseDetails(context->securityOrigin(), name, displayName, estimatedSize); 153 154 context->setHasOpenDatabases(); 144 155 #if ENABLE(INSPECTOR) 145 if (Page* page = document->frame()->page()) 146 page->inspectorController()->didOpenDatabase(database.get(), document->securityOrigin()->host(), name, expectedVersion); 156 if (context->isDocument()) { 157 Document* document = static_cast<Document*>(context); 158 if (Page* page = document->page()) 159 page->inspectorController()->didOpenDatabase(database.get(), context->securityOrigin()->host(), name, expectedVersion); 160 } 147 161 #endif 148 162 … … 150 164 } 151 165 152 Database::Database( Document* document, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize)166 Database::Database(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize) 153 167 : m_transactionInProgress(false) 154 168 , m_isTransactionQueueEnabled(true) 155 , m_ document(document)169 , m_scriptExecutionContext(context) 156 170 , m_name(name.crossThreadString()) 157 171 , m_guid(0) … … 163 177 , m_opened(false) 164 178 { 165 ASSERT( document);166 m_mainThreadSecurityOrigin = document->securityOrigin();179 ASSERT(m_scriptExecutionContext.get()); 180 m_mainThreadSecurityOrigin = m_scriptExecutionContext->securityOrigin(); 167 181 m_databaseThreadSecurityOrigin = m_mainThreadSecurityOrigin->threadsafeCopy(); 168 169 182 if (m_name.isNull()) 170 183 m_name = ""; … … 172 185 ScriptController::initializeThreading(); 173 186 174 m_guid = guidForOriginAndName( m_mainThreadSecurityOrigin->toString(), name);187 m_guid = guidForOriginAndName(securityOrigin()->toString(), name); 175 188 176 189 { … … 186 199 } 187 200 188 ASSERT(m_document->databaseThread()); 189 190 m_filename = DatabaseTracker::tracker().fullPathForDatabase(m_mainThreadSecurityOrigin.get(), m_name); 201 ASSERT(m_scriptExecutionContext->databaseThread()); 202 m_filename = DatabaseTracker::tracker().fullPathForDatabase(securityOrigin(), m_name); 191 203 192 204 DatabaseTracker::tracker().addOpenDatabase(this); 193 m_document->addOpenDatabase(this); 194 } 195 196 static void derefDocument(void* document) 197 { 198 static_cast<Document*>(document)->deref(); 199 } 205 context->addOpenDatabase(this); 206 } 207 208 class DerefContextTask : public ScriptExecutionContext::Task { 209 public: 210 static PassOwnPtr<DerefContextTask> create() 211 { 212 return new DerefContextTask(); 213 } 214 215 virtual void performTask(ScriptExecutionContext* context) 216 { 217 context->deref(); 218 } 219 220 virtual bool isCleanupTask() const { return true; } 221 }; 200 222 201 223 Database::~Database() 202 224 { 203 // Deref m_document on the main thread. 204 callOnMainThread(derefDocument, m_document.release().releaseRef()); 225 // The reference to the ScriptExecutionContext needs to be cleared on the JavaScript thread. If we're on that thread already, we can just let the RefPtr's destruction do the dereffing. 226 if (!m_scriptExecutionContext->isContextThread()) { 227 m_scriptExecutionContext->postTask(DerefContextTask::create()); 228 m_scriptExecutionContext.release().releaseRef(); 229 } 205 230 } 206 231 207 232 bool Database::openAndVerifyVersion(ExceptionCode& e) 208 233 { 209 if (!m_ document->databaseThread())234 if (!m_scriptExecutionContext->databaseThread()) 210 235 return false; 211 236 m_databaseAuthorizer = DatabaseAuthorizer::create(); … … 215 240 OwnPtr<DatabaseOpenTask> task = DatabaseOpenTask::create(this, &synchronizer, e, success); 216 241 217 m_ document->databaseThread()->scheduleImmediateTask(task.release());242 m_scriptExecutionContext->databaseThread()->scheduleImmediateTask(task.release()); 218 243 synchronizer.waitForTaskCompletion(); 219 244 … … 310 335 void Database::markAsDeletedAndClose() 311 336 { 312 if (m_deleted || !m_ document->databaseThread())337 if (m_deleted || !m_scriptExecutionContext->databaseThread()) 313 338 return; 314 339 … … 316 341 m_deleted = true; 317 342 318 if (m_ document->databaseThread()->terminationRequested()) {343 if (m_scriptExecutionContext->databaseThread()->terminationRequested()) { 319 344 LOG(StorageAPI, "Database handle %p is on a terminated DatabaseThread, cannot be marked for normal closure\n", this); 320 345 return; 321 346 } 322 347 323 m_ document->databaseThread()->unscheduleDatabaseTasks(this);348 m_scriptExecutionContext->databaseThread()->unscheduleDatabaseTasks(this); 324 349 325 350 DatabaseTaskSynchronizer synchronizer; 326 351 OwnPtr<DatabaseCloseTask> task = DatabaseCloseTask::create(this, &synchronizer); 327 352 328 m_ document->databaseThread()->scheduleImmediateTask(task.release());353 m_scriptExecutionContext->databaseThread()->scheduleImmediateTask(task.release()); 329 354 synchronizer.waitForTaskCompletion(); 330 355 } 331 356 332 static void documentRemoveOpenDatabase(void* context) 333 { 334 ASSERT(isMainThread()); 335 Database* database = static_cast<Database*>(context); 336 database->document()->removeOpenDatabase(database); 337 database->deref(); 338 } 357 class ContextRemoveOpenDatabaseTask : public ScriptExecutionContext::Task { 358 public: 359 static PassOwnPtr<ContextRemoveOpenDatabaseTask> create(PassRefPtr<Database> database) 360 { 361 return new ContextRemoveOpenDatabaseTask(database); 362 } 363 364 virtual void performTask(ScriptExecutionContext* context) 365 { 366 context->removeOpenDatabase(m_database.get()); 367 DatabaseTracker::tracker().removeOpenDatabase(m_database.get()); 368 } 369 370 virtual bool isCleanupTask() const { return true; } 371 372 private: 373 ContextRemoveOpenDatabaseTask(PassRefPtr<Database> database) 374 : m_database(database) 375 { 376 } 377 378 RefPtr<Database> m_database; 379 }; 339 380 340 381 void Database::close() 341 382 { 383 RefPtr<Database> protect = this; 384 342 385 if (!m_opened) 343 386 return; 344 387 345 ASSERT(m_ document->databaseThread());346 ASSERT(currentThread() == document()->databaseThread()->getThreadID());388 ASSERT(m_scriptExecutionContext->databaseThread()); 389 ASSERT(currentThread() == m_scriptExecutionContext->databaseThread()->getThreadID()); 347 390 m_sqliteDatabase.close(); 348 m_document->databaseThread()->recordDatabaseClosed(this); 391 // Must ref() before calling databaseThread()->recordDatabaseClosed(). 392 m_scriptExecutionContext->databaseThread()->recordDatabaseClosed(this); 349 393 m_opened = false; 350 394 … … 363 407 } 364 408 365 m_document->databaseThread()->unscheduleDatabaseTasks(this); 366 367 DatabaseTracker::tracker().removeOpenDatabase(this); 368 ref(); // deref() called in documentRemoveOpenDatabase() 369 callOnMainThread(documentRemoveOpenDatabase, this); 409 m_scriptExecutionContext->databaseThread()->unscheduleDatabaseTasks(this); 410 m_scriptExecutionContext->postTask(ContextRemoveOpenDatabaseTask::create(this)); 370 411 } 371 412 … … 533 574 // Make sure DatabaseThread closes it when DatabaseThread goes away. 534 575 m_opened = true; 535 if (m_ document->databaseThread())536 m_ document->databaseThread()->recordDatabaseOpen(this);576 if (m_scriptExecutionContext->databaseThread()) 577 m_scriptExecutionContext->databaseThread()->recordDatabaseOpen(this); 537 578 538 579 return true; … … 568 609 } 569 610 570 if (transaction && m_ document->databaseThread()) {611 if (transaction && m_scriptExecutionContext->databaseThread()) { 571 612 OwnPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction); 572 613 LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for transaction %p\n", task.get(), task->transaction()); 573 614 m_transactionInProgress = true; 574 m_ document->databaseThread()->scheduleTask(task.release());615 m_scriptExecutionContext->databaseThread()->scheduleTask(task.release()); 575 616 } else 576 617 m_transactionInProgress = false; … … 579 620 void Database::scheduleTransactionStep(SQLTransaction* transaction, bool immediately) 580 621 { 581 if (!m_ document->databaseThread())622 if (!m_scriptExecutionContext->databaseThread()) 582 623 return; 583 624 … … 585 626 LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for the transaction step\n", task.get()); 586 627 if (immediately) 587 m_ document->databaseThread()->scheduleImmediateTask(task.release());628 m_scriptExecutionContext->databaseThread()->scheduleImmediateTask(task.release()); 588 629 else 589 m_document->databaseThread()->scheduleTask(task.release()); 590 } 630 m_scriptExecutionContext->databaseThread()->scheduleTask(task.release()); 631 } 632 633 class DeliverPendingCallbackTask : public ScriptExecutionContext::Task { 634 public: 635 static PassOwnPtr<DeliverPendingCallbackTask> create(PassRefPtr<SQLTransaction> transaction) 636 { 637 return new DeliverPendingCallbackTask(transaction); 638 } 639 640 virtual void performTask(ScriptExecutionContext*) 641 { 642 m_transaction->performPendingCallback(); 643 } 644 645 private: 646 DeliverPendingCallbackTask(PassRefPtr<SQLTransaction> transaction) 647 : m_transaction(transaction) 648 { 649 } 650 651 RefPtr<SQLTransaction> m_transaction; 652 }; 591 653 592 654 void Database::scheduleTransactionCallback(SQLTransaction* transaction) 593 655 { 594 transaction->ref(); 595 callOnMainThread(deliverPendingCallback, transaction); 656 m_scriptExecutionContext->postTask(DeliverPendingCallbackTask::create(transaction)); 596 657 } 597 658 … … 627 688 SQLTransactionClient* Database::transactionClient() const 628 689 { 629 return m_ document->databaseThread()->transactionClient();690 return m_scriptExecutionContext->databaseThread()->transactionClient(); 630 691 } 631 692 632 693 SQLTransactionCoordinator* Database::transactionCoordinator() const 633 694 { 634 return m_ document->databaseThread()->transactionCoordinator();695 return m_scriptExecutionContext->databaseThread()->transactionCoordinator(); 635 696 } 636 697 … … 643 704 } 644 705 645 void Database::deliverPendingCallback(void* context)646 {647 SQLTransaction* transaction = static_cast<SQLTransaction*>(context);648 transaction->performPendingCallback();649 transaction->deref(); // Was ref'd in scheduleTransactionCallback().650 }651 652 706 Vector<String> Database::tableNames() 653 707 { … … 655 709 // in dealing with them. However, if the code changes, this may not be true anymore. 656 710 Vector<String> result; 657 if (!m_ document->databaseThread())711 if (!m_scriptExecutionContext->databaseThread()) 658 712 return result; 659 713 … … 661 715 OwnPtr<DatabaseTableNamesTask> task = DatabaseTableNamesTask::create(this, &synchronizer, result); 662 716 663 m_ document->databaseThread()->scheduleImmediateTask(task.release());717 m_scriptExecutionContext->databaseThread()->scheduleImmediateTask(task.release()); 664 718 synchronizer.waitForTaskCompletion(); 665 719 … … 677 731 SecurityOrigin* Database::securityOrigin() const 678 732 { 679 if ( isMainThread())733 if (scriptExecutionContext()->isContextThread()) 680 734 return m_mainThreadSecurityOrigin.get(); 681 if (currentThread() == document()->databaseThread()->getThreadID())735 if (currentThread() == m_scriptExecutionContext->databaseThread()->getThreadID()) 682 736 return m_databaseThreadSecurityOrigin.get(); 683 737 return 0; … … 707 761 } 708 762 709 #endif 710 711 } 763 #endif // ENABLE(DATABASE) 764 765 } // namespace WebCore -
trunk/WebCore/storage/Database.h
r50360 r53595 53 53 class DatabaseAuthorizer; 54 54 class DatabaseThread; 55 class Document;55 class ScriptExecutionContext; 56 56 class SQLResultSet; 57 57 class SQLTransactionCallback; … … 68 68 friend class SQLTransaction; 69 69 public: 70 static void setIsAvailable(bool); 71 static bool isAvailable(); 72 70 73 ~Database(); 71 74 72 75 // Direct support for the DOM API 73 static PassRefPtr<Database> openDatabase( Document* document, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, ExceptionCode&);76 static PassRefPtr<Database> openDatabase(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, ExceptionCode&); 74 77 String version() const; 75 78 void changeVersion(const String& oldVersion, const String& newVersion, … … 88 91 Vector<String> tableNames(); 89 92 90 Document* document() const { return m_document.get(); }93 ScriptExecutionContext* scriptExecutionContext() const { return m_scriptExecutionContext.get(); } 91 94 SecurityOrigin* securityOrigin() const; 92 95 String stringIdentifier() const; … … 124 127 125 128 private: 126 Database(Document* document, const String& name, const String& expectedVersion, 127 const String& displayName, unsigned long estimatedSize); 129 Database(ScriptExecutionContext* context, const String& name, 130 const String& expectedVersion, const String& displayName, 131 unsigned long estimatedSize); 128 132 129 133 bool openAndVerifyVersion(ExceptionCode&); … … 140 144 static void deliverPendingCallback(void*); 141 145 142 RefPtr< Document> m_document;146 RefPtr<ScriptExecutionContext> m_scriptExecutionContext; 143 147 RefPtr<SecurityOrigin> m_mainThreadSecurityOrigin; 144 148 RefPtr<SecurityOrigin> m_databaseThreadSecurityOrigin; -
trunk/WebCore/storage/DatabaseTask.h
r50427 r53595 51 51 // Has to be passed into DatabaseTask::create to be associated with the task. 52 52 class DatabaseTaskSynchronizer : public Noncopyable { 53 friend class DatabaseTask;54 53 public: 55 54 DatabaseTaskSynchronizer(); … … 58 57 void waitForTaskCompletion(); 59 58 60 private:61 59 // Called by the task. 62 60 void taskCompleted(); 61 private: 63 62 64 63 bool m_taskCompleted; -
trunk/WebCore/storage/DatabaseThread.cpp
r50427 r53595 45 45 , m_transactionClient(new SQLTransactionClient()) 46 46 , m_transactionCoordinator(new SQLTransactionCoordinator()) 47 , m_cleanupSync(0) 47 48 { 48 49 m_selfRef = this; … … 52 53 { 53 54 // FIXME: Any cleanup required here? Since the thread deletes itself after running its detached course, I don't think so. Lets be sure. 55 ASSERT(terminationRequested()); 54 56 } 55 57 … … 66 68 } 67 69 68 void DatabaseThread::requestTermination( )70 void DatabaseThread::requestTermination(DatabaseTaskSynchronizer *cleanupSync) 69 71 { 72 ASSERT(!m_cleanupSync); 73 m_cleanupSync = cleanupSync; 70 74 LOG(StorageAPI, "DatabaseThread %p was asked to terminate\n", this); 71 75 m_queue.kill(); … … 116 120 detachThread(m_threadID); 117 121 122 DatabaseTaskSynchronizer* cleanupSync = m_cleanupSync; 123 118 124 // Clear the self refptr, possibly resulting in deletion 119 125 m_selfRef = 0; 126 127 if (cleanupSync) // Someone wanted to know when we were done cleaning up. 128 cleanupSync->taskCompleted(); 120 129 121 130 return 0; … … 163 172 m_queue.removeIf(predicate); 164 173 } 165 166 174 } // namespace WebCore 167 175 #endif -
trunk/WebCore/storage/DatabaseThread.h
r50427 r53595 44 44 class Database; 45 45 class DatabaseTask; 46 class DatabaseTaskSynchronizer; 46 47 class Document; 47 48 class SQLTransactionClient; … … 54 55 55 56 bool start(); 56 void requestTermination( );57 void requestTermination(DatabaseTaskSynchronizer* cleanupSync); 57 58 bool terminationRequested() const; 58 59 … … 86 87 OwnPtr<SQLTransactionClient> m_transactionClient; 87 88 OwnPtr<SQLTransactionCoordinator> m_transactionCoordinator; 89 DatabaseTaskSynchronizer* m_cleanupSync; 88 90 }; 89 91 -
trunk/WebCore/storage/DatabaseTracker.cpp
r52314 r53595 37 37 #include "DatabaseThread.h" 38 38 #include "DatabaseTrackerClient.h" 39 #include "Document.h"40 39 #include "Logging.h" 41 40 #include "OriginQuotaManager.h" 42 41 #include "Page.h" 42 #include "ScriptExecutionContext.h" 43 43 #include "SecurityOrigin.h" 44 44 #include "SecurityOriginHash.h" … … 121 121 } 122 122 123 bool DatabaseTracker::canEstablishDatabase( Document* document, const String& name, const String& displayName, unsigned long estimatedSize)123 bool DatabaseTracker::canEstablishDatabase(ScriptExecutionContext* context, const String& name, const String& displayName, unsigned long estimatedSize) 124 124 { 125 125 ASSERT(currentThread() == m_thread); … … 129 129 populateOrigins(); 130 130 131 SecurityOrigin* origin = document->securityOrigin();132 133 // Since we're imminently opening a database within this Document's origin, make sure this origin is being tracked by the QuotaTracker131 SecurityOrigin* origin = context->securityOrigin(); 132 133 // Since we're imminently opening a database within this context's origin, make sure this origin is being tracked by the QuotaTracker 134 134 // by fetching it's current usage now 135 135 unsigned long long usage = usageForOrigin(origin); … … 148 148 // Give the chrome client a chance to increase the quota. 149 149 // Temporarily make the details of the proposed database available, so the client can get at them. 150 Page* page = document->page();151 if (!page)152 return false;153 150 pair<SecurityOrigin*, DatabaseDetails> details(origin, DatabaseDetails(name, displayName, estimatedSize, 0)); 154 151 m_proposedDatabase = &details; 155 page->chrome()->client()->exceededDatabaseQuota(document->frame(),name);152 context->databaseExceededQuota(name); 156 153 m_proposedDatabase = 0; 157 154 … … 187 184 unsigned long long DatabaseTracker::getMaxSizeForDatabase(const Database* database) 188 185 { 189 ASSERT(currentThread() == database-> document()->databaseThread()->getThreadID());186 ASSERT(currentThread() == database->scriptExecutionContext()->databaseThread()->getThreadID()); 190 187 // The maximum size for a database is the full quota for its origin, minus the current usage within the origin, 191 188 // plus the current usage of the given database -
trunk/WebCore/storage/DatabaseTracker.h
r52314 r53595 46 46 47 47 class Database; 48 class Document;48 class ScriptExecutionContext; 49 49 class SecurityOrigin; 50 50 … … 60 60 public: 61 61 static DatabaseTracker& tracker(); 62 // FIXME: Due to workers having multiple threads in a single process sharing 63 // a DatabaseTracker, this singleton will have to be synchronized or moved 64 // to TLS. 62 65 63 bool canEstablishDatabase( Document*, const String& name, const String& displayName, unsigned long estimatedSize);66 bool canEstablishDatabase(ScriptExecutionContext*, const String& name, const String& displayName, unsigned long estimatedSize); 64 67 void setDatabaseDetails(SecurityOrigin*, const String& name, const String& displayName, unsigned long estimatedSize); 65 68 String fullPathForDatabase(SecurityOrigin*, const String& name, bool createIfDoesNotExist = true); -
trunk/WebCore/storage/SQLTransaction.cpp
r50169 r53595 36 36 #include "DatabaseAuthorizer.h" 37 37 #include "DatabaseDetails.h" 38 #include "Document.h"39 38 #include "ExceptionCode.h" 40 39 #include "Logging.h" 41 40 #include "Page.h" 42 41 #include "PlatformString.h" 42 #include "ScriptExecutionContext.h" 43 43 #include "Settings.h" 44 44 #include "SQLError.h" … … 95 95 bool readOnlyMode = m_readOnly; 96 96 if (!readOnlyMode) { 97 Page* page = m_database->document()->page(); 98 if (!page || page->settings()->privateBrowsingEnabled()) 97 if (m_database->scriptExecutionContext()->isDatabaseReadOnly()) 99 98 readOnlyMode = true; 100 99 } -
trunk/WebCore/storage/SQLTransactionClient.cpp
r52314 r53595 48 48 void SQLTransactionClient::didCommitTransaction(SQLTransaction* transaction) 49 49 { 50 ASSERT(currentThread() == transaction->database()-> document()->databaseThread()->getThreadID());50 ASSERT(currentThread() == transaction->database()->scriptExecutionContext()->databaseThread()->getThreadID()); 51 51 Database* database = transaction->database(); 52 52 DatabaseTracker::tracker().scheduleNotifyDatabaseChanged( … … 56 56 void SQLTransactionClient::didExecuteStatement(SQLTransaction* transaction) 57 57 { 58 ASSERT(currentThread() == transaction->database()-> document()->databaseThread()->getThreadID());58 ASSERT(currentThread() == transaction->database()->scriptExecutionContext()->databaseThread()->getThreadID()); 59 59 OriginQuotaManager& manager(DatabaseTracker::tracker().originQuotaManager()); 60 60 Locker<OriginQuotaManager> locker(manager); … … 64 64 bool SQLTransactionClient::didExceedQuota(SQLTransaction* transaction) 65 65 { 66 ASSERT( isMainThread());66 ASSERT(transaction->database()->scriptExecutionContext()->isContextThread()); 67 67 Database* database = transaction->database(); 68 Page* page = database->document()->page();69 ASSERT(page);70 68 71 69 unsigned long long currentQuota = DatabaseTracker::tracker().quotaForOrigin(database->securityOrigin()); 72 page->chrome()->client()->exceededDatabaseQuota(database->document()->frame(),database->stringIdentifier());70 database->scriptExecutionContext()->databaseExceededQuota(database->stringIdentifier()); 73 71 unsigned long long newQuota = DatabaseTracker::tracker().quotaForOrigin(database->securityOrigin()); 74 72 return (newQuota > currentQuota); -
trunk/WebCore/storage/chromium/DatabaseTrackerChromium.cpp
r52372 r53595 36 36 #include "DatabaseObserver.h" 37 37 #include "DatabaseThread.h" 38 #include "Document.h"39 38 #include "QuotaTracker.h" 39 #include "ScriptExecutionContext.h" 40 40 #include "SecurityOrigin.h" 41 41 #include "SQLiteFileSystem.h" … … 57 57 } 58 58 59 bool DatabaseTracker::canEstablishDatabase( Document*, const String&, const String&, unsigned long)59 bool DatabaseTracker::canEstablishDatabase(ScriptExecutionContext*, const String&, const String&, unsigned long) 60 60 { 61 61 // In Chromium, a database can always be established (even though we might not … … 76 76 void DatabaseTracker::addOpenDatabase(Database* database) 77 77 { 78 ASSERT( isMainThread());78 ASSERT(database->scriptExecutionContext()->isContextThread()); 79 79 DatabaseObserver::databaseOpened(database); 80 80 } 81 static void removeOpenDatabaseOnMainThread(void* context) 82 { 83 Database* database = static_cast<Database*>(context); 84 DatabaseTracker::tracker().removeOpenDatabase(database); 85 database->deref(); 86 } 81 82 class TrackerRemoveOpenDatabaseTask : public ScriptExecutionContext::Task { 83 public: 84 static PassOwnPtr<TrackerRemoveOpenDatabaseTask> create(PassRefPtr<Database> database) 85 { 86 return new TrackerRemoveOpenDatabaseTask(database); 87 } 88 89 virtual void performTask(ScriptExecutionContext* context) 90 { 91 DatabaseTracker::tracker().removeOpenDatabase(m_database.get()); 92 } 93 94 private: 95 TrackerRemoveOpenDatabaseTask(PassRefPtr<Database> database) 96 : m_database(database) 97 { 98 } 99 100 RefPtr<Database> m_database; 101 }; 87 102 88 103 void DatabaseTracker::removeOpenDatabase(Database* database) 89 104 { 90 if (!isMainThread()) { 91 database->ref(); 92 callOnMainThread(removeOpenDatabaseOnMainThread, database); 105 if (!database->scriptExecutionContext()->isContextThread()) { 106 database->scriptExecutionContext()->postTask(TrackerRemoveOpenDatabaseTask::create(database)); 93 107 return; 94 108 } … … 99 113 unsigned long long DatabaseTracker::getMaxSizeForDatabase(const Database* database) 100 114 { 101 ASSERT(currentThread() == database-> document()->databaseThread()->getThreadID());115 ASSERT(currentThread() == database->scriptExecutionContext()->databaseThread()->getThreadID()); 102 116 unsigned long long spaceAvailable = 0; 103 117 unsigned long long databaseSize = 0; -
trunk/WebCore/storage/chromium/SQLTransactionClientChromium.cpp
r50434 r53595 39 39 #include <wtf/MainThread.h> 40 40 41 static void notifyDatabaseChanged(void* context) { 42 WebCore::Database* database = static_cast<WebCore::Database*>(context); 43 WebCore::DatabaseObserver::databaseModified(database); 44 database->deref(); // ref()'d in didCommitTransaction() 45 } 41 namespace WebCore { 46 42 47 namespace WebCore { 43 class NotifyDatabaseChangedTask : public ScriptExecutionContext::Task { 44 public: 45 static PassOwnPtr<NotifyDatabaseChangedTask> create(Database *database) 46 { 47 return new NotifyDatabaseChangedTask(database); 48 } 49 50 virtual void performTask(ScriptExecutionContext*) 51 { 52 WebCore::DatabaseObserver::databaseModified(m_database.get()); 53 } 54 55 private: 56 NotifyDatabaseChangedTask(PassRefPtr<Database> database) 57 : m_database(database) 58 { 59 } 60 61 RefPtr<Database> m_database; 62 }; 48 63 49 64 void SQLTransactionClient::didCommitTransaction(SQLTransaction* transaction) 50 65 { 51 ASSERT(currentThread() == transaction->database()-> document()->databaseThread()->getThreadID());66 ASSERT(currentThread() == transaction->database()->scriptExecutionContext()->databaseThread()->getThreadID()); 52 67 if (!transaction->isReadOnly()) { 53 transaction->database()->ref(); // deref()'d in notifyDatabaseChanged() 54 callOnMainThread(notifyDatabaseChanged, transaction->database()); 68 transaction->database()->scriptExecutionContext()->postTask(NotifyDatabaseChangedTask::create(transaction->database())); 55 69 } 56 70 } … … 60 74 // This method is called after executing every statement that changes the DB. 61 75 // Chromium doesn't need to do anything at that point. 62 ASSERT(currentThread() == transaction->database()-> document()->databaseThread()->getThreadID());76 ASSERT(currentThread() == transaction->database()->scriptExecutionContext()->databaseThread()->getThreadID()); 63 77 } 64 78 65 bool SQLTransactionClient::didExceedQuota(SQLTransaction* )79 bool SQLTransactionClient::didExceedQuota(SQLTransaction* transaction) 66 80 { 67 81 // Chromium does not allow users to manually change the quota for an origin (for now, at least). 68 82 // Don't do anything. 69 ASSERT( isMainThread());83 ASSERT(transaction->database()->scriptExecutionContext()->isContextThread()); 70 84 return false; 71 85 } -
trunk/WebCore/workers/WorkerContext.cpp
r50427 r53595 33 33 34 34 #include "ActiveDOMObject.h" 35 #include "Database.h" 35 36 #include "DOMTimer.h" 36 37 #include "DOMWindow.h" … … 255 256 #endif 256 257 258 #if ENABLE(DATABASE) 259 PassRefPtr<Database> WorkerContext::openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, ExceptionCode& ec) 260 { 261 if (!securityOrigin()->canAccessDatabase()) { 262 ec = SECURITY_ERR; 263 return 0; 264 } 265 266 ASSERT(Database::isAvailable()); 267 if (!Database::isAvailable()) 268 return 0; 269 270 return Database::openDatabase(this, name, version, displayName, estimatedSize, ec); 271 } 272 #endif 273 274 bool WorkerContext::isContextThread() const 275 { 276 return currentThread() == thread()->threadID(); 277 } 278 257 279 EventTargetData* WorkerContext::eventTargetData() 258 280 { -
trunk/WebCore/workers/WorkerContext.h
r50427 r53595 31 31 32 32 #include "AtomicStringHash.h" 33 #include "Database.h" 33 34 #include "EventListener.h" 34 35 #include "EventNames.h" … … 36 37 #include "ScriptExecutionContext.h" 37 38 #include "WorkerScriptController.h" 39 #include <wtf/Assertions.h> 38 40 #include <wtf/OwnPtr.h> 39 41 #include <wtf/PassRefPtr.h> … … 43 45 namespace WebCore { 44 46 47 class Database; 45 48 class NotificationCenter; 46 49 class ScheduledAction; … … 66 69 67 70 WorkerScriptController* script() { return m_script.get(); } 68 void clearScript() { returnm_script.clear(); }71 void clearScript() { m_script.clear(); } 69 72 70 WorkerThread* thread() { return m_thread; }73 WorkerThread* thread() const { return m_thread; } 71 74 72 75 bool hasPendingActivity() const; … … 101 104 NotificationCenter* webkitNotifications() const; 102 105 #endif 106 107 #if ENABLE(DATABASE) 108 // HTML 5 client-side database 109 PassRefPtr<Database> openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, ExceptionCode&); 110 // Not implemented yet. 111 virtual bool isDatabaseReadOnly() const { return false; } 112 // Not implemented yet. 113 virtual void databaseExceededQuota(const String&) { } 114 #endif 115 virtual bool isContextThread() const; 116 103 117 104 118 // These methods are used for GC marking. See JSWorkerContext::markChildren(MarkStack&) in -
trunk/WebCore/workers/WorkerRunLoop.cpp
r50427 r53595 153 153 OwnPtr<WorkerRunLoop::Task> task = m_messageQueue.waitForMessageFilteredWithTimeout(result, predicate, absoluteTime); 154 154 155 // If the context is closing, don't dispatch any further tasks (per section 4.1.1 of the Web Workers spec). 156 if (context->isClosing()) 157 return result; 155 // If the context is closing, don't execute any further JavaScript tasks (per section 4.1.1 of the Web Workers spec). However, there may be implementation cleanup tasks in the queue, so keep running through it. 158 156 159 157 switch (result) { … … 166 164 167 165 case MessageQueueTimeout: 168 m_sharedTimer->fire(); 166 if (!context->isClosing()) 167 m_sharedTimer->fire(); 169 168 break; 170 169 } … … 195 194 void WorkerRunLoop::Task::performTask(ScriptExecutionContext* context) 196 195 { 197 m_task->performTask(context); 196 WorkerContext* workerContext = static_cast<WorkerContext *>(context); 197 if (!workerContext->isClosing() || m_task->isCleanupTask()) 198 m_task->performTask(context); 198 199 } 199 200 -
trunk/WebCore/workers/WorkerThread.cpp
r49734 r53595 31 31 #include "WorkerThread.h" 32 32 33 #include "DatabaseTask.h" 33 34 #include "DedicatedWorkerContext.h" 34 35 #include "KURL.h" … … 136 137 ThreadIdentifier threadID = m_threadID; 137 138 138 m_workerContext->stopActiveDOMObjects();139 m_workerContext->clearScript();140 139 ASSERT(m_workerContext->hasOneRef()); 140 141 141 // The below assignment will destroy the context, which will in turn notify messaging proxy. 142 142 // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them. … … 155 155 } 156 156 157 class WorkerThreadShutdownFinishTask : public ScriptExecutionContext::Task { 158 public: 159 static PassOwnPtr<WorkerThreadShutdownFinishTask> create() 160 { 161 return new WorkerThreadShutdownFinishTask(); 162 } 163 164 virtual void performTask(ScriptExecutionContext *context) 165 { 166 ASSERT(context->isWorkerContext()); 167 WorkerContext* workerContext = static_cast<WorkerContext*>(context); 168 workerContext->thread()->runLoop().terminate(); 169 } 170 171 virtual bool isCleanupTask() const { return true; } 172 }; 173 174 class WorkerThreadShutdownStartTask : public ScriptExecutionContext::Task { 175 public: 176 static PassOwnPtr<WorkerThreadShutdownStartTask> create() 177 { 178 return new WorkerThreadShutdownStartTask(); 179 } 180 181 virtual void performTask(ScriptExecutionContext *context) 182 { 183 ASSERT(context->isWorkerContext()); 184 WorkerContext* workerContext = static_cast<WorkerContext*>(context); 185 186 // We currently ignore any DatabasePolicy used for the document's 187 // databases; if it's actually used anywhere, this should be revisited. 188 DatabaseTaskSynchronizer cleanupSync; 189 workerContext->stopDatabases(&cleanupSync); 190 191 workerContext->stopActiveDOMObjects(); 192 workerContext->clearScript(); 193 194 // We wait for the database thread to clean up all its stuff so that we 195 // can do more stringent leak checks as we exit. 196 cleanupSync.waitForTaskCompletion(); 197 198 // Stick a shutdown command at the end of the queue, so that we deal 199 // with all the cleanup tasks the databases post first. 200 workerContext->postTask(WorkerThreadShutdownFinishTask::create()); 201 } 202 203 virtual bool isCleanupTask() const { return true; } 204 }; 205 157 206 void WorkerThread::stop() 158 207 { … … 161 210 162 211 // Ensure that tasks are being handled by thread event loop. If script execution weren't forbidden, a while(1) loop in JS could keep the thread alive forever. 163 if (m_workerContext) 212 if (m_workerContext) { 164 213 m_workerContext->script()->forbidExecution(); 165 214 166 215 // FIXME: Rudely killing the thread won't work when we allow nested workers, because they will try to post notifications of their destruction. 167 m_runLoop.terminate(); 216 // This can likely use the same mechanism as used for databases above. 217 218 m_runLoop.postTask(WorkerThreadShutdownStartTask::create()); 219 } else 220 m_runLoop.terminate(); 168 221 } 169 222
Note: See TracChangeset
for help on using the changeset viewer.