| 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 "bindings/modules/v8/RemotePlaybackAvailabilityCallback.h" | 8 #include "bindings/modules/v8/RemotePlaybackAvailabilityCallback.h" |
| 9 #include "core/HTMLNames.h" | 9 #include "core/HTMLNames.h" |
| 10 #include "core/dom/DOMException.h" | 10 #include "core/dom/DOMException.h" |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 } | 38 } |
| 39 | 39 |
| 40 } // anonymous namespace | 40 } // anonymous namespace |
| 41 | 41 |
| 42 // static | 42 // static |
| 43 RemotePlayback* RemotePlayback::create(ScriptState* scriptState, | 43 RemotePlayback* RemotePlayback::create(ScriptState* scriptState, |
| 44 HTMLMediaElement& element) { | 44 HTMLMediaElement& element) { |
| 45 DCHECK(element.document().frame()); | 45 DCHECK(element.document().frame()); |
| 46 DCHECK(scriptState); | 46 DCHECK(scriptState); |
| 47 | 47 |
| 48 RemotePlayback* remotePlayback = new RemotePlayback(scriptState, element); | 48 return new RemotePlayback(scriptState, element); |
| 49 element.setRemotePlaybackClient(remotePlayback); | |
| 50 | |
| 51 return remotePlayback; | |
| 52 } | 49 } |
| 53 | 50 |
| 54 RemotePlayback::RemotePlayback(ScriptState* scriptState, | 51 RemotePlayback::RemotePlayback(ScriptState* scriptState, |
| 55 HTMLMediaElement& element) | 52 HTMLMediaElement& element) |
| 56 : ActiveScriptWrappable(this), | 53 : ActiveScriptWrappable(this), |
| 57 m_scriptState(scriptState), | 54 m_scriptState(scriptState), |
| 58 m_state(element.isPlayingRemotely() | 55 m_state(element.isPlayingRemotely() |
| 59 ? WebRemotePlaybackState::Connected | 56 ? WebRemotePlaybackState::Connected |
| 60 : WebRemotePlaybackState::Disconnected), | 57 : WebRemotePlaybackState::Disconnected), |
| 61 m_availability(element.hasRemoteRoutes()), | 58 m_routeAvailable(false), |
| 59 m_sourceCompatible(false), |
| 62 m_mediaElement(&element) {} | 60 m_mediaElement(&element) {} |
| 63 | 61 |
| 64 const AtomicString& RemotePlayback::interfaceName() const { | 62 const AtomicString& RemotePlayback::interfaceName() const { |
| 65 return EventTargetNames::RemotePlayback; | 63 return EventTargetNames::RemotePlayback; |
| 66 } | 64 } |
| 67 | 65 |
| 68 ExecutionContext* RemotePlayback::getExecutionContext() const { | 66 ExecutionContext* RemotePlayback::getExecutionContext() const { |
| 69 return &m_mediaElement->document(); | 67 return &m_mediaElement->document(); |
| 70 } | 68 } |
| 71 | 69 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 "A prompt is already being shown for this media element.")); | 166 "A prompt is already being shown for this media element.")); |
| 169 return promise; | 167 return promise; |
| 170 } | 168 } |
| 171 | 169 |
| 172 if (!UserGestureIndicator::utilizeUserGesture()) { | 170 if (!UserGestureIndicator::utilizeUserGesture()) { |
| 173 resolver->reject(DOMException::create( | 171 resolver->reject(DOMException::create( |
| 174 InvalidAccessError, "RemotePlayback::prompt() requires user gesture.")); | 172 InvalidAccessError, "RemotePlayback::prompt() requires user gesture.")); |
| 175 return promise; | 173 return promise; |
| 176 } | 174 } |
| 177 | 175 |
| 176 // TODO(avayvod): don't do this check on low-end devices - merge with |
| 177 // https://codereview.chromium.org/2475293003 |
| 178 if (!m_routeAvailable) { |
| 179 resolver->reject(DOMException::create(NotFoundError, |
| 180 "No remote playback devices found.")); |
| 181 return promise; |
| 182 } |
| 183 |
| 184 if (!m_sourceCompatible) { |
| 185 resolver->reject(DOMException::create( |
| 186 NotSupportedError, |
| 187 "The currentSrc is not compatible with remote playback")); |
| 188 return promise; |
| 189 } |
| 190 |
| 178 if (m_state == WebRemotePlaybackState::Disconnected) { | 191 if (m_state == WebRemotePlaybackState::Disconnected) { |
| 179 m_promptPromiseResolver = resolver; | 192 m_promptPromiseResolver = resolver; |
| 180 m_mediaElement->requestRemotePlayback(); | 193 m_mediaElement->requestRemotePlayback(); |
| 181 } else { | 194 } else { |
| 182 m_promptPromiseResolver = resolver; | 195 m_promptPromiseResolver = resolver; |
| 183 m_mediaElement->requestRemotePlaybackControl(); | 196 m_mediaElement->requestRemotePlaybackControl(); |
| 184 } | 197 } |
| 185 | 198 |
| 186 return promise; | 199 return promise; |
| 187 } | 200 } |
| 188 | 201 |
| 189 String RemotePlayback::state() const { | 202 String RemotePlayback::state() const { |
| 190 return remotePlaybackStateToString(m_state); | 203 return remotePlaybackStateToString(m_state); |
| 191 } | 204 } |
| 192 | 205 |
| 193 bool RemotePlayback::hasPendingActivity() const { | 206 bool RemotePlayback::hasPendingActivity() const { |
| 194 return hasEventListeners() || !m_availabilityCallbacks.isEmpty() || | 207 return hasEventListeners() || !m_availabilityCallbacks.isEmpty() || |
| 195 m_promptPromiseResolver; | 208 m_promptPromiseResolver; |
| 196 } | 209 } |
| 197 | 210 |
| 198 void RemotePlayback::notifyInitialAvailability(int callbackId) { | 211 void RemotePlayback::notifyInitialAvailability(int callbackId) { |
| 199 // May not find the callback if the website cancels it fast enough. | 212 // May not find the callback if the website cancels it fast enough. |
| 200 auto iter = m_availabilityCallbacks.find(callbackId); | 213 auto iter = m_availabilityCallbacks.find(callbackId); |
| 201 if (iter == m_availabilityCallbacks.end()) | 214 if (iter == m_availabilityCallbacks.end()) |
| 202 return; | 215 return; |
| 203 | 216 |
| 204 iter->value->call(this, m_availability); | 217 iter->value->call(this, m_routeAvailable && m_sourceCompatible); |
| 205 } | 218 } |
| 206 | 219 |
| 207 void RemotePlayback::stateChanged(WebRemotePlaybackState state) { | 220 void RemotePlayback::stateChanged(WebRemotePlaybackState state) { |
| 208 if (m_state == state) | 221 if (m_state == state) |
| 209 return; | 222 return; |
| 210 | 223 |
| 211 if (m_promptPromiseResolver) { | 224 if (m_promptPromiseResolver) { |
| 212 // Changing state to Disconnected from "disconnected" or "connecting" means | 225 // Changing state to Disconnected from "disconnected" or "connecting" means |
| 213 // that establishing connection with remote playback device failed. | 226 // that establishing connection with remote playback device failed. |
| 214 // Changing state to anything else means the state change intended by | 227 // Changing state to anything else means the state change intended by |
| (...skipping 19 matching lines...) Expand all Loading... |
| 234 break; | 247 break; |
| 235 case WebRemotePlaybackState::Connected: | 248 case WebRemotePlaybackState::Connected: |
| 236 dispatchEvent(Event::create(EventTypeNames::connect)); | 249 dispatchEvent(Event::create(EventTypeNames::connect)); |
| 237 break; | 250 break; |
| 238 case WebRemotePlaybackState::Disconnected: | 251 case WebRemotePlaybackState::Disconnected: |
| 239 dispatchEvent(Event::create(EventTypeNames::disconnect)); | 252 dispatchEvent(Event::create(EventTypeNames::disconnect)); |
| 240 break; | 253 break; |
| 241 } | 254 } |
| 242 } | 255 } |
| 243 | 256 |
| 244 void RemotePlayback::availabilityChanged(bool available) { | 257 void RemotePlayback::availabilityChanged(bool isRouteAvailable, |
| 245 if (m_availability == available) | 258 bool isSourceCompatible) { |
| 259 if (m_routeAvailable == isRouteAvailable && |
| 260 m_sourceCompatible == isSourceCompatible) { |
| 261 return; |
| 262 } |
| 263 |
| 264 bool oldAvailability = m_routeAvailable && m_sourceCompatible; |
| 265 m_routeAvailable = isRouteAvailable; |
| 266 m_sourceCompatible = isSourceCompatible; |
| 267 |
| 268 bool newAvailability = isRouteAvailable && isSourceCompatible; |
| 269 if (newAvailability == oldAvailability) |
| 246 return; | 270 return; |
| 247 | 271 |
| 248 m_availability = available; | |
| 249 for (auto& callback : m_availabilityCallbacks.values()) | 272 for (auto& callback : m_availabilityCallbacks.values()) |
| 250 callback->call(this, m_availability); | 273 callback->call(this, newAvailability); |
| 251 } | 274 } |
| 252 | 275 |
| 253 void RemotePlayback::promptCancelled() { | 276 void RemotePlayback::promptCancelled() { |
| 254 if (!m_promptPromiseResolver) | 277 if (!m_promptPromiseResolver) |
| 255 return; | 278 return; |
| 256 | 279 |
| 257 m_promptPromiseResolver->reject( | 280 m_promptPromiseResolver->reject( |
| 258 DOMException::create(NotAllowedError, "The prompt was dismissed.")); | 281 DOMException::create(NotAllowedError, "The prompt was dismissed.")); |
| 259 m_promptPromiseResolver = nullptr; | 282 m_promptPromiseResolver = nullptr; |
| 260 } | 283 } |
| 261 | 284 |
| 285 bool RemotePlayback::remotePlaybackAvailable() const { |
| 286 return m_routeAvailable && m_sourceCompatible; |
| 287 } |
| 288 |
| 262 void RemotePlayback::remotePlaybackDisabled() { | 289 void RemotePlayback::remotePlaybackDisabled() { |
| 263 if (m_promptPromiseResolver) { | 290 if (m_promptPromiseResolver) { |
| 264 m_promptPromiseResolver->reject(DOMException::create( | 291 m_promptPromiseResolver->reject(DOMException::create( |
| 265 InvalidStateError, "disableRemotePlayback attribute is present.")); | 292 InvalidStateError, "disableRemotePlayback attribute is present.")); |
| 266 m_promptPromiseResolver = nullptr; | 293 m_promptPromiseResolver = nullptr; |
| 267 } | 294 } |
| 268 | 295 |
| 269 m_availabilityCallbacks.clear(); | 296 m_availabilityCallbacks.clear(); |
| 270 | 297 |
| 271 if (m_state != WebRemotePlaybackState::Disconnected) | 298 if (m_state != WebRemotePlaybackState::Disconnected) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 287 } | 314 } |
| 288 | 315 |
| 289 DEFINE_TRACE_WRAPPERS(RemotePlayback) { | 316 DEFINE_TRACE_WRAPPERS(RemotePlayback) { |
| 290 for (auto callback : m_availabilityCallbacks.values()) { | 317 for (auto callback : m_availabilityCallbacks.values()) { |
| 291 visitor->traceWrappers(callback); | 318 visitor->traceWrappers(callback); |
| 292 } | 319 } |
| 293 EventTargetWithInlineData::traceWrappers(visitor); | 320 EventTargetWithInlineData::traceWrappers(visitor); |
| 294 } | 321 } |
| 295 | 322 |
| 296 } // namespace blink | 323 } // namespace blink |
| OLD | NEW |