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