| Index: third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
|
| diff --git a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
|
| index bddeb4b1c5ef5001569be2140ada60a7eb849d03..5684cebadab64a91da37f52ec2903a68f29d7073 100644
|
| --- a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
|
| +++ b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
|
| @@ -5,13 +5,14 @@
|
| #include "modules/remoteplayback/RemotePlayback.h"
|
|
|
| #include "bindings/core/v8/ScriptPromiseResolver.h"
|
| +#include "bindings/modules/v8/RemotePlaybackAvailabilityCallback.h"
|
| #include "core/HTMLNames.h"
|
| #include "core/dom/DOMException.h"
|
| #include "core/dom/Document.h"
|
| +#include "core/dom/ExecutionContextTask.h"
|
| #include "core/events/Event.h"
|
| #include "core/html/HTMLMediaElement.h"
|
| #include "modules/EventTargetModules.h"
|
| -#include "modules/remoteplayback/RemotePlaybackAvailability.h"
|
| #include "platform/UserGestureIndicator.h"
|
|
|
| namespace blink {
|
| @@ -39,17 +40,21 @@ const AtomicString& remotePlaybackStateToString(WebRemotePlaybackState state) {
|
| } // anonymous namespace
|
|
|
| // static
|
| -RemotePlayback* RemotePlayback::create(HTMLMediaElement& element) {
|
| - ASSERT(element.document().frame());
|
| +RemotePlayback* RemotePlayback::create(ScriptState* scriptState,
|
| + HTMLMediaElement& element) {
|
| + DCHECK(element.document().frame());
|
| + DCHECK(scriptState);
|
|
|
| - RemotePlayback* remotePlayback = new RemotePlayback(element);
|
| + RemotePlayback* remotePlayback = new RemotePlayback(scriptState, element);
|
| element.setRemotePlaybackClient(remotePlayback);
|
|
|
| return remotePlayback;
|
| }
|
|
|
| -RemotePlayback::RemotePlayback(HTMLMediaElement& element)
|
| +RemotePlayback::RemotePlayback(ScriptState* scriptState,
|
| + HTMLMediaElement& element)
|
| : ActiveScriptWrappable(this),
|
| + m_scriptState(scriptState),
|
| m_state(element.isPlayingRemotely()
|
| ? WebRemotePlaybackState::Connected
|
| : WebRemotePlaybackState::Disconnected),
|
| @@ -64,27 +69,88 @@ ExecutionContext* RemotePlayback::getExecutionContext() const {
|
| return &m_mediaElement->document();
|
| }
|
|
|
| -ScriptPromise RemotePlayback::getAvailability(ScriptState* scriptState) {
|
| - ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
|
| +ScriptPromise RemotePlayback::watchAvailability(
|
| + RemotePlaybackAvailabilityCallback* callback) {
|
| + ScriptPromiseResolver* resolver =
|
| + ScriptPromiseResolver::create(m_scriptState.get());
|
| ScriptPromise promise = resolver->promise();
|
|
|
| + if (m_mediaElement->fastHasAttribute(HTMLNames::disableremoteplaybackAttr)) {
|
| + resolver->reject(DOMException::create(
|
| + InvalidStateError, "disableRemotePlayback attribute is present."));
|
| + return promise;
|
| + }
|
| +
|
| + // TODO(avayvod): implement steps 4 and 5 of the algorithm.
|
| + // https://crbug.com/655233
|
| + int id;
|
| + do {
|
| + id = getExecutionContext()->circularSequentialID();
|
| + } while (!m_availabilityCallbacks.add(id, callback).isNewEntry);
|
| +
|
| + // Report the current availability via the callback.
|
| + getExecutionContext()->postTask(
|
| + BLINK_FROM_HERE,
|
| + createSameThreadTask(&RemotePlayback::notifyInitialAvailability,
|
| + wrapPersistent(this), id),
|
| + "watchAvailabilityCallback");
|
| +
|
| // TODO(avayvod): Currently the availability is tracked for each media element
|
| // as soon as it's created, we probably want to limit that to when the
|
| // page/element is visible (see https://crbug.com/597281) and has default
|
| // controls. If there are no default controls, we should also start tracking
|
| - // availability on demand meaning the Promise returned by getAvailability()
|
| + // availability on demand meaning the Promise returned by watchAvailability()
|
| // will be resolved asynchronously.
|
| - RemotePlaybackAvailability* availability =
|
| - RemotePlaybackAvailability::take(resolver, m_availability);
|
| - m_availabilityObjects.append(availability);
|
| - resolver->resolve(availability);
|
| + resolver->resolve(id);
|
| + return promise;
|
| +}
|
| +
|
| +ScriptPromise RemotePlayback::cancelWatchAvailability(int id) {
|
| + ScriptPromiseResolver* resolver =
|
| + ScriptPromiseResolver::create(m_scriptState.get());
|
| + ScriptPromise promise = resolver->promise();
|
| +
|
| + if (m_mediaElement->fastHasAttribute(HTMLNames::disableremoteplaybackAttr)) {
|
| + resolver->reject(DOMException::create(
|
| + InvalidStateError, "disableRemotePlayback attribute is present."));
|
| + return promise;
|
| + }
|
| +
|
| + auto iter = m_availabilityCallbacks.find(id);
|
| + if (iter == m_availabilityCallbacks.end()) {
|
| + resolver->reject(DOMException::create(
|
| + NotFoundError, "A callback with the given id is not found."));
|
| + return promise;
|
| + }
|
| +
|
| + m_availabilityCallbacks.remove(iter);
|
| +
|
| + resolver->resolve();
|
| return promise;
|
| }
|
|
|
| -ScriptPromise RemotePlayback::prompt(ScriptState* scriptState) {
|
| - // TODO(avayvod): implement steps 4, 5, 8, 9 of the algorithm.
|
| +ScriptPromise RemotePlayback::cancelWatchAvailability() {
|
| + ScriptPromiseResolver* resolver =
|
| + ScriptPromiseResolver::create(m_scriptState.get());
|
| + ScriptPromise promise = resolver->promise();
|
| +
|
| + if (m_mediaElement->fastHasAttribute(HTMLNames::disableremoteplaybackAttr)) {
|
| + resolver->reject(DOMException::create(
|
| + InvalidStateError, "disableRemotePlayback attribute is present."));
|
| + return promise;
|
| + }
|
| +
|
| + m_availabilityCallbacks.clear();
|
| +
|
| + resolver->resolve();
|
| + return promise;
|
| +}
|
| +
|
| +ScriptPromise RemotePlayback::prompt() {
|
| + // TODO(avayvod): implement steps 5, 8, 9 of the algorithm.
|
| // https://crbug.com/647441
|
| - ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
|
| + ScriptPromiseResolver* resolver =
|
| + ScriptPromiseResolver::create(m_scriptState.get());
|
| ScriptPromise promise = resolver->promise();
|
|
|
| if (m_mediaElement->fastHasAttribute(HTMLNames::disableremoteplaybackAttr)) {
|
| @@ -126,10 +192,19 @@ String RemotePlayback::state() const {
|
| }
|
|
|
| bool RemotePlayback::hasPendingActivity() const {
|
| - return hasEventListeners() || !m_availabilityObjects.isEmpty() ||
|
| + return hasEventListeners() || !m_availabilityCallbacks.isEmpty() ||
|
| m_promptPromiseResolver;
|
| }
|
|
|
| +void RemotePlayback::notifyInitialAvailability(int callbackId) {
|
| + // May not find the callback if the website cancels it fast enough.
|
| + auto iter = m_availabilityCallbacks.find(callbackId);
|
| + if (iter == m_availabilityCallbacks.end())
|
| + return;
|
| +
|
| + iter->value->call(m_scriptState.get(), this, m_availability);
|
| +}
|
| +
|
| void RemotePlayback::stateChanged(WebRemotePlaybackState state) {
|
| // We may get a "disconnected" state change while in the "disconnected"
|
| // state if initiated connection fails. So cleanup the promise resolvers
|
| @@ -167,8 +242,8 @@ void RemotePlayback::availabilityChanged(bool available) {
|
| return;
|
|
|
| m_availability = available;
|
| - for (auto& availabilityObject : m_availabilityObjects)
|
| - availabilityObject->availabilityChanged(available);
|
| + for (auto& callback : m_availabilityCallbacks.values())
|
| + callback->call(m_scriptState.get(), this, m_availability);
|
| }
|
|
|
| void RemotePlayback::promptCancelled() {
|
| @@ -180,8 +255,15 @@ void RemotePlayback::promptCancelled() {
|
| m_promptPromiseResolver = nullptr;
|
| }
|
|
|
| +void RemotePlayback::setV8ReferencesForCallbacks(
|
| + v8::Isolate* isolate,
|
| + const v8::Persistent<v8::Object>& wrapper) {
|
| + for (auto callback : m_availabilityCallbacks.values())
|
| + callback->setWrapperReference(isolate, wrapper);
|
| +}
|
| +
|
| DEFINE_TRACE(RemotePlayback) {
|
| - visitor->trace(m_availabilityObjects);
|
| + visitor->trace(m_availabilityCallbacks);
|
| visitor->trace(m_promptPromiseResolver);
|
| visitor->trace(m_mediaElement);
|
| EventTargetWithInlineData::trace(visitor);
|
|
|