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

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: rebase 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
« no previous file with comments | « third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "wtf/debug/Alias.h" 46 #include "wtf/debug/Alias.h"
52 #include <memory> 47 #include <memory>
53 48
54 namespace blink { 49 namespace blink {
55 50
56 static std::unique_ptr<Vector<char>> createVectorFromMemoryRegion(const char* da ta, unsigned dataLength) 51 namespace {
52
53 std::unique_ptr<Vector<char>> createVectorFromMemoryRegion(const char* data, uns igned dataLength)
57 { 54 {
58 std::unique_ptr<Vector<char>> buffer = wrapUnique(new Vector<char>(dataLengt h)); 55 std::unique_ptr<Vector<char>> buffer = wrapUnique(new Vector<char>(dataLengt h));
59 memcpy(buffer->data(), data, dataLength); 56 memcpy(buffer->data(), data, dataLength);
60 return buffer; 57 return buffer;
61 } 58 }
62 59
63 WorkerThreadableLoader::WorkerThreadableLoader(WorkerGlobalScope& workerGlobalSc ope, ThreadableLoaderClient* client, const ThreadableLoaderOptions& options, con st ResourceLoaderOptions& resourceLoaderOptions, BlockingBehavior blockingBehavi or) 60 } // namespace
61
62 class WorkerThreadableLoader::AsyncTaskForwarder final : public WorkerThreadable Loader::TaskForwarder {
63 public:
64 explicit AsyncTaskForwarder(PassRefPtr<WorkerLoaderProxy> loaderProxy)
65 : m_loaderProxy(loaderProxy)
66 {
67 DCHECK(isMainThread());
68 }
69 ~AsyncTaskForwarder() override
70 {
71 DCHECK(isMainThread());
72 }
73
74 void forwardTask(const WebTraceLocation& location, std::unique_ptr<Execution ContextTask> task) override
75 {
76 DCHECK(isMainThread());
77 m_loaderProxy->postTaskToWorkerGlobalScope(location, std::move(task));
78 }
79 void forwardTaskWithDoneSignal(const WebTraceLocation& location, std::unique _ptr<ExecutionContextTask> task) override
80 {
81 DCHECK(isMainThread());
82 m_loaderProxy->postTaskToWorkerGlobalScope(location, std::move(task));
83 }
84 void abort() override
85 {
86 DCHECK(isMainThread());
87 }
88
89 private:
90 RefPtr<WorkerLoaderProxy> m_loaderProxy;
91 };
92
93 struct WorkerThreadableLoader::TaskWithLocation final {
94 TaskWithLocation(const WebTraceLocation& location, std::unique_ptr<Execution ContextTask> task)
95 : m_location(location)
96 , m_task(std::move(task))
97 {
98 }
99 TaskWithLocation(TaskWithLocation&& task)
100 : TaskWithLocation(task.m_location, std::move(task.m_task))
101 {
102 }
103 ~TaskWithLocation() = default;
104
105 WebTraceLocation m_location;
106 std::unique_ptr<ExecutionContextTask> m_task;
107 };
108
109 // Observing functions and wait() need to be called on the worker thread.
110 // Setting functions and signal() need to be called on the main thread.
111 // All observing functions must be called after wait() returns, and all
112 // setting functions must be called before signal() is called.
113 class WorkerThreadableLoader::WaitableEventWithTasks final : public ThreadSafeRe fCounted<WaitableEventWithTasks> {
114 public:
115 static PassRefPtr<WaitableEventWithTasks> create() { return adoptRef(new Wai tableEventWithTasks); }
116
117 void signal()
118 {
119 DCHECK(isMainThread());
120 CHECK(!m_isSignalCalled);
121 m_isSignalCalled = true;
122 m_event.signal();
123 }
124 void wait()
125 {
126 DCHECK(!isMainThread());
127 CHECK(!m_isWaitDone);
128 m_event.wait();
129 m_isWaitDone = true;
130 }
131
132 // Observing functions
133 bool isAborted() const
134 {
135 DCHECK(!isMainThread());
136 CHECK(m_isWaitDone);
137 return m_isAborted;
138 }
139 Vector<TaskWithLocation> take()
140 {
141 DCHECK(!isMainThread());
142 CHECK(m_isWaitDone);
143 return std::move(m_tasks);
144 }
145
146 // Setting functions
147 void append(TaskWithLocation task)
148 {
149 DCHECK(isMainThread());
150 CHECK(!m_isSignalCalled);
151 m_tasks.append(std::move(task));
152 }
153 void setIsAborted()
154 {
155 DCHECK(isMainThread());
156 CHECK(!m_isSignalCalled);
157 m_isAborted = true;
158 }
159
160 private:
161 WaitableEventWithTasks() {}
162
163 WaitableEvent m_event;
164 Vector<TaskWithLocation> m_tasks;
165 bool m_isAborted = false;
166 bool m_isSignalCalled = false;
167 bool m_isWaitDone = false;
168 };
169
170 class WorkerThreadableLoader::SyncTaskForwarder final : public WorkerThreadableL oader::TaskForwarder {
171 public:
172 explicit SyncTaskForwarder(PassRefPtr<WaitableEventWithTasks> eventWithTasks )
173 : m_eventWithTasks(eventWithTasks)
174 {
175 DCHECK(isMainThread());
176 }
177 ~SyncTaskForwarder() override
178 {
179 DCHECK(isMainThread());
180 }
181
182 void forwardTask(const WebTraceLocation& location, std::unique_ptr<Execution ContextTask> task) override
183 {
184 DCHECK(isMainThread());
185 m_eventWithTasks->append(TaskWithLocation(location, std::move(task)));
186 }
187 void forwardTaskWithDoneSignal(const WebTraceLocation& location, std::unique _ptr<ExecutionContextTask> task) override
188 {
189 DCHECK(isMainThread());
190 m_eventWithTasks->append(TaskWithLocation(location, std::move(task)));
191 m_eventWithTasks->signal();
192 }
193 void abort() override
194 {
195 DCHECK(isMainThread());
196 m_eventWithTasks->setIsAborted();
197 m_eventWithTasks->signal();
198 }
199
200 private:
201 RefPtr<WaitableEventWithTasks> m_eventWithTasks;
202 };
203
204 WorkerThreadableLoader::WorkerThreadableLoader(
205 WorkerGlobalScope& workerGlobalScope,
206 ThreadableLoaderClient* client,
207 const ThreadableLoaderOptions& options,
208 const ResourceLoaderOptions& resourceLoaderOptions,
209 BlockingBehavior blockingBehavior)
64 : m_workerGlobalScope(&workerGlobalScope) 210 : m_workerGlobalScope(&workerGlobalScope)
65 , m_workerClientWrapper(new ThreadableLoaderClientWrapper(workerGlobalScope, client)) 211 , m_workerClientWrapper(new ThreadableLoaderClientWrapper(workerGlobalScope, client))
212 , m_bridge(new Bridge(m_workerClientWrapper, workerGlobalScope.thread()->wor kerLoaderProxy(), options, resourceLoaderOptions, blockingBehavior))
66 { 213 {
67 if (blockingBehavior == LoadAsynchronously) {
68 m_bridge = new MainThreadAsyncBridge(workerGlobalScope, m_workerClientWr apper, options, resourceLoaderOptions);
69 } else {
70 m_bridge = new MainThreadSyncBridge(workerGlobalScope, m_workerClientWra pper, options, resourceLoaderOptions);
71 }
72 } 214 }
73 215
74 void WorkerThreadableLoader::loadResourceSynchronously(WorkerGlobalScope& worker GlobalScope, const ResourceRequest& request, ThreadableLoaderClient& client, con st ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoader Options) 216 void WorkerThreadableLoader::loadResourceSynchronously(WorkerGlobalScope& worker GlobalScope, const ResourceRequest& request, ThreadableLoaderClient& client, con st ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoader Options)
75 { 217 {
76 std::unique_ptr<WorkerThreadableLoader> loader = wrapUnique(new WorkerThread ableLoader(workerGlobalScope, &client, options, resourceLoaderOptions, LoadSynch ronously)); 218 std::unique_ptr<WorkerThreadableLoader> loader = wrapUnique(new WorkerThread ableLoader(workerGlobalScope, &client, options, resourceLoaderOptions, LoadSynch ronously));
77 loader->start(request); 219 loader->start(request);
78 } 220 }
79 221
80 WorkerThreadableLoader::~WorkerThreadableLoader() 222 WorkerThreadableLoader::~WorkerThreadableLoader()
81 { 223 {
82 DCHECK(m_workerClientWrapper->done()); 224 DCHECK(m_workerClientWrapper->done());
83 m_bridge->destroy(); 225 m_bridge->destroy();
84 m_bridge = nullptr;
85 } 226 }
86 227
87 void WorkerThreadableLoader::start(const ResourceRequest& request) 228 void WorkerThreadableLoader::start(const ResourceRequest& request)
88 { 229 {
89 ResourceRequest requestToPass(request); 230 ResourceRequest requestToPass(request);
90 if (!requestToPass.didSetHTTPReferrer()) 231 if (!requestToPass.didSetHTTPReferrer())
91 requestToPass.setHTTPReferrer(SecurityPolicy::generateReferrer(m_workerG lobalScope->getReferrerPolicy(), request.url(), m_workerGlobalScope->outgoingRef errer())); 232 requestToPass.setHTTPReferrer(SecurityPolicy::generateReferrer(m_workerG lobalScope->getReferrerPolicy(), request.url(), m_workerGlobalScope->outgoingRef errer()));
92 m_bridge->start(requestToPass, *m_workerGlobalScope); 233 m_bridge->start(requestToPass, *m_workerGlobalScope);
93 } 234 }
94 235
95 void WorkerThreadableLoader::overrideTimeout(unsigned long timeoutMilliseconds) 236 void WorkerThreadableLoader::overrideTimeout(unsigned long timeoutMilliseconds)
96 { 237 {
97 ASSERT(m_bridge);
98 m_bridge->overrideTimeout(timeoutMilliseconds); 238 m_bridge->overrideTimeout(timeoutMilliseconds);
99 } 239 }
100 240
101 void WorkerThreadableLoader::cancel() 241 void WorkerThreadableLoader::cancel()
102 { 242 {
103 ASSERT(m_bridge);
104 m_bridge->cancel(); 243 m_bridge->cancel();
105 } 244 }
106 245
107 WorkerThreadableLoader::MainThreadBridgeBase::MainThreadBridgeBase( 246 WorkerThreadableLoader::Bridge::Bridge(
108 ThreadableLoaderClientWrapper* workerClientWrapper, 247 ThreadableLoaderClientWrapper* clientWrapper,
109 PassRefPtr<WorkerLoaderProxy> loaderProxy) 248 PassRefPtr<WorkerLoaderProxy> loaderProxy,
110 : m_workerClientWrapper(workerClientWrapper) 249 const ThreadableLoaderOptions& threadableLoaderOptions,
250 const ResourceLoaderOptions& resourceLoaderOptions,
251 BlockingBehavior blockingBehavior)
252 : m_clientWrapper(clientWrapper)
111 , m_loaderProxy(loaderProxy) 253 , m_loaderProxy(loaderProxy)
112 { 254 , m_threadableLoaderOptions(threadableLoaderOptions)
113 ASSERT(m_workerClientWrapper.get()); 255 , m_resourceLoaderOptions(resourceLoaderOptions)
114 ASSERT(m_loaderProxy.get()); 256 , m_blockingBehavior(blockingBehavior)
115 } 257 {
116 258 DCHECK(!isMainThread());
117 WorkerThreadableLoader::MainThreadBridgeBase::~MainThreadBridgeBase() 259 }
118 { 260
119 } 261 WorkerThreadableLoader::Bridge::~Bridge()
120 262 {
121 void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadCreateLoader(Thread ableLoaderOptions options, ResourceLoaderOptions resourceLoaderOptions, Executio nContext* context) 263 DCHECK(!isMainThread());
122 { 264 DCHECK(!m_peer);
123 ASSERT(isMainThread()); 265 }
124 Document* document = toDocument(context); 266
125 267 void WorkerThreadableLoader::Bridge::start(const ResourceRequest& request, const WorkerGlobalScope& workerGlobalScope)
126 resourceLoaderOptions.requestInitiatorContext = WorkerContext; 268 {
127 m_mainThreadLoader = DocumentThreadableLoader::create(*document, this, optio ns, resourceLoaderOptions); 269 DCHECK(!isMainThread());
128 ASSERT(m_mainThreadLoader); 270 RefPtr<WaitableEventWithTasks> eventWithTasks;
129 } 271 if (m_blockingBehavior == LoadSynchronously)
130 272 eventWithTasks = WaitableEventWithTasks::create();
131 void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadStart(std::unique_p tr<CrossThreadResourceRequestData> requestData) 273
132 { 274 m_loaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(
133 ASSERT(isMainThread()); 275 &Peer::createAndStart,
134 ASSERT(m_mainThreadLoader); 276 wrapCrossThreadPersistent(this),
135 m_mainThreadLoader->start(ResourceRequest(requestData.get())); 277 m_loaderProxy,
136 } 278 wrapCrossThreadPersistent(workerGlobalScope.thread()->getWorkerThreadLif ecycleContext()),
137 279 request,
138 void WorkerThreadableLoader::MainThreadBridgeBase::createLoaderInMainThread(cons t ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderO ptions) 280 m_threadableLoaderOptions,
139 { 281 m_resourceLoaderOptions,
140 m_loaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&Main ThreadBridgeBase::mainThreadCreateLoader, crossThreadUnretained(this), options, resourceLoaderOptions)); 282 eventWithTasks));
141 } 283
142 284 if (m_blockingBehavior == LoadAsynchronously)
143 void WorkerThreadableLoader::MainThreadBridgeBase::startInMainThread(const Resou rceRequest& request, const WorkerGlobalScope& workerGlobalScope) 285 return;
144 { 286
145 loaderProxy()->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&Main ThreadBridgeBase::mainThreadStart, crossThreadUnretained(this), request));
146 }
147
148 void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadDestroy(ExecutionCo ntext* context)
149 {
150 ASSERT(isMainThread());
151 ASSERT_UNUSED(context, context->isDocument());
152 delete this;
153 }
154
155 void WorkerThreadableLoader::MainThreadBridgeBase::destroy()
156 {
157 // Ensure that no more client callbacks are done in the worker context's
158 // thread.
159 // ThreadableLoaderClientWrapper is an on-heap class and this function can
160 // be called in the finalization step but it is safe because
161 // m_workerClientWrapper is a CrossThreadPersistent.
162 m_workerClientWrapper->clearClient();
163
164 // "delete this" and m_mainThreadLoader::deref() on the worker object's
165 // thread.
166 m_loaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&Main ThreadBridgeBase::mainThreadDestroy, crossThreadUnretained(this)));
167 }
168
169 void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadOverrideTimeout(uns igned long timeoutMilliseconds, ExecutionContext* context)
170 {
171 ASSERT(isMainThread());
172 ASSERT_UNUSED(context, context->isDocument());
173
174 if (!m_mainThreadLoader)
175 return;
176 m_mainThreadLoader->overrideTimeout(timeoutMilliseconds);
177 }
178
179 void WorkerThreadableLoader::MainThreadBridgeBase::overrideTimeout(unsigned long timeoutMilliseconds)
180 {
181 m_loaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&Main ThreadBridgeBase::mainThreadOverrideTimeout, crossThreadUnretained(this), timeou tMilliseconds));
182 }
183
184 void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadCancel(ExecutionCon text* context)
185 {
186 ASSERT(isMainThread());
187 ASSERT_UNUSED(context, context->isDocument());
188
189 if (!m_mainThreadLoader)
190 return;
191 m_mainThreadLoader->cancel();
192 m_mainThreadLoader = nullptr;
193 }
194
195 void WorkerThreadableLoader::MainThreadBridgeBase::cancel()
196 {
197 m_loaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&Main ThreadBridgeBase::mainThreadCancel, crossThreadUnretained(this)));
198 ThreadableLoaderClientWrapper* clientWrapper = m_workerClientWrapper;
199 if (!clientWrapper->done()) {
200 // If the client hasn't reached a termination state, then transition it
201 // by sending a cancellation error.
202 // Note: no more client callbacks will be done after this method -- the
203 // m_workerClientWrapper->clearClient() call ensures that.
204 ResourceError error(String(), 0, String(), String());
205 error.setIsCancellation(true);
206 clientWrapper->didFail(error);
207 }
208 // |this| might be already destructed here because didFail() might
209 // clear a reference to ThreadableLoader, which might destruct
210 // WorkerThreadableLoader and then MainThreadBridge.
211 // Therefore we call clearClient() directly, rather than calling
212 // this->m_workerClientWrapper->clearClient().
213 clientWrapper->clearClient();
214 }
215
216 void WorkerThreadableLoader::MainThreadBridgeBase::didSendData(unsigned long lon g bytesSent, unsigned long long totalBytesToBeSent)
217 {
218 forwardTaskToWorker(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoader ClientWrapper::didSendData, m_workerClientWrapper, bytesSent, totalBytesToBeSent ));
219 }
220
221 void WorkerThreadableLoader::MainThreadBridgeBase::didReceiveResponse(unsigned l ong identifier, const ResourceResponse& response, std::unique_ptr<WebDataConsume rHandle> handle)
222 {
223 forwardTaskToWorker(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoader ClientWrapper::didReceiveResponse, m_workerClientWrapper, identifier, response, passed(std::move(handle))));
224 }
225
226 void WorkerThreadableLoader::MainThreadBridgeBase::didReceiveData(const char* da ta, unsigned dataLength)
227 {
228 forwardTaskToWorker(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoader ClientWrapper::didReceiveData, m_workerClientWrapper, passed(createVectorFromMem oryRegion(data, dataLength))));
229 }
230
231 void WorkerThreadableLoader::MainThreadBridgeBase::didDownloadData(int dataLengt h)
232 {
233 forwardTaskToWorker(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoader ClientWrapper::didDownloadData, m_workerClientWrapper, dataLength));
234 }
235
236 void WorkerThreadableLoader::MainThreadBridgeBase::didReceiveCachedMetadata(cons t char* data, int dataLength)
237 {
238 forwardTaskToWorker(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoader ClientWrapper::didReceiveCachedMetadata, m_workerClientWrapper, passed(createVec torFromMemoryRegion(data, dataLength))));
239 }
240
241 void WorkerThreadableLoader::MainThreadBridgeBase::didFinishLoading(unsigned lon g identifier, double finishTime)
242 {
243 forwardTaskToWorkerOnLoaderDone(BLINK_FROM_HERE, createCrossThreadTask(&Thre adableLoaderClientWrapper::didFinishLoading, m_workerClientWrapper, identifier, finishTime));
244 }
245
246 void WorkerThreadableLoader::MainThreadBridgeBase::didFail(const ResourceError& error)
247 {
248 forwardTaskToWorkerOnLoaderDone(BLINK_FROM_HERE, createCrossThreadTask(&Thre adableLoaderClientWrapper::didFail, m_workerClientWrapper, error));
249 }
250
251 void WorkerThreadableLoader::MainThreadBridgeBase::didFailAccessControlCheck(con st ResourceError& error)
252 {
253 forwardTaskToWorkerOnLoaderDone(BLINK_FROM_HERE, createCrossThreadTask(&Thre adableLoaderClientWrapper::didFailAccessControlCheck, m_workerClientWrapper, err or));
254 }
255
256 void WorkerThreadableLoader::MainThreadBridgeBase::didFailRedirectCheck()
257 {
258 forwardTaskToWorkerOnLoaderDone(BLINK_FROM_HERE, createCrossThreadTask(&Thre adableLoaderClientWrapper::didFailRedirectCheck, m_workerClientWrapper));
259 }
260
261 void WorkerThreadableLoader::MainThreadBridgeBase::didReceiveResourceTiming(cons t ResourceTimingInfo& info)
262 {
263 forwardTaskToWorker(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoader ClientWrapper::didReceiveResourceTiming, m_workerClientWrapper, info));
264 }
265
266 WorkerThreadableLoader::MainThreadAsyncBridge::MainThreadAsyncBridge(
267 WorkerGlobalScope& workerGlobalScope,
268 ThreadableLoaderClientWrapper* workerClientWrapper,
269 const ThreadableLoaderOptions& options,
270 const ResourceLoaderOptions& resourceLoaderOptions)
271 : MainThreadBridgeBase(workerClientWrapper, workerGlobalScope.thread()->work erLoaderProxy())
272 {
273 createLoaderInMainThread(options, resourceLoaderOptions);
274 }
275
276 void WorkerThreadableLoader::MainThreadAsyncBridge::start(const ResourceRequest& request, const WorkerGlobalScope& workerGlobalScope)
277 {
278 startInMainThread(request, workerGlobalScope);
279 }
280
281 WorkerThreadableLoader::MainThreadAsyncBridge::~MainThreadAsyncBridge()
282 {
283 }
284
285 void WorkerThreadableLoader::MainThreadAsyncBridge::forwardTaskToWorker(const We bTraceLocation& location, std::unique_ptr<ExecutionContextTask> task)
286 {
287 loaderProxy()->postTaskToWorkerGlobalScope(location, std::move(task));
288 }
289
290 void WorkerThreadableLoader::MainThreadAsyncBridge::forwardTaskToWorkerOnLoaderD one(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task )
291 {
292 loaderProxy()->postTaskToWorkerGlobalScope(location, std::move(task));
293 }
294
295 WorkerThreadableLoader::MainThreadSyncBridge::MainThreadSyncBridge(
296 WorkerGlobalScope& workerGlobalScope,
297 ThreadableLoaderClientWrapper* workerClientWrapper,
298 const ThreadableLoaderOptions& options,
299 const ResourceLoaderOptions& resourceLoaderOptions)
300 : MainThreadBridgeBase(workerClientWrapper, workerGlobalScope.thread()->work erLoaderProxy())
301 , m_done(false)
302 {
303 createLoaderInMainThread(options, resourceLoaderOptions);
304 }
305
306 void WorkerThreadableLoader::MainThreadSyncBridge::start(const ResourceRequest& request, const WorkerGlobalScope& workerGlobalScope)
307 {
308 WaitableEvent* terminationEvent = workerGlobalScope.thread()->terminationEve nt();
309 m_loaderDoneEvent = wrapUnique(new WaitableEvent());
310
311 startInMainThread(request, workerGlobalScope);
312
313 size_t signaledIndex;
314 { 287 {
315 Vector<WaitableEvent*> events;
316 // Order is important; indicies are used later.
317 events.append(terminationEvent);
318 events.append(m_loaderDoneEvent.get());
319
320 SafePointScope scope(BlinkGC::HeapPointersOnStack); 288 SafePointScope scope(BlinkGC::HeapPointersOnStack);
321 signaledIndex = WaitableEvent::waitMultiple(events); 289 eventWithTasks->wait();
322 } 290 }
323 // |signaledIndex| is 0; which is terminationEvent. 291
324 if (signaledIndex == 0) { 292 if (eventWithTasks->isAborted()) {
293 // This thread is going to terminate.
325 cancel(); 294 cancel();
326 return; 295 return;
327 } 296 }
328 297
329 // The following code must be run only after |m_loaderDoneEvent| is 298 for (const auto& task : eventWithTasks->take()) {
330 // signalled.
331
332 Vector<ClientTask> tasks;
333 {
334 MutexLocker lock(m_lock);
335 ASSERT(m_done);
336 m_clientTasks.swap(tasks);
337 }
338 for (const auto& task : tasks) {
339 // Store the program counter where the task is posted from, and alias 299 // Store the program counter where the task is posted from, and alias
340 // it to ensure it is stored in the crash dump. 300 // it to ensure it is stored in the crash dump.
341 const void* programCounter = task.m_location.program_counter(); 301 const void* programCounter = task.m_location.program_counter();
342 WTF::debug::alias(&programCounter); 302 WTF::debug::alias(&programCounter);
343 303
344 // m_clientTask contains only CallClosureTasks. So, it's ok to pass 304 // m_clientTask contains only CallClosureTasks. So, it's ok to pass
345 // the nullptr. 305 // the nullptr.
346 task.m_task->performTask(nullptr); 306 task.m_task->performTask(nullptr);
347 } 307 }
348 } 308 }
349 309
350 WorkerThreadableLoader::MainThreadSyncBridge::ClientTask::ClientTask(const WebTr aceLocation& location, std::unique_ptr<ExecutionContextTask> task) 310 void WorkerThreadableLoader::Bridge::overrideTimeout(unsigned long timeoutMillis econds)
351 : m_location(location) 311 {
352 , m_task(std::move(task)) {} 312 DCHECK(!isMainThread());
353 313 if (!m_peer)
354 WorkerThreadableLoader::MainThreadSyncBridge::ClientTask::~ClientTask() = defaul t; 314 return;
355 WorkerThreadableLoader::MainThreadSyncBridge::ClientTask::ClientTask(ClientTask& &) = default; 315 m_loaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&Peer ::overrideTimeout, m_peer, timeoutMilliseconds));
356 316 }
357 WorkerThreadableLoader::MainThreadSyncBridge::~MainThreadSyncBridge() 317
358 { 318 void WorkerThreadableLoader::Bridge::cancel()
359 ASSERT(isMainThread()); 319 {
360 } 320 DCHECK(!isMainThread());
361 321 cancelPeer();
362 void WorkerThreadableLoader::MainThreadSyncBridge::forwardTaskToWorker(const Web TraceLocation& location, std::unique_ptr<ExecutionContextTask> task) 322
363 { 323 if (m_clientWrapper->done())
364 ASSERT(isMainThread()); 324 return;
365 325 // If the client hasn't reached a termination state, then transition it
366 MutexLocker lock(m_lock); 326 // by sending a cancellation error.
367 RELEASE_ASSERT(!m_done); 327 // Note: no more client callbacks will be done after this method -- the
368 328 // clearClient() call ensures that.
369 m_clientTasks.append(ClientTask(location, std::move(task))); 329 ResourceError error(String(), 0, String(), String());
370 } 330 error.setIsCancellation(true);
371 331 m_clientWrapper->didFail(error);
372 void WorkerThreadableLoader::MainThreadSyncBridge::forwardTaskToWorkerOnLoaderDo ne(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) 332 m_clientWrapper->clearClient();
373 { 333 }
374 ASSERT(isMainThread()); 334
375 335 void WorkerThreadableLoader::Bridge::destroy()
376 MutexLocker lock(m_lock); 336 {
377 RELEASE_ASSERT(!m_done); 337 DCHECK(!isMainThread());
378 338 cancelPeer();
379 m_clientTasks.append(ClientTask(location, std::move(task))); 339 m_clientWrapper->clearClient();
380 m_done = true; 340 }
381 m_loaderDoneEvent->signal(); 341
342 void WorkerThreadableLoader::Bridge::didStart(Peer* peer)
343 {
344 DCHECK(!isMainThread());
345 DCHECK(!m_peer);
346 DCHECK(peer);
347 if (m_clientWrapper->done()) {
348 // The loading is already cancelled.
349 return;
350 }
351
352 m_peer = peer;
353 }
354
355 DEFINE_TRACE(WorkerThreadableLoader::Bridge)
356 {
357 visitor->trace(m_clientWrapper);
358 }
359
360 void WorkerThreadableLoader::Bridge::cancelPeer()
361 {
362 DCHECK(!isMainThread());
363 if (!m_peer)
364 return;
365 m_loaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&Peer ::cancel, m_peer));
366 m_peer = nullptr;
367 }
368
369 void WorkerThreadableLoader::Peer::createAndStart(
370 Bridge* bridge,
371 PassRefPtr<WorkerLoaderProxy> passLoaderProxy,
372 WorkerThreadLifecycleContext* workerThreadLifecycleContext,
373 std::unique_ptr<CrossThreadResourceRequestData> request,
374 const ThreadableLoaderOptions& options,
375 const ResourceLoaderOptions& resourceLoaderOptions,
376 PassRefPtr<WaitableEventWithTasks> eventWithTasks,
377 ExecutionContext* executionContext)
378 {
379 DCHECK(isMainThread());
380 TaskForwarder* forwarder;
381 RefPtr<WorkerLoaderProxy> loaderProxy = passLoaderProxy;
382 if (eventWithTasks)
383 forwarder = new SyncTaskForwarder(eventWithTasks);
384 else
385 forwarder = new AsyncTaskForwarder(loaderProxy);
386
387 Peer* peer = new Peer(forwarder, workerThreadLifecycleContext);
388 if (peer->wasContextDestroyedBeforeObserverCreation()) {
389 // The thread is already terminating.
390 forwarder->abort();
391 peer->m_forwarder = nullptr;
392 return;
393 }
394 peer->m_clientWrapper = bridge->clientWrapper();
395 peer->start(*toDocument(executionContext), std::move(request), options, reso urceLoaderOptions);
396 forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&Bridge::didSt art, wrapCrossThreadPersistent(bridge), wrapCrossThreadPersistent(peer)));
397 }
398
399 WorkerThreadableLoader::Peer::~Peer()
400 {
401 DCHECK(isMainThread());
402 DCHECK(!m_mainThreadLoader);
403 }
404
405 void WorkerThreadableLoader::Peer::overrideTimeout(unsigned long timeoutMillisec onds)
406 {
407 DCHECK(isMainThread());
408 if (!m_mainThreadLoader)
409 return;
410 m_mainThreadLoader->overrideTimeout(timeoutMilliseconds);
411 }
412
413 void WorkerThreadableLoader::Peer::cancel()
414 {
415 DCHECK(isMainThread());
416 if (!m_mainThreadLoader)
417 return;
418 m_mainThreadLoader->cancel();
419 m_mainThreadLoader = nullptr;
420 }
421
422 void WorkerThreadableLoader::Peer::didSendData(unsigned long long bytesSent, uns igned long long totalBytesToBeSent)
423 {
424 DCHECK(isMainThread());
425 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get();
426 if (!clientWrapper || !m_forwarder)
427 return;
428 m_forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableL oaderClientWrapper::didSendData, clientWrapper, bytesSent, totalBytesToBeSent));
429 }
430
431 void WorkerThreadableLoader::Peer::didReceiveResponse(unsigned long identifier, const ResourceResponse& response, std::unique_ptr<WebDataConsumerHandle> handle)
432 {
433 DCHECK(isMainThread());
434 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get();
435 if (!clientWrapper || !m_forwarder)
436 return;
437 m_forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableL oaderClientWrapper::didReceiveResponse, clientWrapper, identifier, response, pas sed(std::move(handle))));
438 }
439
440 void WorkerThreadableLoader::Peer::didReceiveData(const char* data, unsigned dat aLength)
441 {
442 DCHECK(isMainThread());
443 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get();
444 if (!clientWrapper || !m_forwarder)
445 return;
446 m_forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableL oaderClientWrapper::didReceiveData, clientWrapper, passed(createVectorFromMemory Region(data, dataLength))));
447 }
448
449 void WorkerThreadableLoader::Peer::didDownloadData(int dataLength)
450 {
451 DCHECK(isMainThread());
452 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get();
453 if (!clientWrapper || !m_forwarder)
454 return;
455 m_forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableL oaderClientWrapper::didDownloadData, clientWrapper, dataLength));
456 }
457
458 void WorkerThreadableLoader::Peer::didReceiveCachedMetadata(const char* data, in t dataLength)
459 {
460 DCHECK(isMainThread());
461 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get();
462 if (!clientWrapper || !m_forwarder)
463 return;
464 m_forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableL oaderClientWrapper::didReceiveCachedMetadata, clientWrapper, passed(createVector FromMemoryRegion(data, dataLength))));
465 }
466
467 void WorkerThreadableLoader::Peer::didFinishLoading(unsigned long identifier, do uble finishTime)
468 {
469 DCHECK(isMainThread());
470 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get();
471 if (!clientWrapper || !m_forwarder)
472 return;
473 m_forwarder->forwardTaskWithDoneSignal(BLINK_FROM_HERE, createCrossThreadTas k(&ThreadableLoaderClientWrapper::didFinishLoading, clientWrapper, identifier, f inishTime));
474 m_forwarder = nullptr;
475 }
476
477 void WorkerThreadableLoader::Peer::didFail(const ResourceError& error)
478 {
479 DCHECK(isMainThread());
480 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get();
481 if (!clientWrapper || !m_forwarder)
482 return;
483 m_forwarder->forwardTaskWithDoneSignal(BLINK_FROM_HERE, createCrossThreadTas k(&ThreadableLoaderClientWrapper::didFail, clientWrapper, error));
484 m_forwarder = nullptr;
485 }
486
487 void WorkerThreadableLoader::Peer::didFailAccessControlCheck(const ResourceError & error)
488 {
489 DCHECK(isMainThread());
490 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get();
491 if (!clientWrapper || !m_forwarder)
492 return;
493 m_forwarder->forwardTaskWithDoneSignal(BLINK_FROM_HERE, createCrossThreadTas k(&ThreadableLoaderClientWrapper::didFailAccessControlCheck, clientWrapper, erro r));
494 m_forwarder = nullptr;
495 }
496
497 void WorkerThreadableLoader::Peer::didFailRedirectCheck()
498 {
499 DCHECK(isMainThread());
500 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get();
501 if (!clientWrapper || !m_forwarder)
502 return;
503 m_forwarder->forwardTaskWithDoneSignal(BLINK_FROM_HERE, createCrossThreadTas k(&ThreadableLoaderClientWrapper::didFailRedirectCheck, clientWrapper));
504 m_forwarder = nullptr;
505 }
506
507 void WorkerThreadableLoader::Peer::didReceiveResourceTiming(const ResourceTiming Info& info)
508 {
509 DCHECK(isMainThread());
510 CrossThreadPersistent<ThreadableLoaderClientWrapper> clientWrapper = m_clien tWrapper.get();
511 if (!clientWrapper || !m_forwarder)
512 return;
513 m_forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableL oaderClientWrapper::didReceiveResourceTiming, clientWrapper, info));
514 }
515
516 void WorkerThreadableLoader::Peer::contextDestroyed()
517 {
518 DCHECK(isMainThread());
519 if (m_forwarder) {
520 m_forwarder->abort();
521 m_forwarder = nullptr;
522 }
523 m_clientWrapper = nullptr;
524 cancel();
525 }
526
527 DEFINE_TRACE(WorkerThreadableLoader::Peer)
528 {
529 visitor->trace(m_forwarder);
530 WorkerThreadLifecycleObserver::trace(visitor);
531 }
532
533 WorkerThreadableLoader::Peer::Peer(TaskForwarder* forwarder, WorkerThreadLifecyc leContext* context)
534 : WorkerThreadLifecycleObserver(context)
535 , m_forwarder(forwarder)
536 {
537 DCHECK(isMainThread());
538 }
539
540 void WorkerThreadableLoader::Peer::start(
541 Document& document,
542 std::unique_ptr<CrossThreadResourceRequestData> request,
543 const ThreadableLoaderOptions& options,
544 const ResourceLoaderOptions& originalResourceLoaderOptions)
545 {
546 DCHECK(isMainThread());
547 ResourceLoaderOptions resourceLoaderOptions = originalResourceLoaderOptions;
548 resourceLoaderOptions.requestInitiatorContext = WorkerContext;
549 m_mainThreadLoader = DocumentThreadableLoader::create(document, this, option s, resourceLoaderOptions);
550 m_mainThreadLoader->start(ResourceRequest(request.get()));
382 } 551 }
383 552
384 } // namespace blink 553 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698