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

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

Powered by Google App Engine
This is Rietveld 408576698