WinCairo build fails to link.
[WebKit-https.git] / Source / WebKit / chromium / src / WorkerStorageQuotaCallbacksBridge.cpp
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 "CrossThreadTask.h"
35 #include "WebCommonWorkerClient.h"
36 #include "WebStorageQuotaCallbacks.h"
37 #include "WebStorageQuotaCallbacksImpl.h"
38 #include "WebWorkerBase.h"
39 #include "WorkerContext.h"
40 #include "WorkerLoaderProxy.h"
41
42 using namespace WebCore;
43
44 namespace WebKit {
45
46 // FIXME: Replace WebFrame parameter in queryStorageUsageAndQuota() with WebString and move the method to Platform so that we can remove all these complexity for Worker.
47 class MainThreadStorageQuotaCallbacks : public WebStorageQuotaCallbacks {
48 public:
49     // Callbacks are self-destructed and we always return leaked pointer here.
50     static MainThreadStorageQuotaCallbacks* createLeakedPtr(PassRefPtr<WorkerStorageQuotaCallbacksBridge> bridge, const String& mode)
51     {
52         OwnPtr<MainThreadStorageQuotaCallbacks> callbacks = adoptPtr(new MainThreadStorageQuotaCallbacks(bridge, mode));
53         return callbacks.leakPtr();
54     }
55
56     virtual ~MainThreadStorageQuotaCallbacks()
57     {
58     }
59
60     virtual void didQueryStorageUsageAndQuota(unsigned long long usageInBytes, unsigned long long quotaInBytes)
61     {
62         m_bridge->didQueryStorageUsageAndQuotaOnMainThread(usageInBytes, quotaInBytes, m_mode);
63         delete this;
64     }
65
66     virtual void didFail(WebStorageQuotaError error)
67     {
68         m_bridge->didFailOnMainThread(error, m_mode);
69         delete this;
70     }
71
72     virtual void didGrantStorageQuota(unsigned long long grantedQuotaInBytes)
73     {
74         ASSERT_NOT_REACHED();
75     }
76
77 private:
78     MainThreadStorageQuotaCallbacks(PassRefPtr<WorkerStorageQuotaCallbacksBridge> bridge, const String& mode)
79         : m_bridge(bridge)
80         , m_mode(mode)
81     {
82         ASSERT(m_bridge);
83     }
84
85     RefPtr<WorkerStorageQuotaCallbacksBridge> m_bridge;
86     const String m_mode;
87 };
88
89 // FIXME: Replace WebFrame parameter in queryStorageUsageAndQuota() with WebString and move the method to Platform so that we can remove all these complexity for Worker."
90 // Observes the worker context. By keeping this separate, it is easier to verify
91 // that it only gets deleted on the worker context thread which is verified by ~Observer.
92 class WorkerStorageQuotaContextObserver : public WebCore::WorkerContext::Observer {
93 public:
94     static PassOwnPtr<WorkerStorageQuotaContextObserver> create(WorkerContext* context, PassRefPtr<WorkerStorageQuotaCallbacksBridge> bridge)
95     {
96         return adoptPtr(new WorkerStorageQuotaContextObserver(context, bridge));
97     }
98
99     // WorkerContext::Observer method.
100     virtual void notifyStop()
101     {
102         m_bridge->stop();
103     }
104
105 private:
106     WorkerStorageQuotaContextObserver(WorkerContext* context, PassRefPtr<WorkerStorageQuotaCallbacksBridge> bridge)
107         : WebCore::WorkerContext::Observer(context)
108         , m_bridge(bridge)
109     {
110     }
111
112     RefPtr<WorkerStorageQuotaCallbacksBridge> m_bridge;
113 };
114
115 void WorkerStorageQuotaCallbacksBridge::stop()
116 {
117     ASSERT(m_workerContext->isContextThread());
118     {
119         MutexLocker locker(m_loaderProxyMutex);
120         m_workerLoaderProxy = 0;
121     }
122
123     if (m_callbacksOnWorkerThread)
124         m_callbacksOnWorkerThread->didFail(WebStorageQuotaErrorAbort);
125
126     cleanUpAfterCallback();
127 }
128
129 void WorkerStorageQuotaCallbacksBridge::cleanUpAfterCallback()
130 {
131     ASSERT(m_workerContext->isContextThread());
132
133     m_callbacksOnWorkerThread = 0;
134     if (m_workerContextObserver) {
135         WorkerStorageQuotaContextObserver* observer = m_workerContextObserver;
136         m_workerContextObserver = 0;
137         // The next line may delete this.
138         delete observer;
139     }
140 }
141
142 WorkerStorageQuotaCallbacksBridge::WorkerStorageQuotaCallbacksBridge(WebCore::WorkerLoaderProxy* workerLoaderProxy, WebCore::ScriptExecutionContext* workerContext, WebStorageQuotaCallbacksImpl* callbacks)
143     : m_workerLoaderProxy(workerLoaderProxy)
144     , m_workerContext(workerContext)
145     , m_workerContextObserver(WorkerStorageQuotaContextObserver::create(static_cast<WorkerContext*>(m_workerContext), this).leakPtr())
146     , m_callbacksOnWorkerThread(callbacks)
147 {
148     ASSERT(m_workerContext->isContextThread());
149 }
150
151 WorkerStorageQuotaCallbacksBridge::~WorkerStorageQuotaCallbacksBridge()
152 {
153     // One way or another, the bridge should be stopped before it is destroyed.
154     ASSERT(!m_callbacksOnWorkerThread);
155 }
156
157 void WorkerStorageQuotaCallbacksBridge::postQueryUsageAndQuotaToMainThread(WebCommonWorkerClient* commonClient, WebStorageQuotaType storageType, const String& mode)
158 {
159     dispatchTaskToMainThread(createCallbackTask(&queryUsageAndQuotaOnMainThread, AllowCrossThreadAccess(commonClient), storageType, this, mode));
160 }
161
162 void WorkerStorageQuotaCallbacksBridge::queryUsageAndQuotaOnMainThread(ScriptExecutionContext*, WebCommonWorkerClient* commonClient, WebStorageQuotaType storageType, PassRefPtr<WorkerStorageQuotaCallbacksBridge> bridge, const String& mode)
163 {
164     if (!commonClient)
165         bridge->didFailOnMainThread(WebStorageQuotaErrorAbort, mode);
166     else
167         commonClient->queryUsageAndQuota(storageType, MainThreadStorageQuotaCallbacks::createLeakedPtr(bridge, mode));
168 }
169
170 void WorkerStorageQuotaCallbacksBridge::didFailOnMainThread(WebStorageQuotaError error, const String& mode)
171 {
172     mayPostTaskToWorker(createCallbackTask(&didFailOnWorkerThread, this, error), mode);
173 }
174
175 void WorkerStorageQuotaCallbacksBridge::didQueryStorageUsageAndQuotaOnMainThread(unsigned long long usageInBytes, unsigned long long quotaInBytes, const String& mode)
176 {
177     mayPostTaskToWorker(createCallbackTask(&didQueryStorageUsageAndQuotaOnWorkerThread, this, usageInBytes, quotaInBytes), mode);
178 }
179
180 void WorkerStorageQuotaCallbacksBridge::didFailOnWorkerThread(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerStorageQuotaCallbacksBridge> bridge, WebStorageQuotaError error)
181 {
182     bridge->m_callbacksOnWorkerThread->didFail(error);
183 }
184
185 void WorkerStorageQuotaCallbacksBridge::didQueryStorageUsageAndQuotaOnWorkerThread(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerStorageQuotaCallbacksBridge> bridge, unsigned long long usageInBytes, unsigned long long quotaInBytes)
186 {
187     bridge->m_callbacksOnWorkerThread->didQueryStorageUsageAndQuota(usageInBytes, quotaInBytes);
188 }
189
190 void WorkerStorageQuotaCallbacksBridge::runTaskOnMainThread(WebCore::ScriptExecutionContext* scriptExecutionContext, PassRefPtr<WorkerStorageQuotaCallbacksBridge> bridge, PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun)
191 {
192     ASSERT(isMainThread());
193     taskToRun->performTask(scriptExecutionContext);
194 }
195
196 void WorkerStorageQuotaCallbacksBridge::runTaskOnWorkerThread(WebCore::ScriptExecutionContext* scriptExecutionContext, PassRefPtr<WorkerStorageQuotaCallbacksBridge> bridge, PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun)
197 {
198     ASSERT(bridge);
199     if (!bridge->m_callbacksOnWorkerThread)
200         return;
201     ASSERT(bridge->m_workerContext);
202     ASSERT(bridge->m_workerContext->isContextThread());
203     ASSERT(taskToRun);
204     taskToRun->performTask(scriptExecutionContext);
205
206     // taskToRun does the callback.
207     bridge->cleanUpAfterCallback();
208
209     // WorkerStorageQuotaCallbacksBridge may be deleted here when bridge goes out of scope.
210 }
211
212 void WorkerStorageQuotaCallbacksBridge::dispatchTaskToMainThread(PassOwnPtr<WebCore::ScriptExecutionContext::Task> task)
213 {
214     ASSERT(m_workerLoaderProxy);
215     ASSERT(m_workerContext->isContextThread());
216     WebWorkerBase::dispatchTaskToMainThread(createCallbackTask(&runTaskOnMainThread, RefPtr<WorkerStorageQuotaCallbacksBridge>(this).release(), task));
217 }
218
219 void WorkerStorageQuotaCallbacksBridge::mayPostTaskToWorker(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode)
220 {
221     // Relies on its caller (MainThreadStorageQuotaCallbacks:did*) to keep WorkerStorageQuotaCallbacksBridge alive.
222     ASSERT(isMainThread());
223
224     MutexLocker locker(m_loaderProxyMutex);
225     if (m_workerLoaderProxy)
226         m_workerLoaderProxy->postTaskForModeToWorkerContext(createCallbackTask(&runTaskOnWorkerThread, this, task), mode);
227 }
228
229 } // namespace WebCore