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

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: ... 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
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, 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_mayBeDestroyed(false)
26 , m_unconfirmedMessageCount(0)
27 , m_workerGlobalScopeMayHavePendingActivity(false)
28 , m_askedToTerminate(false)
29 , m_workerInspectorProxy(WorkerInspectorProxy::create())
30 , m_parentFrameTaskRunners(ParentFrameTaskRunners::create(toDocument(m_execu tionContext.get())->frame()))
78 { 31 {
79 DCHECK(m_workerObject); 32 DCHECK(isParentContextThread());
33 s_liveMessagingProxyCount++;
80 } 34 }
81 35
82 InProcessWorkerMessagingProxy::~InProcessWorkerMessagingProxy() 36 ThreadedMessagingProxyBase::~ThreadedMessagingProxyBase()
83 { 37 {
84 DCHECK(isParentContextThread()); 38 DCHECK(isParentContextThread());
85 DCHECK(!m_workerObject);
86 if (m_loaderProxy) 39 if (m_loaderProxy)
87 m_loaderProxy->detachProvider(this); 40 m_loaderProxy->detachProvider(this);
88 s_liveMessagingProxyCount--; 41 s_liveMessagingProxyCount--;
89 } 42 }
90 43
91 int InProcessWorkerMessagingProxy::proxyCount() 44 int ThreadedMessagingProxyBase::proxyCount()
92 { 45 {
93 DCHECK(isMainThread()); 46 DCHECK(isMainThread());
94 return s_liveMessagingProxyCount; 47 return s_liveMessagingProxyCount;
95 } 48 }
96 49
97 void InProcessWorkerMessagingProxy::startWorkerGlobalScope(const KURL& scriptURL , const String& userAgent, const String& sourceCode) 50 void ThreadedMessagingProxyBase::initializeWorkerThread(std::unique_ptr<WorkerTh readStartupData> startupData)
98 { 51 {
99 DCHECK(isParentContextThread()); 52 DCHECK(isParentContextThread());
100 if (m_askedToTerminate) {
101 // Worker.terminate() could be called from JS before the thread was
102 // created.
103 return;
104 }
105 53
106 Document* document = toDocument(getExecutionContext()); 54 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(); 55 double originTime = document->loader() ? document->loader()->timing().refere nceMonotonicTime() : monotonicallyIncreasingTime();
116 56
117 m_loaderProxy = WorkerLoaderProxy::create(this); 57 m_loaderProxy = WorkerLoaderProxy::create(this);
118 m_workerThread = createWorkerThread(originTime); 58 m_workerThread = createWorkerThread(originTime);
119 m_workerThread->start(std::move(startupData)); 59 m_workerThread->start(std::move(startupData));
120 workerThreadCreated(); 60 workerThreadCreated();
121 m_workerInspectorProxy->workerThreadCreated(document, m_workerThread.get(), scriptURL);
122 } 61 }
123 62
124 void InProcessWorkerMessagingProxy::postMessageToWorkerObject(PassRefPtr<Seriali zedScriptValue> message, std::unique_ptr<MessagePortChannelArray> channels) 63 void ThreadedMessagingProxyBase::postOrQueueTaskToWorkerGlobalScope(std::unique_ ptr<ExecutionContextTask> task)
nhiroki 2016/09/06 07:07:08 I'd prefer to keep 'Message(Event)' instead of 'Ta
ikilpatrick 2016/09/06 18:59:49 Acknowledged.
125 { 64 {
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, 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()));
nhiroki 2016/09/06 07:07:08 Will Worklet support postMessage()? If it'll be su
ikilpatrick 2016/09/06 18:59:50 Yeah I wasn't sure what to do here initially. My i
141 if (m_workerThread) { 65 if (m_workerThread) {
142 // A message event is an activity and may initiate another activity. 66 // A message event is an activity and may initiate another activity.
143 m_workerGlobalScopeMayHavePendingActivity = true; 67 m_workerGlobalScopeMayHavePendingActivity = true;
144 ++m_unconfirmedMessageCount; 68 ++m_unconfirmedMessageCount;
145 m_workerThread->postTask(BLINK_FROM_HERE, std::move(task)); 69 m_workerThread->postTask(BLINK_FROM_HERE, std::move(task));
146 } else { 70 } else {
147 m_queuedEarlyTasks.append(std::move(task)); 71 m_queuedEarlyTasks.append(std::move(task));
148 } 72 }
149 } 73 }
150 74
151 void InProcessWorkerMessagingProxy::postTaskToWorkerGlobalScope(const WebTraceLo cation& location, std::unique_ptr<ExecutionContextTask> task) 75 void ThreadedMessagingProxyBase::postTaskToWorkerGlobalScope(const WebTraceLocat ion& location, std::unique_ptr<ExecutionContextTask> task)
152 { 76 {
153 if (m_askedToTerminate) 77 if (m_askedToTerminate)
154 return; 78 return;
155 79
156 DCHECK(m_workerThread); 80 DCHECK(m_workerThread);
157 m_workerThread->postTask(location, std::move(task)); 81 m_workerThread->postTask(location, std::move(task));
158 } 82 }
159 83
160 void InProcessWorkerMessagingProxy::postTaskToLoader(const WebTraceLocation& loc ation, std::unique_ptr<ExecutionContextTask> task) 84 void ThreadedMessagingProxyBase::postTaskToLoader(const WebTraceLocation& locati on, std::unique_ptr<ExecutionContextTask> task)
161 { 85 {
162 DCHECK(getExecutionContext()->isDocument()); 86 DCHECK(getExecutionContext()->isDocument());
163 // TODO(hiroshige,yuryu): Make this not use ExecutionContextTask and use 87 // TODO(hiroshige,yuryu): Make this not use ExecutionContextTask and use
164 // m_parentFrameTaskRunners->get(TaskType::Networking) instead. 88 // m_parentFrameTaskRunners->get(TaskType::Networking) instead.
165 getExecutionContext()->postTask(location, std::move(task)); 89 getExecutionContext()->postTask(location, std::move(task));
166 } 90 }
167 91
168 void InProcessWorkerMessagingProxy::dispatchErrorEvent(const String& errorMessag e, std::unique_ptr<SourceLocation> location, int exceptionId) 92 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 { 93 {
187 DCHECK(isParentContextThread()); 94 DCHECK(isParentContextThread());
188 if (m_askedToTerminate) 95 if (m_askedToTerminate)
189 return; 96 return;
190 if (m_workerInspectorProxy) 97 if (m_workerInspectorProxy)
191 m_workerInspectorProxy->addConsoleMessageFromWorker(level, message, std: :move(location)); 98 m_workerInspectorProxy->addConsoleMessageFromWorker(level, message, std: :move(location));
192 } 99 }
193 100
194 void InProcessWorkerMessagingProxy::workerThreadCreated() 101 void ThreadedMessagingProxyBase::workerThreadCreated()
195 { 102 {
196 DCHECK(isParentContextThread()); 103 DCHECK(isParentContextThread());
197 DCHECK(!m_askedToTerminate); 104 DCHECK(!m_askedToTerminate);
198 DCHECK(m_workerThread); 105 DCHECK(m_workerThread);
199 106
200 DCHECK(!m_unconfirmedMessageCount); 107 DCHECK(!m_unconfirmedMessageCount);
201 m_unconfirmedMessageCount = m_queuedEarlyTasks.size(); 108 m_unconfirmedMessageCount = m_queuedEarlyTasks.size();
202 109
203 // Worker initialization means a pending activity. 110 // Worker initialization means a pending activity.
204 m_workerGlobalScopeMayHavePendingActivity = true; 111 m_workerGlobalScopeMayHavePendingActivity = true;
205 112
206 for (auto& earlyTasks : m_queuedEarlyTasks) 113 for (auto& earlyTasks : m_queuedEarlyTasks)
207 m_workerThread->postTask(BLINK_FROM_HERE, std::move(earlyTasks)); 114 m_workerThread->postTask(BLINK_FROM_HERE, std::move(earlyTasks));
208 m_queuedEarlyTasks.clear(); 115 m_queuedEarlyTasks.clear();
209 } 116 }
210 117
211 InProcessWorkerMessagingProxy::InProcessWorkerMessagingProxy(ExecutionContext* e xecutionContext, InProcessWorkerBase* workerObject, WorkerClients* workerClients ) 118 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 { 119 {
229 DCHECK(isParentContextThread()); 120 DCHECK(isParentContextThread());
230 121
231 // workerObjectDestroyed() is called in InProcessWorkerBase's destructor. 122 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 } 123 }
238 124
239 void InProcessWorkerMessagingProxy::workerObjectDestroyedInternal() 125 void ThreadedMessagingProxyBase::parentObjectDestroyedInternal()
240 { 126 {
241 DCHECK(isParentContextThread()); 127 DCHECK(isParentContextThread());
242 m_mayBeDestroyed = true; 128 m_mayBeDestroyed = true;
243 if (m_workerThread) 129 if (m_workerThread)
244 terminateWorkerGlobalScope(); 130 terminateGlobalScope();
245 else 131 else
246 workerThreadTerminated(); 132 workerThreadTerminated();
247 } 133 }
248 134
249 void InProcessWorkerMessagingProxy::workerThreadTerminated() 135 void ThreadedMessagingProxyBase::workerThreadTerminated()
250 { 136 {
251 DCHECK(isParentContextThread()); 137 DCHECK(isParentContextThread());
252 138
253 // This method is always the last to be performed, so the proxy is not 139 // 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 140 // needed for communication in either side any more. However, the Worker
255 // object may still exist, and it assumes that the proxy exists, too. 141 // object may still exist, and it assumes that the proxy exists, too.
256 m_askedToTerminate = true; 142 m_askedToTerminate = true;
257 m_workerThread = nullptr; 143 m_workerThread = nullptr;
258 m_workerInspectorProxy->workerThreadTerminated(); 144 m_workerInspectorProxy->workerThreadTerminated();
259 if (m_mayBeDestroyed) 145 if (m_mayBeDestroyed)
260 delete this; 146 delete this;
261 } 147 }
262 148
263 void InProcessWorkerMessagingProxy::terminateWorkerGlobalScope() 149 void ThreadedMessagingProxyBase::terminateGlobalScope()
264 { 150 {
265 DCHECK(isParentContextThread()); 151 DCHECK(isParentContextThread());
266 152
267 if (m_askedToTerminate) 153 if (m_askedToTerminate)
268 return; 154 return;
269 m_askedToTerminate = true; 155 m_askedToTerminate = true;
270 156
271 if (m_workerThread) 157 if (m_workerThread)
272 m_workerThread->terminate(); 158 m_workerThread->terminate();
273 159
274 m_workerInspectorProxy->workerThreadTerminated(); 160 m_workerInspectorProxy->workerThreadTerminated();
275 } 161 }
276 162
277 void InProcessWorkerMessagingProxy::postMessageToPageInspector(const String& mes sage) 163 void ThreadedMessagingProxyBase::postMessageToPageInspector(const String& messag e)
278 { 164 {
279 DCHECK(isParentContextThread()); 165 DCHECK(isParentContextThread());
280 if (m_workerInspectorProxy) 166 if (m_workerInspectorProxy)
281 m_workerInspectorProxy->dispatchMessageFromWorker(message); 167 m_workerInspectorProxy->dispatchMessageFromWorker(message);
282 } 168 }
283 169
284 void InProcessWorkerMessagingProxy::confirmMessageFromWorkerObject() 170 void ThreadedMessagingProxyBase::confirmMessageFromWorkerObject()
285 { 171 {
286 DCHECK(isParentContextThread()); 172 DCHECK(isParentContextThread());
287 if (m_askedToTerminate) 173 if (m_askedToTerminate)
288 return; 174 return;
289 DCHECK(m_unconfirmedMessageCount); 175 DCHECK(m_unconfirmedMessageCount);
290 --m_unconfirmedMessageCount; 176 --m_unconfirmedMessageCount;
291 } 177 }
292 178
293 void InProcessWorkerMessagingProxy::pendingActivityFinished() 179 void ThreadedMessagingProxyBase::pendingActivityFinished()
294 { 180 {
295 DCHECK(isParentContextThread()); 181 DCHECK(isParentContextThread());
296 DCHECK(m_workerGlobalScopeMayHavePendingActivity); 182 DCHECK(m_workerGlobalScopeMayHavePendingActivity);
297 if (m_unconfirmedMessageCount > 0) { 183 if (m_unconfirmedMessageCount > 0) {
298 // Ignore the report because an inflight message event may initiate a 184 // Ignore the report because an inflight message event may initiate a
299 // new activity. 185 // new activity.
300 return; 186 return;
301 } 187 }
302 m_workerGlobalScopeMayHavePendingActivity = false; 188 m_workerGlobalScopeMayHavePendingActivity = false;
303 } 189 }
304 190
305 bool InProcessWorkerMessagingProxy::hasPendingActivity() const 191 bool ThreadedMessagingProxyBase::hasPendingActivity() const
306 { 192 {
307 DCHECK(isParentContextThread()); 193 DCHECK(isParentContextThread());
308 if (m_askedToTerminate) 194 if (m_askedToTerminate)
309 return false; 195 return false;
310 return m_unconfirmedMessageCount || m_workerGlobalScopeMayHavePendingActivit y; 196 return m_unconfirmedMessageCount || m_workerGlobalScopeMayHavePendingActivit y;
311 } 197 }
312 198
313 bool InProcessWorkerMessagingProxy::isParentContextThread() const 199 bool ThreadedMessagingProxyBase::isParentContextThread() const
314 { 200 {
315 // TODO(nhiroki): Nested worker is not supported yet, so the parent context 201 // 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). 202 // thread should be equal to the main thread (http://crbug.com/31666).
317 DCHECK(getExecutionContext()->isDocument()); 203 DCHECK(getExecutionContext()->isDocument());
318 return isMainThread(); 204 return isMainThread();
319 } 205 }
320 206
321 } // namespace blink 207 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698