| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "modules/remoteplayback/RemotePlayback.h" | 5 #include "modules/remoteplayback/RemotePlayback.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/ScriptPromiseResolver.h" | 7 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| 8 #include "core/dom/Document.h" | 8 #include "core/dom/Document.h" |
| 9 #include "core/events/Event.h" | 9 #include "core/events/Event.h" |
| 10 #include "core/html/HTMLMediaElement.h" | 10 #include "core/html/HTMLMediaElement.h" |
| 11 #include "modules/EventTargetModules.h" | 11 #include "modules/EventTargetModules.h" |
| 12 #include "modules/remoteplayback/RemotePlaybackAvailability.h" | 12 #include "modules/remoteplayback/RemotePlaybackAvailability.h" |
| 13 #include "platform/UserGestureIndicator.h" |
| 13 | 14 |
| 14 namespace blink { | 15 namespace blink { |
| 15 | 16 |
| 16 namespace { | 17 namespace { |
| 17 | 18 |
| 18 const AtomicString& remotePlaybackStateToString(WebRemotePlaybackState state) | 19 const AtomicString& remotePlaybackStateToString(WebRemotePlaybackState state) |
| 19 { | 20 { |
| 20 DEFINE_STATIC_LOCAL(const AtomicString, connectedValue, ("connected", Atomic
String::ConstructFromLiteral)); | 21 DEFINE_STATIC_LOCAL(const AtomicString, connectedValue, ("connected", Atomic
String::ConstructFromLiteral)); |
| 21 DEFINE_STATIC_LOCAL(const AtomicString, disconnectedValue, ("disconnected",
AtomicString::ConstructFromLiteral)); | 22 DEFINE_STATIC_LOCAL(const AtomicString, disconnectedValue, ("disconnected",
AtomicString::ConstructFromLiteral)); |
| 22 | 23 |
| 23 switch (state) { | 24 switch (state) { |
| 24 case WebRemotePlaybackState::Connected: | 25 case WebRemotePlaybackState::Connected: |
| 25 return connectedValue; | 26 return connectedValue; |
| 26 case WebRemotePlaybackState::Disconnected: | 27 case WebRemotePlaybackState::Disconnected: |
| 27 return disconnectedValue; | 28 return disconnectedValue; |
| 28 } | 29 } |
| 29 | 30 |
| 30 ASSERT_NOT_REACHED(); | 31 ASSERT_NOT_REACHED(); |
| 31 return disconnectedValue; | 32 return disconnectedValue; |
| 32 } | 33 } |
| 33 | 34 |
| 34 } // anonymous namespace | 35 } // anonymous namespace |
| 35 | 36 |
| 36 // static | 37 // static |
| 37 RemotePlayback* RemotePlayback::create(HTMLMediaElement& element) | 38 RemotePlayback* RemotePlayback::create(HTMLMediaElement& element) |
| 38 { | 39 { |
| 39 ASSERT(element.document().frame()); | 40 ASSERT(element.document().frame()); |
| 40 | 41 |
| 41 RemotePlayback* remotePlayback = new RemotePlayback( | 42 RemotePlayback* remotePlayback = new RemotePlayback(element); |
| 42 element.document().frame(), | |
| 43 element.isPlayingRemotely() ? WebRemotePlaybackState::Connected : WebRem
otePlaybackState::Disconnected, | |
| 44 element.hasRemoteRoutes()); | |
| 45 element.setRemotePlaybackClient(remotePlayback); | 43 element.setRemotePlaybackClient(remotePlayback); |
| 46 | 44 |
| 47 return remotePlayback; | 45 return remotePlayback; |
| 48 } | 46 } |
| 49 | 47 |
| 50 RemotePlayback::RemotePlayback(LocalFrame* frame, WebRemotePlaybackState state,
bool availability) | 48 RemotePlayback::RemotePlayback(HTMLMediaElement& element) |
| 51 : DOMWindowProperty(frame) | 49 : DOMWindowProperty(element.document().frame()) |
| 52 , m_state(state) | 50 , m_state(element.isPlayingRemotely() ? WebRemotePlaybackState::Connected :
WebRemotePlaybackState::Disconnected) |
| 53 , m_availability(availability) | 51 , m_availability(element.hasRemoteRoutes()) |
| 52 , m_mediaElement(adoptRefWillBeNoop(&element)) |
| 54 { | 53 { |
| 55 } | 54 } |
| 56 | 55 |
| 56 #if ENABLE(OILPAN) |
| 57 RemotePlayback::~RemotePlayback() = default; |
| 58 #else |
| 59 RemotePlayback::~RemotePlayback() |
| 60 { |
| 61 m_mediaElement->setRemotePlaybackClient(nullptr); |
| 62 } |
| 63 #endif |
| 64 |
| 57 const AtomicString& RemotePlayback::interfaceName() const | 65 const AtomicString& RemotePlayback::interfaceName() const |
| 58 { | 66 { |
| 59 return EventTargetNames::RemotePlayback; | 67 return EventTargetNames::RemotePlayback; |
| 60 } | 68 } |
| 61 | 69 |
| 62 ExecutionContext* RemotePlayback::getExecutionContext() const | 70 ExecutionContext* RemotePlayback::getExecutionContext() const |
| 63 { | 71 { |
| 64 if (!m_frame) | 72 if (!m_frame) |
| 65 return 0; | 73 return 0; |
| 66 return m_frame->document(); | 74 return m_frame->document(); |
| 67 } | 75 } |
| 68 | 76 |
| 69 ScriptPromise RemotePlayback::getAvailability(ScriptState* scriptState) | 77 ScriptPromise RemotePlayback::getAvailability(ScriptState* scriptState) |
| 70 { | 78 { |
| 71 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 79 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 72 ScriptPromise promise = resolver->promise(); | 80 ScriptPromise promise = resolver->promise(); |
| 73 | 81 |
| 74 // TODO(avayvod): currently the availability is tracked for each media eleme
nt | 82 // TODO(avayvod): currently the availability is tracked for each media eleme
nt |
| 75 // as soon as it's created, we probably want to limit that to when the page/
element | 83 // as soon as it's created, we probably want to limit that to when the page/
element |
| 76 // is visible (see https://crbug.com/597281) and has default controls. If th
ere's | 84 // is visible (see https://crbug.com/597281) and has default controls. If th
ere's |
| 77 // no default controls, we should also start tracking availability on demand | 85 // no default controls, we should also start tracking availability on demand |
| 78 // meaning the Promise returned by getAvailability() will be resolved asynch
ronously. | 86 // meaning the Promise returned by getAvailability() will be resolved asynch
ronously. |
| 79 RemotePlaybackAvailability* availability = RemotePlaybackAvailability::take(
resolver, m_availability); | 87 RemotePlaybackAvailability* availability = RemotePlaybackAvailability::take(
resolver, m_availability); |
| 80 m_availabilityObjects.append(availability); | 88 m_availabilityObjects.append(availability); |
| 81 resolver->resolve(availability); | 89 resolver->resolve(availability); |
| 82 return promise; | 90 return promise; |
| 83 } | 91 } |
| 84 | 92 |
| 93 ScriptPromise RemotePlayback::connect(ScriptState* scriptState) |
| 94 { |
| 95 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 96 ScriptPromise promise = resolver->promise(); |
| 97 |
| 98 // TODO(avayvod): should we have a separate flag to disable the user gesture |
| 99 // requirement (for tests) or reuse the one for the PresentationRequest::sta
rt()? |
| 100 if (!UserGestureIndicator::processingUserGesture()) { |
| 101 resolver->reject(DOMException::create(InvalidAccessError, "RemotePlaybac
k::connect() requires user gesture.")); |
| 102 return promise; |
| 103 } |
| 104 |
| 105 if (m_state == WebRemotePlaybackState::Disconnected) { |
| 106 m_connectPromiseResolvers.append(resolver); |
| 107 m_mediaElement->requestRemotePlayback(); |
| 108 } else { |
| 109 m_mediaElement->requestRemotePlaybackControl(); |
| 110 resolver->resolve(false); |
| 111 } |
| 112 |
| 113 return promise; |
| 114 } |
| 115 |
| 85 String RemotePlayback::state() const | 116 String RemotePlayback::state() const |
| 86 { | 117 { |
| 87 return remotePlaybackStateToString(m_state); | 118 return remotePlaybackStateToString(m_state); |
| 88 } | 119 } |
| 89 | 120 |
| 90 void RemotePlayback::stateChanged(WebRemotePlaybackState state) | 121 void RemotePlayback::stateChanged(WebRemotePlaybackState state) |
| 91 { | 122 { |
| 92 if (m_state == state) | 123 if (m_state == state) |
| 93 return; | 124 return; |
| 94 | 125 |
| 126 if (state != WebRemotePlaybackState::Disconnected) { |
| 127 for (auto& resolver : m_connectPromiseResolvers) |
| 128 resolver->resolve(true); |
| 129 } else { |
| 130 for (auto& resolver : m_connectPromiseResolvers) |
| 131 resolver->reject(DOMException::create(AbortError, "Failed to connect
to the remote device.")); |
| 132 } |
| 133 m_connectPromiseResolvers.clear(); |
| 134 |
| 95 m_state = state; | 135 m_state = state; |
| 96 dispatchEvent(Event::create(EventTypeNames::statechange)); | 136 dispatchEvent(Event::create(EventTypeNames::statechange)); |
| 97 } | 137 } |
| 98 | 138 |
| 99 void RemotePlayback::availabilityChanged(bool available) | 139 void RemotePlayback::availabilityChanged(bool available) |
| 100 { | 140 { |
| 101 if (m_availability == available) | 141 if (m_availability == available) |
| 102 return; | 142 return; |
| 103 | 143 |
| 104 m_availability = available; | 144 m_availability = available; |
| 105 for (auto& availabilityObject : m_availabilityObjects) | 145 for (auto& availabilityObject : m_availabilityObjects) |
| 106 availabilityObject->availabilityChanged(available); | 146 availabilityObject->availabilityChanged(available); |
| 107 } | 147 } |
| 108 | 148 |
| 109 DEFINE_TRACE(RemotePlayback) | 149 DEFINE_TRACE(RemotePlayback) |
| 110 { | 150 { |
| 111 visitor->trace(m_availabilityObjects); | 151 visitor->trace(m_availabilityObjects); |
| 152 visitor->trace(m_mediaElement); |
| 153 visitor->trace(m_connectPromiseResolvers); |
| 112 RefCountedGarbageCollectedEventTargetWithInlineData<RemotePlayback>::trace(v
isitor); | 154 RefCountedGarbageCollectedEventTargetWithInlineData<RemotePlayback>::trace(v
isitor); |
| 113 DOMWindowProperty::trace(visitor); | 155 DOMWindowProperty::trace(visitor); |
| 114 } | 156 } |
| 115 | 157 |
| 116 } // namespace blink | 158 } // namespace blink |
| OLD | NEW |