1 /* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "modules/webdatabase/DatabaseObserver.h" 33 34 #include "WebCommonWorkerClient.h" 35 #include "WebDatabase.h" 36 #include "WebDatabaseObserver.h" 37 #include "WebFrameClient.h" 38 #include "WebFrameImpl.h" 39 #include "WebPermissionClient.h" 40 #include "WebSecurityOrigin.h" 41 #include "WebViewImpl.h" 42 #include "WebWorkerBase.h" 43 #include "WorkerAllowMainThreadBridgeBase.h" 44 #include "bindings/v8/WorkerScriptController.h" 45 #include "core/dom/CrossThreadTask.h" 46 #include "core/dom/Document.h" 47 #include "core/dom/ScriptExecutionContext.h" 48 #include "core/platform/CrossThreadCopier.h" 49 #include "core/workers/WorkerGlobalScope.h" 50 #include "core/workers/WorkerLoaderProxy.h" 51 #include "core/workers/WorkerThread.h" 52 #include "modules/webdatabase/DatabaseBackendBase.h" 53 #include "modules/webdatabase/DatabaseBackendContext.h" 54 55 using namespace WebKit; 56 57 namespace { 58 59 static const char allowDatabaseMode[] = "allowDatabaseMode"; 60 61 // This class is used to route the result of the WebWorkerBase::allowDatabase 62 // call back to the worker context. 63 class AllowDatabaseMainThreadBridge : public WorkerAllowMainThreadBridgeBase { 64 public: 65 static PassRefPtr<AllowDatabaseMainThreadBridge> create(WebCore::WorkerGlobalScope* workerGlobalScope, WebWorkerBase* webWorkerBase, const String& mode, WebFrame* frame, const String& name, const String& displayName, unsigned long estimatedSize) 66 { 67 return adoptRef(new AllowDatabaseMainThreadBridge(workerGlobalScope, webWorkerBase, mode, frame, name, displayName, estimatedSize)); 68 } 69 70 private: 71 class AllowDatabaseParams : public AllowParams 72 { 73 public: 74 AllowDatabaseParams(const String& mode, WebFrame* frame, const String& name, const String& displayName, unsigned long estimatedSize) 75 : AllowParams(mode) 76 , m_frame(WebCore::AllowCrossThreadAccess(frame)) 77 , m_name(name.isolatedCopy()) 78 , m_displayName(displayName.isolatedCopy()) 79 , m_estimatedSize(estimatedSize) 80 { 81 } 82 WebCore::AllowCrossThreadAccessWrapper<WebFrame> m_frame; 83 String m_name; 84 String m_displayName; 85 unsigned long m_estimatedSize; 86 }; 87 88 AllowDatabaseMainThreadBridge(WebCore::WorkerGlobalScope* workerGlobalScope, WebWorkerBase* webWorkerBase, const String& mode, WebFrame* frame, const String& name, const String& displayName, unsigned long estimatedSize) 89 : WorkerAllowMainThreadBridgeBase(workerGlobalScope, webWorkerBase) 90 { 91 postTaskToMainThread( 92 adoptPtr(new AllowDatabaseParams(mode, frame, name, displayName, estimatedSize))); 93 } 94 95 virtual bool allowOnMainThread(WebCommonWorkerClient* commonClient, AllowParams* params) 96 { 97 ASSERT(isMainThread()); 98 AllowDatabaseParams* allowDBParams = static_cast<AllowDatabaseParams*>(params); 99 return commonClient->allowDatabase( 100 allowDBParams->m_frame.value(), allowDBParams->m_name, allowDBParams->m_displayName, allowDBParams->m_estimatedSize); 101 } 102 }; 103 104 bool allowDatabaseForWorker(WebFrame* frame, const WebString& name, const WebString& displayName, unsigned long estimatedSize) 105 { 106 WebCore::WorkerScriptController* controller = WebCore::WorkerScriptController::controllerForContext(); 107 WebCore::WorkerGlobalScope* workerGlobalScope = controller->workerGlobalScope(); 108 WebCore::WorkerThread* workerThread = workerGlobalScope->thread(); 109 WebCore::WorkerRunLoop& runLoop = workerThread->runLoop(); 110 WebCore::WorkerLoaderProxy* workerLoaderProxy = &workerThread->workerLoaderProxy(); 111 112 // Create a unique mode just for this synchronous call. 113 String mode = allowDatabaseMode; 114 mode.append(String::number(runLoop.createUniqueId())); 115 116 RefPtr<AllowDatabaseMainThreadBridge> bridge = AllowDatabaseMainThreadBridge::create(workerGlobalScope, workerLoaderProxy->toWebWorkerBase(), mode, frame, name, displayName, estimatedSize); 117 118 // Either the bridge returns, or the queue gets terminated. 119 if (runLoop.runInMode(workerGlobalScope, mode) == MessageQueueTerminated) { 120 bridge->cancel(); 121 return false; 122 } 123 124 return bridge->result(); 125 } 126 127 } 128 129 namespace WebCore { 130 131 bool DatabaseObserver::canEstablishDatabase(ScriptExecutionContext* scriptExecutionContext, const String& name, const String& displayName, unsigned long estimatedSize) 132 { 133 ASSERT(scriptExecutionContext->isContextThread()); 134 ASSERT(scriptExecutionContext->isDocument() || scriptExecutionContext->isWorkerGlobalScope()); 135 if (scriptExecutionContext->isDocument()) { 136 Document* document = toDocument(scriptExecutionContext); 137 WebFrameImpl* webFrame = WebFrameImpl::fromFrame(document->frame()); 138 if (!webFrame) 139 return false; 140 WebViewImpl* webView = webFrame->viewImpl(); 141 if (!webView) 142 return false; 143 if (webView->permissionClient()) 144 return webView->permissionClient()->allowDatabase(webFrame, name, displayName, estimatedSize); 145 } else { 146 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(scriptExecutionContext); 147 WebWorkerBase* webWorker = static_cast<WebWorkerBase*>(workerGlobalScope->thread()->workerLoaderProxy().toWebWorkerBase()); 148 WebView* view = webWorker->view(); 149 if (!view) 150 return false; 151 return allowDatabaseForWorker(view->mainFrame(), name, displayName, estimatedSize); 152 } 153 154 return true; 155 } 156 157 void DatabaseObserver::databaseOpened(DatabaseBackendBase* database) 158 { 159 ASSERT(database->databaseContext()->scriptExecutionContext()->isContextThread()); 160 WebDatabase::observer()->databaseOpened(WebDatabase(database)); 161 } 162 163 void DatabaseObserver::databaseModified(DatabaseBackendBase* database) 164 { 165 ASSERT(database->databaseContext()->scriptExecutionContext()->isContextThread()); 166 WebDatabase::observer()->databaseModified(WebDatabase(database)); 167 } 168 169 void DatabaseObserver::databaseClosed(DatabaseBackendBase* database) 170 { 171 ASSERT(database->databaseContext()->scriptExecutionContext()->isContextThread()); 172 WebDatabase::observer()->databaseClosed(WebDatabase(database)); 173 } 174 175 void DatabaseObserver::reportOpenDatabaseResult(DatabaseBackendBase* database, int errorSite, int webSqlErrorCode, int sqliteErrorCode) 176 { 177 WebDatabase::observer()->reportOpenDatabaseResult(WebDatabase(database), errorSite, webSqlErrorCode, sqliteErrorCode); 178 } 179 180 void DatabaseObserver::reportChangeVersionResult(DatabaseBackendBase* database, int errorSite, int webSqlErrorCode, int sqliteErrorCode) 181 { 182 WebDatabase::observer()->reportChangeVersionResult(WebDatabase(database), errorSite, webSqlErrorCode, sqliteErrorCode); 183 } 184 185 void DatabaseObserver::reportStartTransactionResult(DatabaseBackendBase* database, int errorSite, int webSqlErrorCode, int sqliteErrorCode) 186 { 187 WebDatabase::observer()->reportStartTransactionResult(WebDatabase(database), errorSite, webSqlErrorCode, sqliteErrorCode); 188 } 189 190 void DatabaseObserver::reportCommitTransactionResult(DatabaseBackendBase* database, int errorSite, int webSqlErrorCode, int sqliteErrorCode) 191 { 192 WebDatabase::observer()->reportCommitTransactionResult(WebDatabase(database), errorSite, webSqlErrorCode, sqliteErrorCode); 193 } 194 195 void DatabaseObserver::reportExecuteStatementResult(DatabaseBackendBase* database, int errorSite, int webSqlErrorCode, int sqliteErrorCode) 196 { 197 WebDatabase::observer()->reportExecuteStatementResult(WebDatabase(database), errorSite, webSqlErrorCode, sqliteErrorCode); 198 } 199 200 void DatabaseObserver::reportVacuumDatabaseResult(DatabaseBackendBase* database, int sqliteErrorCode) 201 { 202 WebDatabase::observer()->reportVacuumDatabaseResult(WebDatabase(database), sqliteErrorCode); 203 } 204 205 } // namespace WebCore 206