2 * Copyright (C) 2009, 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
33 #include "core/loader/WorkerThreadableLoader.h"
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/timing/WorkerGlobalScopePerformance.h"
40 #include "core/workers/WorkerGlobalScope.h"
41 #include "core/workers/WorkerLoaderProxy.h"
42 #include "core/workers/WorkerThread.h"
43 #include "platform/heap/SafePoint.h"
44 #include "platform/network/ResourceError.h"
45 #include "platform/network/ResourceRequest.h"
46 #include "platform/network/ResourceResponse.h"
47 #include "platform/weborigin/SecurityPolicy.h"
48 #include "public/platform/Platform.h"
49 #include "public/platform/WebWaitableEvent.h"
50 #include "wtf/MainThread.h"
51 #include "wtf/OwnPtr.h"
52 #include "wtf/Vector.h"
56 WorkerThreadableLoader::WorkerThreadableLoader(WorkerGlobalScope
& workerGlobalScope
, PassRefPtr
<ThreadableLoaderClientWrapper
> clientWrapper
, PassOwnPtr
<ThreadableLoaderClient
> clientBridge
, const ResourceRequest
& request
, const ThreadableLoaderOptions
& options
, const ResourceLoaderOptions
& resourceLoaderOptions
)
57 : m_workerGlobalScope(&workerGlobalScope
)
58 , m_workerClientWrapper(clientWrapper
)
59 , m_bridge(*(new MainThreadBridge(m_workerClientWrapper
, clientBridge
, workerGlobalScope
.thread()->workerLoaderProxy(), request
, options
, resourceLoaderOptions
, workerGlobalScope
.referrerPolicy(), workerGlobalScope
.url().strippedForUseAsReferrer())))
61 m_workerClientWrapper
->setResourceTimingClient(this);
64 WorkerThreadableLoader::~WorkerThreadableLoader()
66 m_workerClientWrapper
->clearResourceTimingClient();
70 void WorkerThreadableLoader::loadResourceSynchronously(WorkerGlobalScope
& workerGlobalScope
, const ResourceRequest
& request
, ThreadableLoaderClient
& client
, const ThreadableLoaderOptions
& options
, const ResourceLoaderOptions
& resourceLoaderOptions
)
72 WebWaitableEvent
* shutdownEvent
=
73 workerGlobalScope
.thread()->shutdownEvent();
74 OwnPtr
<WebWaitableEvent
> loaderDone
=
75 adoptPtr(Platform::current()->createWaitableEvent());
77 Vector
<WebWaitableEvent
*> events
;
78 events
.append(shutdownEvent
);
79 events
.append(loaderDone
.get());
81 RefPtr
<ThreadableLoaderClientWrapper
> clientWrapper(ThreadableLoaderClientWrapper::create(&client
));
82 OwnPtr
<WorkerLoaderClientBridgeSyncHelper
> clientBridge(WorkerLoaderClientBridgeSyncHelper::create(clientWrapper
.get(), loaderDone
.release()));
84 // This must be valid while loader is around.
85 WorkerLoaderClientBridgeSyncHelper
* clientBridgePtr
= clientBridge
.get();
87 RefPtr
<WorkerThreadableLoader
> loader
= WorkerThreadableLoader::create(workerGlobalScope
, clientWrapper
, clientBridge
.release(), request
, options
, resourceLoaderOptions
);
89 WebWaitableEvent
* signalled
;
91 SafePointScope
scope(ThreadState::HeapPointersOnStack
);
92 signalled
= Platform::current()->waitMultipleEvents(events
);
94 if (signalled
== shutdownEvent
) {
99 clientBridgePtr
->run();
102 void WorkerThreadableLoader::overrideTimeout(unsigned long timeoutMilliseconds
)
104 m_bridge
.overrideTimeout(timeoutMilliseconds
);
107 void WorkerThreadableLoader::cancel()
112 void WorkerThreadableLoader::didReceiveResourceTiming(const ResourceTimingInfo
& info
)
114 WorkerGlobalScopePerformance::performance(*m_workerGlobalScope
)->addResourceTiming(info
);
117 WorkerThreadableLoader::MainThreadBridge::MainThreadBridge(
118 PassRefPtr
<ThreadableLoaderClientWrapper
> workerClientWrapper
,
119 PassOwnPtr
<ThreadableLoaderClient
> clientBridge
,
120 PassRefPtr
<WorkerLoaderProxy
> loaderProxy
,
121 const ResourceRequest
& request
,
122 const ThreadableLoaderOptions
& options
,
123 const ResourceLoaderOptions
& resourceLoaderOptions
,
124 const ReferrerPolicy referrerPolicy
,
125 const String
& outgoingReferrer
)
126 : m_clientBridge(clientBridge
)
127 , m_workerClientWrapper(workerClientWrapper
)
128 , m_loaderProxy(loaderProxy
)
130 ASSERT(m_workerClientWrapper
.get());
131 ASSERT(m_clientBridge
.get());
132 m_loaderProxy
->postTaskToLoader(
133 createCrossThreadTask(&MainThreadBridge::mainThreadCreateLoader
, this, request
, options
, resourceLoaderOptions
, referrerPolicy
, outgoingReferrer
));
136 WorkerThreadableLoader::MainThreadBridge::~MainThreadBridge()
140 void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(PassOwnPtr
<CrossThreadResourceRequestData
> requestData
, ThreadableLoaderOptions options
, ResourceLoaderOptions resourceLoaderOptions
, const ReferrerPolicy referrerPolicy
, const String
& outgoingReferrer
, ExecutionContext
* context
)
142 ASSERT(isMainThread());
143 Document
* document
= toDocument(context
);
145 OwnPtr
<ResourceRequest
> request(ResourceRequest::adopt(requestData
));
146 if (!request
->didSetHTTPReferrer())
147 request
->setHTTPReferrer(SecurityPolicy::generateReferrer(referrerPolicy
, request
->url(), outgoingReferrer
));
148 resourceLoaderOptions
.requestInitiatorContext
= WorkerContext
;
149 m_mainThreadLoader
= DocumentThreadableLoader::create(*document
, this, *request
, options
, resourceLoaderOptions
);
150 if (!m_mainThreadLoader
) {
151 // DocumentThreadableLoader::create may return 0 when the document loader has been already changed.
152 didFail(ResourceError(errorDomainBlinkInternal
, 0, request
->url().string(), "Can't create DocumentThreadableLoader"));
156 void WorkerThreadableLoader::MainThreadBridge::mainThreadDestroy(ExecutionContext
* context
)
158 ASSERT(isMainThread());
159 ASSERT_UNUSED(context
, context
->isDocument());
163 void WorkerThreadableLoader::MainThreadBridge::destroy()
165 // Ensure that no more client callbacks are done in the worker context's thread.
166 clearClientWrapper();
168 // "delete this" and m_mainThreadLoader::deref() on the worker object's thread.
169 m_loaderProxy
->postTaskToLoader(
170 createCrossThreadTask(&MainThreadBridge::mainThreadDestroy
, this));
173 void WorkerThreadableLoader::MainThreadBridge::mainThreadOverrideTimeout(unsigned long timeoutMilliseconds
, ExecutionContext
* context
)
175 ASSERT(isMainThread());
176 ASSERT_UNUSED(context
, context
->isDocument());
178 if (!m_mainThreadLoader
)
180 m_mainThreadLoader
->overrideTimeout(timeoutMilliseconds
);
183 void WorkerThreadableLoader::MainThreadBridge::overrideTimeout(unsigned long timeoutMilliseconds
)
185 m_loaderProxy
->postTaskToLoader(
186 createCrossThreadTask(&MainThreadBridge::mainThreadOverrideTimeout
, this,
187 timeoutMilliseconds
));
190 void WorkerThreadableLoader::MainThreadBridge::mainThreadCancel(ExecutionContext
* context
)
192 ASSERT(isMainThread());
193 ASSERT_UNUSED(context
, context
->isDocument());
195 if (!m_mainThreadLoader
)
197 m_mainThreadLoader
->cancel();
198 m_mainThreadLoader
= nullptr;
201 void WorkerThreadableLoader::MainThreadBridge::cancel()
203 m_loaderProxy
->postTaskToLoader(
204 createCrossThreadTask(&MainThreadBridge::mainThreadCancel
, this));
205 RefPtr
<ThreadableLoaderClientWrapper
> clientWrapper
= m_workerClientWrapper
;
206 if (!clientWrapper
->done()) {
207 // If the client hasn't reached a termination state, then transition it by sending a cancellation error.
208 // Note: no more client callbacks will be done after this method -- the clearClientWrapper() call ensures that.
209 ResourceError
error(String(), 0, String(), String());
210 error
.setIsCancellation(true);
211 clientWrapper
->didFail(error
);
213 // |this| might be already destructed here because didFail() might
214 // clear a reference to ThreadableLoader, which might destruct
215 // WorkerThreadableLoader and then MainThreadBridge.
216 // Therefore we call clearClient() directly, rather than calling
217 // this->clearClientWrapper().
218 clientWrapper
->clearClient();
221 void WorkerThreadableLoader::MainThreadBridge::clearClientWrapper()
223 m_workerClientWrapper
->clearClient();
226 void WorkerThreadableLoader::MainThreadBridge::didSendData(unsigned long long bytesSent
, unsigned long long totalBytesToBeSent
)
228 m_clientBridge
->didSendData(bytesSent
, totalBytesToBeSent
);
231 void WorkerThreadableLoader::MainThreadBridge::didReceiveResponse(unsigned long identifier
, const ResourceResponse
& response
, PassOwnPtr
<WebDataConsumerHandle
> handle
)
233 m_clientBridge
->didReceiveResponse(identifier
, response
, handle
);
236 void WorkerThreadableLoader::MainThreadBridge::didReceiveData(const char* data
, unsigned dataLength
)
238 m_clientBridge
->didReceiveData(data
, dataLength
);
241 void WorkerThreadableLoader::MainThreadBridge::didDownloadData(int dataLength
)
243 m_clientBridge
->didDownloadData(dataLength
);
246 void WorkerThreadableLoader::MainThreadBridge::didReceiveCachedMetadata(const char* data
, int dataLength
)
248 m_clientBridge
->didReceiveCachedMetadata(data
, dataLength
);
251 void WorkerThreadableLoader::MainThreadBridge::didFinishLoading(unsigned long identifier
, double finishTime
)
253 m_clientBridge
->didFinishLoading(identifier
, finishTime
);
256 void WorkerThreadableLoader::MainThreadBridge::didFail(const ResourceError
& error
)
258 m_clientBridge
->didFail(error
);
261 void WorkerThreadableLoader::MainThreadBridge::didFailAccessControlCheck(const ResourceError
& error
)
263 m_clientBridge
->didFailAccessControlCheck(error
);
266 void WorkerThreadableLoader::MainThreadBridge::didFailRedirectCheck()
268 m_clientBridge
->didFailRedirectCheck();
271 void WorkerThreadableLoader::MainThreadBridge::didReceiveResourceTiming(const ResourceTimingInfo
& info
)
273 m_clientBridge
->didReceiveResourceTiming(info
);