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

Side by Side Diff: third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp

Issue 2310673002: [worklets] Split up InProcessWorkerMessagingProxy into a base+worker class. (Closed)
Patch Set: address comments. Created 4 years, 3 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/workers/ThreadedMessagingProxyBase.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 // Copyright 2016 The Chromium Authors. All rights reserved.
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 2 // Use of this source code is governed by a BSD-style license that can be
3 * Copyright (C) 2009 Google Inc. All Rights Reserved. 3 // found in the LICENSE file.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27 4
28 #include "core/workers/InProcessWorkerMessagingProxy.h" 5 #include "core/workers/ThreadedMessagingProxyBase.h"
29 6
7 #include "bindings/core/v8/SourceLocation.h"
30 #include "core/dom/Document.h" 8 #include "core/dom/Document.h"
31 #include "core/dom/ExecutionContextTask.h"
32 #include "core/dom/SecurityContext.h"
33 #include "core/events/ErrorEvent.h"
34 #include "core/events/MessageEvent.h"
35 #include "core/frame/FrameConsole.h"
36 #include "core/frame/LocalFrame.h"
37 #include "core/frame/csp/ContentSecurityPolicy.h"
38 #include "core/inspector/ConsoleMessage.h"
39 #include "core/loader/DocumentLoadTiming.h"
40 #include "core/loader/DocumentLoader.h" 9 #include "core/loader/DocumentLoader.h"
41 #include "core/origin_trials/OriginTrialContext.h"
42 #include "core/workers/InProcessWorkerBase.h"
43 #include "core/workers/InProcessWorkerObjectProxy.h"
44 #include "core/workers/ParentFrameTaskRunners.h" 10 #include "core/workers/ParentFrameTaskRunners.h"
45 #include "core/workers/WorkerClients.h"
46 #include "core/workers/WorkerGlobalScope.h"
47 #include "core/workers/WorkerInspectorProxy.h" 11 #include "core/workers/WorkerInspectorProxy.h"
48 #include "core/workers/WorkerThreadStartupData.h" 12 #include "core/workers/WorkerThreadStartupData.h"
49 #include "public/platform/WebTaskRunner.h" 13 #include "wtf/CurrentTime.h"
50 #include "wtf/WTF.h"
51 #include <memory>
52 14
53 namespace blink { 15 namespace blink {
54 16
55 namespace { 17 namespace {
56 18
57 void processUnhandledExceptionOnWorkerGlobalScope(int exceptionId, ExecutionCont ext* scriptContext)
58 {
59 WorkerGlobalScope* globalScope = toWorkerGlobalScope(scriptContext);
60 globalScope->exceptionUnhandled(exceptionId);
61 }
62
63 void processMessageOnWorkerGlobalScope(PassRefPtr<SerializedScriptValue> message , std::unique_ptr<MessagePortChannelArray> channels, InProcessWorkerObjectProxy* workerObjectProxy, ExecutionContext* scriptContext)
64 {
65 WorkerGlobalScope* globalScope = toWorkerGlobalScope(scriptContext);
66 MessagePortArray* ports = MessagePort::entanglePorts(*scriptContext, std::mo ve(channels));
67 globalScope->dispatchEvent(MessageEvent::create(ports, std::move(message)));
68 workerObjectProxy->confirmMessageFromWorkerObject();
69 workerObjectProxy->startPendingActivityTimer();
70 }
71
72 static int s_liveMessagingProxyCount = 0; 19 static int s_liveMessagingProxyCount = 0;
73 20
74 } // namespace 21 } // namespace
75 22
76 InProcessWorkerMessagingProxy::InProcessWorkerMessagingProxy(InProcessWorkerBase * workerObject, WorkerClients* workerClients) 23 ThreadedMessagingProxyBase::ThreadedMessagingProxyBase(ExecutionContext* executi onContext)
77 : InProcessWorkerMessagingProxy(workerObject->getExecutionContext(), workerO bject, workerClients) 24 : m_executionContext(executionContext)
25 , m_workerInspectorProxy(WorkerInspectorProxy::create())
26 , m_parentFrameTaskRunners(ParentFrameTaskRunners::create(toDocument(m_execu tionContext.get())->frame()))
27 , m_mayBeDestroyed(false)
28 , m_askedToTerminate(false)
78 { 29 {
79 DCHECK(m_workerObject); 30 DCHECK(isParentContextThread());
31 s_liveMessagingProxyCount++;
80 } 32 }
81 33
82 InProcessWorkerMessagingProxy::~InProcessWorkerMessagingProxy() 34 ThreadedMessagingProxyBase::~ThreadedMessagingProxyBase()
83 { 35 {
84 DCHECK(isParentContextThread()); 36 DCHECK(isParentContextThread());
85 DCHECK(!m_workerObject);
86 if (m_loaderProxy) 37 if (m_loaderProxy)
87 m_loaderProxy->detachProvider(this); 38 m_loaderProxy->detachProvider(this);
88 s_liveMessagingProxyCount--; 39 s_liveMessagingProxyCount--;
89 } 40 }
90 41
91 int InProcessWorkerMessagingProxy::proxyCount() 42 int ThreadedMessagingProxyBase::proxyCount()
92 { 43 {
93 DCHECK(isMainThread()); 44 DCHECK(isMainThread());
94 return s_liveMessagingProxyCount; 45 return s_liveMessagingProxyCount;
95 } 46 }
96 47
97 void InProcessWorkerMessagingProxy::startWorkerGlobalScope(const KURL& scriptURL , const String& userAgent, const String& sourceCode) 48 void ThreadedMessagingProxyBase::initializeWorkerThread(std::unique_ptr<WorkerTh readStartupData> startupData)
98 { 49 {
99 DCHECK(isParentContextThread()); 50 DCHECK(isParentContextThread());
100 if (m_askedToTerminate) {
101 // Worker.terminate() could be called from JS before the thread was
102 // created.
103 return;
104 }
105 51
106 Document* document = toDocument(getExecutionContext()); 52 Document* document = toDocument(getExecutionContext());
107 SecurityOrigin* starterOrigin = document->getSecurityOrigin();
108
109 ContentSecurityPolicy* csp = m_workerObject->contentSecurityPolicy() ? m_wor kerObject->contentSecurityPolicy() : document->contentSecurityPolicy();
110 DCHECK(csp);
111
112 WorkerThreadStartMode startMode = m_workerInspectorProxy->workerStartMode(do cument);
113 std::unique_ptr<WorkerSettings> workerSettings = wrapUnique(new WorkerSettin gs(document->settings()));
114 std::unique_ptr<WorkerThreadStartupData> startupData = WorkerThreadStartupDa ta::create(scriptURL, userAgent, sourceCode, nullptr, startMode, csp->headers(). get(), m_workerObject->referrerPolicy(), starterOrigin, m_workerClients.release( ), document->addressSpace(), OriginTrialContext::getTokens(document).get(), std: :move(workerSettings));
115 double originTime = document->loader() ? document->loader()->timing().refere nceMonotonicTime() : monotonicallyIncreasingTime(); 53 double originTime = document->loader() ? document->loader()->timing().refere nceMonotonicTime() : monotonicallyIncreasingTime();
116 54
117 m_loaderProxy = WorkerLoaderProxy::create(this); 55 m_loaderProxy = WorkerLoaderProxy::create(this);
118 m_workerThread = createWorkerThread(originTime); 56 m_workerThread = createWorkerThread(originTime);
119 m_workerThread->start(std::move(startupData)); 57 m_workerThread->start(std::move(startupData));
120 workerThreadCreated(); 58 workerThreadCreated();
121 m_workerInspectorProxy->workerThreadCreated(document, m_workerThread.get(), scriptURL);
122 } 59 }
123 60
124 void InProcessWorkerMessagingProxy::postMessageToWorkerObject(PassRefPtr<Seriali zedScriptValue> message, std::unique_ptr<MessagePortChannelArray> channels) 61 void ThreadedMessagingProxyBase::postTaskToWorkerGlobalScope(const WebTraceLocat ion& location, std::unique_ptr<ExecutionContextTask> task)
125 {
126 DCHECK(isParentContextThread());
127 if (!m_workerObject || m_askedToTerminate)
128 return;
129
130 MessagePortArray* ports = MessagePort::entanglePorts(*getExecutionContext(), std::move(channels));
131 m_workerObject->dispatchEvent(MessageEvent::create(ports, std::move(message) ));
132 }
133
134 void InProcessWorkerMessagingProxy::postMessageToWorkerGlobalScope(PassRefPtr<Se rializedScriptValue> message, std::unique_ptr<MessagePortChannelArray> channels)
135 {
136 DCHECK(isParentContextThread());
137 if (m_askedToTerminate)
138 return;
139
140 std::unique_ptr<ExecutionContextTask> task = createCrossThreadTask(&processM essageOnWorkerGlobalScope, message, passed(std::move(channels)), crossThreadUnre tained(&workerObjectProxy()));
141 if (m_workerThread) {
142 // A message event is an activity and may initiate another activity.
143 m_workerGlobalScopeMayHavePendingActivity = true;
144 ++m_unconfirmedMessageCount;
145 m_workerThread->postTask(BLINK_FROM_HERE, std::move(task));
146 } else {
147 m_queuedEarlyTasks.append(std::move(task));
148 }
149 }
150
151 void InProcessWorkerMessagingProxy::postTaskToWorkerGlobalScope(const WebTraceLo cation& location, std::unique_ptr<ExecutionContextTask> task)
152 { 62 {
153 if (m_askedToTerminate) 63 if (m_askedToTerminate)
154 return; 64 return;
155 65
156 DCHECK(m_workerThread); 66 DCHECK(m_workerThread);
157 m_workerThread->postTask(location, std::move(task)); 67 m_workerThread->postTask(location, std::move(task));
158 } 68 }
159 69
160 void InProcessWorkerMessagingProxy::postTaskToLoader(const WebTraceLocation& loc ation, std::unique_ptr<ExecutionContextTask> task) 70 void ThreadedMessagingProxyBase::postTaskToLoader(const WebTraceLocation& locati on, std::unique_ptr<ExecutionContextTask> task)
161 { 71 {
162 DCHECK(getExecutionContext()->isDocument()); 72 DCHECK(getExecutionContext()->isDocument());
163 // TODO(hiroshige,yuryu): Make this not use ExecutionContextTask and use 73 // TODO(hiroshige,yuryu): Make this not use ExecutionContextTask and use
164 // m_parentFrameTaskRunners->get(TaskType::Networking) instead. 74 // m_parentFrameTaskRunners->get(TaskType::Networking) instead.
165 getExecutionContext()->postTask(location, std::move(task)); 75 getExecutionContext()->postTask(location, std::move(task));
166 } 76 }
167 77
168 void InProcessWorkerMessagingProxy::dispatchErrorEvent(const String& errorMessag e, std::unique_ptr<SourceLocation> location, int exceptionId) 78 void ThreadedMessagingProxyBase::reportConsoleMessage(MessageSource source, Mess ageLevel level, const String& message, std::unique_ptr<SourceLocation> location)
169 {
170 DCHECK(isParentContextThread());
171 if (!m_workerObject)
172 return;
173
174 // We don't bother checking the askedToTerminate() flag here, because
175 // exceptions should *always* be reported even if the thread is terminated.
176 // This is intentionally different than the behavior in MessageWorkerTask,
177 // because terminated workers no longer deliver messages (section 4.6 of the
178 // WebWorker spec), but they do report exceptions.
179
180 ErrorEvent* event = ErrorEvent::create(errorMessage, location->clone(), null ptr);
181 if (m_workerObject->dispatchEvent(event) == DispatchEventResult::NotCanceled )
182 postTaskToWorkerGlobalScope(BLINK_FROM_HERE, createCrossThreadTask(&proc essUnhandledExceptionOnWorkerGlobalScope, exceptionId));
183 }
184
185 void InProcessWorkerMessagingProxy::reportConsoleMessage(MessageSource source, M essageLevel level, const String& message, std::unique_ptr<SourceLocation> locati on)
186 { 79 {
187 DCHECK(isParentContextThread()); 80 DCHECK(isParentContextThread());
188 if (m_askedToTerminate) 81 if (m_askedToTerminate)
189 return; 82 return;
190 if (m_workerInspectorProxy) 83 if (m_workerInspectorProxy)
191 m_workerInspectorProxy->addConsoleMessageFromWorker(level, message, std: :move(location)); 84 m_workerInspectorProxy->addConsoleMessageFromWorker(level, message, std: :move(location));
192 } 85 }
193 86
194 void InProcessWorkerMessagingProxy::workerThreadCreated() 87 void ThreadedMessagingProxyBase::workerThreadCreated()
195 { 88 {
196 DCHECK(isParentContextThread()); 89 DCHECK(isParentContextThread());
197 DCHECK(!m_askedToTerminate); 90 DCHECK(!m_askedToTerminate);
198 DCHECK(m_workerThread); 91 DCHECK(m_workerThread);
199
200 DCHECK(!m_unconfirmedMessageCount);
201 m_unconfirmedMessageCount = m_queuedEarlyTasks.size();
202
203 // Worker initialization means a pending activity.
204 m_workerGlobalScopeMayHavePendingActivity = true;
205
206 for (auto& earlyTasks : m_queuedEarlyTasks)
207 m_workerThread->postTask(BLINK_FROM_HERE, std::move(earlyTasks));
208 m_queuedEarlyTasks.clear();
209 } 92 }
210 93
211 InProcessWorkerMessagingProxy::InProcessWorkerMessagingProxy(ExecutionContext* e xecutionContext, InProcessWorkerBase* workerObject, WorkerClients* workerClients ) 94 void ThreadedMessagingProxyBase::parentObjectDestroyed()
212 : m_executionContext(executionContext)
213 , m_workerObjectProxy(InProcessWorkerObjectProxy::create(this))
214 , m_workerObject(workerObject)
215 , m_mayBeDestroyed(false)
216 , m_unconfirmedMessageCount(0)
217 , m_workerGlobalScopeMayHavePendingActivity(false)
218 , m_askedToTerminate(false)
219 , m_workerInspectorProxy(WorkerInspectorProxy::create())
220 , m_workerClients(workerClients)
221 , m_parentFrameTaskRunners(ParentFrameTaskRunners::create(toDocument(m_execu tionContext.get())->frame()))
222 {
223 DCHECK(isParentContextThread());
224 s_liveMessagingProxyCount++;
225 }
226
227 void InProcessWorkerMessagingProxy::workerObjectDestroyed()
228 { 95 {
229 DCHECK(isParentContextThread()); 96 DCHECK(isParentContextThread());
230 97
231 // workerObjectDestroyed() is called in InProcessWorkerBase's destructor. 98 m_parentFrameTaskRunners->get(TaskType::Internal)->postTask(BLINK_FROM_HERE, WTF::bind(&ThreadedMessagingProxyBase::parentObjectDestroyedInternal, unretaine d(this)));
232 // Thus it should be guaranteed that a weak pointer m_workerObject has been
233 // cleared before this method gets called.
234 DCHECK(!m_workerObject);
235
236 m_parentFrameTaskRunners->get(TaskType::Internal)->postTask(BLINK_FROM_HERE, WTF::bind(&InProcessWorkerMessagingProxy::workerObjectDestroyedInternal, unreta ined(this)));
237 } 99 }
238 100
239 void InProcessWorkerMessagingProxy::workerObjectDestroyedInternal() 101 void ThreadedMessagingProxyBase::parentObjectDestroyedInternal()
240 { 102 {
241 DCHECK(isParentContextThread()); 103 DCHECK(isParentContextThread());
242 m_mayBeDestroyed = true; 104 m_mayBeDestroyed = true;
243 if (m_workerThread) 105 if (m_workerThread)
244 terminateWorkerGlobalScope(); 106 terminateGlobalScope();
245 else 107 else
246 workerThreadTerminated(); 108 workerThreadTerminated();
247 } 109 }
248 110
249 void InProcessWorkerMessagingProxy::workerThreadTerminated() 111 void ThreadedMessagingProxyBase::workerThreadTerminated()
250 { 112 {
251 DCHECK(isParentContextThread()); 113 DCHECK(isParentContextThread());
252 114
253 // This method is always the last to be performed, so the proxy is not 115 // This method is always the last to be performed, so the proxy is not
254 // needed for communication in either side any more. However, the Worker 116 // needed for communication in either side any more. However, the Worker
255 // object may still exist, and it assumes that the proxy exists, too. 117 // object may still exist, and it assumes that the proxy exists, too.
256 m_askedToTerminate = true; 118 m_askedToTerminate = true;
257 m_workerThread = nullptr; 119 m_workerThread = nullptr;
258 m_workerInspectorProxy->workerThreadTerminated(); 120 m_workerInspectorProxy->workerThreadTerminated();
259 if (m_mayBeDestroyed) 121 if (m_mayBeDestroyed)
260 delete this; 122 delete this;
261 } 123 }
262 124
263 void InProcessWorkerMessagingProxy::terminateWorkerGlobalScope() 125 void ThreadedMessagingProxyBase::terminateGlobalScope()
264 { 126 {
265 DCHECK(isParentContextThread()); 127 DCHECK(isParentContextThread());
266 128
267 if (m_askedToTerminate) 129 if (m_askedToTerminate)
268 return; 130 return;
269 m_askedToTerminate = true; 131 m_askedToTerminate = true;
270 132
271 if (m_workerThread) 133 if (m_workerThread)
272 m_workerThread->terminate(); 134 m_workerThread->terminate();
273 135
274 m_workerInspectorProxy->workerThreadTerminated(); 136 m_workerInspectorProxy->workerThreadTerminated();
275 } 137 }
276 138
277 void InProcessWorkerMessagingProxy::postMessageToPageInspector(const String& mes sage) 139 void ThreadedMessagingProxyBase::postMessageToPageInspector(const String& messag e)
278 { 140 {
279 DCHECK(isParentContextThread()); 141 DCHECK(isParentContextThread());
280 if (m_workerInspectorProxy) 142 if (m_workerInspectorProxy)
281 m_workerInspectorProxy->dispatchMessageFromWorker(message); 143 m_workerInspectorProxy->dispatchMessageFromWorker(message);
282 } 144 }
283 145
284 void InProcessWorkerMessagingProxy::confirmMessageFromWorkerObject() 146 bool ThreadedMessagingProxyBase::isParentContextThread() const
285 {
286 DCHECK(isParentContextThread());
287 if (m_askedToTerminate)
288 return;
289 DCHECK(m_unconfirmedMessageCount);
290 --m_unconfirmedMessageCount;
291 }
292
293 void InProcessWorkerMessagingProxy::pendingActivityFinished()
294 {
295 DCHECK(isParentContextThread());
296 DCHECK(m_workerGlobalScopeMayHavePendingActivity);
297 if (m_unconfirmedMessageCount > 0) {
298 // Ignore the report because an inflight message event may initiate a
299 // new activity.
300 return;
301 }
302 m_workerGlobalScopeMayHavePendingActivity = false;
303 }
304
305 bool InProcessWorkerMessagingProxy::hasPendingActivity() const
306 {
307 DCHECK(isParentContextThread());
308 if (m_askedToTerminate)
309 return false;
310 return m_unconfirmedMessageCount || m_workerGlobalScopeMayHavePendingActivit y;
311 }
312
313 bool InProcessWorkerMessagingProxy::isParentContextThread() const
314 { 147 {
315 // TODO(nhiroki): Nested worker is not supported yet, so the parent context 148 // TODO(nhiroki): Nested worker is not supported yet, so the parent context
316 // thread should be equal to the main thread (http://crbug.com/31666). 149 // thread should be equal to the main thread (http://crbug.com/31666).
317 DCHECK(getExecutionContext()->isDocument()); 150 DCHECK(getExecutionContext()->isDocument());
318 return isMainThread(); 151 return isMainThread();
319 } 152 }
320 153
321 } // namespace blink 154 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698