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()) | |
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); | 375 visitor->trace(m_bridge); |
yhirano
2016/06/09 11:36:20
Peer::m_bridge is not Member. Should we keep this?
nhiroki
2016/06/09 13:23:51
Removed.
| |
363 visitor->trace(m_mainWebSocketChannel); | 376 visitor->trace(m_mainWebSocketChannel); |
364 visitor->trace(m_syncHelper); | 377 visitor->trace(m_syncHelper); |
365 WebSocketChannelClient::trace(visitor); | 378 WebSocketChannelClient::trace(visitor); |
379 WorkerThreadLifecycleObserver::trace(visitor); | |
366 } | 380 } |
367 | 381 |
368 Bridge::Bridge(WebSocketChannelClient* client, WorkerGlobalScope& workerGlobalSc ope) | 382 Bridge::Bridge(WebSocketChannelClient* client, WorkerGlobalScope& workerGlobalSc ope) |
369 : m_client(client) | 383 : m_client(client) |
370 , m_workerGlobalScope(workerGlobalScope) | 384 , m_workerGlobalScope(workerGlobalScope) |
371 , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) | 385 , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) |
372 , m_syncHelper(WebSocketChannelSyncHelper::create(adoptPtr(new WaitableEvent ()))) | 386 , m_syncHelper(WebSocketChannelSyncHelper::create(adoptPtr(new WaitableEvent ()))) |
373 , m_peer(new Peer(this, m_loaderProxy, m_syncHelper)) | |
374 { | 387 { |
375 } | 388 } |
376 | 389 |
377 Bridge::~Bridge() | 390 Bridge::~Bridge() |
378 { | 391 { |
379 ASSERT(!m_peer); | 392 ASSERT(!m_peer); |
380 } | 393 } |
381 | 394 |
395 void Bridge::createPeerOnMainThread(PassOwnPtr<SourceLocation> location, WorkerT hreadContext* workerThreadContext, ExecutionContext* context) | |
396 { | |
397 DCHECK(isMainThread()); | |
398 DCHECK(!m_peer); | |
399 Peer* peer = new Peer(this, m_loaderProxy, m_syncHelper, workerThreadContext ); | |
400 if (peer->initialize(std::move(location), context)) | |
401 m_peer = peer; | |
402 m_syncHelper->signalWorkerThread(); | |
403 } | |
404 | |
382 void Bridge::initialize(PassOwnPtr<SourceLocation> location) | 405 void Bridge::initialize(PassOwnPtr<SourceLocation> location) |
383 { | 406 { |
384 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::initialize, wrapCr ossThreadPersistent(m_peer.get()), passed(std::move(location))))) { | 407 // Wait for completion of the task on the main thread because the connection |
408 // must synchronously be established (see Bridge::connect). | |
409 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. | 410 // The worker thread has been signalled to shutdown before method comple tion. |
386 disconnect(); | 411 disconnect(); |
387 } | 412 } |
388 } | 413 } |
389 | 414 |
390 bool Bridge::connect(const KURL& url, const String& protocol) | 415 bool Bridge::connect(const KURL& url, const String& protocol) |
391 { | 416 { |
392 if (!m_peer) | 417 if (!m_peer) |
393 return false; | 418 return false; |
394 | 419 |
420 // Wait for completion of the task on the main thread because the mixed | |
421 // content check must synchronously be conducted. | |
395 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, wrapCross ThreadPersistent(m_peer.get()), url, protocol))) | 422 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, wrapCross ThreadPersistent(m_peer.get()), url, protocol))) |
396 return false; | 423 return false; |
397 | 424 |
398 return m_syncHelper->connectRequestResult(); | 425 return m_syncHelper->connectRequestResult(); |
399 } | 426 } |
400 | 427 |
401 void Bridge::send(const CString& message) | 428 void Bridge::send(const CString& message) |
402 { | 429 { |
403 ASSERT(m_peer); | 430 ASSERT(m_peer); |
404 OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>(message.length())); | 431 OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>(message.length())); |
(...skipping 30 matching lines...) Expand all Loading... | |
435 { | 462 { |
436 ASSERT(m_peer); | 463 ASSERT(m_peer); |
437 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::fail, wrapCross ThreadPersistent(m_peer.get()), reason, level, passed(std::move(location)))); | 464 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::fail, wrapCross ThreadPersistent(m_peer.get()), reason, level, passed(std::move(location)))); |
438 } | 465 } |
439 | 466 |
440 void Bridge::disconnect() | 467 void Bridge::disconnect() |
441 { | 468 { |
442 if (!m_peer) | 469 if (!m_peer) |
443 return; | 470 return; |
444 | 471 |
472 // Wait for completion of the task on the main thread to ensure that | |
473 // |m_peer| does not touch this Bridge object after this point. | |
445 waitForMethodCompletion(createCrossThreadTask(&Peer::disconnect, wrapCrossTh readPersistent(m_peer.get()))); | 474 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 | 475 |
448 m_client = nullptr; | 476 m_client = nullptr; |
449 m_peer = nullptr; | 477 m_peer = nullptr; |
450 m_syncHelper = nullptr; | 478 m_syncHelper = nullptr; |
451 // We won't use this any more. | 479 // We won't use this any more. |
452 m_workerGlobalScope.clear(); | 480 m_workerGlobalScope.clear(); |
453 } | 481 } |
454 | 482 |
455 // Caller of this function should hold a reference to the bridge, because this f unction may call WebSocket::didClose() in the end, | 483 // 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. | 484 // 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(); | 495 m_syncHelper->wait(); |
468 // This is checking whether a shutdown event is fired or not. | 496 // This is checking whether a shutdown event is fired or not. |
469 return !m_workerGlobalScope->thread()->terminated(); | 497 return !m_workerGlobalScope->thread()->terminated(); |
470 } | 498 } |
471 | 499 |
472 DEFINE_TRACE(Bridge) | 500 DEFINE_TRACE(Bridge) |
473 { | 501 { |
474 visitor->trace(m_client); | 502 visitor->trace(m_client); |
475 visitor->trace(m_workerGlobalScope); | 503 visitor->trace(m_workerGlobalScope); |
476 visitor->trace(m_syncHelper); | 504 visitor->trace(m_syncHelper); |
477 visitor->trace(m_peer); | 505 visitor->trace(m_peer); |
yhirano
2016/06/09 11:36:20
Bridge::m_peer is not Member. Should we keep this?
nhiroki
2016/06/09 13:23:51
Removed.
| |
478 } | 506 } |
479 | 507 |
480 } // namespace blink | 508 } // namespace blink |
OLD | NEW |