Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple 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 | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 #endif | 361 #endif |
| 362 , m_initialPlayWithoutUserGestures(false) | 362 , m_initialPlayWithoutUserGestures(false) |
| 363 , m_autoplayMediaCounted(false) | 363 , m_autoplayMediaCounted(false) |
| 364 , m_audioTracks(AudioTrackList::create(*this)) | 364 , m_audioTracks(AudioTrackList::create(*this)) |
| 365 , m_videoTracks(VideoTrackList::create(*this)) | 365 , m_videoTracks(VideoTrackList::create(*this)) |
| 366 , m_textTracks(nullptr) | 366 , m_textTracks(nullptr) |
| 367 #if ENABLE(WEB_AUDIO) | 367 #if ENABLE(WEB_AUDIO) |
| 368 , m_audioSourceNode(nullptr) | 368 , m_audioSourceNode(nullptr) |
| 369 #endif | 369 #endif |
| 370 { | 370 { |
| 371 #if ENABLE(OILPAN) | |
| 372 ThreadState::current()->registerPreFinalizer(*this); | |
| 373 #endif | |
| 371 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); | 374 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); |
| 372 | 375 |
| 373 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this); | 376 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this); |
| 374 | 377 |
| 375 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes ture()) | 378 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes ture()) |
| 376 m_userGestureRequiredForPlay = true; | 379 m_userGestureRequiredForPlay = true; |
| 377 | 380 |
| 378 setHasCustomStyleCallbacks(); | 381 setHasCustomStyleCallbacks(); |
| 379 addElementToDocumentMap(this, &document); | 382 addElementToDocumentMap(this, &document); |
| 380 } | 383 } |
| 381 | 384 |
| 382 HTMLMediaElement::~HTMLMediaElement() | 385 HTMLMediaElement::~HTMLMediaElement() |
| 383 { | 386 { |
| 384 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this); | 387 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this); |
| 385 | 388 |
| 386 #if ENABLE(OILPAN) | 389 #if ENABLE(OILPAN) |
| 387 // If the HTMLMediaElement dies with the document we are not | 390 if (m_closeMediaSourceWhenFinalizing) |
|
haraken
2015/06/17 20:29:02
I guess this hack could be moved to the pre-finali
sof
2015/06/17 20:40:46
I don't think it can be, as it allocates & fires a
haraken
2015/06/17 20:47:15
Allocation is allowed in pre-finalizers.
closeMed
| |
| 388 // allowed to touch the document to adjust delay load event counts | 391 closeMediaSource(); |
| 389 // because the document could have been already | 392 |
| 390 // destructed. However, if the HTMLMediaElement dies with the | 393 // Oilpan: the player must be released, but the player object |
| 391 // document there is no need to change the delayed load counts | 394 // cannot safely access this player client any longer as parts of |
| 392 // because no load event will fire anyway. If the document is | 395 // it may have been finalized already (like the media element's |
| 393 // still alive we do have to decrement the load delay counts. We | 396 // supplementable table.) Handled for now by entering an |
| 394 // determine if the document is alive via the ActiveDOMObject | 397 // is-finalizing state, which is explicitly checked for if the |
| 395 // which is a context lifecycle observer. If the Document has been | 398 // player tries to access the media element during shutdown. |
| 396 // destructed ActiveDOMObject::executionContext() returns 0. | 399 // |
| 397 if (ActiveDOMObject::executionContext()) | 400 // FIXME: Oilpan: move the media player to the heap instead and |
| 398 setShouldDelayLoadEvent(false); | 401 // avoid having to finalize it from here; this whole #if block |
| 402 // could then be removed (along with the state bit it depends on.) | |
| 403 // crbug.com/378229 | |
| 404 m_isFinalizing = true; | |
| 399 #else | 405 #else |
| 400 // HTMLMediaElement and m_asyncEventQueue always become unreachable | 406 // HTMLMediaElement and m_asyncEventQueue always become unreachable |
| 401 // together. So HTMLMediaElemenet and m_asyncEventQueue are destructed in | 407 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in |
| 402 // the same GC. We don't need to close it explicitly in Oilpan. | 408 // the same GC. We don't need to close it explicitly in Oilpan. |
| 403 m_asyncEventQueue->close(); | 409 m_asyncEventQueue->close(); |
| 404 | 410 |
| 405 setShouldDelayLoadEvent(false); | 411 setShouldDelayLoadEvent(false); |
| 406 | 412 |
| 407 if (m_textTracks) | 413 if (m_textTracks) |
| 408 m_textTracks->clearOwner(); | 414 m_textTracks->clearOwner(); |
| 409 m_audioTracks->shutdown(); | 415 m_audioTracks->shutdown(); |
| 410 m_videoTracks->shutdown(); | 416 m_videoTracks->shutdown(); |
| 411 | 417 |
| 412 if (m_mediaController) { | 418 if (m_mediaController) { |
| 413 m_mediaController->removeMediaElement(this); | 419 m_mediaController->removeMediaElement(this); |
| 414 m_mediaController = nullptr; | 420 m_mediaController = nullptr; |
| 415 } | 421 } |
| 416 #endif | |
| 417 | |
| 418 #if ENABLE(OILPAN) | |
| 419 if (m_closeMediaSourceWhenFinalizing) | |
| 420 closeMediaSource(); | |
| 421 #else | |
| 422 closeMediaSource(); | 422 closeMediaSource(); |
| 423 | 423 |
| 424 removeElementFromDocumentMap(this, &document()); | 424 removeElementFromDocumentMap(this, &document()); |
| 425 #endif | 425 #endif |
| 426 | 426 |
| 427 // Destroying the player may cause a resource load to be canceled, | 427 // Destroying the player may cause a resource load to be canceled, |
| 428 // which could result in userCancelledLoad() being called back. | 428 // which could result in userCancelledLoad() being called back. |
| 429 // Setting m_completelyLoaded ensures that such a call will not cause | 429 // Setting m_completelyLoaded ensures that such a call will not cause |
| 430 // us to dispatch an abort event, which would result in a crash. | 430 // us to dispatch an abort event, which would result in a crash. |
| 431 // See http://crbug.com/233654 for more details. | 431 // See http://crbug.com/233654 for more details. |
| 432 m_completelyLoaded = true; | 432 m_completelyLoaded = true; |
| 433 | 433 |
| 434 // With Oilpan load events on the Document are always delayed during | 434 // With Oilpan load events on the Document are always delayed during |
| 435 // sweeping so we don't need to explicitly increment and decrement | 435 // sweeping so we don't need to explicitly increment and decrement |
| 436 // load event delay counts. | 436 // load event delay counts. |
| 437 #if !ENABLE(OILPAN) | 437 #if !ENABLE(OILPAN) |
| 438 // Destroying the player may cause a resource load to be canceled, | 438 // Destroying the player may cause a resource load to be canceled, |
| 439 // which could result in Document::dispatchWindowLoadEvent() being | 439 // which could result in Document::dispatchWindowLoadEvent() being |
| 440 // called via ResourceFetch::didLoadResource() then | 440 // called via ResourceFetch::didLoadResource() then |
| 441 // FrameLoader::checkCompleted(). To prevent load event dispatching during | 441 // FrameLoader::checkCompleted(). To prevent load event dispatching during |
| 442 // object destruction, we use Document::incrementLoadEventDelayCount(). | 442 // object destruction, we use Document::incrementLoadEventDelayCount(). |
| 443 // See http://crbug.com/275223 for more details. | 443 // See http://crbug.com/275223 for more details. |
| 444 document().incrementLoadEventDelayCount(); | 444 document().incrementLoadEventDelayCount(); |
| 445 #endif | 445 #endif |
| 446 | 446 |
| 447 #if ENABLE(OILPAN) | |
| 448 // Oilpan: the player must be released, but the player object | |
| 449 // cannot safely access this player client any longer as parts of | |
| 450 // it may have been finalized already (like the media element's | |
| 451 // supplementable table.) Handled for now by entering an | |
| 452 // is-finalizing state, which is explicitly checked for if the | |
| 453 // player tries to access the media element during shutdown. | |
| 454 // | |
| 455 // FIXME: Oilpan: move the media player to the heap instead and | |
| 456 // avoid having to finalize it from here; this whole #if block | |
| 457 // could then be removed (along with the state bit it depends on.) | |
| 458 // crbug.com/378229 | |
| 459 m_isFinalizing = true; | |
| 460 #endif | |
| 461 | |
| 462 // m_audioSourceNode is explicitly cleared by AudioNode::dispose(). | 447 // m_audioSourceNode is explicitly cleared by AudioNode::dispose(). |
| 463 // Since AudioNode::dispose() is guaranteed to be always called before | 448 // Since AudioNode::dispose() is guaranteed to be always called before |
| 464 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared | 449 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared |
| 465 // even if the AudioNode and the HTMLMediaElement die together. | 450 // even if the AudioNode and the HTMLMediaElement die together. |
| 466 #if ENABLE(WEB_AUDIO) | 451 #if ENABLE(WEB_AUDIO) |
| 467 ASSERT(!m_audioSourceNode); | 452 ASSERT(!m_audioSourceNode); |
| 468 #endif | 453 #endif |
| 469 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); | 454 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); |
| 470 | 455 |
| 471 #if !ENABLE(OILPAN) | 456 #if !ENABLE(OILPAN) |
| 472 document().decrementLoadEventDelayCount(); | 457 document().decrementLoadEventDelayCount(); |
| 473 #endif | 458 #endif |
| 474 } | 459 } |
| 475 | 460 |
| 476 #if ENABLE(OILPAN) | 461 #if ENABLE(OILPAN) |
| 462 void HTMLMediaElement::dispose() | |
| 463 { | |
| 464 // If the HTMLMediaElement dies with the Document we are not | |
| 465 // allowed to touch the Document to adjust delay load event counts | |
| 466 // from the destructor, as the Document could have been already | |
| 467 // destructed. | |
| 468 // | |
| 469 // Work around that restriction by accessing the Document from | |
| 470 // a prefinalizer action instead, updating its delayed load count. | |
| 471 // If needed - if the Document has been detached and informed its | |
| 472 // ContextLifecycleObservers (which HTMLMediaElement is) that | |
| 473 // it is being destroyed, the connection to the Document will | |
| 474 // have been severed already, but in that case there is no need | |
| 475 // to update the delayed load count. But if the Document hasn't | |
| 476 // been detached cleanly from any frame or it isn't dying in the | |
| 477 // same GC, we do update the delayed load count from the prefinalizer. | |
| 478 if (ActiveDOMObject::executionContext()) | |
| 479 setShouldDelayLoadEvent(false); | |
| 480 } | |
| 481 | |
| 477 void HTMLMediaElement::setCloseMediaSourceWhenFinalizing() | 482 void HTMLMediaElement::setCloseMediaSourceWhenFinalizing() |
| 478 { | 483 { |
| 479 ASSERT(!m_closeMediaSourceWhenFinalizing); | 484 ASSERT(!m_closeMediaSourceWhenFinalizing); |
| 480 m_closeMediaSourceWhenFinalizing = true; | 485 m_closeMediaSourceWhenFinalizing = true; |
| 481 } | 486 } |
| 482 #endif | 487 #endif |
| 483 | 488 |
| 484 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) | 489 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) |
| 485 { | 490 { |
| 486 WTF_LOG(Media, "HTMLMediaElement::didMoveToNewDocument(%p)", this); | 491 WTF_LOG(Media, "HTMLMediaElement::didMoveToNewDocument(%p)", this); |
| (...skipping 3180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3667 | 3672 |
| 3668 #if ENABLE(WEB_AUDIO) | 3673 #if ENABLE(WEB_AUDIO) |
| 3669 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) | 3674 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) |
| 3670 { | 3675 { |
| 3671 if (!Heap::isHeapObjectAlive(m_audioSourceNode) && audioSourceProvider()) | 3676 if (!Heap::isHeapObjectAlive(m_audioSourceNode) && audioSourceProvider()) |
| 3672 audioSourceProvider()->setClient(nullptr); | 3677 audioSourceProvider()->setClient(nullptr); |
| 3673 } | 3678 } |
| 3674 #endif | 3679 #endif |
| 3675 | 3680 |
| 3676 } | 3681 } |
| OLD | NEW |