| OLD | NEW | 
 | (Empty) | 
|    1 /* |  | 
|    2  * Copyright (C) 2013 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 "WorkerStorageQuotaCallbacksBridge.h" |  | 
|   33  |  | 
|   34 #include "WebCommonWorkerClient.h" |  | 
|   35 #include "WebStorageQuotaCallbacks.h" |  | 
|   36 #include "WebStorageQuotaCallbacksImpl.h" |  | 
|   37 #include "WebWorkerBase.h" |  | 
|   38 #include "core/dom/CrossThreadTask.h" |  | 
|   39 #include "core/workers/WorkerGlobalScope.h" |  | 
|   40 #include "core/workers/WorkerLoaderProxy.h" |  | 
|   41 #include "wtf/MainThread.h" |  | 
|   42  |  | 
|   43 using namespace WebCore; |  | 
|   44  |  | 
|   45 namespace WebKit { |  | 
|   46  |  | 
|   47 // FIXME: Replace WebFrame parameter in queryStorageUsageAndQuota() with WebStri
     ng and move the method to Platform so that we can remove all these complexity fo
     r Worker. |  | 
|   48 class MainThreadStorageQuotaCallbacks : public WebStorageQuotaCallbacks { |  | 
|   49 public: |  | 
|   50     // Callbacks are self-destructed and we always return leaked pointer here. |  | 
|   51     static MainThreadStorageQuotaCallbacks* createLeakedPtr(PassRefPtr<WorkerSto
     rageQuotaCallbacksBridge> bridge, const String& mode) |  | 
|   52     { |  | 
|   53         OwnPtr<MainThreadStorageQuotaCallbacks> callbacks = adoptPtr(new MainThr
     eadStorageQuotaCallbacks(bridge, mode)); |  | 
|   54         return callbacks.leakPtr(); |  | 
|   55     } |  | 
|   56  |  | 
|   57     virtual ~MainThreadStorageQuotaCallbacks() |  | 
|   58     { |  | 
|   59     } |  | 
|   60  |  | 
|   61     virtual void didQueryStorageUsageAndQuota(unsigned long long usageInBytes, u
     nsigned long long quotaInBytes) |  | 
|   62     { |  | 
|   63         m_bridge->didQueryStorageUsageAndQuotaOnMainThread(usageInBytes, quotaIn
     Bytes, m_mode); |  | 
|   64         delete this; |  | 
|   65     } |  | 
|   66  |  | 
|   67     virtual void didFail(WebStorageQuotaError error) |  | 
|   68     { |  | 
|   69         m_bridge->didFailOnMainThread(error, m_mode); |  | 
|   70         delete this; |  | 
|   71     } |  | 
|   72  |  | 
|   73     virtual void didGrantStorageQuota(unsigned long long grantedQuotaInBytes) |  | 
|   74     { |  | 
|   75         ASSERT_NOT_REACHED(); |  | 
|   76     } |  | 
|   77  |  | 
|   78 private: |  | 
|   79     MainThreadStorageQuotaCallbacks(PassRefPtr<WorkerStorageQuotaCallbacksBridge
     > bridge, const String& mode) |  | 
|   80         : m_bridge(bridge) |  | 
|   81         , m_mode(mode) |  | 
|   82     { |  | 
|   83         ASSERT(m_bridge); |  | 
|   84     } |  | 
|   85  |  | 
|   86     RefPtr<WorkerStorageQuotaCallbacksBridge> m_bridge; |  | 
|   87     const String m_mode; |  | 
|   88 }; |  | 
|   89  |  | 
|   90 // FIXME: Replace WebFrame parameter in queryStorageUsageAndQuota() with WebStri
     ng and move the method to Platform so that we can remove all these complexity fo
     r Worker." |  | 
|   91 // Observes the worker context. By keeping this separate, it is easier to verify |  | 
|   92 // that it only gets deleted on the worker context thread which is verified by ~
     Observer. |  | 
|   93 class WorkerStorageQuotaContextObserver : public WebCore::WorkerGlobalScope::Obs
     erver { |  | 
|   94 public: |  | 
|   95     static PassOwnPtr<WorkerStorageQuotaContextObserver> create(WorkerGlobalScop
     e* context, PassRefPtr<WorkerStorageQuotaCallbacksBridge> bridge) |  | 
|   96     { |  | 
|   97         return adoptPtr(new WorkerStorageQuotaContextObserver(context, bridge)); |  | 
|   98     } |  | 
|   99  |  | 
|  100     // WorkerGlobalScope::Observer method. |  | 
|  101     virtual void notifyStop() |  | 
|  102     { |  | 
|  103         m_bridge->stop(); |  | 
|  104     } |  | 
|  105  |  | 
|  106 private: |  | 
|  107     WorkerStorageQuotaContextObserver(WorkerGlobalScope* context, PassRefPtr<Wor
     kerStorageQuotaCallbacksBridge> bridge) |  | 
|  108         : WebCore::WorkerGlobalScope::Observer(context) |  | 
|  109         , m_bridge(bridge) |  | 
|  110     { |  | 
|  111     } |  | 
|  112  |  | 
|  113     RefPtr<WorkerStorageQuotaCallbacksBridge> m_bridge; |  | 
|  114 }; |  | 
|  115  |  | 
|  116 void WorkerStorageQuotaCallbacksBridge::stop() |  | 
|  117 { |  | 
|  118     ASSERT(m_workerGlobalScope->isContextThread()); |  | 
|  119     { |  | 
|  120         MutexLocker locker(m_loaderProxyMutex); |  | 
|  121         m_workerLoaderProxy = 0; |  | 
|  122     } |  | 
|  123  |  | 
|  124     if (m_callbacksOnWorkerThread) |  | 
|  125         m_callbacksOnWorkerThread->didFail(WebStorageQuotaErrorAbort); |  | 
|  126  |  | 
|  127     cleanUpAfterCallback(); |  | 
|  128 } |  | 
|  129  |  | 
|  130 void WorkerStorageQuotaCallbacksBridge::cleanUpAfterCallback() |  | 
|  131 { |  | 
|  132     ASSERT(m_workerGlobalScope->isContextThread()); |  | 
|  133  |  | 
|  134     m_callbacksOnWorkerThread = 0; |  | 
|  135     if (m_workerGlobalScopeObserver) { |  | 
|  136         WorkerStorageQuotaContextObserver* observer = m_workerGlobalScopeObserve
     r; |  | 
|  137         m_workerGlobalScopeObserver = 0; |  | 
|  138         // The next line may delete this. |  | 
|  139         delete observer; |  | 
|  140     } |  | 
|  141 } |  | 
|  142  |  | 
|  143 WorkerStorageQuotaCallbacksBridge::WorkerStorageQuotaCallbacksBridge(WebCore::Wo
     rkerLoaderProxy* workerLoaderProxy, WebCore::ScriptExecutionContext* workerGloba
     lScope, WebStorageQuotaCallbacksImpl* callbacks) |  | 
|  144     : m_workerLoaderProxy(workerLoaderProxy) |  | 
|  145     , m_workerGlobalScope(workerGlobalScope) |  | 
|  146     , m_workerGlobalScopeObserver(WorkerStorageQuotaContextObserver::create(toWo
     rkerGlobalScope(m_workerGlobalScope), this).leakPtr()) |  | 
|  147     , m_callbacksOnWorkerThread(callbacks) |  | 
|  148 { |  | 
|  149     ASSERT(m_workerGlobalScope->isContextThread()); |  | 
|  150 } |  | 
|  151  |  | 
|  152 WorkerStorageQuotaCallbacksBridge::~WorkerStorageQuotaCallbacksBridge() |  | 
|  153 { |  | 
|  154     // One way or another, the bridge should be stopped before it is destroyed. |  | 
|  155     ASSERT(!m_callbacksOnWorkerThread); |  | 
|  156 } |  | 
|  157  |  | 
|  158 void WorkerStorageQuotaCallbacksBridge::postQueryUsageAndQuotaToMainThread(WebCo
     mmonWorkerClient* commonClient, WebStorageQuotaType storageType, const String& m
     ode) |  | 
|  159 { |  | 
|  160     dispatchTaskToMainThread(createCallbackTask(&queryUsageAndQuotaOnMainThread,
      AllowCrossThreadAccess(commonClient), storageType, this, mode)); |  | 
|  161 } |  | 
|  162  |  | 
|  163 void WorkerStorageQuotaCallbacksBridge::queryUsageAndQuotaOnMainThread(ScriptExe
     cutionContext*, WebCommonWorkerClient* commonClient, WebStorageQuotaType storage
     Type, PassRefPtr<WorkerStorageQuotaCallbacksBridge> bridge, const String& mode) |  | 
|  164 { |  | 
|  165     if (!commonClient) |  | 
|  166         bridge->didFailOnMainThread(WebStorageQuotaErrorAbort, mode); |  | 
|  167     else |  | 
|  168         commonClient->queryUsageAndQuota(storageType, MainThreadStorageQuotaCall
     backs::createLeakedPtr(bridge, mode)); |  | 
|  169 } |  | 
|  170  |  | 
|  171 void WorkerStorageQuotaCallbacksBridge::didFailOnMainThread(WebStorageQuotaError
      error, const String& mode) |  | 
|  172 { |  | 
|  173     mayPostTaskToWorker(createCallbackTask(&didFailOnWorkerThread, this, error),
      mode); |  | 
|  174 } |  | 
|  175  |  | 
|  176 void WorkerStorageQuotaCallbacksBridge::didQueryStorageUsageAndQuotaOnMainThread
     (unsigned long long usageInBytes, unsigned long long quotaInBytes, const String&
      mode) |  | 
|  177 { |  | 
|  178     mayPostTaskToWorker(createCallbackTask(&didQueryStorageUsageAndQuotaOnWorker
     Thread, this, usageInBytes, quotaInBytes), mode); |  | 
|  179 } |  | 
|  180  |  | 
|  181 void WorkerStorageQuotaCallbacksBridge::didFailOnWorkerThread(WebCore::ScriptExe
     cutionContext*, PassRefPtr<WorkerStorageQuotaCallbacksBridge> bridge, WebStorage
     QuotaError error) |  | 
|  182 { |  | 
|  183     bridge->m_callbacksOnWorkerThread->didFail(error); |  | 
|  184 } |  | 
|  185  |  | 
|  186 void WorkerStorageQuotaCallbacksBridge::didQueryStorageUsageAndQuotaOnWorkerThre
     ad(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerStorageQuotaCallbacksBridg
     e> bridge, unsigned long long usageInBytes, unsigned long long quotaInBytes) |  | 
|  187 { |  | 
|  188     bridge->m_callbacksOnWorkerThread->didQueryStorageUsageAndQuota(usageInBytes
     , quotaInBytes); |  | 
|  189 } |  | 
|  190  |  | 
|  191 void WorkerStorageQuotaCallbacksBridge::runTaskOnMainThread(WebCore::ScriptExecu
     tionContext* scriptExecutionContext, PassRefPtr<WorkerStorageQuotaCallbacksBridg
     e> bridge, PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun) |  | 
|  192 { |  | 
|  193     ASSERT(isMainThread()); |  | 
|  194     taskToRun->performTask(scriptExecutionContext); |  | 
|  195 } |  | 
|  196  |  | 
|  197 void WorkerStorageQuotaCallbacksBridge::runTaskOnWorkerThread(WebCore::ScriptExe
     cutionContext* scriptExecutionContext, PassRefPtr<WorkerStorageQuotaCallbacksBri
     dge> bridge, PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun) |  | 
|  198 { |  | 
|  199     ASSERT(bridge); |  | 
|  200     if (!bridge->m_callbacksOnWorkerThread) |  | 
|  201         return; |  | 
|  202     ASSERT(bridge->m_workerGlobalScope); |  | 
|  203     ASSERT(bridge->m_workerGlobalScope->isContextThread()); |  | 
|  204     ASSERT(taskToRun); |  | 
|  205     taskToRun->performTask(scriptExecutionContext); |  | 
|  206  |  | 
|  207     // taskToRun does the callback. |  | 
|  208     bridge->cleanUpAfterCallback(); |  | 
|  209  |  | 
|  210     // WorkerStorageQuotaCallbacksBridge may be deleted here when bridge goes ou
     t of scope. |  | 
|  211 } |  | 
|  212  |  | 
|  213 void WorkerStorageQuotaCallbacksBridge::dispatchTaskToMainThread(PassOwnPtr<WebC
     ore::ScriptExecutionContext::Task> task) |  | 
|  214 { |  | 
|  215     ASSERT(m_workerLoaderProxy); |  | 
|  216     ASSERT(m_workerGlobalScope->isContextThread()); |  | 
|  217     WebWorkerBase::dispatchTaskToMainThread(createCallbackTask(&runTaskOnMainThr
     ead, RefPtr<WorkerStorageQuotaCallbacksBridge>(this).release(), task)); |  | 
|  218 } |  | 
|  219  |  | 
|  220 void WorkerStorageQuotaCallbacksBridge::mayPostTaskToWorker(PassOwnPtr<ScriptExe
     cutionContext::Task> task, const String& mode) |  | 
|  221 { |  | 
|  222     // Relies on its caller (MainThreadStorageQuotaCallbacks:did*) to keep Worke
     rStorageQuotaCallbacksBridge alive. |  | 
|  223     ASSERT(isMainThread()); |  | 
|  224  |  | 
|  225     MutexLocker locker(m_loaderProxyMutex); |  | 
|  226     if (m_workerLoaderProxy) |  | 
|  227         m_workerLoaderProxy->postTaskForModeToWorkerGlobalScope(createCallbackTa
     sk(&runTaskOnWorkerThread, this, task), mode); |  | 
|  228 } |  | 
|  229  |  | 
|  230 } // namespace WebCore |  | 
| OLD | NEW |