OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2009, 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2009, 2010 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 18 matching lines...) Expand all Loading... | |
29 */ | 29 */ |
30 | 30 |
31 #include "core/loader/WorkerThreadableLoader.h" | 31 #include "core/loader/WorkerThreadableLoader.h" |
32 | 32 |
33 #include "core/dom/CrossThreadTask.h" | 33 #include "core/dom/CrossThreadTask.h" |
34 #include "core/dom/Document.h" | 34 #include "core/dom/Document.h" |
35 #include "core/loader/DocumentThreadableLoader.h" | 35 #include "core/loader/DocumentThreadableLoader.h" |
36 #include "core/timing/WorkerGlobalScopePerformance.h" | 36 #include "core/timing/WorkerGlobalScopePerformance.h" |
37 #include "core/workers/WorkerGlobalScope.h" | 37 #include "core/workers/WorkerGlobalScope.h" |
38 #include "core/workers/WorkerLoaderProxy.h" | 38 #include "core/workers/WorkerLoaderProxy.h" |
39 #include "core/workers/WorkerThread.h" | |
40 #include "platform/CrossThreadFunctional.h" | 39 #include "platform/CrossThreadFunctional.h" |
41 #include "platform/WaitableEvent.h" | |
42 #include "platform/heap/SafePoint.h" | 40 #include "platform/heap/SafePoint.h" |
43 #include "platform/network/ResourceError.h" | 41 #include "platform/network/ResourceError.h" |
44 #include "platform/network/ResourceRequest.h" | 42 #include "platform/network/ResourceRequest.h" |
45 #include "platform/network/ResourceResponse.h" | 43 #include "platform/network/ResourceResponse.h" |
46 #include "platform/network/ResourceTimingInfo.h" | 44 #include "platform/network/ResourceTimingInfo.h" |
47 #include "platform/weborigin/SecurityPolicy.h" | 45 #include "platform/weborigin/SecurityPolicy.h" |
48 #include "public/platform/Platform.h" | |
49 #include "wtf/PtrUtil.h" | |
50 #include "wtf/Vector.h" | |
51 #include <memory> | 46 #include <memory> |
52 | 47 |
53 namespace blink { | 48 namespace blink { |
54 | 49 |
55 static std::unique_ptr<Vector<char>> createVectorFromMemoryRegion(const char* da ta, unsigned dataLength) | 50 namespace { |
51 | |
52 std::unique_ptr<Vector<char>> createVectorFromMemoryRegion(const char* data, uns igned dataLength) | |
56 { | 53 { |
57 std::unique_ptr<Vector<char>> buffer = wrapUnique(new Vector<char>(dataLengt h)); | 54 std::unique_ptr<Vector<char>> buffer = wrapUnique(new Vector<char>(dataLengt h)); |
58 memcpy(buffer->data(), data, dataLength); | 55 memcpy(buffer->data(), data, dataLength); |
59 return buffer; | 56 return buffer; |
60 } | 57 } |
61 | 58 |
62 WorkerThreadableLoader::WorkerThreadableLoader(WorkerGlobalScope& workerGlobalSc ope, ThreadableLoaderClient* client, const ThreadableLoaderOptions& options, con st ResourceLoaderOptions& resourceLoaderOptions, BlockingBehavior blockingBehavi or) | 59 } // namespace |
60 | |
61 WorkerThreadableLoader::WorkerThreadableLoader( | |
62 WorkerGlobalScope& workerGlobalScope, | |
63 ThreadableLoaderClient* client, | |
64 const ThreadableLoaderOptions& options, | |
65 const ResourceLoaderOptions& resourceLoaderOptions, | |
66 BlockingBehavior blockingBehavior) | |
63 : m_workerGlobalScope(&workerGlobalScope) | 67 : m_workerGlobalScope(&workerGlobalScope) |
64 , m_workerClientWrapper(new ThreadableLoaderClientWrapper(workerGlobalScope, client)) | 68 , m_workerClientWrapper(new ThreadableLoaderClientWrapper(workerGlobalScope, client)) |
69 , m_bridge(new Bridge(m_workerClientWrapper, workerGlobalScope.thread()->wor kerLoaderProxy(), options, resourceLoaderOptions, blockingBehavior)) | |
65 { | 70 { |
66 if (blockingBehavior == LoadAsynchronously) { | |
67 m_bridge = new MainThreadAsyncBridge(workerGlobalScope, m_workerClientWr apper, options, resourceLoaderOptions); | |
68 } else { | |
69 m_bridge = new MainThreadSyncBridge(workerGlobalScope, m_workerClientWra pper, options, resourceLoaderOptions); | |
70 } | |
71 } | 71 } |
72 | 72 |
73 void WorkerThreadableLoader::loadResourceSynchronously(WorkerGlobalScope& worker GlobalScope, const ResourceRequest& request, ThreadableLoaderClient& client, con st ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoader Options) | 73 void WorkerThreadableLoader::loadResourceSynchronously(WorkerGlobalScope& worker GlobalScope, const ResourceRequest& request, ThreadableLoaderClient& client, con st ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoader Options) |
74 { | 74 { |
75 std::unique_ptr<WorkerThreadableLoader> loader = wrapUnique(new WorkerThread ableLoader(workerGlobalScope, &client, options, resourceLoaderOptions, LoadSynch ronously)); | 75 std::unique_ptr<WorkerThreadableLoader> loader = wrapUnique(new WorkerThread ableLoader(workerGlobalScope, &client, options, resourceLoaderOptions, LoadSynch ronously)); |
76 loader->start(request); | 76 loader->start(request); |
77 } | 77 } |
78 | 78 |
79 WorkerThreadableLoader::~WorkerThreadableLoader() | 79 WorkerThreadableLoader::~WorkerThreadableLoader() |
80 { | 80 { |
81 DCHECK(m_workerClientWrapper->done()); | 81 DCHECK(m_workerClientWrapper->done()); |
82 m_bridge->destroy(); | 82 m_bridge->destroy(); |
83 m_bridge = nullptr; | |
84 } | 83 } |
85 | 84 |
86 void WorkerThreadableLoader::start(const ResourceRequest& request) | 85 void WorkerThreadableLoader::start(const ResourceRequest& request) |
87 { | 86 { |
88 ResourceRequest requestToPass(request); | 87 ResourceRequest requestToPass(request); |
89 if (!requestToPass.didSetHTTPReferrer()) | 88 if (!requestToPass.didSetHTTPReferrer()) |
90 requestToPass.setHTTPReferrer(SecurityPolicy::generateReferrer(m_workerG lobalScope->getReferrerPolicy(), request.url(), m_workerGlobalScope->outgoingRef errer())); | 89 requestToPass.setHTTPReferrer(SecurityPolicy::generateReferrer(m_workerG lobalScope->getReferrerPolicy(), request.url(), m_workerGlobalScope->outgoingRef errer())); |
91 m_bridge->start(requestToPass, *m_workerGlobalScope); | 90 m_bridge->start(requestToPass, *m_workerGlobalScope); |
92 } | 91 } |
93 | 92 |
94 void WorkerThreadableLoader::overrideTimeout(unsigned long timeoutMilliseconds) | 93 void WorkerThreadableLoader::overrideTimeout(unsigned long timeoutMilliseconds) |
95 { | 94 { |
96 ASSERT(m_bridge); | |
97 m_bridge->overrideTimeout(timeoutMilliseconds); | 95 m_bridge->overrideTimeout(timeoutMilliseconds); |
98 } | 96 } |
99 | 97 |
100 void WorkerThreadableLoader::cancel() | 98 void WorkerThreadableLoader::cancel() |
101 { | 99 { |
102 ASSERT(m_bridge); | |
103 m_bridge->cancel(); | 100 m_bridge->cancel(); |
104 } | 101 } |
105 | 102 |
106 WorkerThreadableLoader::MainThreadBridgeBase::MainThreadBridgeBase( | 103 WorkerThreadableLoader::AsyncTaskForwarder::AsyncTaskForwarder(PassRefPtr<Worker LoaderProxy> loaderProxy) |
107 ThreadableLoaderClientWrapper* workerClientWrapper, | 104 : m_loaderProxy(loaderProxy) |
108 PassRefPtr<WorkerLoaderProxy> loaderProxy) | 105 { |
109 : m_workerClientWrapper(workerClientWrapper) | 106 DCHECK(isMainThread()); |
107 } | |
108 | |
109 WorkerThreadableLoader::AsyncTaskForwarder::~AsyncTaskForwarder() | |
110 { | |
111 DCHECK(isMainThread()); | |
112 } | |
113 | |
114 void WorkerThreadableLoader::AsyncTaskForwarder::forwardTask(std::unique_ptr<Exe cutionContextTask> task) | |
115 { | |
116 DCHECK(isMainThread()); | |
117 m_loaderProxy->postTaskToWorkerGlobalScope(std::move(task)); | |
118 } | |
119 | |
120 void WorkerThreadableLoader::AsyncTaskForwarder::forwardTaskWithDoneSignal(std:: unique_ptr<ExecutionContextTask> task) | |
121 { | |
122 DCHECK(isMainThread()); | |
123 m_loaderProxy->postTaskToWorkerGlobalScope(std::move(task)); | |
124 } | |
125 | |
126 void WorkerThreadableLoader::AsyncTaskForwarder::abort() | |
127 { | |
128 DCHECK(isMainThread()); | |
129 } | |
130 | |
131 WorkerThreadableLoader::WaitableEventWithTasks::~WaitableEventWithTasks() {} | |
132 | |
133 void WorkerThreadableLoader::WaitableEventWithTasks::signal() | |
134 { | |
135 DCHECK(isMainThread()); | |
136 DCHECK(!m_isSignalCalled); | |
hiroshige
2016/07/26 07:32:52
Violations to DCHECKs on |m_isSignalCalled| and |m
yhirano
2016/07/26 09:57:34
Done.
| |
137 m_isSignalCalled = true; | |
138 m_event.signal(); | |
139 } | |
140 | |
141 void WorkerThreadableLoader::WaitableEventWithTasks::wait() | |
142 { | |
143 DCHECK(!isMainThread()); | |
144 DCHECK(!m_isWaitDone); | |
145 m_event.wait(); | |
146 m_isWaitDone = true; | |
147 } | |
148 | |
149 bool WorkerThreadableLoader::WaitableEventWithTasks::isAborted() const | |
150 { | |
151 DCHECK(!isMainThread()); | |
152 DCHECK(m_isWaitDone); | |
153 return m_isAborted; | |
154 } | |
155 | |
156 Vector<std::unique_ptr<ExecutionContextTask>> WorkerThreadableLoader::WaitableEv entWithTasks::take() | |
157 { | |
158 DCHECK(!isMainThread()); | |
159 DCHECK(m_isWaitDone); | |
160 return std::move(m_tasks); | |
161 } | |
162 | |
163 void WorkerThreadableLoader::WaitableEventWithTasks::setIsAborted() | |
164 { | |
165 DCHECK(isMainThread()); | |
166 DCHECK(!m_isSignalCalled); | |
167 m_isAborted = true; | |
168 } | |
169 | |
170 void WorkerThreadableLoader::WaitableEventWithTasks::append(std::unique_ptr<Exec utionContextTask> task) | |
171 { | |
172 DCHECK(isMainThread()); | |
173 DCHECK(!m_isSignalCalled); | |
174 m_tasks.append(std::move(task)); | |
175 } | |
176 | |
177 WorkerThreadableLoader::SyncTaskForwarder::SyncTaskForwarder(PassRefPtr<Waitable EventWithTasks> eventWithTasks) | |
178 : m_eventWithTasks(eventWithTasks) | |
179 { | |
180 DCHECK(isMainThread()); | |
181 } | |
182 | |
183 WorkerThreadableLoader::SyncTaskForwarder::~SyncTaskForwarder() | |
184 { | |
185 DCHECK(isMainThread()); | |
186 } | |
187 | |
188 void WorkerThreadableLoader::SyncTaskForwarder::forwardTask(std::unique_ptr<Exec utionContextTask> task) | |
189 { | |
190 DCHECK(isMainThread()); | |
191 m_eventWithTasks->append(std::move(task)); | |
192 } | |
193 | |
194 void WorkerThreadableLoader::SyncTaskForwarder::forwardTaskWithDoneSignal(std::u nique_ptr<ExecutionContextTask> task) | |
195 { | |
196 DCHECK(isMainThread()); | |
197 m_eventWithTasks->append(std::move(task)); | |
198 m_eventWithTasks->signal(); | |
199 } | |
200 | |
201 void WorkerThreadableLoader::SyncTaskForwarder::abort() | |
202 { | |
203 DCHECK(isMainThread()); | |
204 m_eventWithTasks->setIsAborted(); | |
205 m_eventWithTasks->signal(); | |
206 } | |
207 | |
208 WorkerThreadableLoader::Bridge::Bridge( | |
209 ThreadableLoaderClientWrapper* clientWrapper, | |
210 PassRefPtr<WorkerLoaderProxy> loaderProxy, | |
211 const ThreadableLoaderOptions& threadableLoaderOptions, | |
212 const ResourceLoaderOptions& resourceLoaderOptions, | |
213 BlockingBehavior blockingBehavior) | |
214 : m_clientWrapper(clientWrapper) | |
110 , m_loaderProxy(loaderProxy) | 215 , m_loaderProxy(loaderProxy) |
111 { | 216 , m_threadableLoaderOptions(threadableLoaderOptions) |
112 ASSERT(m_workerClientWrapper.get()); | 217 , m_resourceLoaderOptions(resourceLoaderOptions) |
113 ASSERT(m_loaderProxy.get()); | 218 , m_blockingBehavior(blockingBehavior) |
114 } | 219 { |
115 | 220 DCHECK(!isMainThread()); |
116 WorkerThreadableLoader::MainThreadBridgeBase::~MainThreadBridgeBase() | 221 } |
117 { | 222 |
118 } | 223 WorkerThreadableLoader::Bridge::~Bridge() |
119 | 224 { |
120 void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadCreateLoader(Thread ableLoaderOptions options, ResourceLoaderOptions resourceLoaderOptions, Executio nContext* context) | 225 DCHECK(!isMainThread()); |
121 { | 226 DCHECK(!m_peer); |
122 ASSERT(isMainThread()); | 227 } |
123 Document* document = toDocument(context); | 228 |
124 | 229 void WorkerThreadableLoader::Bridge::start(const ResourceRequest& request, const WorkerGlobalScope& workerGlobalScope) |
125 resourceLoaderOptions.requestInitiatorContext = WorkerContext; | 230 { |
126 m_mainThreadLoader = DocumentThreadableLoader::create(*document, this, optio ns, resourceLoaderOptions); | 231 DCHECK(!isMainThread()); |
127 ASSERT(m_mainThreadLoader); | 232 RefPtr<WaitableEventWithTasks> eventWithTasks; |
128 } | 233 if (m_blockingBehavior == LoadSynchronously) |
129 | 234 eventWithTasks = WaitableEventWithTasks::create(); |
130 void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadStart(std::unique_p tr<CrossThreadResourceRequestData> requestData) | 235 |
131 { | 236 m_loaderProxy->postTaskToLoader(createCrossThreadTask( |
132 ASSERT(isMainThread()); | 237 &Peer::createAndStart, |
133 ASSERT(m_mainThreadLoader); | 238 wrapCrossThreadPersistent(this), |
134 m_mainThreadLoader->start(ResourceRequest(requestData.get())); | 239 m_loaderProxy, |
135 } | 240 wrapCrossThreadPersistent(workerGlobalScope.thread()->getWorkerThreadLif ecycleContext()), |
136 | 241 request, |
137 void WorkerThreadableLoader::MainThreadBridgeBase::createLoaderInMainThread(cons t ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderO ptions) | 242 m_threadableLoaderOptions, |
138 { | 243 m_resourceLoaderOptions, |
139 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&MainThreadBridgeBase: :mainThreadCreateLoader, crossThreadUnretained(this), options, resourceLoaderOpt ions)); | 244 eventWithTasks)); |
140 } | 245 |
141 | 246 if (m_blockingBehavior == LoadAsynchronously) |
142 void WorkerThreadableLoader::MainThreadBridgeBase::startInMainThread(const Resou rceRequest& request, const WorkerGlobalScope& workerGlobalScope) | 247 return; |
143 { | 248 |
144 loaderProxy()->postTaskToLoader(createCrossThreadTask(&MainThreadBridgeBase: :mainThreadStart, crossThreadUnretained(this), request)); | |
145 } | |
146 | |
147 void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadDestroy(ExecutionCo ntext* context) | |
148 { | |
149 ASSERT(isMainThread()); | |
150 ASSERT_UNUSED(context, context->isDocument()); | |
151 delete this; | |
152 } | |
153 | |
154 void WorkerThreadableLoader::MainThreadBridgeBase::destroy() | |
155 { | |
156 // Ensure that no more client callbacks are done in the worker context's | |
157 // thread. | |
158 // ThreadableLoaderClientWrapper is an on-heap class and this function can | |
159 // be called in the finalization step but it is safe because | |
160 // m_workerClientWrapper is a CrossThreadPersistent. | |
161 m_workerClientWrapper->clearClient(); | |
162 | |
163 // "delete this" and m_mainThreadLoader::deref() on the worker object's | |
164 // thread. | |
165 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&MainThreadBridgeBase: :mainThreadDestroy, crossThreadUnretained(this))); | |
166 } | |
167 | |
168 void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadOverrideTimeout(uns igned long timeoutMilliseconds, ExecutionContext* context) | |
169 { | |
170 ASSERT(isMainThread()); | |
171 ASSERT_UNUSED(context, context->isDocument()); | |
172 | |
173 if (!m_mainThreadLoader) | |
174 return; | |
175 m_mainThreadLoader->overrideTimeout(timeoutMilliseconds); | |
176 } | |
177 | |
178 void WorkerThreadableLoader::MainThreadBridgeBase::overrideTimeout(unsigned long timeoutMilliseconds) | |
179 { | |
180 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&MainThreadBridgeBase: :mainThreadOverrideTimeout, crossThreadUnretained(this), timeoutMilliseconds)); | |
181 } | |
182 | |
183 void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadCancel(ExecutionCon text* context) | |
184 { | |
185 ASSERT(isMainThread()); | |
186 ASSERT_UNUSED(context, context->isDocument()); | |
187 | |
188 if (!m_mainThreadLoader) | |
189 return; | |
190 m_mainThreadLoader->cancel(); | |
191 m_mainThreadLoader = nullptr; | |
192 } | |
193 | |
194 void WorkerThreadableLoader::MainThreadBridgeBase::cancel() | |
195 { | |
196 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&MainThreadBridgeBase: :mainThreadCancel, crossThreadUnretained(this))); | |
197 ThreadableLoaderClientWrapper* clientWrapper = m_workerClientWrapper; | |
198 if (!clientWrapper->done()) { | |
199 // If the client hasn't reached a termination state, then transition it | |
200 // by sending a cancellation error. | |
201 // Note: no more client callbacks will be done after this method -- the | |
202 // m_workerClientWrapper->clearClient() call ensures that. | |
203 ResourceError error(String(), 0, String(), String()); | |
204 error.setIsCancellation(true); | |
205 clientWrapper->didFail(error); | |
206 } | |
207 // |this| might be already destructed here because didFail() might | |
208 // clear a reference to ThreadableLoader, which might destruct | |
209 // WorkerThreadableLoader and then MainThreadBridge. | |
210 // Therefore we call clearClient() directly, rather than calling | |
211 // this->m_workerClientWrapper->clearClient(). | |
212 clientWrapper->clearClient(); | |
213 } | |
214 | |
215 void WorkerThreadableLoader::MainThreadBridgeBase::didSendData(unsigned long lon g bytesSent, unsigned long long totalBytesToBeSent) | |
216 { | |
217 forwardTaskToWorker(createCrossThreadTask(&ThreadableLoaderClientWrapper::di dSendData, m_workerClientWrapper, bytesSent, totalBytesToBeSent)); | |
218 } | |
219 | |
220 void WorkerThreadableLoader::MainThreadBridgeBase::didReceiveResponse(unsigned l ong identifier, const ResourceResponse& response, std::unique_ptr<WebDataConsume rHandle> handle) | |
221 { | |
222 forwardTaskToWorker(createCrossThreadTask(&ThreadableLoaderClientWrapper::di dReceiveResponse, m_workerClientWrapper, identifier, response, passed(std::move( handle)))); | |
223 } | |
224 | |
225 void WorkerThreadableLoader::MainThreadBridgeBase::didReceiveData(const char* da ta, unsigned dataLength) | |
226 { | |
227 forwardTaskToWorker(createCrossThreadTask(&ThreadableLoaderClientWrapper::di dReceiveData, m_workerClientWrapper, passed(createVectorFromMemoryRegion(data, d ataLength)))); | |
228 } | |
229 | |
230 void WorkerThreadableLoader::MainThreadBridgeBase::didDownloadData(int dataLengt h) | |
231 { | |
232 forwardTaskToWorker(createCrossThreadTask(&ThreadableLoaderClientWrapper::di dDownloadData, m_workerClientWrapper, dataLength)); | |
233 } | |
234 | |
235 void WorkerThreadableLoader::MainThreadBridgeBase::didReceiveCachedMetadata(cons t char* data, int dataLength) | |
236 { | |
237 forwardTaskToWorker(createCrossThreadTask(&ThreadableLoaderClientWrapper::di dReceiveCachedMetadata, m_workerClientWrapper, passed(createVectorFromMemoryRegi on(data, dataLength)))); | |
238 } | |
239 | |
240 void WorkerThreadableLoader::MainThreadBridgeBase::didFinishLoading(unsigned lon g identifier, double finishTime) | |
241 { | |
242 forwardTaskToWorkerOnLoaderDone(createCrossThreadTask(&ThreadableLoaderClien tWrapper::didFinishLoading, m_workerClientWrapper, identifier, finishTime)); | |
243 } | |
244 | |
245 void WorkerThreadableLoader::MainThreadBridgeBase::didFail(const ResourceError& error) | |
246 { | |
247 forwardTaskToWorkerOnLoaderDone(createCrossThreadTask(&ThreadableLoaderClien tWrapper::didFail, m_workerClientWrapper, error)); | |
248 } | |
249 | |
250 void WorkerThreadableLoader::MainThreadBridgeBase::didFailAccessControlCheck(con st ResourceError& error) | |
251 { | |
252 forwardTaskToWorkerOnLoaderDone(createCrossThreadTask(&ThreadableLoaderClien tWrapper::didFailAccessControlCheck, m_workerClientWrapper, error)); | |
253 } | |
254 | |
255 void WorkerThreadableLoader::MainThreadBridgeBase::didFailRedirectCheck() | |
256 { | |
257 forwardTaskToWorkerOnLoaderDone(createCrossThreadTask(&ThreadableLoaderClien tWrapper::didFailRedirectCheck, m_workerClientWrapper)); | |
258 } | |
259 | |
260 void WorkerThreadableLoader::MainThreadBridgeBase::didReceiveResourceTiming(cons t ResourceTimingInfo& info) | |
261 { | |
262 forwardTaskToWorker(createCrossThreadTask(&ThreadableLoaderClientWrapper::di dReceiveResourceTiming, m_workerClientWrapper, info)); | |
263 } | |
264 | |
265 WorkerThreadableLoader::MainThreadAsyncBridge::MainThreadAsyncBridge( | |
266 WorkerGlobalScope& workerGlobalScope, | |
267 ThreadableLoaderClientWrapper* workerClientWrapper, | |
268 const ThreadableLoaderOptions& options, | |
269 const ResourceLoaderOptions& resourceLoaderOptions) | |
270 : MainThreadBridgeBase(workerClientWrapper, workerGlobalScope.thread()->work erLoaderProxy()) | |
271 { | |
272 createLoaderInMainThread(options, resourceLoaderOptions); | |
273 } | |
274 | |
275 void WorkerThreadableLoader::MainThreadAsyncBridge::start(const ResourceRequest& request, const WorkerGlobalScope& workerGlobalScope) | |
276 { | |
277 startInMainThread(request, workerGlobalScope); | |
278 } | |
279 | |
280 WorkerThreadableLoader::MainThreadAsyncBridge::~MainThreadAsyncBridge() | |
281 { | |
282 } | |
283 | |
284 void WorkerThreadableLoader::MainThreadAsyncBridge::forwardTaskToWorker(std::uni que_ptr<ExecutionContextTask> task) | |
285 { | |
286 loaderProxy()->postTaskToWorkerGlobalScope(std::move(task)); | |
287 } | |
288 | |
289 void WorkerThreadableLoader::MainThreadAsyncBridge::forwardTaskToWorkerOnLoaderD one(std::unique_ptr<ExecutionContextTask> task) | |
290 { | |
291 loaderProxy()->postTaskToWorkerGlobalScope(std::move(task)); | |
292 } | |
293 | |
294 WorkerThreadableLoader::MainThreadSyncBridge::MainThreadSyncBridge( | |
295 WorkerGlobalScope& workerGlobalScope, | |
296 ThreadableLoaderClientWrapper* workerClientWrapper, | |
297 const ThreadableLoaderOptions& options, | |
298 const ResourceLoaderOptions& resourceLoaderOptions) | |
299 : MainThreadBridgeBase(workerClientWrapper, workerGlobalScope.thread()->work erLoaderProxy()) | |
300 , m_done(false) | |
301 { | |
302 createLoaderInMainThread(options, resourceLoaderOptions); | |
303 } | |
304 | |
305 void WorkerThreadableLoader::MainThreadSyncBridge::start(const ResourceRequest& request, const WorkerGlobalScope& workerGlobalScope) | |
306 { | |
307 WaitableEvent* terminationEvent = workerGlobalScope.thread()->terminationEve nt(); | |
308 m_loaderDoneEvent = wrapUnique(new WaitableEvent()); | |
309 | |
310 startInMainThread(request, workerGlobalScope); | |
311 | |
312 size_t signaledIndex; | |
313 { | 249 { |
314 Vector<WaitableEvent*> events; | |
315 // Order is important; indicies are used later. | |
316 events.append(terminationEvent); | |
317 events.append(m_loaderDoneEvent.get()); | |
318 | |
319 SafePointScope scope(BlinkGC::HeapPointersOnStack); | 250 SafePointScope scope(BlinkGC::HeapPointersOnStack); |
320 signaledIndex = WaitableEvent::waitMultiple(events); | 251 eventWithTasks->wait(); |
321 } | 252 } |
322 // |signaledIndex| is 0; which is terminationEvent. | 253 |
323 if (signaledIndex == 0) { | 254 if (eventWithTasks->isAborted()) { |
255 // This thread is going to terminate. | |
324 cancel(); | 256 cancel(); |
325 return; | 257 return; |
326 } | 258 } |
327 | 259 |
328 // The following code must be run only after |m_loaderDoneEvent| is | 260 for (const auto& task : eventWithTasks->take()) { |
329 // signalled. | |
330 | |
331 Vector<std::unique_ptr<ExecutionContextTask>> tasks; | |
332 { | |
333 MutexLocker lock(m_lock); | |
334 ASSERT(m_done); | |
335 m_clientTasks.swap(tasks); | |
336 } | |
337 for (const auto& task : tasks) { | |
338 // m_clientTask contains only CallClosureTasks. So, it's ok to pass | 261 // m_clientTask contains only CallClosureTasks. So, it's ok to pass |
339 // the nullptr. | 262 // the nullptr. |
340 task->performTask(nullptr); | 263 task->performTask(nullptr); |
341 } | 264 } |
342 } | 265 } |
343 | 266 |
344 WorkerThreadableLoader::MainThreadSyncBridge::~MainThreadSyncBridge() | 267 void WorkerThreadableLoader::Bridge::overrideTimeout(unsigned long timeoutMillis econds) |
345 { | 268 { |
346 ASSERT(isMainThread()); | 269 DCHECK(!isMainThread()); |
347 } | 270 if (!m_peer) |
348 | 271 return; |
349 void WorkerThreadableLoader::MainThreadSyncBridge::forwardTaskToWorker(std::uniq ue_ptr<ExecutionContextTask> task) | 272 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::overrideTimeout , m_peer, timeoutMilliseconds)); |
350 { | 273 } |
351 ASSERT(isMainThread()); | 274 |
352 | 275 void WorkerThreadableLoader::Bridge::cancel() |
353 MutexLocker lock(m_lock); | 276 { |
354 RELEASE_ASSERT(!m_done); | 277 DCHECK(!isMainThread()); |
355 | 278 cancelPeer(); |
356 m_clientTasks.append(std::move(task)); | 279 |
357 } | 280 if (m_clientWrapper->done()) |
358 | 281 return; |
359 void WorkerThreadableLoader::MainThreadSyncBridge::forwardTaskToWorkerOnLoaderDo ne(std::unique_ptr<ExecutionContextTask> task) | 282 // If the client hasn't reached a termination state, then transition it |
360 { | 283 // by sending a cancellation error. |
361 ASSERT(isMainThread()); | 284 // Note: no more client callbacks will be done after this method -- the |
362 | 285 // clearClient() call ensures that. |
363 MutexLocker lock(m_lock); | 286 ResourceError error(String(), 0, String(), String()); |
364 RELEASE_ASSERT(!m_done); | 287 error.setIsCancellation(true); |
365 | 288 m_clientWrapper->didFail(error); |
366 m_clientTasks.append(std::move(task)); | 289 m_clientWrapper->clearClient(); |
367 m_done = true; | 290 } |
368 m_loaderDoneEvent->signal(); | 291 |
292 void WorkerThreadableLoader::Bridge::destroy() | |
293 { | |
294 DCHECK(!isMainThread()); | |
295 cancelPeer(); | |
296 m_clientWrapper->clearClient(); | |
297 } | |
298 | |
299 void WorkerThreadableLoader::Bridge::didStart(Peer* peer) | |
300 { | |
301 DCHECK(!isMainThread()); | |
302 DCHECK(!m_peer); | |
303 DCHECK(peer); | |
304 if (m_clientWrapper->done()) { | |
305 // The loading is already cancelled. | |
306 return; | |
307 } | |
308 | |
309 m_peer = peer; | |
310 } | |
311 | |
312 DEFINE_TRACE(WorkerThreadableLoader::Bridge) | |
313 { | |
314 visitor->trace(m_clientWrapper); | |
315 } | |
316 | |
317 void WorkerThreadableLoader::Bridge::cancelPeer() | |
318 { | |
319 DCHECK(!isMainThread()); | |
320 if (!m_peer) | |
321 return; | |
322 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::cancel, m_peer) ); | |
323 m_peer = nullptr; | |
324 } | |
325 | |
326 void WorkerThreadableLoader::Peer::createAndStart( | |
327 Bridge* bridge, | |
328 PassRefPtr<WorkerLoaderProxy> passLoaderProxy, | |
329 WorkerThreadLifecycleContext* workerThreadLifecycleContext, | |
330 std::unique_ptr<CrossThreadResourceRequestData> request, | |
331 const ThreadableLoaderOptions& options, | |
332 const ResourceLoaderOptions& resourceLoaderOptions, | |
333 PassRefPtr<WaitableEventWithTasks> eventWithTasks, | |
334 ExecutionContext* executionContext) | |
335 { | |
336 DCHECK(isMainThread()); | |
337 TaskForwarder* forwarder; | |
338 RefPtr<WorkerLoaderProxy> loaderProxy = passLoaderProxy; | |
339 if (eventWithTasks) | |
340 forwarder = new SyncTaskForwarder(eventWithTasks); | |
341 else | |
342 forwarder = new AsyncTaskForwarder(loaderProxy); | |
343 | |
344 Peer* peer = new Peer(forwarder, workerThreadLifecycleContext); | |
345 if (peer->wasContextDestroyedBeforeObserverCreation()) { | |
346 // The thread is already terminating. | |
347 forwarder->abort(); | |
348 peer->m_forwarder = nullptr; | |
349 return; | |
350 } | |
351 peer->m_clientWrapper = bridge->clientWrapper(); | |
352 peer->start(*toDocument(executionContext), std::move(request), options, reso urceLoaderOptions); | |
353 forwarder->forwardTask(createCrossThreadTask(&Bridge::didStart, wrapCrossThr eadPersistent(bridge), wrapCrossThreadPersistent(peer))); | |
354 } | |
355 | |
356 WorkerThreadableLoader::Peer::~Peer() | |
357 { | |
358 DCHECK(isMainThread()); | |
359 DCHECK(!m_mainThreadLoader); | |
360 } | |
361 | |
362 void WorkerThreadableLoader::Peer::overrideTimeout(unsigned long timeoutMillisec onds) | |
363 { | |
364 DCHECK(isMainThread()); | |
365 if (!m_mainThreadLoader) | |
366 return; | |
367 m_mainThreadLoader->overrideTimeout(timeoutMilliseconds); | |
368 } | |
369 | |
370 void WorkerThreadableLoader::Peer::cancel() | |
371 { | |
372 DCHECK(isMainThread()); | |
373 if (!m_mainThreadLoader) | |
374 return; | |
375 m_mainThreadLoader->cancel(); | |
376 m_mainThreadLoader = nullptr; | |
377 } | |
378 | |
379 void WorkerThreadableLoader::Peer::didSendData(unsigned long long bytesSent, uns igned long long totalBytesToBeSent) | |
380 { | |
381 DCHECK(isMainThread()); | |
382 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get(); | |
383 if (!clientWrapper || !m_forwarder) | |
384 return; | |
385 m_forwarder->forwardTask(createCrossThreadTask(&ThreadableLoaderClientWrappe r::didSendData, clientWrapper, bytesSent, totalBytesToBeSent)); | |
386 } | |
387 | |
388 void WorkerThreadableLoader::Peer::didReceiveResponse(unsigned long identifier, const ResourceResponse& response, std::unique_ptr<WebDataConsumerHandle> handle) | |
389 { | |
390 DCHECK(isMainThread()); | |
391 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get(); | |
392 if (!clientWrapper || !m_forwarder) | |
393 return; | |
394 m_forwarder->forwardTask(createCrossThreadTask(&ThreadableLoaderClientWrappe r::didReceiveResponse, clientWrapper, identifier, response, passed(std::move(han dle)))); | |
395 } | |
396 | |
397 void WorkerThreadableLoader::Peer::didReceiveData(const char* data, unsigned dat aLength) | |
398 { | |
399 DCHECK(isMainThread()); | |
400 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get(); | |
401 if (!clientWrapper || !m_forwarder) | |
402 return; | |
403 m_forwarder->forwardTask(createCrossThreadTask(&ThreadableLoaderClientWrappe r::didReceiveData, clientWrapper, passed(createVectorFromMemoryRegion(data, data Length)))); | |
404 } | |
405 | |
406 void WorkerThreadableLoader::Peer::didDownloadData(int dataLength) | |
407 { | |
408 DCHECK(isMainThread()); | |
409 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get(); | |
410 if (!clientWrapper || !m_forwarder) | |
411 return; | |
412 m_forwarder->forwardTask(createCrossThreadTask(&ThreadableLoaderClientWrappe r::didDownloadData, clientWrapper, dataLength)); | |
413 } | |
414 | |
415 void WorkerThreadableLoader::Peer::didReceiveCachedMetadata(const char* data, in t dataLength) | |
416 { | |
417 DCHECK(isMainThread()); | |
418 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get(); | |
419 if (!clientWrapper || !m_forwarder) | |
420 return; | |
421 m_forwarder->forwardTask(createCrossThreadTask(&ThreadableLoaderClientWrappe r::didReceiveCachedMetadata, clientWrapper, passed(createVectorFromMemoryRegion( data, dataLength)))); | |
422 } | |
423 | |
424 void WorkerThreadableLoader::Peer::didFinishLoading(unsigned long identifier, do uble finishTime) | |
425 { | |
426 DCHECK(isMainThread()); | |
427 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get(); | |
428 if (!clientWrapper || !m_forwarder) | |
429 return; | |
430 m_forwarder->forwardTaskWithDoneSignal(createCrossThreadTask(&ThreadableLoad erClientWrapper::didFinishLoading, clientWrapper, identifier, finishTime)); | |
431 m_forwarder = nullptr; | |
432 } | |
433 | |
434 void WorkerThreadableLoader::Peer::didFail(const ResourceError& error) | |
435 { | |
436 DCHECK(isMainThread()); | |
437 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get(); | |
438 if (!clientWrapper || !m_forwarder) | |
439 return; | |
440 m_forwarder->forwardTaskWithDoneSignal(createCrossThreadTask(&ThreadableLoad erClientWrapper::didFail, clientWrapper, error)); | |
441 m_forwarder = nullptr; | |
442 } | |
443 | |
444 void WorkerThreadableLoader::Peer::didFailAccessControlCheck(const ResourceError & error) | |
445 { | |
446 DCHECK(isMainThread()); | |
447 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get(); | |
448 if (!clientWrapper || !m_forwarder) | |
449 return; | |
450 m_forwarder->forwardTaskWithDoneSignal(createCrossThreadTask(&ThreadableLoad erClientWrapper::didFailAccessControlCheck, clientWrapper, error)); | |
451 m_forwarder = nullptr; | |
452 } | |
453 | |
454 void WorkerThreadableLoader::Peer::didFailRedirectCheck() | |
455 { | |
456 DCHECK(isMainThread()); | |
457 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get(); | |
458 if (!clientWrapper || !m_forwarder) | |
459 return; | |
460 m_forwarder->forwardTaskWithDoneSignal(createCrossThreadTask(&ThreadableLoad erClientWrapper::didFailRedirectCheck, clientWrapper)); | |
461 m_forwarder = nullptr; | |
462 } | |
463 | |
464 void WorkerThreadableLoader::Peer::didReceiveResourceTiming(const ResourceTiming Info& info) | |
465 { | |
466 DCHECK(isMainThread()); | |
467 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get(); | |
468 if (!clientWrapper || !m_forwarder) | |
469 return; | |
470 m_forwarder->forwardTask(createCrossThreadTask(&ThreadableLoaderClientWrappe r::didReceiveResourceTiming, clientWrapper, info)); | |
471 } | |
472 | |
473 void WorkerThreadableLoader::Peer::contextDestroyed() | |
474 { | |
475 DCHECK(isMainThread()); | |
476 if (m_forwarder) { | |
477 m_forwarder->abort(); | |
478 m_forwarder = nullptr; | |
479 } | |
480 m_clientWrapper = nullptr; | |
481 cancel(); | |
482 } | |
483 | |
484 DEFINE_TRACE(WorkerThreadableLoader::Peer) | |
485 { | |
486 visitor->trace(m_forwarder); | |
487 WorkerThreadLifecycleObserver::trace(visitor); | |
488 } | |
489 | |
490 WorkerThreadableLoader::Peer::Peer(TaskForwarder* forwarder, WorkerThreadLifecyc leContext* context) | |
491 : WorkerThreadLifecycleObserver(context) | |
492 , m_forwarder(forwarder) | |
493 { | |
494 DCHECK(isMainThread()); | |
495 } | |
496 | |
497 void WorkerThreadableLoader::Peer::start( | |
498 Document& document, | |
499 std::unique_ptr<CrossThreadResourceRequestData> request, | |
500 const ThreadableLoaderOptions& options, | |
501 const ResourceLoaderOptions& originalResourceLoaderOptions) | |
502 { | |
503 DCHECK(isMainThread()); | |
504 ResourceLoaderOptions resourceLoaderOptions = originalResourceLoaderOptions; | |
505 resourceLoaderOptions.requestInitiatorContext = WorkerContext; | |
506 m_mainThreadLoader = DocumentThreadableLoader::create(document, this, option s, resourceLoaderOptions); | |
507 m_mainThreadLoader->start(ResourceRequest(request.get())); | |
369 } | 508 } |
370 | 509 |
371 } // namespace blink | 510 } // namespace blink |
OLD | NEW |