Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / loader / WorkerThreadableLoader.cpp
1 /*
2  * Copyright (C) 2009, 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
33 #include "core/loader/WorkerThreadableLoader.h"
34
35 #include "core/dom/CrossThreadTask.h"
36 #include "core/dom/Document.h"
37 #include "core/loader/DocumentThreadableLoader.h"
38 #include "core/loader/WorkerLoaderClientBridgeSyncHelper.h"
39 #include "core/workers/WorkerGlobalScope.h"
40 #include "core/workers/WorkerLoaderProxy.h"
41 #include "core/workers/WorkerThread.h"
42 #include "platform/network/ResourceError.h"
43 #include "platform/network/ResourceRequest.h"
44 #include "platform/network/ResourceResponse.h"
45 #include "platform/weborigin/Referrer.h"
46 #include "public/platform/Platform.h"
47 #include "public/platform/WebWaitableEvent.h"
48 #include "wtf/MainThread.h"
49 #include "wtf/OwnPtr.h"
50 #include "wtf/Vector.h"
51
52 namespace WebCore {
53
54 WorkerThreadableLoader::WorkerThreadableLoader(WorkerGlobalScope& workerGlobalScope, PassRefPtr<ThreadableLoaderClientWrapper> clientWrapper, PassOwnPtr<ThreadableLoaderClient> clientBridge, const ResourceRequest& request, const ThreadableLoaderOptions& options)
55     : m_workerGlobalScope(&workerGlobalScope)
56     , m_workerClientWrapper(clientWrapper)
57     , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, clientBridge, workerGlobalScope.thread()->workerLoaderProxy(), request, options, workerGlobalScope.url().strippedForUseAsReferrer())))
58 {
59 }
60
61 WorkerThreadableLoader::~WorkerThreadableLoader()
62 {
63     m_bridge.destroy();
64 }
65
66 void WorkerThreadableLoader::loadResourceSynchronously(WorkerGlobalScope& workerGlobalScope, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options)
67 {
68     blink::WebWaitableEvent* shutdownEvent =
69         workerGlobalScope.thread()->shutdownEvent();
70     OwnPtr<blink::WebWaitableEvent> loaderDone =
71         adoptPtr(blink::Platform::current()->createWaitableEvent());
72
73     Vector<blink::WebWaitableEvent*> events;
74     events.append(shutdownEvent);
75     events.append(loaderDone.get());
76
77     RefPtr<ThreadableLoaderClientWrapper> clientWrapper(ThreadableLoaderClientWrapper::create(&client));
78     OwnPtr<WorkerLoaderClientBridgeSyncHelper> clientBridge(WorkerLoaderClientBridgeSyncHelper::create(client, loaderDone.release()));
79
80     // This must be valid while loader is around.
81     WorkerLoaderClientBridgeSyncHelper* clientBridgePtr = clientBridge.get();
82
83     RefPtr<WorkerThreadableLoader> loader = WorkerThreadableLoader::create(workerGlobalScope, clientWrapper, clientBridge.release(), request, options);
84
85     blink::WebWaitableEvent* signalled;
86     {
87         ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack);
88         signalled = blink::Platform::current()->waitMultipleEvents(events);
89     }
90     if (signalled == shutdownEvent) {
91         loader->cancel();
92         return;
93     }
94
95     clientBridgePtr->run();
96 }
97
98 void WorkerThreadableLoader::cancel()
99 {
100     m_bridge.cancel();
101 }
102
103 WorkerThreadableLoader::MainThreadBridge::MainThreadBridge(
104     PassRefPtr<ThreadableLoaderClientWrapper> workerClientWrapper,
105     PassOwnPtr<ThreadableLoaderClient> clientBridge,
106     WorkerLoaderProxy& loaderProxy,
107     const ResourceRequest& request, const ThreadableLoaderOptions& options, const String& outgoingReferrer)
108     : m_clientBridge(clientBridge)
109     , m_workerClientWrapper(workerClientWrapper)
110     , m_loaderProxy(loaderProxy)
111 {
112     ASSERT(m_workerClientWrapper.get());
113     ASSERT(m_clientBridge.get());
114     m_loaderProxy.postTaskToLoader(
115         createCallbackTask(&MainThreadBridge::mainThreadCreateLoader,
116                            AllowCrossThreadAccess(this), request, options, outgoingReferrer));
117 }
118
119 WorkerThreadableLoader::MainThreadBridge::~MainThreadBridge()
120 {
121 }
122
123 void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ExecutionContext* context, MainThreadBridge* thisPtr, PassOwnPtr<CrossThreadResourceRequestData> requestData, ThreadableLoaderOptions options, const String& outgoingReferrer)
124 {
125     ASSERT(isMainThread());
126     Document* document = toDocument(context);
127
128     OwnPtr<ResourceRequest> request(ResourceRequest::adopt(requestData));
129     request->setHTTPReferrer(Referrer(outgoingReferrer, ReferrerPolicyDefault));
130     options.requestInitiatorContext = WorkerContext;
131     thisPtr->m_mainThreadLoader = DocumentThreadableLoader::create(*document, thisPtr, *request, options);
132     if (!thisPtr->m_mainThreadLoader) {
133         // DocumentThreadableLoader::create may return 0 when the document loader has been already changed.
134         thisPtr->didFail(ResourceError(errorDomainBlinkInternal, 0, request->url().string(), "Can't create DocumentThreadableLoader"));
135     }
136 }
137
138 void WorkerThreadableLoader::MainThreadBridge::mainThreadDestroy(ExecutionContext* context, MainThreadBridge* thisPtr)
139 {
140     ASSERT(isMainThread());
141     ASSERT_UNUSED(context, context->isDocument());
142     delete thisPtr;
143 }
144
145 void WorkerThreadableLoader::MainThreadBridge::destroy()
146 {
147     // Ensure that no more client callbacks are done in the worker context's thread.
148     clearClientWrapper();
149
150     // "delete this" and m_mainThreadLoader::deref() on the worker object's thread.
151     m_loaderProxy.postTaskToLoader(
152         createCallbackTask(&MainThreadBridge::mainThreadDestroy, AllowCrossThreadAccess(this)));
153 }
154
155 void WorkerThreadableLoader::MainThreadBridge::mainThreadCancel(ExecutionContext* context, MainThreadBridge* thisPtr)
156 {
157     ASSERT(isMainThread());
158     ASSERT_UNUSED(context, context->isDocument());
159
160     if (!thisPtr->m_mainThreadLoader)
161         return;
162     thisPtr->m_mainThreadLoader->cancel();
163     thisPtr->m_mainThreadLoader = nullptr;
164 }
165
166 void WorkerThreadableLoader::MainThreadBridge::cancel()
167 {
168     m_loaderProxy.postTaskToLoader(
169         createCallbackTask(&MainThreadBridge::mainThreadCancel, AllowCrossThreadAccess(this)));
170     ThreadableLoaderClientWrapper* clientWrapper = m_workerClientWrapper.get();
171     if (!clientWrapper->done()) {
172         // If the client hasn't reached a termination state, then transition it by sending a cancellation error.
173         // Note: no more client callbacks will be done after this method -- the clearClientWrapper() call ensures that.
174         ResourceError error(String(), 0, String(), String());
175         error.setIsCancellation(true);
176         clientWrapper->didFail(error);
177     }
178     clearClientWrapper();
179 }
180
181 void WorkerThreadableLoader::MainThreadBridge::clearClientWrapper()
182 {
183     m_workerClientWrapper->clearClient();
184 }
185
186 void WorkerThreadableLoader::MainThreadBridge::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
187 {
188     m_clientBridge->didSendData(bytesSent, totalBytesToBeSent);
189 }
190
191 void WorkerThreadableLoader::MainThreadBridge::didReceiveResponse(unsigned long identifier, const ResourceResponse& response)
192 {
193     m_clientBridge->didReceiveResponse(identifier, response);
194 }
195
196 void WorkerThreadableLoader::MainThreadBridge::didReceiveData(const char* data, int dataLength)
197 {
198     m_clientBridge->didReceiveData(data, dataLength);
199 }
200
201 void WorkerThreadableLoader::MainThreadBridge::didDownloadData(int dataLength)
202 {
203     m_clientBridge->didDownloadData(dataLength);
204 }
205
206 void WorkerThreadableLoader::MainThreadBridge::didReceiveCachedMetadata(const char* data, int dataLength)
207 {
208     m_clientBridge->didReceiveCachedMetadata(data, dataLength);
209 }
210
211 void WorkerThreadableLoader::MainThreadBridge::didFinishLoading(unsigned long identifier, double finishTime)
212 {
213     m_clientBridge->didFinishLoading(identifier, finishTime);
214 }
215
216 void WorkerThreadableLoader::MainThreadBridge::didFail(const ResourceError& error)
217 {
218     m_clientBridge->didFail(error);
219 }
220
221 void WorkerThreadableLoader::MainThreadBridge::didFailAccessControlCheck(const ResourceError& error)
222 {
223     m_clientBridge->didFailAccessControlCheck(error);
224 }
225
226 void WorkerThreadableLoader::MainThreadBridge::didFailRedirectCheck()
227 {
228     m_clientBridge->didFailRedirectCheck();
229 }
230
231 } // namespace WebCore