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 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 , m_sentStalledEvent(false) | 350 , m_sentStalledEvent(false) |
| 351 , m_sentEndEvent(false) | 351 , m_sentEndEvent(false) |
| 352 , m_closedCaptionsVisible(false) | 352 , m_closedCaptionsVisible(false) |
| 353 , m_completelyLoaded(false) | 353 , m_completelyLoaded(false) |
| 354 , m_havePreparedToPlay(false) | 354 , m_havePreparedToPlay(false) |
| 355 , m_tracksAreReady(true) | 355 , m_tracksAreReady(true) |
| 356 , m_haveVisibleTextTrack(false) | 356 , m_haveVisibleTextTrack(false) |
| 357 , m_processingPreferenceChange(false) | 357 , m_processingPreferenceChange(false) |
| 358 , m_remoteRoutesAvailable(false) | 358 , m_remoteRoutesAvailable(false) |
| 359 , m_playingRemotely(false) | 359 , m_playingRemotely(false) |
| 360 , m_isFinalizing(false) | |
| 360 #if ENABLE(OILPAN) | 361 #if ENABLE(OILPAN) |
| 361 , m_isFinalizing(false) | |
| 362 , m_closeMediaSourceWhenFinalizing(false) | 362 , m_closeMediaSourceWhenFinalizing(false) |
| 363 #endif | 363 #endif |
| 364 , m_initialPlayWithoutUserGestures(false) | 364 , m_initialPlayWithoutUserGestures(false) |
| 365 , m_autoplayMediaCounted(false) | 365 , m_autoplayMediaCounted(false) |
| 366 , m_audioTracks(AudioTrackList::create(*this)) | 366 , m_audioTracks(AudioTrackList::create(*this)) |
| 367 , m_videoTracks(VideoTrackList::create(*this)) | 367 , m_videoTracks(VideoTrackList::create(*this)) |
| 368 , m_textTracks(nullptr) | 368 , m_textTracks(nullptr) |
| 369 #if ENABLE(WEB_AUDIO) | 369 #if ENABLE(WEB_AUDIO) |
| 370 , m_audioSourceNode(nullptr) | 370 , m_audioSourceNode(nullptr) |
| 371 #endif | 371 #endif |
| 372 { | 372 { |
| 373 #if ENABLE(OILPAN) | 373 #if ENABLE(OILPAN) |
| 374 ThreadState::current()->registerPreFinalizer(*this); | 374 ThreadState::current()->registerPreFinalizer(*this); |
| 375 #endif | 375 #endif |
| 376 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); | 376 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); |
| 377 | 377 |
| 378 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this); | 378 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this); |
| 379 | 379 |
| 380 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes ture()) | 380 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes ture()) |
| 381 m_userGestureRequiredForPlay = true; | 381 m_userGestureRequiredForPlay = true; |
| 382 | 382 |
| 383 setHasCustomStyleCallbacks(); | 383 setHasCustomStyleCallbacks(); |
| 384 addElementToDocumentMap(this, &document); | 384 addElementToDocumentMap(this, &document); |
| 385 } | 385 } |
| 386 | 386 |
| 387 HTMLMediaElement::~HTMLMediaElement() | 387 HTMLMediaElement::~HTMLMediaElement() |
| 388 { | 388 { |
| 389 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this); | 389 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this); |
| 390 | 390 #if !ENABLE(OILPAN) |
| 391 #if ENABLE(OILPAN) | |
| 392 if (m_closeMediaSourceWhenFinalizing) | |
| 393 closeMediaSource(); | |
| 394 | |
| 395 // Oilpan: the player must be released, but the player object | |
| 396 // cannot safely access this player client any longer as parts of | |
| 397 // it may have been finalized already (like the media element's | |
| 398 // supplementable table.) Handled for now by entering an | |
| 399 // is-finalizing state, which is explicitly checked for if the | |
| 400 // player tries to access the media element during shutdown. | |
| 401 // | |
| 402 // FIXME: Oilpan: move the media player to the heap instead and | |
| 403 // avoid having to finalize it from here; this whole #if block | |
| 404 // could then be removed (along with the state bit it depends on.) | |
| 405 // crbug.com/378229 | |
| 406 m_isFinalizing = true; | |
| 407 #else | |
| 408 // HTMLMediaElement and m_asyncEventQueue always become unreachable | 391 // HTMLMediaElement and m_asyncEventQueue always become unreachable |
| 409 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in | 392 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in |
| 410 // the same GC. We don't need to close it explicitly in Oilpan. | 393 // the same GC. We don't need to close it explicitly in Oilpan. |
| 411 m_asyncEventQueue->close(); | 394 m_asyncEventQueue->close(); |
| 412 | 395 |
| 413 setShouldDelayLoadEvent(false); | 396 setShouldDelayLoadEvent(false); |
| 414 | 397 |
| 415 if (m_textTracks) | 398 if (m_textTracks) |
| 416 m_textTracks->clearOwner(); | 399 m_textTracks->clearOwner(); |
| 417 m_audioTracks->shutdown(); | 400 m_audioTracks->shutdown(); |
| 418 m_videoTracks->shutdown(); | 401 m_videoTracks->shutdown(); |
| 419 | 402 |
| 420 if (m_mediaController) { | 403 if (m_mediaController) { |
| 421 m_mediaController->removeMediaElement(this); | 404 m_mediaController->removeMediaElement(this); |
| 422 m_mediaController = nullptr; | 405 m_mediaController = nullptr; |
| 423 } | 406 } |
| 424 closeMediaSource(); | 407 closeMediaSource(); |
| 425 | 408 |
| 426 removeElementFromDocumentMap(this, &document()); | 409 removeElementFromDocumentMap(this, &document()); |
| 427 #endif | |
| 428 | 410 |
| 429 // Destroying the player may cause a resource load to be canceled, | 411 // Destroying the player may cause a resource load to be canceled, |
| 430 // which could result in userCancelledLoad() being called back. | 412 // which could result in userCancelledLoad() being called back. |
| 431 // Setting m_completelyLoaded ensures that such a call will not cause | 413 // Setting m_isFinalizing ensures that such a call will not cause |
| 432 // us to dispatch an abort event, which would result in a crash. | 414 // us to dispatch an abort event, which would result in a crash. |
| 433 // See http://crbug.com/233654 for more details. | 415 // See http://crbug.com/233654 for more details. |
| 434 m_completelyLoaded = true; | 416 m_isFinalizing = true; |
| 435 | 417 |
| 436 // With Oilpan load events on the Document are always delayed during | |
| 437 // sweeping so we don't need to explicitly increment and decrement | |
| 438 // load event delay counts. | |
| 439 #if !ENABLE(OILPAN) | |
| 440 // Destroying the player may cause a resource load to be canceled, | 418 // Destroying the player may cause a resource load to be canceled, |
| 441 // which could result in Document::dispatchWindowLoadEvent() being | 419 // which could result in Document::dispatchWindowLoadEvent() being |
| 442 // called via ResourceFetch::didLoadResource() then | 420 // called via ResourceFetch::didLoadResource() then |
| 443 // FrameLoader::checkCompleted(). To prevent load event dispatching during | 421 // FrameLoader::checkCompleted(). To prevent load event dispatching during |
| 444 // object destruction, we use Document::incrementLoadEventDelayCount(). | 422 // object destruction, we use Document::incrementLoadEventDelayCount(). |
| 445 // See http://crbug.com/275223 for more details. | 423 // See http://crbug.com/275223 for more details. |
| 446 document().incrementLoadEventDelayCount(); | 424 document().incrementLoadEventDelayCount(); |
| 425 | |
| 426 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); | |
| 427 | |
| 428 document().decrementLoadEventDelayCount(); | |
| 447 #endif | 429 #endif |
| 448 | 430 |
| 431 #if ENABLE(WEB_AUDIO) | |
| 449 // m_audioSourceNode is explicitly cleared by AudioNode::dispose(). | 432 // m_audioSourceNode is explicitly cleared by AudioNode::dispose(). |
| 450 // Since AudioNode::dispose() is guaranteed to be always called before | 433 // Since AudioNode::dispose() is guaranteed to be always called before |
| 451 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared | 434 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared |
| 452 // even if the AudioNode and the HTMLMediaElement die together. | 435 // even if the AudioNode and the HTMLMediaElement die together. |
| 453 #if ENABLE(WEB_AUDIO) | |
| 454 ASSERT(!m_audioSourceNode); | 436 ASSERT(!m_audioSourceNode); |
| 455 #endif | 437 #endif |
| 456 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); | |
| 457 | |
| 458 #if !ENABLE(OILPAN) | |
| 459 document().decrementLoadEventDelayCount(); | |
| 460 #endif | |
| 461 } | 438 } |
| 462 | 439 |
| 463 #if ENABLE(OILPAN) | 440 #if ENABLE(OILPAN) |
| 464 void HTMLMediaElement::dispose() | 441 void HTMLMediaElement::dispose() |
| 465 { | 442 { |
| 466 // If the HTMLMediaElement dies with the Document we are not | 443 // If the HTMLMediaElement dies with the Document we are not |
| 467 // allowed to touch the Document to adjust delay load event counts | 444 // allowed to touch the Document to adjust delay load event counts |
| 468 // from the destructor, as the Document could have been already | 445 // from the destructor, as the Document could have been already |
| 469 // destructed. | 446 // destructed. |
| 470 // | 447 // |
| 471 // Work around that restriction by accessing the Document from | 448 // Work around that restriction by accessing the Document from |
| 472 // a prefinalizer action instead, updating its delayed load count. | 449 // a prefinalizer action instead, updating its delayed load count. |
| 473 // If needed - if the Document has been detached and informed its | 450 // If needed - if the Document has been detached and informed its |
| 474 // ContextLifecycleObservers (which HTMLMediaElement is) that | 451 // ContextLifecycleObservers (which HTMLMediaElement is) that |
| 475 // it is being destroyed, the connection to the Document will | 452 // it is being destroyed, the connection to the Document will |
| 476 // have been severed already, but in that case there is no need | 453 // have been severed already, but in that case there is no need |
| 477 // to update the delayed load count. But if the Document hasn't | 454 // to update the delayed load count. But if the Document hasn't |
| 478 // been detached cleanly from any frame or it isn't dying in the | 455 // been detached cleanly from any frame or it isn't dying in the |
| 479 // same GC, we do update the delayed load count from the prefinalizer. | 456 // same GC, we do update the delayed load count from the prefinalizer. |
| 480 if (ActiveDOMObject::executionContext()) | 457 if (ActiveDOMObject::executionContext()) |
| 481 setShouldDelayLoadEvent(false); | 458 setShouldDelayLoadEvent(false); |
| 459 | |
| 460 if (m_closeMediaSourceWhenFinalizing) | |
|
haraken
2015/06/22 13:25:40
Maybe can we remove m_closeMediaSourceWhenFinalizi
sof
2015/06/22 13:31:56
I would prefer not to, as it would call MediaSourc
haraken
2015/06/22 13:43:36
Makes sense; Then would it be a bit tidier to dire
| |
| 461 closeMediaSource(); | |
| 462 | |
| 463 // Oilpan: the player must be released, but the player object | |
| 464 // cannot safely access this player client any longer as parts of | |
| 465 // it may have been finalized already (like the media element's | |
| 466 // supplementable table.) Handled for now by entering an | |
| 467 // is-finalizing state, which is explicitly checked for if the | |
| 468 // player tries to access the media element during shutdown. | |
| 469 // | |
| 470 // FIXME: Oilpan: move the media player to the heap instead and | |
| 471 // avoid having to finalize it from here; this whole #if block | |
| 472 // could then be removed (along with the state bit it depends on.) | |
| 473 // crbug.com/378229 | |
| 474 m_isFinalizing = true; | |
| 475 | |
| 476 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); | |
| 482 } | 477 } |
| 483 | 478 |
| 484 void HTMLMediaElement::setCloseMediaSourceWhenFinalizing() | 479 void HTMLMediaElement::setCloseMediaSourceWhenFinalizing() |
| 485 { | 480 { |
| 486 ASSERT(!m_closeMediaSourceWhenFinalizing); | 481 ASSERT(!m_closeMediaSourceWhenFinalizing); |
| 487 m_closeMediaSourceWhenFinalizing = true; | 482 m_closeMediaSourceWhenFinalizing = true; |
| 488 } | 483 } |
| 489 #endif | 484 #endif |
| 490 | 485 |
| 491 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) | 486 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) |
| (...skipping 2497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2989 | 2984 |
| 2990 void HTMLMediaElement::userCancelledLoad() | 2985 void HTMLMediaElement::userCancelledLoad() |
| 2991 { | 2986 { |
| 2992 WTF_LOG(Media, "HTMLMediaElement::userCancelledLoad(%p)", this); | 2987 WTF_LOG(Media, "HTMLMediaElement::userCancelledLoad(%p)", this); |
| 2993 | 2988 |
| 2994 // If the media data fetching process is aborted by the user: | 2989 // If the media data fetching process is aborted by the user: |
| 2995 | 2990 |
| 2996 // 1 - The user agent should cancel the fetching process. | 2991 // 1 - The user agent should cancel the fetching process. |
| 2997 clearMediaPlayer(-1); | 2992 clearMediaPlayer(-1); |
| 2998 | 2993 |
| 2999 if (m_networkState == NETWORK_EMPTY || m_completelyLoaded) | 2994 if (m_networkState == NETWORK_EMPTY || m_completelyLoaded || m_isFinalizing) |
| 3000 return; | 2995 return; |
| 3001 | 2996 |
| 3002 // 2 - Set the error attribute to a new MediaError object whose code attribu te is set to MEDIA_ERR_ABORTED. | 2997 // 2 - Set the error attribute to a new MediaError object whose code attribu te is set to MEDIA_ERR_ABORTED. |
| 3003 m_error = MediaError::create(MediaError::MEDIA_ERR_ABORTED); | 2998 m_error = MediaError::create(MediaError::MEDIA_ERR_ABORTED); |
| 3004 | 2999 |
| 3005 // 3 - Queue a task to fire a simple event named error at the media element. | 3000 // 3 - Queue a task to fire a simple event named error at the media element. |
| 3006 scheduleEvent(EventTypeNames::abort); | 3001 scheduleEvent(EventTypeNames::abort); |
| 3007 | 3002 |
| 3008 closeMediaSource(); | 3003 closeMediaSource(); |
| 3009 | 3004 |
| (...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3680 | 3675 |
| 3681 #if ENABLE(WEB_AUDIO) | 3676 #if ENABLE(WEB_AUDIO) |
| 3682 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) | 3677 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) |
| 3683 { | 3678 { |
| 3684 if (!Heap::isHeapObjectAlive(m_audioSourceNode) && audioSourceProvider()) | 3679 if (!Heap::isHeapObjectAlive(m_audioSourceNode) && audioSourceProvider()) |
| 3685 audioSourceProvider()->setClient(nullptr); | 3680 audioSourceProvider()->setClient(nullptr); |
| 3686 } | 3681 } |
| 3687 #endif | 3682 #endif |
| 3688 | 3683 |
| 3689 } | 3684 } |
| OLD | NEW |