Commit db9b03b0 authored by Mounir Lamouri's avatar Mounir Lamouri Committed by Commit Bot

Video Wake Lock: cancel wake lock when context is paused/destroyed.

Bug: 980024
Change-Id: I49fdaac8ea558a6068a3de6ba7d74e922ee9de81
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1691255Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Commit-Queue: Mounir Lamouri <mlamouri@chromium.org>
Cr-Commit-Position: refs/heads/master@{#675699}
parent 769107aa
...@@ -603,6 +603,8 @@ void HTMLVideoElement::DidMoveToNewDocument(Document& old_document) { ...@@ -603,6 +603,8 @@ void HTMLVideoElement::DidMoveToNewDocument(Document& old_document) {
ActivateViewportIntersectionMonitoring(true); ActivateViewportIntersectionMonitoring(true);
} }
wake_lock_->ElementDidMoveToNewDocument();
HTMLMediaElement::DidMoveToNewDocument(old_document); HTMLMediaElement::DidMoveToNewDocument(old_document);
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/html/media/video_wake_lock.h" #include "third_party/blink/renderer/core/html/media/video_wake_lock.h"
#include "services/service_manager/public/cpp/interface_provider.h" #include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/mojom/wake_lock/wake_lock.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
...@@ -12,12 +13,11 @@ ...@@ -12,12 +13,11 @@
#include "third_party/blink/renderer/core/html/media/html_video_element.h" #include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/html/media/remote_playback_controller.h" #include "third_party/blink/renderer/core/html/media/remote_playback_controller.h"
#include "third_party/blink/public/mojom/wake_lock/wake_lock.mojom-blink.h"
namespace blink { namespace blink {
VideoWakeLock::VideoWakeLock(HTMLVideoElement& video) VideoWakeLock::VideoWakeLock(HTMLVideoElement& video)
: PageVisibilityObserver(video.GetDocument().GetPage()), : PageVisibilityObserver(video.GetDocument().GetPage()),
ContextLifecycleStateObserver(&video.GetDocument()),
video_element_(video) { video_element_(video) {
VideoElement().addEventListener(event_type_names::kPlaying, this, true); VideoElement().addEventListener(event_type_names::kPlaying, this, true);
VideoElement().addEventListener(event_type_names::kPause, this, true); VideoElement().addEventListener(event_type_names::kPause, this, true);
...@@ -30,6 +30,13 @@ VideoWakeLock::VideoWakeLock(HTMLVideoElement& video) ...@@ -30,6 +30,13 @@ VideoWakeLock::VideoWakeLock(HTMLVideoElement& video)
RemotePlaybackController::From(VideoElement()); RemotePlaybackController::From(VideoElement());
if (remote_playback_controller) if (remote_playback_controller)
remote_playback_controller->AddObserver(this); remote_playback_controller->AddObserver(this);
UpdateStateIfNeeded();
}
void VideoWakeLock::ElementDidMoveToNewDocument() {
ContextLifecycleStateObserver::DidMoveToNewExecutionContext(
&VideoElement().GetDocument());
} }
void VideoWakeLock::PageVisibilityChanged() { void VideoWakeLock::PageVisibilityChanged() {
...@@ -39,6 +46,7 @@ void VideoWakeLock::PageVisibilityChanged() { ...@@ -39,6 +46,7 @@ void VideoWakeLock::PageVisibilityChanged() {
void VideoWakeLock::Trace(Visitor* visitor) { void VideoWakeLock::Trace(Visitor* visitor) {
NativeEventListener::Trace(visitor); NativeEventListener::Trace(visitor);
PageVisibilityObserver::Trace(visitor); PageVisibilityObserver::Trace(visitor);
ContextLifecycleStateObserver::Trace(visitor);
visitor->Trace(video_element_); visitor->Trace(video_element_);
} }
...@@ -61,6 +69,14 @@ void VideoWakeLock::OnRemotePlaybackStateChanged( ...@@ -61,6 +69,14 @@ void VideoWakeLock::OnRemotePlaybackStateChanged(
Update(); Update();
} }
void VideoWakeLock::ContextLifecycleStateChanged(mojom::FrameLifecycleState) {
Update();
}
void VideoWakeLock::ContextDestroyed(ExecutionContext*) {
Update();
}
void VideoWakeLock::Update() { void VideoWakeLock::Update() {
bool should_be_active = ShouldBeActive(); bool should_be_active = ShouldBeActive();
if (should_be_active == active_) if (should_be_active == active_)
...@@ -74,9 +90,12 @@ bool VideoWakeLock::ShouldBeActive() const { ...@@ -74,9 +90,12 @@ bool VideoWakeLock::ShouldBeActive() const {
bool page_visible = GetPage() && GetPage()->IsPageVisible(); bool page_visible = GetPage() && GetPage()->IsPageVisible();
bool in_picture_in_picture = bool in_picture_in_picture =
PictureInPictureController::IsElementInPictureInPicture(&VideoElement()); PictureInPictureController::IsElementInPictureInPicture(&VideoElement());
return playing_ && (page_visible || in_picture_in_picture) && return playing_ && (page_visible || in_picture_in_picture) &&
remote_playback_state_ != remote_playback_state_ !=
mojom::blink::PresentationConnectionState::CONNECTED; mojom::blink::PresentationConnectionState::CONNECTED &&
!(VideoElement().GetDocument().IsContextPaused() ||
VideoElement().GetDocument().IsContextDestroyed());
} }
void VideoWakeLock::EnsureWakeLockService() { void VideoWakeLock::EnsureWakeLockService() {
...@@ -87,8 +106,12 @@ void VideoWakeLock::EnsureWakeLockService() { ...@@ -87,8 +106,12 @@ void VideoWakeLock::EnsureWakeLockService() {
if (!frame) if (!frame)
return; return;
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
frame->GetTaskRunner(TaskType::kMediaElementEvent);
blink::mojom::blink::WakeLockServicePtr service; blink::mojom::blink::WakeLockServicePtr service;
frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(&service)); frame->GetInterfaceProvider().GetInterface(
mojo::MakeRequest(&service, task_runner));
service->GetWakeLock(device::mojom::WakeLockType::kPreventDisplaySleep, service->GetWakeLock(device::mojom::WakeLockType::kPreventDisplaySleep,
device::mojom::blink::WakeLockReason::kVideoPlayback, device::mojom::blink::WakeLockReason::kVideoPlayback,
"Video Wake Lock", "Video Wake Lock",
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "services/device/public/mojom/wake_lock.mojom-blink.h" #include "services/device/public/mojom/wake_lock.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/native_event_listener.h" #include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_state_observer.h"
#include "third_party/blink/renderer/core/html/media/remote_playback_observer.h" #include "third_party/blink/renderer/core/html/media/remote_playback_observer.h"
#include "third_party/blink/renderer/core/page/page_visibility_observer.h" #include "third_party/blink/renderer/core/page/page_visibility_observer.h"
...@@ -19,19 +20,23 @@ class HTMLVideoElement; ...@@ -19,19 +20,23 @@ class HTMLVideoElement;
// take wake lock iif: // take wake lock iif:
// - the video is playing; // - the video is playing;
// - the page is visible OR the video is in picture-in-picture; // - the page is visible OR the video is in picture-in-picture;
// - the video isn't being remoted. // - the video isn't being remoted;
// - the execution context is neither paused nor destroyed.
// Each video element implements its own wake lock logic. The service will then // Each video element implements its own wake lock logic. The service will then
// merge all the requests and take the appropriate system wake lock. // merge all the requests and take the appropriate system wake lock.
// VideoWakeLock only uses "screen" related wake lock: it prevents the screen // VideoWakeLock only uses "screen" related wake lock: it prevents the screen
// from locking on mobile or the lockscreen to show up on desktop. // from locking on mobile or the lockscreen to show up on desktop.
class CORE_EXPORT VideoWakeLock final : public NativeEventListener, class CORE_EXPORT VideoWakeLock final : public NativeEventListener,
public PageVisibilityObserver, public PageVisibilityObserver,
public RemotePlaybackObserver { public RemotePlaybackObserver,
public ContextLifecycleStateObserver {
USING_GARBAGE_COLLECTED_MIXIN(VideoWakeLock); USING_GARBAGE_COLLECTED_MIXIN(VideoWakeLock);
public: public:
explicit VideoWakeLock(HTMLVideoElement&); explicit VideoWakeLock(HTMLVideoElement&);
void ElementDidMoveToNewDocument();
void Trace(Visitor*) final; void Trace(Visitor*) final;
// EventListener implementation. // EventListener implementation.
...@@ -41,6 +46,10 @@ class CORE_EXPORT VideoWakeLock final : public NativeEventListener, ...@@ -41,6 +46,10 @@ class CORE_EXPORT VideoWakeLock final : public NativeEventListener,
void OnRemotePlaybackStateChanged( void OnRemotePlaybackStateChanged(
mojom::blink::PresentationConnectionState) final; mojom::blink::PresentationConnectionState) final;
// ContextLifecycleStateObserver
void ContextLifecycleStateChanged(mojom::FrameLifecycleState) override;
void ContextDestroyed(ExecutionContext*) override;
bool active_for_tests() const { return active_; } bool active_for_tests() const { return active_; }
private: private:
......
...@@ -153,6 +153,16 @@ class VideoWakeLockTest : public PageTestBase { ...@@ -153,6 +153,16 @@ class VideoWakeLockTest : public PageTestBase {
video_.Get(), event_type_names::kLeavepictureinpicture); video_.Get(), event_type_names::kLeavepictureinpicture);
} }
void SimulateContextPause() {
GetDocument().SetLifecycleState(mojom::FrameLifecycleState::kPaused);
}
void SimulateContextRunning() {
GetDocument().SetLifecycleState(mojom::FrameLifecycleState::kRunning);
}
void SimulateContextDestroyed() { GetDocument().NotifyContextDestroyed(); }
private: private:
Persistent<HTMLVideoElement> video_; Persistent<HTMLVideoElement> video_;
Persistent<VideoWakeLock> video_wake_lock_; Persistent<VideoWakeLock> video_wake_lock_;
...@@ -311,4 +321,31 @@ TEST_F(VideoWakeLockTest, RemotingVideoInPictureInPictureDoesNotRequestLock) { ...@@ -311,4 +321,31 @@ TEST_F(VideoWakeLockTest, RemotingVideoInPictureInPictureDoesNotRequestLock) {
EXPECT_FALSE(GetVideoWakeLock()->active_for_tests()); EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
} }
TEST_F(VideoWakeLockTest, PausingContextCancelsLock) {
SimulatePlaying();
EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
SimulateContextPause();
EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
}
TEST_F(VideoWakeLockTest, ResumingContextResumesLock) {
SimulatePlaying();
EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
SimulateContextPause();
EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
SimulateContextRunning();
EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
}
TEST_F(VideoWakeLockTest, DestroyingContextCancelsLock) {
SimulatePlaying();
EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
SimulateContextDestroyed();
EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
}
} // namespace blink } // namespace blink
...@@ -2,7 +2,7 @@ Tests that reparenting media elements also reparents ActiveDOMObject. ...@@ -2,7 +2,7 @@ Tests that reparenting media elements also reparents ActiveDOMObject.
Before Reparenting Before Reparenting
PASS: internals.contextLifecycleStateObserverObjectCount(document) should be '0' and is. PASS: internals.contextLifecycleStateObserverObjectCount(document) should be '0' and is.
PASS: internals.contextLifecycleStateObserverObjectCount(iframe) should be '1' and is. PASS: internals.contextLifecycleStateObserverObjectCount(iframe) should be '2' and is.
After Reparenting After Reparenting
PASS: internals.contextLifecycleStateObserverObjectCount(document) should be '1' and is. PASS: internals.contextLifecycleStateObserverObjectCount(document) should be '2' and is.
PASS: internals.contextLifecycleStateObserverObjectCount(iframe) should be '0' and is. PASS: internals.contextLifecycleStateObserverObjectCount(iframe) should be '0' and is.
...@@ -11,12 +11,12 @@ ...@@ -11,12 +11,12 @@
log('Before Reparenting'); log('Before Reparenting');
shouldBe('internals.contextLifecycleStateObserverObjectCount(document)', 0); shouldBe('internals.contextLifecycleStateObserverObjectCount(document)', 0);
shouldBe('internals.contextLifecycleStateObserverObjectCount(iframe)', 1); shouldBe('internals.contextLifecycleStateObserverObjectCount(iframe)', 2);
document.body.appendChild(window.iframe.querySelector('video')); document.body.appendChild(window.iframe.querySelector('video'));
log('After Reparenting'); log('After Reparenting');
shouldBe('internals.contextLifecycleStateObserverObjectCount(document)', 1); shouldBe('internals.contextLifecycleStateObserverObjectCount(document)', 2);
shouldBe('internals.contextLifecycleStateObserverObjectCount(iframe)', 0); shouldBe('internals.contextLifecycleStateObserverObjectCount(iframe)', 0);
} }
</script> </script>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment