| 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 #if !ENABLE(OILPAN) |
| 53 , m_mediaElement(element.createWeakPtr()) |
| 54 #else |
| 55 , m_mediaElement(&element) |
| 56 #endif |
| 54 { | 57 { |
| 55 } | 58 } |
| 56 | 59 |
| 60 #if ENABLE(OILPAN) |
| 61 RemotePlayback::~RemotePlayback() = default; |
| 62 #else |
| 63 RemotePlayback::~RemotePlayback() |
| 64 { |
| 65 m_mediaElement->setRemotePlaybackClient(nullptr); |
| 66 } |
| 67 #endif |
| 68 |
| 57 const AtomicString& RemotePlayback::interfaceName() const | 69 const AtomicString& RemotePlayback::interfaceName() const |
| 58 { | 70 { |
| 59 return EventTargetNames::RemotePlayback; | 71 return EventTargetNames::RemotePlayback; |
| 60 } | 72 } |
| 61 | 73 |
| 62 ExecutionContext* RemotePlayback::getExecutionContext() const | 74 ExecutionContext* RemotePlayback::getExecutionContext() const |
| 63 { | 75 { |
| 64 if (!m_frame) | 76 if (!m_frame) |
| 65 return 0; | 77 return 0; |
| 66 return m_frame->document(); | 78 return m_frame->document(); |
| 67 } | 79 } |
| 68 | 80 |
| 69 ScriptPromise RemotePlayback::getAvailability(ScriptState* scriptState) | 81 ScriptPromise RemotePlayback::getAvailability(ScriptState* scriptState) |
| 70 { | 82 { |
| 71 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 83 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 72 ScriptPromise promise = resolver->promise(); | 84 ScriptPromise promise = resolver->promise(); |
| 73 | 85 |
| 74 // TODO(avayvod): currently the availability is tracked for each media eleme
nt | 86 // 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 | 87 // 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 | 88 // 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 | 89 // no default controls, we should also start tracking availability on demand |
| 78 // meaning the Promise returned by getAvailability() will be resolved asynch
ronously. | 90 // meaning the Promise returned by getAvailability() will be resolved asynch
ronously. |
| 79 RemotePlaybackAvailability* availability = RemotePlaybackAvailability::take(
resolver, m_availability); | 91 RemotePlaybackAvailability* availability = RemotePlaybackAvailability::take(
resolver, m_availability); |
| 80 m_availabilityObjects.append(availability); | 92 m_availabilityObjects.append(availability); |
| 81 resolver->resolve(availability); | 93 resolver->resolve(availability); |
| 82 return promise; | 94 return promise; |
| 83 } | 95 } |
| 84 | 96 |
| 97 ScriptPromise RemotePlayback::connect(ScriptState* scriptState) |
| 98 { |
| 99 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 100 ScriptPromise promise = resolver->promise(); |
| 101 |
| 102 // TODO(avayvod): should we have a separate flag to disable the user gesture |
| 103 // requirement (for tests) or reuse the one for the PresentationRequest::sta
rt()? |
| 104 if (!UserGestureIndicator::processingUserGesture()) { |
| 105 resolver->reject(DOMException::create(InvalidAccessError, "RemotePlaybac
k::connect() requires user gesture.")); |
| 106 return promise; |
| 107 } |
| 108 |
| 109 if (m_state == WebRemotePlaybackState::Disconnected) { |
| 110 m_connectPromiseResolvers.append(resolver); |
| 111 m_mediaElement->requestRemotePlayback(); |
| 112 } else { |
| 113 m_mediaElement->requestRemotePlaybackControl(); |
| 114 resolver->resolve(false); |
| 115 } |
| 116 |
| 117 return promise; |
| 118 } |
| 119 |
| 85 String RemotePlayback::state() const | 120 String RemotePlayback::state() const |
| 86 { | 121 { |
| 87 return remotePlaybackStateToString(m_state); | 122 return remotePlaybackStateToString(m_state); |
| 88 } | 123 } |
| 89 | 124 |
| 90 void RemotePlayback::stateChanged(WebRemotePlaybackState state) | 125 void RemotePlayback::stateChanged(WebRemotePlaybackState state) |
| 91 { | 126 { |
| 127 // We may get a "disconnected" state change while in the "disconnected" |
| 128 // state if initiated connection fails. So cleanup the promise resolvers |
| 129 // before checking if anything changed. |
| 130 // TODO(avayvod): cleanup this logic when we implementing the "connecting" |
| 131 // state. |
| 132 if (state != WebRemotePlaybackState::Disconnected) { |
| 133 for (auto& resolver : m_connectPromiseResolvers) |
| 134 resolver->resolve(true); |
| 135 } else { |
| 136 for (auto& resolver : m_connectPromiseResolvers) |
| 137 resolver->reject(DOMException::create(AbortError, "Failed to connect
to the remote device.")); |
| 138 } |
| 139 m_connectPromiseResolvers.clear(); |
| 140 |
| 92 if (m_state == state) | 141 if (m_state == state) |
| 93 return; | 142 return; |
| 94 | 143 |
| 95 m_state = state; | 144 m_state = state; |
| 96 dispatchEvent(Event::create(EventTypeNames::statechange)); | 145 dispatchEvent(Event::create(EventTypeNames::statechange)); |
| 97 } | 146 } |
| 98 | 147 |
| 99 void RemotePlayback::availabilityChanged(bool available) | 148 void RemotePlayback::availabilityChanged(bool available) |
| 100 { | 149 { |
| 101 if (m_availability == available) | 150 if (m_availability == available) |
| 102 return; | 151 return; |
| 103 | 152 |
| 104 m_availability = available; | 153 m_availability = available; |
| 105 for (auto& availabilityObject : m_availabilityObjects) | 154 for (auto& availabilityObject : m_availabilityObjects) |
| 106 availabilityObject->availabilityChanged(available); | 155 availabilityObject->availabilityChanged(available); |
| 107 } | 156 } |
| 108 | 157 |
| 109 DEFINE_TRACE(RemotePlayback) | 158 DEFINE_TRACE(RemotePlayback) |
| 110 { | 159 { |
| 111 visitor->trace(m_availabilityObjects); | 160 visitor->trace(m_availabilityObjects); |
| 161 visitor->trace(m_mediaElement); |
| 162 visitor->trace(m_connectPromiseResolvers); |
| 112 RefCountedGarbageCollectedEventTargetWithInlineData<RemotePlayback>::trace(v
isitor); | 163 RefCountedGarbageCollectedEventTargetWithInlineData<RemotePlayback>::trace(v
isitor); |
| 113 DOMWindowProperty::trace(visitor); | 164 DOMWindowProperty::trace(visitor); |
| 114 } | 165 } |
| 115 | 166 |
| 116 } // namespace blink | 167 } // namespace blink |
| OLD | NEW |