Chromium Code Reviews| 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 DCHECK(isMainThread()); |
| 192 } | 193 } |
| 193 | 194 |
| 194 void Peer::initialize(PassOwnPtr<SourceLocation> location, ExecutionContext* con text) | 195 bool Peer::initialize(PassOwnPtr<SourceLocation> location, ExecutionContext* con text) |
| 195 { | 196 { |
| 196 ASSERT(isMainThread()); | 197 ASSERT(isMainThread()); |
| 198 if (wasContextDestroyedBeforeObserverCreation()) | |
|
kinuko
2016/06/10 02:05:28
Yeah this feels weird. should just check lifecycle
| |
| 199 return false; | |
| 197 Document* document = toDocument(context); | 200 Document* document = toDocument(context); |
| 198 m_mainWebSocketChannel = DocumentWebSocketChannel::create(document, this, st d::move(location)); | 201 m_mainWebSocketChannel = DocumentWebSocketChannel::create(document, this, st d::move(location)); |
| 199 m_syncHelper->signalWorkerThread(); | 202 return true; |
| 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 { |
| 209 bool connectRequestResult = m_mainWebSocketChannel->connect(url, protoco l); | 212 bool connectRequestResult = m_mainWebSocketChannel->connect(url, protoco l); |
| (...skipping 140 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 } | |
| 370 m_bridge = nullptr; | |
| 371 } | |
| 372 | |
| 360 DEFINE_TRACE(Peer) | 373 DEFINE_TRACE(Peer) |
| 361 { | 374 { |
| 362 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()); | |
| 397 DCHECK(!m_peer); | |
| 398 Peer* peer = new Peer(this, m_loaderProxy, m_syncHelper, workerThreadContext ); | |
| 399 if (peer->initialize(std::move(location), context)) | |
| 400 m_peer = peer; | |
| 401 m_syncHelper->signalWorkerThread(); | |
| 402 } | |
| 403 | |
| 382 void Bridge::initialize(PassOwnPtr<SourceLocation> location) | 404 void Bridge::initialize(PassOwnPtr<SourceLocation> location) |
| 383 { | 405 { |
| 384 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::initialize, wrapCr ossThreadPersistent(m_peer.get()), passed(std::move(location))))) { | 406 // Wait for completion of the task on the main thread because the connection |
| 407 // must synchronously be established (see Bridge::connect). | |
| 408 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. | 409 // The worker thread has been signalled to shutdown before method comple tion. |
| 386 disconnect(); | 410 disconnect(); |
| 387 } | 411 } |
| 388 } | 412 } |
| 389 | 413 |
| 390 bool Bridge::connect(const KURL& url, const String& protocol) | 414 bool Bridge::connect(const KURL& url, const String& protocol) |
| 391 { | 415 { |
| 392 if (!m_peer) | 416 if (!m_peer) |
| 393 return false; | 417 return false; |
| 394 | 418 |
| 419 // Wait for completion of the task on the main thread because the mixed | |
| 420 // content check must synchronously be conducted. | |
| 395 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, wrapCross ThreadPersistent(m_peer.get()), url, protocol))) | 421 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, wrapCross ThreadPersistent(m_peer.get()), url, protocol))) |
| 396 return false; | 422 return false; |
| 397 | 423 |
| 398 return m_syncHelper->connectRequestResult(); | 424 return m_syncHelper->connectRequestResult(); |
| 399 } | 425 } |
| 400 | 426 |
| 401 void Bridge::send(const CString& message) | 427 void Bridge::send(const CString& message) |
| 402 { | 428 { |
| 403 ASSERT(m_peer); | 429 ASSERT(m_peer); |
| 404 OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>(message.length())); | 430 OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>(message.length())); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 435 { | 461 { |
| 436 ASSERT(m_peer); | 462 ASSERT(m_peer); |
| 437 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::fail, wrapCross ThreadPersistent(m_peer.get()), reason, level, passed(std::move(location)))); | 463 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::fail, wrapCross ThreadPersistent(m_peer.get()), reason, level, passed(std::move(location)))); |
| 438 } | 464 } |
| 439 | 465 |
| 440 void Bridge::disconnect() | 466 void Bridge::disconnect() |
| 441 { | 467 { |
| 442 if (!m_peer) | 468 if (!m_peer) |
| 443 return; | 469 return; |
| 444 | 470 |
| 471 // Wait for completion of the task on the main thread to ensure that | |
| 472 // |m_peer| does not touch this Bridge object after this point. | |
| 445 waitForMethodCompletion(createCrossThreadTask(&Peer::disconnect, wrapCrossTh readPersistent(m_peer.get()))); | 473 waitForMethodCompletion(createCrossThreadTask(&Peer::disconnect, wrapCrossTh readPersistent(m_peer.get()))); |
| 446 // Here |m_peer| is detached from the main thread and we can delete it. | |
| 447 | 474 |
| 448 m_client = nullptr; | 475 m_client = nullptr; |
| 449 m_peer = nullptr; | 476 m_peer = nullptr; |
| 450 m_syncHelper = nullptr; | 477 m_syncHelper = nullptr; |
| 451 // We won't use this any more. | 478 // We won't use this any more. |
| 452 m_workerGlobalScope.clear(); | 479 m_workerGlobalScope.clear(); |
| 453 } | 480 } |
| 454 | 481 |
| 455 // Caller of this function should hold a reference to the bridge, because this f unction may call WebSocket::didClose() in the end, | 482 // Caller of this function should hold a reference to the bridge, because this f unction may call WebSocket::didClose() in the end, |
| 456 // which causes the bridge to get disconnected from the WebSocket and deleted if there is no other reference. | 483 // which causes the bridge to get disconnected from the WebSocket and deleted if there is no other reference. |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 467 m_syncHelper->wait(); | 494 m_syncHelper->wait(); |
| 468 // This is checking whether a shutdown event is fired or not. | 495 // This is checking whether a shutdown event is fired or not. |
| 469 return !m_workerGlobalScope->thread()->terminated(); | 496 return !m_workerGlobalScope->thread()->terminated(); |
| 470 } | 497 } |
| 471 | 498 |
| 472 DEFINE_TRACE(Bridge) | 499 DEFINE_TRACE(Bridge) |
| 473 { | 500 { |
| 474 visitor->trace(m_client); | 501 visitor->trace(m_client); |
| 475 visitor->trace(m_workerGlobalScope); | 502 visitor->trace(m_workerGlobalScope); |
| 476 visitor->trace(m_syncHelper); | 503 visitor->trace(m_syncHelper); |
| 477 visitor->trace(m_peer); | |
| 478 } | 504 } |
| 479 | 505 |
| 480 } // namespace blink | 506 } // namespace blink |
| OLD | NEW |