Chromium Code Reviews| 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/imagecapture/ImageCapture.h" | 5 #include "modules/imagecapture/ImageCapture.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/CallbackPromiseAdapter.h" | 7 #include "bindings/core/v8/CallbackPromiseAdapter.h" |
| 8 #include "bindings/core/v8/ScriptPromiseResolver.h" | 8 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| 9 #include "core/dom/DOMException.h" | 9 #include "core/dom/DOMException.h" |
| 10 #include "core/dom/ExceptionCode.h" | 10 #include "core/dom/ExceptionCode.h" |
| 11 #include "core/fileapi/Blob.h" | 11 #include "core/fileapi/Blob.h" |
| 12 #include "core/frame/ImageBitmap.h" | 12 #include "core/frame/ImageBitmap.h" |
| 13 #include "modules/EventTargetModules.h" | 13 #include "modules/EventTargetModules.h" |
| 14 #include "modules/imagecapture/MediaSettingsRange.h" | 14 #include "modules/imagecapture/MediaSettingsRange.h" |
| 15 #include "modules/imagecapture/PhotoCapabilities.h" | 15 #include "modules/imagecapture/PhotoCapabilities.h" |
| 16 #include "modules/imagecapture/PhotoSettings.h" | 16 #include "modules/imagecapture/PhotoSettings.h" |
| 17 #include "modules/mediastream/MediaStreamTrack.h" | 17 #include "modules/mediastream/MediaStreamTrack.h" |
| 18 #include "modules/mediastream/MediaTrackCapabilities.h" | 18 #include "modules/mediastream/MediaTrackCapabilities.h" |
| 19 #include "modules/mediastream/MediaTrackConstraintSet.h" | |
| 19 #include "platform/WaitableEvent.h" | 20 #include "platform/WaitableEvent.h" |
| 20 #include "platform/mojo/MojoHelper.h" | 21 #include "platform/mojo/MojoHelper.h" |
| 21 #include "public/platform/InterfaceProvider.h" | 22 #include "public/platform/InterfaceProvider.h" |
| 22 #include "public/platform/Platform.h" | 23 #include "public/platform/Platform.h" |
| 23 #include "public/platform/WebImageCaptureFrameGrabber.h" | 24 #include "public/platform/WebImageCaptureFrameGrabber.h" |
| 24 #include "public/platform/WebMediaStreamTrack.h" | 25 #include "public/platform/WebMediaStreamTrack.h" |
| 25 #include "wtf/PtrUtil.h" | 26 #include "wtf/PtrUtil.h" |
| 26 | 27 |
| 27 namespace blink { | 28 namespace blink { |
| 28 | 29 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 bool ImageCapture::hasPendingActivity() const { | 108 bool ImageCapture::hasPendingActivity() const { |
| 108 return getExecutionContext() && hasEventListeners(); | 109 return getExecutionContext() && hasEventListeners(); |
| 109 } | 110 } |
| 110 | 111 |
| 111 void ImageCapture::contextDestroyed(ExecutionContext*) { | 112 void ImageCapture::contextDestroyed(ExecutionContext*) { |
| 112 removeAllEventListeners(); | 113 removeAllEventListeners(); |
| 113 m_serviceRequests.clear(); | 114 m_serviceRequests.clear(); |
| 114 DCHECK(!hasEventListeners()); | 115 DCHECK(!hasEventListeners()); |
| 115 } | 116 } |
| 116 | 117 |
| 117 ScriptPromise ImageCapture::getPhotoCapabilities( | 118 ScriptPromise ImageCapture::getPhotoCapabilities(ScriptState* scriptState) { |
| 118 ScriptState* scriptState, | |
| 119 ExceptionState& exceptionState) { | |
| 120 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 119 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
| 121 ScriptPromise promise = resolver->promise(); | 120 ScriptPromise promise = resolver->promise(); |
| 122 | 121 |
| 123 if (!m_service) { | 122 if (!m_service) { |
| 124 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); | 123 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); |
| 125 return promise; | 124 return promise; |
| 126 } | 125 } |
| 127 | |
| 128 m_serviceRequests.insert(resolver); | 126 m_serviceRequests.insert(resolver); |
| 129 | 127 |
| 130 // m_streamTrack->component()->source()->id() is the renderer "name" of the | 128 // m_streamTrack->component()->source()->id() is the renderer "name" of the |
| 131 // camera; | 129 // camera; |
| 132 // TODO(mcasas) consider sending the security origin as well: | 130 // TODO(mcasas) consider sending the security origin as well: |
| 133 // scriptState->getExecutionContext()->getSecurityOrigin()->toString() | 131 // scriptState->getExecutionContext()->getSecurityOrigin()->toString() |
| 134 m_service->GetCapabilities( | 132 m_service->GetCapabilities( |
| 135 m_streamTrack->component()->source()->id(), | 133 m_streamTrack->component()->source()->id(), |
| 136 convertToBaseCallback(WTF::bind(&ImageCapture::onCapabilities, | 134 convertToBaseCallback(WTF::bind(&ImageCapture::onCapabilities, |
| 137 wrapPersistent(this), | 135 wrapPersistent(this), |
| 138 wrapPersistent(resolver)))); | 136 wrapPersistent(resolver)))); |
| 139 return promise; | 137 return promise; |
| 140 } | 138 } |
| 141 | 139 |
| 142 ScriptPromise ImageCapture::setOptions(ScriptState* scriptState, | 140 ScriptPromise ImageCapture::setOptions(ScriptState* scriptState, |
| 143 const PhotoSettings& photoSettings, | 141 const PhotoSettings& photoSettings) { |
| 144 ExceptionState& exceptionState) { | |
| 145 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 142 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
| 146 ScriptPromise promise = resolver->promise(); | 143 ScriptPromise promise = resolver->promise(); |
| 147 | 144 |
| 148 if (trackIsInactive(*m_streamTrack)) { | 145 if (trackIsInactive(*m_streamTrack)) { |
| 149 resolver->reject(DOMException::create( | 146 resolver->reject(DOMException::create( |
| 150 InvalidStateError, "The associated Track is in an invalid state.")); | 147 InvalidStateError, "The associated Track is in an invalid state.")); |
| 151 return promise; | 148 return promise; |
| 152 } | 149 } |
| 153 | 150 |
| 154 if (!m_service) { | 151 if (!m_service) { |
| 155 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); | 152 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); |
| 156 return promise; | 153 return promise; |
| 157 } | 154 } |
| 158 | |
| 159 m_serviceRequests.insert(resolver); | 155 m_serviceRequests.insert(resolver); |
| 160 | 156 |
| 161 // TODO(mcasas): should be using a mojo::StructTraits instead. | 157 // TODO(mcasas): should be using a mojo::StructTraits instead. |
| 162 media::mojom::blink::PhotoSettingsPtr settings = | 158 auto settings = media::mojom::blink::PhotoSettings::New(); |
| 163 media::mojom::blink::PhotoSettings::New(); | 159 |
| 164 settings->has_zoom = photoSettings.hasZoom(); | 160 settings->has_zoom = photoSettings.hasZoom(); |
| 165 if (settings->has_zoom) | 161 if (settings->has_zoom) |
| 166 settings->zoom = photoSettings.zoom(); | 162 settings->zoom = photoSettings.zoom(); |
| 167 settings->has_height = photoSettings.hasImageHeight(); | 163 settings->has_height = photoSettings.hasImageHeight(); |
| 168 if (settings->has_height) | 164 if (settings->has_height) |
| 169 settings->height = photoSettings.imageHeight(); | 165 settings->height = photoSettings.imageHeight(); |
| 170 settings->has_width = photoSettings.hasImageWidth(); | 166 settings->has_width = photoSettings.hasImageWidth(); |
| 171 if (settings->has_width) | 167 if (settings->has_width) |
| 172 settings->width = photoSettings.imageWidth(); | 168 settings->width = photoSettings.imageWidth(); |
| 173 settings->has_focus_mode = photoSettings.hasFocusMode(); | 169 settings->has_focus_mode = photoSettings.hasFocusMode(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 settings->sharpness = photoSettings.sharpness(); | 214 settings->sharpness = photoSettings.sharpness(); |
| 219 | 215 |
| 220 m_service->SetOptions(m_streamTrack->component()->source()->id(), | 216 m_service->SetOptions(m_streamTrack->component()->source()->id(), |
| 221 std::move(settings), | 217 std::move(settings), |
| 222 convertToBaseCallback(WTF::bind( | 218 convertToBaseCallback(WTF::bind( |
| 223 &ImageCapture::onSetOptions, wrapPersistent(this), | 219 &ImageCapture::onSetOptions, wrapPersistent(this), |
| 224 wrapPersistent(resolver)))); | 220 wrapPersistent(resolver)))); |
| 225 return promise; | 221 return promise; |
| 226 } | 222 } |
| 227 | 223 |
| 228 ScriptPromise ImageCapture::takePhoto(ScriptState* scriptState, | 224 ScriptPromise ImageCapture::takePhoto(ScriptState* scriptState) { |
| 229 ExceptionState& exceptionState) { | |
| 230 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 225 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
| 231 ScriptPromise promise = resolver->promise(); | 226 ScriptPromise promise = resolver->promise(); |
| 232 | 227 |
| 233 if (trackIsInactive(*m_streamTrack)) { | 228 if (trackIsInactive(*m_streamTrack)) { |
| 234 resolver->reject(DOMException::create( | 229 resolver->reject(DOMException::create( |
| 235 InvalidStateError, "The associated Track is in an invalid state.")); | 230 InvalidStateError, "The associated Track is in an invalid state.")); |
| 236 return promise; | 231 return promise; |
| 237 } | 232 } |
| 238 | |
| 239 if (!m_service) { | 233 if (!m_service) { |
| 240 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); | 234 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); |
| 241 return promise; | 235 return promise; |
| 242 } | 236 } |
| 243 | 237 |
| 244 m_serviceRequests.insert(resolver); | 238 m_serviceRequests.insert(resolver); |
| 245 | 239 |
| 246 // m_streamTrack->component()->source()->id() is the renderer "name" of the | 240 // m_streamTrack->component()->source()->id() is the renderer "name" of the |
| 247 // camera; | 241 // camera; |
| 248 // TODO(mcasas) consider sending the security origin as well: | 242 // TODO(mcasas) consider sending the security origin as well: |
| 249 // scriptState->getExecutionContext()->getSecurityOrigin()->toString() | 243 // scriptState->getExecutionContext()->getSecurityOrigin()->toString() |
| 250 m_service->TakePhoto(m_streamTrack->component()->source()->id(), | 244 m_service->TakePhoto(m_streamTrack->component()->source()->id(), |
| 251 convertToBaseCallback(WTF::bind( | 245 convertToBaseCallback(WTF::bind( |
| 252 &ImageCapture::onTakePhoto, wrapPersistent(this), | 246 &ImageCapture::onTakePhoto, wrapPersistent(this), |
| 253 wrapPersistent(resolver)))); | 247 wrapPersistent(resolver)))); |
| 254 return promise; | 248 return promise; |
| 255 } | 249 } |
| 256 | 250 |
| 257 ScriptPromise ImageCapture::grabFrame(ScriptState* scriptState, | 251 ScriptPromise ImageCapture::grabFrame(ScriptState* scriptState) { |
| 258 ExceptionState& exceptionState) { | |
| 259 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 252 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
| 260 ScriptPromise promise = resolver->promise(); | 253 ScriptPromise promise = resolver->promise(); |
| 261 | 254 |
| 262 if (trackIsInactive(*m_streamTrack)) { | 255 if (trackIsInactive(*m_streamTrack)) { |
| 263 resolver->reject(DOMException::create( | 256 resolver->reject(DOMException::create( |
| 264 InvalidStateError, "The associated Track is in an invalid state.")); | 257 InvalidStateError, "The associated Track is in an invalid state.")); |
| 265 return promise; | 258 return promise; |
| 266 } | 259 } |
| 267 | 260 |
| 268 // Create |m_frameGrabber| the first time. | 261 // Create |m_frameGrabber| the first time. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 282 m_frameGrabber->grabFrame( | 275 m_frameGrabber->grabFrame( |
| 283 &track, new CallbackPromiseAdapter<ImageBitmap, void>(resolver)); | 276 &track, new CallbackPromiseAdapter<ImageBitmap, void>(resolver)); |
| 284 | 277 |
| 285 return promise; | 278 return promise; |
| 286 } | 279 } |
| 287 | 280 |
| 288 MediaTrackCapabilities& ImageCapture::getMediaTrackCapabilities() { | 281 MediaTrackCapabilities& ImageCapture::getMediaTrackCapabilities() { |
| 289 return m_capabilities; | 282 return m_capabilities; |
| 290 } | 283 } |
| 291 | 284 |
| 285 void ImageCapture::setMediaTrackConstraints( | |
| 286 ScriptPromiseResolver* resolver, | |
|
Guido Urdaneta
2017/03/17 00:30:27
Maybe add a TODO indicating that the constraints a
mcasas
2017/03/17 00:49:22
Done.
| |
| 287 const MediaTrackConstraintSet& constraints) { | |
| 288 if (!m_service) { | |
| 289 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); | |
| 290 return; | |
| 291 } | |
| 292 m_serviceRequests.insert(resolver); | |
| 293 | |
| 294 auto settings = media::mojom::blink::PhotoSettings::New(); | |
| 295 | |
| 296 // TODO(mcasas): support other Mode types beyond simple string i.e. the | |
| 297 // equivalents of "sequence<DOMString>"" or "ConstrainDOMStringParameters". | |
| 298 settings->has_white_balance_mode = constraints.hasWhiteBalanceMode() && | |
| 299 constraints.whiteBalanceMode().isString(); | |
| 300 if (settings->has_white_balance_mode) { | |
| 301 settings->white_balance_mode = | |
| 302 parseMeteringMode(constraints.whiteBalanceMode().getAsString()); | |
| 303 } | |
| 304 settings->has_exposure_mode = | |
| 305 constraints.hasExposureMode() && constraints.exposureMode().isString(); | |
| 306 if (settings->has_exposure_mode) { | |
| 307 settings->exposure_mode = | |
| 308 parseMeteringMode(constraints.exposureMode().getAsString()); | |
| 309 } | |
| 310 | |
| 311 settings->has_focus_mode = | |
| 312 constraints.hasFocusMode() && constraints.focusMode().isString(); | |
| 313 if (settings->has_focus_mode) { | |
| 314 settings->focus_mode = | |
| 315 parseMeteringMode(constraints.focusMode().getAsString()); | |
| 316 } | |
| 317 | |
| 318 // TODO(mcasas): support ConstrainDoubleRange where applicable. | |
| 319 settings->has_exposure_compensation = | |
| 320 constraints.hasExposureCompensation() && | |
| 321 constraints.exposureCompensation().isDouble(); | |
| 322 if (settings->has_exposure_compensation) { | |
| 323 settings->exposure_compensation = | |
| 324 constraints.exposureCompensation().getAsDouble(); | |
| 325 } | |
| 326 settings->has_color_temperature = constraints.hasColorTemperature() && | |
| 327 constraints.colorTemperature().isDouble(); | |
| 328 if (settings->has_color_temperature) | |
| 329 settings->color_temperature = constraints.colorTemperature().getAsDouble(); | |
| 330 settings->has_iso = constraints.hasIso() && constraints.iso().isDouble(); | |
| 331 if (settings->has_iso) | |
| 332 settings->iso = constraints.iso().getAsDouble(); | |
| 333 | |
| 334 settings->has_brightness = | |
| 335 constraints.hasBrightness() && constraints.brightness().isDouble(); | |
| 336 if (settings->has_brightness) | |
| 337 settings->brightness = constraints.brightness().getAsDouble(); | |
| 338 settings->has_contrast = | |
| 339 constraints.hasContrast() && constraints.contrast().isDouble(); | |
| 340 if (settings->has_contrast) | |
| 341 settings->contrast = constraints.contrast().getAsDouble(); | |
| 342 settings->has_saturation = | |
| 343 constraints.hasSaturation() && constraints.saturation().isDouble(); | |
| 344 if (settings->has_saturation) | |
| 345 settings->saturation = constraints.saturation().getAsDouble(); | |
| 346 settings->has_sharpness = | |
| 347 constraints.hasSharpness() && constraints.sharpness().isDouble(); | |
| 348 if (settings->has_sharpness) | |
| 349 settings->sharpness = constraints.sharpness().getAsDouble(); | |
| 350 | |
| 351 settings->has_zoom = constraints.hasZoom() && constraints.zoom().isDouble(); | |
| 352 if (settings->has_zoom) | |
| 353 settings->zoom = constraints.zoom().getAsDouble(); | |
| 354 | |
| 355 // TODO(mcasas): add |torch| when the mojom interface is updated, | |
| 356 // https://crbug.com/700607. | |
| 357 | |
| 358 m_service->SetOptions(m_streamTrack->component()->source()->id(), | |
| 359 std::move(settings), | |
| 360 convertToBaseCallback(WTF::bind( | |
| 361 &ImageCapture::onSetOptions, wrapPersistent(this), | |
| 362 wrapPersistent(resolver)))); | |
| 363 } | |
| 364 | |
| 292 ImageCapture::ImageCapture(ExecutionContext* context, MediaStreamTrack* track) | 365 ImageCapture::ImageCapture(ExecutionContext* context, MediaStreamTrack* track) |
| 293 : ContextLifecycleObserver(context), m_streamTrack(track) { | 366 : ContextLifecycleObserver(context), m_streamTrack(track) { |
| 294 DCHECK(m_streamTrack); | 367 DCHECK(m_streamTrack); |
| 295 DCHECK(!m_service.is_bound()); | 368 DCHECK(!m_service.is_bound()); |
| 296 | 369 |
| 297 Platform::current()->interfaceProvider()->getInterface( | 370 Platform::current()->interfaceProvider()->getInterface( |
| 298 mojo::MakeRequest(&m_service)); | 371 mojo::MakeRequest(&m_service)); |
| 299 | 372 |
| 300 m_service.set_connection_error_handler(convertToBaseCallback(WTF::bind( | 373 m_service.set_connection_error_handler(convertToBaseCallback(WTF::bind( |
| 301 &ImageCapture::onServiceConnectionError, wrapWeakPersistent(this)))); | 374 &ImageCapture::onServiceConnectionError, wrapWeakPersistent(this)))); |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 444 | 517 |
| 445 DEFINE_TRACE(ImageCapture) { | 518 DEFINE_TRACE(ImageCapture) { |
| 446 visitor->trace(m_streamTrack); | 519 visitor->trace(m_streamTrack); |
| 447 visitor->trace(m_capabilities); | 520 visitor->trace(m_capabilities); |
| 448 visitor->trace(m_serviceRequests); | 521 visitor->trace(m_serviceRequests); |
| 449 EventTargetWithInlineData::trace(visitor); | 522 EventTargetWithInlineData::trace(visitor); |
| 450 ContextLifecycleObserver::trace(visitor); | 523 ContextLifecycleObserver::trace(visitor); |
| 451 } | 524 } |
| 452 | 525 |
| 453 } // namespace blink | 526 } // namespace blink |
| OLD | NEW |