Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp

Issue 1926873002: MediaStream Image Capture (3): Adding mojo and browser impl for dummy takePhoto(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: reillyg@ comments Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/ScriptPromiseResolver.h" 7 #include "bindings/core/v8/ScriptPromiseResolver.h"
8 #include "core/dom/DOMException.h" 8 #include "core/dom/DOMException.h"
9 #include "core/dom/ExceptionCode.h" 9 #include "core/dom/ExceptionCode.h"
10 #include "core/fileapi/Blob.h"
10 #include "modules/EventTargetModules.h" 11 #include "modules/EventTargetModules.h"
11 #include "modules/mediastream/MediaStreamTrack.h" 12 #include "modules/mediastream/MediaStreamTrack.h"
13 #include "platform/mojo/MojoHelper.h"
12 #include "public/platform/Platform.h" 14 #include "public/platform/Platform.h"
15 #include "public/platform/ServiceRegistry.h"
13 16
14 namespace blink { 17 namespace blink {
15 18
19 namespace {
20
21 const char kNoServiceError[] = "ImageCapture service unavailable.";
22
23 bool isActive(ScriptPromiseResolver* resolver)
24 {
25 ExecutionContext* context = resolver->getExecutionContext();
26 return context && !context->activeDOMObjectsAreStopped();
27 }
28
29 } // anonymous namespace
30
16 ImageCapture* ImageCapture::create(ExecutionContext* context, MediaStreamTrack* track, ExceptionState& exceptionState) 31 ImageCapture* ImageCapture::create(ExecutionContext* context, MediaStreamTrack* track, ExceptionState& exceptionState)
17 { 32 {
18 if (track->kind() != "video") { 33 if (track->kind() != "video") {
19 exceptionState.throwDOMException(NotSupportedError, "Cannot create an Im ageCapturer from a non-video Track."); 34 exceptionState.throwDOMException(NotSupportedError, "Cannot create an Im ageCapturer from a non-video Track.");
20 return nullptr; 35 return nullptr;
21 } 36 }
22 37
23 return new ImageCapture(context, track); 38 return new ImageCapture(context, track);
24 } 39 }
25 40
26 ImageCapture::~ImageCapture() 41 ImageCapture::~ImageCapture()
27 { 42 {
28 DCHECK(!hasEventListeners()); 43 DCHECK(!hasEventListeners());
44 // There should be no more outstanding |m_serviceRequests| at this point
45 // since each of them holds a persistent handle to this object.
46 DCHECK(m_serviceRequests.isEmpty());
29 } 47 }
30 48
31 const AtomicString& ImageCapture::interfaceName() const 49 const AtomicString& ImageCapture::interfaceName() const
32 { 50 {
33 return EventTargetNames::ImageCapture; 51 return EventTargetNames::ImageCapture;
34 } 52 }
35 53
36 ExecutionContext* ImageCapture::getExecutionContext() const 54 ExecutionContext* ImageCapture::getExecutionContext() const
37 { 55 {
38 return ContextLifecycleObserver::getExecutionContext(); 56 return ContextLifecycleObserver::getExecutionContext();
39 } 57 }
40 58
41 bool ImageCapture::hasPendingActivity() const 59 bool ImageCapture::hasPendingActivity() const
42 { 60 {
43 return hasEventListeners(); 61 return hasEventListeners();
44 } 62 }
45 63
46 void ImageCapture::contextDestroyed() 64 void ImageCapture::contextDestroyed()
47 { 65 {
48 removeAllEventListeners(); 66 removeAllEventListeners();
67 m_serviceRequests.clear();
49 DCHECK(!hasEventListeners()); 68 DCHECK(!hasEventListeners());
50 } 69 }
51 70
71 ScriptPromise ImageCapture::takePhoto(ScriptState* scriptState, ExceptionState& exceptionState)
72 {
73
74 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ;
75 ScriptPromise promise = resolver->promise();
76
77 // Spec instructs to return an exception if the track's ready state is not " live". Also reject if the track is disabled or muted.
78 if (m_streamTrack->readyState() != "live" || !m_streamTrack->enabled() || m_ streamTrack->muted()) {
79 resolver->reject(DOMException::create(InvalidStateError, "The associated Track is in an invalid state."));
80 return promise;
81 }
82
83 if (!m_service) {
84 resolver->reject(DOMException::create(NotFoundError, kNoServiceError));
85 return promise;
86 }
87
88 m_serviceRequests.add(resolver);
89
90 // m_streamTrack->component()->source()->id() is the renderer "name" of the camera;
91 // TODO(mcasas) consider sending the security origin as well:
92 // scriptState->getExecutionContext()->getSecurityOrigin()->toString()
93 m_service->TakePhoto(m_streamTrack->component()->source()->id(), createBaseC allback(bind<String, String>(&ImageCapture::onTakePhoto, this, resolver)));
94 return promise;
95 }
96
52 ScriptPromise ImageCapture::grabFrame(ScriptState* scriptState, ExceptionState& exceptionState) 97 ScriptPromise ImageCapture::grabFrame(ScriptState* scriptState, ExceptionState& exceptionState)
53 { 98 {
54 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; 99 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ;
55 ScriptPromise promise = resolver->promise(); 100 ScriptPromise promise = resolver->promise();
56 101
57 // Spec instructs to return an exception if the track's ready state is not " live". Also reject if the track is disabled or muted. 102 // Spec instructs to return an exception if the track's ready state is not " live". Also reject if the track is disabled or muted.
58 if (m_streamTrack->readyState() != "live" || !m_streamTrack->enabled() || m_ streamTrack->muted()) { 103 if (m_streamTrack->readyState() != "live" || !m_streamTrack->enabled() || m_ streamTrack->muted()) {
59 resolver->reject(DOMException::create(InvalidStateError, "The associated Track is in an invalid state.")); 104 resolver->reject(DOMException::create(InvalidStateError, "The associated Track is in an invalid state."));
60 return promise; 105 return promise;
61 } 106 }
62 107
63 resolver->reject(DOMException::create(NotSupportedError, "Not implemented ye t")); 108 resolver->reject(DOMException::create(NotSupportedError, "Not implemented ye t"));
64 return promise; 109 return promise;
65 } 110 }
66 111
67 ImageCapture::ImageCapture(ExecutionContext* context, MediaStreamTrack* track) 112 ImageCapture::ImageCapture(ExecutionContext* context, MediaStreamTrack* track)
68 : ActiveScriptWrappable(this) 113 : ActiveScriptWrappable(this)
69 , ContextLifecycleObserver(context) 114 , ContextLifecycleObserver(context)
70 , m_streamTrack(track) 115 , m_streamTrack(track)
71 { 116 {
72 DCHECK(m_streamTrack); 117 DCHECK(m_streamTrack);
118 DCHECK(!m_service.is_bound());
119
120 Platform::current()->serviceRegistry()->connectToRemoteService(mojo::GetProx y(&m_service));
121
122 m_service.set_connection_error_handler(createBaseCallback(bind(&ImageCapture ::onServiceConnectionError, WeakPersistentThisPointer<ImageCapture>(this))));
123 }
124
125 void ImageCapture::onTakePhoto(ScriptPromiseResolver* resolver, const String& mi meType, const String& data)
126 {
127 if (!isActive(resolver)) {
128 resolver->reject(DOMException::create(AbortError, "Operation was aborted "));
Reilly Grant (use Gerrit) 2016/04/28 16:19:40 If the context is inactive you don't need to resol
mcasas 2016/04/28 19:35:49 Done.
129 return;
130 }
131 WTF::CString string = data.utf8();
132 DCHECK(!string.isNull());
133 resolver->resolve(Blob::create(reinterpret_cast<unsigned char*>(string.mutab leData()), string.length(), mimeType));
134 m_serviceRequests.remove(resolver);
135 }
136
137 void ImageCapture::onServiceConnectionError()
138 {
139 m_service.reset();
140 for (ScriptPromiseResolver* resolver : m_serviceRequests) {
141 if (isActive(resolver))
haraken 2016/04/28 15:19:59 Why do we need to check isActive? The m_serviceReq
Reilly Grant (use Gerrit) 2016/04/28 15:27:56 I cargo culted this check from CallbackPromiseAdap
haraken 2016/04/28 15:45:00 I'm saying the context is guaranteed to be alive h
Reilly Grant (use Gerrit) 2016/04/28 16:19:40 Ah, I see now.
mcasas 2016/04/28 19:35:49 Remove the check for isActive() then.
142 resolver->reject(DOMException::create(NotFoundError, kNoServiceError ));
143 }
144 m_serviceRequests.clear();
73 } 145 }
74 146
75 bool ImageCapture::addEventListenerInternal(const AtomicString& eventType, Event Listener* listener, const EventListenerOptions& options) 147 bool ImageCapture::addEventListenerInternal(const AtomicString& eventType, Event Listener* listener, const EventListenerOptions& options)
76 { 148 {
77 return EventTarget::addEventListenerInternal(eventType, listener, options); 149 return EventTarget::addEventListenerInternal(eventType, listener, options);
78 } 150 }
79 151
80 DEFINE_TRACE(ImageCapture) 152 DEFINE_TRACE(ImageCapture)
81 { 153 {
82 visitor->trace(m_streamTrack); 154 visitor->trace(m_streamTrack);
155 visitor->trace(m_serviceRequests);
83 EventTargetWithInlineData::trace(visitor); 156 EventTargetWithInlineData::trace(visitor);
84 ContextLifecycleObserver::trace(visitor); 157 ContextLifecycleObserver::trace(visitor);
85 } 158 }
86 159
87 } // namespace blink 160 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698