Commit abdffaa2 authored by avayvod's avatar avayvod Committed by Commit bot

[Blink, RemotePlayback] Handle disabling remote playback

Notifies RemotePlayback about the attribute being set that
rejects the pending prompt() promise and cancels all availability watch callbacks.

BUG=657566
TEST=RemotePlaybackTest

Review-Url: https://chromiumcodereview.appspot.com/2432173006
Cr-Commit-Position: refs/heads/master@{#426516}
parent 1abcf254
...@@ -27,6 +27,11 @@ void HTMLMediaElementRemotePlayback::setBooleanAttribute( ...@@ -27,6 +27,11 @@ void HTMLMediaElementRemotePlayback::setBooleanAttribute(
bool value) { bool value) {
ASSERT(name == HTMLNames::disableremoteplaybackAttr); ASSERT(name == HTMLNames::disableremoteplaybackAttr);
element.setBooleanAttribute(name, value); element.setBooleanAttribute(name, value);
HTMLMediaElementRemotePlayback& self =
HTMLMediaElementRemotePlayback::from(element);
if (self.m_remote && value)
self.m_remote->remotePlaybackDisabled();
} }
// static // static
......
...@@ -18,7 +18,7 @@ class ScriptState; ...@@ -18,7 +18,7 @@ class ScriptState;
// Class used to implement the Remote Playback API. It is a supplement to // Class used to implement the Remote Playback API. It is a supplement to
// HTMLMediaElement. // HTMLMediaElement.
class HTMLMediaElementRemotePlayback final class MODULES_EXPORT HTMLMediaElementRemotePlayback final
: public GarbageCollected<HTMLMediaElementRemotePlayback>, : public GarbageCollected<HTMLMediaElementRemotePlayback>,
public Supplement<HTMLMediaElement> { public Supplement<HTMLMediaElement> {
USING_GARBAGE_COLLECTED_MIXIN(HTMLMediaElementRemotePlayback); USING_GARBAGE_COLLECTED_MIXIN(HTMLMediaElementRemotePlayback);
......
...@@ -255,6 +255,18 @@ void RemotePlayback::promptCancelled() { ...@@ -255,6 +255,18 @@ void RemotePlayback::promptCancelled() {
m_promptPromiseResolver = nullptr; m_promptPromiseResolver = nullptr;
} }
void RemotePlayback::remotePlaybackDisabled() {
if (m_promptPromiseResolver) {
m_promptPromiseResolver->reject(DOMException::create(
InvalidStateError, "disableRemotePlayback attribute is present."));
m_promptPromiseResolver = nullptr;
}
m_availabilityCallbacks.clear();
// TODO(avayvod): stop remote playback too. https://crbug.com/657566.
}
void RemotePlayback::setV8ReferencesForCallbacks( void RemotePlayback::setV8ReferencesForCallbacks(
v8::Isolate* isolate, v8::Isolate* isolate,
const v8::Persistent<v8::Object>& wrapper) { const v8::Persistent<v8::Object>& wrapper) {
......
...@@ -35,6 +35,10 @@ class MODULES_EXPORT RemotePlayback final ...@@ -35,6 +35,10 @@ class MODULES_EXPORT RemotePlayback final
public: public:
static RemotePlayback* create(ScriptState*, HTMLMediaElement&); static RemotePlayback* create(ScriptState*, HTMLMediaElement&);
// Notifies this object that disableRemotePlayback attribute was set on the
// corresponding media element.
void remotePlaybackDisabled();
// EventTarget implementation. // EventTarget implementation.
const WTF::AtomicString& interfaceName() const override; const WTF::AtomicString& interfaceName() const override;
ExecutionContext* getExecutionContext() const override; ExecutionContext* getExecutionContext() const override;
......
...@@ -6,9 +6,12 @@ ...@@ -6,9 +6,12 @@
#include "bindings/core/v8/ExceptionStatePlaceholder.h" #include "bindings/core/v8/ExceptionStatePlaceholder.h"
#include "bindings/core/v8/V8BindingForTesting.h" #include "bindings/core/v8/V8BindingForTesting.h"
#include "bindings/modules/v8/RemotePlaybackAvailabilityCallback.h"
#include "core/html/HTMLMediaElement.h" #include "core/html/HTMLMediaElement.h"
#include "core/html/HTMLVideoElement.h" #include "core/html/HTMLVideoElement.h"
#include "core/testing/DummyPageHolder.h" #include "core/testing/DummyPageHolder.h"
#include "modules/remoteplayback/HTMLMediaElementRemotePlayback.h"
#include "platform/UserGestureIndicator.h"
#include "platform/testing/UnitTestHelpers.h" #include "platform/testing/UnitTestHelpers.h"
#include "public/platform/modules/remoteplayback/WebRemotePlaybackState.h" #include "public/platform/modules/remoteplayback/WebRemotePlaybackState.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
...@@ -51,6 +54,10 @@ class RemotePlaybackTest : public ::testing::Test { ...@@ -51,6 +54,10 @@ class RemotePlaybackTest : public ::testing::Test {
void setState(RemotePlayback* remotePlayback, WebRemotePlaybackState state) { void setState(RemotePlayback* remotePlayback, WebRemotePlaybackState state) {
remotePlayback->stateChanged(state); remotePlayback->stateChanged(state);
} }
void setAvailability(RemotePlayback* remotePlayback, bool available) {
remotePlayback->availabilityChanged(available);
}
}; };
TEST_F(RemotePlaybackTest, PromptCancelledRejectsWithNotAllowedError) { TEST_F(RemotePlaybackTest, PromptCancelledRejectsWithNotAllowedError) {
...@@ -60,7 +67,7 @@ TEST_F(RemotePlaybackTest, PromptCancelledRejectsWithNotAllowedError) { ...@@ -60,7 +67,7 @@ TEST_F(RemotePlaybackTest, PromptCancelledRejectsWithNotAllowedError) {
HTMLMediaElement* element = HTMLVideoElement::create(pageHolder->document()); HTMLMediaElement* element = HTMLVideoElement::create(pageHolder->document());
RemotePlayback* remotePlayback = RemotePlayback* remotePlayback =
RemotePlayback::create(scope.getScriptState(), *element); HTMLMediaElementRemotePlayback::remote(scope.getScriptState(), *element);
MockFunction* resolve = MockFunction::create(scope.getScriptState()); MockFunction* resolve = MockFunction::create(scope.getScriptState());
MockFunction* reject = MockFunction::create(scope.getScriptState()); MockFunction* reject = MockFunction::create(scope.getScriptState());
...@@ -68,6 +75,8 @@ TEST_F(RemotePlaybackTest, PromptCancelledRejectsWithNotAllowedError) { ...@@ -68,6 +75,8 @@ TEST_F(RemotePlaybackTest, PromptCancelledRejectsWithNotAllowedError) {
EXPECT_CALL(*resolve, call(::testing::_)).Times(0); EXPECT_CALL(*resolve, call(::testing::_)).Times(0);
EXPECT_CALL(*reject, call(::testing::_)).Times(1); EXPECT_CALL(*reject, call(::testing::_)).Times(1);
UserGestureIndicator indicator(
UserGestureToken::create(UserGestureToken::NewGesture));
remotePlayback->prompt().then(resolve->bind(), reject->bind()); remotePlayback->prompt().then(resolve->bind(), reject->bind());
cancelPrompt(remotePlayback); cancelPrompt(remotePlayback);
} }
...@@ -79,7 +88,7 @@ TEST_F(RemotePlaybackTest, StateChangeEvents) { ...@@ -79,7 +88,7 @@ TEST_F(RemotePlaybackTest, StateChangeEvents) {
HTMLMediaElement* element = HTMLVideoElement::create(pageHolder->document()); HTMLMediaElement* element = HTMLVideoElement::create(pageHolder->document());
RemotePlayback* remotePlayback = RemotePlayback* remotePlayback =
RemotePlayback::create(scope.getScriptState(), *element); HTMLMediaElementRemotePlayback::remote(scope.getScriptState(), *element);
auto connectingHandler = new ::testing::StrictMock<MockEventListener>(); auto connectingHandler = new ::testing::StrictMock<MockEventListener>();
auto connectHandler = new ::testing::StrictMock<MockEventListener>(); auto connectHandler = new ::testing::StrictMock<MockEventListener>();
...@@ -106,4 +115,59 @@ TEST_F(RemotePlaybackTest, StateChangeEvents) { ...@@ -106,4 +115,59 @@ TEST_F(RemotePlaybackTest, StateChangeEvents) {
setState(remotePlayback, WebRemotePlaybackState::Disconnected); setState(remotePlayback, WebRemotePlaybackState::Disconnected);
} }
TEST_F(RemotePlaybackTest,
DisableRemotePlaybackRejectsPromptWithInvalidStateError) {
V8TestingScope scope;
auto pageHolder = DummyPageHolder::create();
HTMLMediaElement* element = HTMLVideoElement::create(pageHolder->document());
RemotePlayback* remotePlayback =
HTMLMediaElementRemotePlayback::remote(scope.getScriptState(), *element);
MockFunction* resolve = MockFunction::create(scope.getScriptState());
MockFunction* reject = MockFunction::create(scope.getScriptState());
EXPECT_CALL(*resolve, call(::testing::_)).Times(0);
EXPECT_CALL(*reject, call(::testing::_)).Times(1);
UserGestureIndicator indicator(
UserGestureToken::create(UserGestureToken::NewGesture));
remotePlayback->prompt().then(resolve->bind(), reject->bind());
HTMLMediaElementRemotePlayback::setBooleanAttribute(
HTMLNames::disableremoteplaybackAttr, *element, true);
}
TEST_F(RemotePlaybackTest, DisableRemotePlaybackCancelsAvailabilityCallbacks) {
V8TestingScope scope;
auto pageHolder = DummyPageHolder::create();
HTMLMediaElement* element = HTMLVideoElement::create(pageHolder->document());
RemotePlayback* remotePlayback =
HTMLMediaElementRemotePlayback::remote(scope.getScriptState(), *element);
MockFunction* callbackFunction = MockFunction::create(scope.getScriptState());
RemotePlaybackAvailabilityCallback* availabilityCallback =
RemotePlaybackAvailabilityCallback::create(scope.isolate(),
callbackFunction->bind());
// The initial call upon registering will not happen as it's posted on the
// message loop.
EXPECT_CALL(*callbackFunction, call(::testing::_)).Times(0);
MockFunction* watchResolve = MockFunction::create(scope.getScriptState());
MockFunction* watchReject = MockFunction::create(scope.getScriptState());
EXPECT_CALL(*watchResolve, call(::testing::_)).Times(1);
EXPECT_CALL(*watchReject, call(::testing::_)).Times(0);
remotePlayback->watchAvailability(availabilityCallback)
.then(watchResolve->bind(), watchReject->bind());
HTMLMediaElementRemotePlayback::setBooleanAttribute(
HTMLNames::disableremoteplaybackAttr, *element, true);
setAvailability(remotePlayback, true);
}
} // namespace blink } // namespace blink
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