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 // TODO(mcasas): make the implementation fully Spec compliant, see inside the |
| 286 // method, https://crbug.com/700607. |
| 287 void ImageCapture::setMediaTrackConstraints( |
| 288 ScriptPromiseResolver* resolver, |
| 289 const MediaTrackConstraintSet& constraints) { |
| 290 if (!m_service) { |
| 291 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); |
| 292 return; |
| 293 } |
| 294 m_serviceRequests.insert(resolver); |
| 295 |
| 296 auto settings = media::mojom::blink::PhotoSettings::New(); |
| 297 |
| 298 // TODO(mcasas): support other Mode types beyond simple string i.e. the |
| 299 // equivalents of "sequence<DOMString>"" or "ConstrainDOMStringParameters". |
| 300 settings->has_white_balance_mode = constraints.hasWhiteBalanceMode() && |
| 301 constraints.whiteBalanceMode().isString(); |
| 302 if (settings->has_white_balance_mode) { |
| 303 settings->white_balance_mode = |
| 304 parseMeteringMode(constraints.whiteBalanceMode().getAsString()); |
| 305 } |
| 306 settings->has_exposure_mode = |
| 307 constraints.hasExposureMode() && constraints.exposureMode().isString(); |
| 308 if (settings->has_exposure_mode) { |
| 309 settings->exposure_mode = |
| 310 parseMeteringMode(constraints.exposureMode().getAsString()); |
| 311 } |
| 312 |
| 313 settings->has_focus_mode = |
| 314 constraints.hasFocusMode() && constraints.focusMode().isString(); |
| 315 if (settings->has_focus_mode) { |
| 316 settings->focus_mode = |
| 317 parseMeteringMode(constraints.focusMode().getAsString()); |
| 318 } |
| 319 |
| 320 // TODO(mcasas): support ConstrainDoubleRange where applicable. |
| 321 settings->has_exposure_compensation = |
| 322 constraints.hasExposureCompensation() && |
| 323 constraints.exposureCompensation().isDouble(); |
| 324 if (settings->has_exposure_compensation) { |
| 325 settings->exposure_compensation = |
| 326 constraints.exposureCompensation().getAsDouble(); |
| 327 } |
| 328 settings->has_color_temperature = constraints.hasColorTemperature() && |
| 329 constraints.colorTemperature().isDouble(); |
| 330 if (settings->has_color_temperature) |
| 331 settings->color_temperature = constraints.colorTemperature().getAsDouble(); |
| 332 settings->has_iso = constraints.hasIso() && constraints.iso().isDouble(); |
| 333 if (settings->has_iso) |
| 334 settings->iso = constraints.iso().getAsDouble(); |
| 335 |
| 336 settings->has_brightness = |
| 337 constraints.hasBrightness() && constraints.brightness().isDouble(); |
| 338 if (settings->has_brightness) |
| 339 settings->brightness = constraints.brightness().getAsDouble(); |
| 340 settings->has_contrast = |
| 341 constraints.hasContrast() && constraints.contrast().isDouble(); |
| 342 if (settings->has_contrast) |
| 343 settings->contrast = constraints.contrast().getAsDouble(); |
| 344 settings->has_saturation = |
| 345 constraints.hasSaturation() && constraints.saturation().isDouble(); |
| 346 if (settings->has_saturation) |
| 347 settings->saturation = constraints.saturation().getAsDouble(); |
| 348 settings->has_sharpness = |
| 349 constraints.hasSharpness() && constraints.sharpness().isDouble(); |
| 350 if (settings->has_sharpness) |
| 351 settings->sharpness = constraints.sharpness().getAsDouble(); |
| 352 |
| 353 settings->has_zoom = constraints.hasZoom() && constraints.zoom().isDouble(); |
| 354 if (settings->has_zoom) |
| 355 settings->zoom = constraints.zoom().getAsDouble(); |
| 356 |
| 357 // TODO(mcasas): add |torch| when the mojom interface is updated, |
| 358 // https://crbug.com/700607. |
| 359 |
| 360 m_service->SetOptions(m_streamTrack->component()->source()->id(), |
| 361 std::move(settings), |
| 362 convertToBaseCallback(WTF::bind( |
| 363 &ImageCapture::onSetOptions, wrapPersistent(this), |
| 364 wrapPersistent(resolver)))); |
| 365 } |
| 366 |
292 ImageCapture::ImageCapture(ExecutionContext* context, MediaStreamTrack* track) | 367 ImageCapture::ImageCapture(ExecutionContext* context, MediaStreamTrack* track) |
293 : ContextLifecycleObserver(context), m_streamTrack(track) { | 368 : ContextLifecycleObserver(context), m_streamTrack(track) { |
294 DCHECK(m_streamTrack); | 369 DCHECK(m_streamTrack); |
295 DCHECK(!m_service.is_bound()); | 370 DCHECK(!m_service.is_bound()); |
296 | 371 |
297 Platform::current()->interfaceProvider()->getInterface( | 372 Platform::current()->interfaceProvider()->getInterface( |
298 mojo::MakeRequest(&m_service)); | 373 mojo::MakeRequest(&m_service)); |
299 | 374 |
300 m_service.set_connection_error_handler(convertToBaseCallback(WTF::bind( | 375 m_service.set_connection_error_handler(convertToBaseCallback(WTF::bind( |
301 &ImageCapture::onServiceConnectionError, wrapWeakPersistent(this)))); | 376 &ImageCapture::onServiceConnectionError, wrapWeakPersistent(this)))); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 | 519 |
445 DEFINE_TRACE(ImageCapture) { | 520 DEFINE_TRACE(ImageCapture) { |
446 visitor->trace(m_streamTrack); | 521 visitor->trace(m_streamTrack); |
447 visitor->trace(m_capabilities); | 522 visitor->trace(m_capabilities); |
448 visitor->trace(m_serviceRequests); | 523 visitor->trace(m_serviceRequests); |
449 EventTargetWithInlineData::trace(visitor); | 524 EventTargetWithInlineData::trace(visitor); |
450 ContextLifecycleObserver::trace(visitor); | 525 ContextLifecycleObserver::trace(visitor); |
451 } | 526 } |
452 | 527 |
453 } // namespace blink | 528 } // namespace blink |
OLD | NEW |