Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1006)

Unified Diff: third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp

Issue 2415723002: [Blink, RemotePlayback] watchAvailability() implementation. (Closed)
Patch Set: Added layout test for callback gc Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);

Powered by Google App Engine
This is Rietveld 408576698