Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp

Issue 2151173003: Move WorkerThreadable internal classes to Oilpan heap (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@onheap-threadable-loader-client-wrapper
Patch Set: fix Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 CHECK(!m_isSignalCalled);
137 m_isSignalCalled = true;
138 m_event.signal();
139 }
140
141 void WorkerThreadableLoader::WaitableEventWithTasks::wait()
142 {
143 DCHECK(!isMainThread());
144 CHECK(!m_isWaitDone);
145 m_event.wait();
146 m_isWaitDone = true;
147 }
148
149 bool WorkerThreadableLoader::WaitableEventWithTasks::isAborted() const
150 {
151 DCHECK(!isMainThread());
152 CHECK(m_isWaitDone);
153 return m_isAborted;
154 }
155
156 Vector<std::unique_ptr<ExecutionContextTask>> WorkerThreadableLoader::WaitableEv entWithTasks::take()
157 {
158 DCHECK(!isMainThread());
159 CHECK(m_isWaitDone);
160 return std::move(m_tasks);
161 }
162
163 void WorkerThreadableLoader::WaitableEventWithTasks::setIsAborted()
164 {
165 DCHECK(isMainThread());
166 CHECK(!m_isSignalCalled);
167 m_isAborted = true;
168 }
169
170 void WorkerThreadableLoader::WaitableEventWithTasks::append(std::unique_ptr<Exec utionContextTask> task)
171 {
172 DCHECK(isMainThread());
173 CHECK(!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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698