OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 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 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
170 m_bridge->disconnect(); | 170 m_bridge->disconnect(); |
171 m_bridge.clear(); | 171 m_bridge.clear(); |
172 } | 172 } |
173 | 173 |
174 DEFINE_TRACE(WorkerWebSocketChannel) | 174 DEFINE_TRACE(WorkerWebSocketChannel) |
175 { | 175 { |
176 visitor->trace(m_bridge); | 176 visitor->trace(m_bridge); |
177 WebSocketChannel::trace(visitor); | 177 WebSocketChannel::trace(visitor); |
178 } | 178 } |
179 | 179 |
180 Peer::Peer(Bridge* bridge, PassRefPtr<WorkerLoaderProxy> loaderProxy, WebSocketC hannelSyncHelper* syncHelper) | 180 Peer::Peer(Bridge* bridge, PassRefPtr<WorkerLoaderProxy> loaderProxy, WebSocketC hannelSyncHelper* syncHelper, WorkerThreadContext* workerThreadContext) |
181 : m_bridge(bridge) | 181 : WorkerThreadLifecycleObserver(workerThreadContext) |
182 , m_bridge(bridge) | |
182 , m_loaderProxy(loaderProxy) | 183 , m_loaderProxy(loaderProxy) |
183 , m_mainWebSocketChannel(nullptr) | 184 , m_mainWebSocketChannel(nullptr) |
184 , m_syncHelper(syncHelper) | 185 , m_syncHelper(syncHelper) |
185 { | 186 { |
186 ASSERT(!isMainThread()); | 187 DCHECK(isMainThread()); |
187 } | 188 } |
188 | 189 |
189 Peer::~Peer() | 190 Peer::~Peer() |
190 { | 191 { |
191 ASSERT(!isMainThread()); | 192 ASSERT(!isMainThread()); |
yhirano
2016/06/09 04:55:13
DCHECK(isMainThread())
nhiroki
2016/06/09 07:37:07
Done.
| |
192 } | 193 } |
193 | 194 |
194 void Peer::initialize(PassOwnPtr<SourceLocation> location, ExecutionContext* con text) | 195 void Peer::initialize(PassOwnPtr<SourceLocation> location, ExecutionContext* con text) |
195 { | 196 { |
196 ASSERT(isMainThread()); | 197 ASSERT(isMainThread()); |
197 Document* document = toDocument(context); | 198 if (!wasContextDestroyedBeforeObserverCreation()) { |
198 m_mainWebSocketChannel = DocumentWebSocketChannel::create(document, this, st d::move(location)); | 199 Document* document = toDocument(context); |
200 m_mainWebSocketChannel = DocumentWebSocketChannel::create(document, this , std::move(location)); | |
201 } | |
199 m_syncHelper->signalWorkerThread(); | 202 m_syncHelper->signalWorkerThread(); |
200 } | 203 } |
201 | 204 |
202 void Peer::connect(const KURL& url, const String& protocol) | 205 void Peer::connect(const KURL& url, const String& protocol) |
203 { | 206 { |
204 ASSERT(isMainThread()); | 207 ASSERT(isMainThread()); |
205 ASSERT(m_syncHelper); | 208 ASSERT(m_syncHelper); |
206 if (!m_mainWebSocketChannel) { | 209 if (!m_mainWebSocketChannel) { |
207 m_syncHelper->setConnectRequestResult(false); | 210 m_syncHelper->setConnectRequestResult(false); |
208 } else { | 211 } else { |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
350 if (bridge->client()) | 353 if (bridge->client()) |
351 bridge->client()->didError(); | 354 bridge->client()->didError(); |
352 } | 355 } |
353 | 356 |
354 void Peer::didError() | 357 void Peer::didError() |
355 { | 358 { |
356 ASSERT(isMainThread()); | 359 ASSERT(isMainThread()); |
357 m_loaderProxy->postTaskToWorkerGlobalScope(createCrossThreadTask(&workerGlob alScopeDidError, m_bridge)); | 360 m_loaderProxy->postTaskToWorkerGlobalScope(createCrossThreadTask(&workerGlob alScopeDidError, m_bridge)); |
358 } | 361 } |
359 | 362 |
363 void Peer::contextDestroyed() | |
364 { | |
365 DCHECK(isMainThread()); | |
366 if (m_mainWebSocketChannel) { | |
367 m_mainWebSocketChannel->disconnect(); | |
368 m_mainWebSocketChannel = nullptr; | |
369 } | |
yhirano
2016/06/09 04:55:13
m_bridge = nullptr;
nhiroki
2016/06/09 07:37:07
Done.
| |
370 } | |
371 | |
360 DEFINE_TRACE(Peer) | 372 DEFINE_TRACE(Peer) |
361 { | 373 { |
362 visitor->trace(m_bridge); | 374 visitor->trace(m_bridge); |
363 visitor->trace(m_mainWebSocketChannel); | 375 visitor->trace(m_mainWebSocketChannel); |
364 visitor->trace(m_syncHelper); | 376 visitor->trace(m_syncHelper); |
365 WebSocketChannelClient::trace(visitor); | 377 WebSocketChannelClient::trace(visitor); |
378 WorkerThreadLifecycleObserver::trace(visitor); | |
366 } | 379 } |
367 | 380 |
368 Bridge::Bridge(WebSocketChannelClient* client, WorkerGlobalScope& workerGlobalSc ope) | 381 Bridge::Bridge(WebSocketChannelClient* client, WorkerGlobalScope& workerGlobalSc ope) |
369 : m_client(client) | 382 : m_client(client) |
370 , m_workerGlobalScope(workerGlobalScope) | 383 , m_workerGlobalScope(workerGlobalScope) |
371 , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) | 384 , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) |
372 , m_syncHelper(WebSocketChannelSyncHelper::create(adoptPtr(new WaitableEvent ()))) | 385 , m_syncHelper(WebSocketChannelSyncHelper::create(adoptPtr(new WaitableEvent ()))) |
373 , m_peer(new Peer(this, m_loaderProxy, m_syncHelper)) | |
374 { | 386 { |
375 } | 387 } |
376 | 388 |
377 Bridge::~Bridge() | 389 Bridge::~Bridge() |
378 { | 390 { |
379 ASSERT(!m_peer); | 391 ASSERT(!m_peer); |
380 } | 392 } |
381 | 393 |
394 void Bridge::createPeerOnMainThread(PassOwnPtr<SourceLocation> location, WorkerT hreadContext* workerThreadContext, ExecutionContext* context) | |
395 { | |
396 DCHECK(isMainThread()); | |
yhirano
2016/06/09 04:55:13
+DCHECK(!m_peer);
nhiroki
2016/06/09 07:37:07
Done.
| |
397 m_peer = new Peer(this, m_loaderProxy, m_syncHelper, workerThreadContext); | |
398 m_peer->initialize(std::move(location), context); | |
yhirano
2016/06/09 04:55:13
[optional] Is it good to set |m_peer| only when ne
nhiroki
2016/06/09 07:37:06
Done.
| |
399 } | |
400 | |
382 void Bridge::initialize(PassOwnPtr<SourceLocation> location) | 401 void Bridge::initialize(PassOwnPtr<SourceLocation> location) |
383 { | 402 { |
384 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::initialize, wrapCr ossThreadPersistent(m_peer.get()), passed(std::move(location))))) { | 403 // TODO(nhiroki): Stop waiting for completion of the task on the main |
404 // thread and make this function async instead. This wait was necessary to | |
405 // prevent worker thread shutdown during initialization on the main thread. | |
406 // If it happens, the main thread may retain dangling pointers to objects on | |
407 // the worker thread. However, in the current implementation, the shutdown | |
408 // sequence always goes through the main thread and gives a chance to | |
409 // release pointers before they dangle. See Peer::contextDestroyed. | |
410 if (!waitForMethodCompletion(createCrossThreadTask(&Bridge::createPeerOnMain Thread, wrapCrossThreadPersistent(this), passed(std::move(location)), wrapCrossT hreadPersistent(m_workerGlobalScope->thread()->workerThreadContext())))) { | |
385 // The worker thread has been signalled to shutdown before method comple tion. | 411 // The worker thread has been signalled to shutdown before method comple tion. |
386 disconnect(); | 412 disconnect(); |
387 } | 413 } |
388 } | 414 } |
389 | 415 |
390 bool Bridge::connect(const KURL& url, const String& protocol) | 416 bool Bridge::connect(const KURL& url, const String& protocol) |
391 { | 417 { |
392 if (!m_peer) | 418 if (!m_peer) |
393 return false; | 419 return false; |
394 | 420 |
421 // Wait for completion of the task on the main thread because the mixed | |
422 // content check must synchronously be conducted. | |
395 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, wrapCross ThreadPersistent(m_peer.get()), url, protocol))) | 423 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, wrapCross ThreadPersistent(m_peer.get()), url, protocol))) |
396 return false; | 424 return false; |
397 | 425 |
398 return m_syncHelper->connectRequestResult(); | 426 return m_syncHelper->connectRequestResult(); |
399 } | 427 } |
400 | 428 |
401 void Bridge::send(const CString& message) | 429 void Bridge::send(const CString& message) |
402 { | 430 { |
403 ASSERT(m_peer); | 431 ASSERT(m_peer); |
404 OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>(message.length())); | 432 OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>(message.length())); |
(...skipping 30 matching lines...) Expand all Loading... | |
435 { | 463 { |
436 ASSERT(m_peer); | 464 ASSERT(m_peer); |
437 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::fail, wrapCross ThreadPersistent(m_peer.get()), reason, level, passed(std::move(location)))); | 465 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::fail, wrapCross ThreadPersistent(m_peer.get()), reason, level, passed(std::move(location)))); |
438 } | 466 } |
439 | 467 |
440 void Bridge::disconnect() | 468 void Bridge::disconnect() |
441 { | 469 { |
442 if (!m_peer) | 470 if (!m_peer) |
443 return; | 471 return; |
444 | 472 |
473 // TODO(nhiroki): Stop waiting for completion of the task on the main thread | |
474 // and make this function async instead. See a comment on Bridge::initialize | |
475 // for more details. | |
445 waitForMethodCompletion(createCrossThreadTask(&Peer::disconnect, wrapCrossTh readPersistent(m_peer.get()))); | 476 waitForMethodCompletion(createCrossThreadTask(&Peer::disconnect, wrapCrossTh readPersistent(m_peer.get()))); |
446 // Here |m_peer| is detached from the main thread and we can delete it. | 477 // Here |m_peer| is detached from the main thread and we can delete it. |
447 | 478 |
448 m_client = nullptr; | 479 m_client = nullptr; |
449 m_peer = nullptr; | 480 m_peer = nullptr; |
450 m_syncHelper = nullptr; | 481 m_syncHelper = nullptr; |
451 // We won't use this any more. | 482 // We won't use this any more. |
452 m_workerGlobalScope.clear(); | 483 m_workerGlobalScope.clear(); |
453 } | 484 } |
454 | 485 |
(...skipping 16 matching lines...) Expand all Loading... | |
471 | 502 |
472 DEFINE_TRACE(Bridge) | 503 DEFINE_TRACE(Bridge) |
473 { | 504 { |
474 visitor->trace(m_client); | 505 visitor->trace(m_client); |
475 visitor->trace(m_workerGlobalScope); | 506 visitor->trace(m_workerGlobalScope); |
476 visitor->trace(m_syncHelper); | 507 visitor->trace(m_syncHelper); |
477 visitor->trace(m_peer); | 508 visitor->trace(m_peer); |
478 } | 509 } |
479 | 510 |
480 } // namespace blink | 511 } // namespace blink |
OLD | NEW |