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
3 // found in the LICENSE file.
4 
5 #include "content/browser/image_capture/image_capture_impl.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/task/post_task.h"
12 #include "base/unguessable_token.h"
13 #include "content/browser/browser_main_loop.h"
14 #include "content/browser/renderer_host/media/media_stream_manager.h"
15 #include "content/browser/renderer_host/media/video_capture_manager.h"
16 #include "content/public/browser/browser_task_traits.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/common/content_features.h"
19 #include "media/base/bind_to_current_loop.h"
20 #include "media/capture/mojom/image_capture_types.h"
21 #include "media/capture/video/video_capture_device.h"
22 #include "mojo/public/cpp/bindings/callback_helpers.h"
23 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
24 #include "third_party/blink/public/common/mediastream/media_stream_request.h"
25 
26 namespace content {
27 
28 namespace {
29 
GetPhotoStateOnIOThread(const std::string & source_id,MediaStreamManager * media_stream_manager,ImageCaptureImpl::GetPhotoStateCallback callback)30 void GetPhotoStateOnIOThread(const std::string& source_id,
31                              MediaStreamManager* media_stream_manager,
32                              ImageCaptureImpl::GetPhotoStateCallback callback) {
33   DCHECK_CURRENTLY_ON(BrowserThread::IO);
34 
35   const base::UnguessableToken session_id =
36       media_stream_manager->VideoDeviceIdToSessionId(source_id);
37   if (session_id.is_empty())
38     return;
39 
40   media_stream_manager->video_capture_manager()->GetPhotoState(
41       session_id, std::move(callback));
42 }
43 
SetOptionsOnIOThread(const std::string & source_id,MediaStreamManager * media_stream_manager,media::mojom::PhotoSettingsPtr settings,ImageCaptureImpl::SetOptionsCallback callback)44 void SetOptionsOnIOThread(const std::string& source_id,
45                           MediaStreamManager* media_stream_manager,
46                           media::mojom::PhotoSettingsPtr settings,
47                           ImageCaptureImpl::SetOptionsCallback callback) {
48   DCHECK_CURRENTLY_ON(BrowserThread::IO);
49 
50   const base::UnguessableToken session_id =
51       media_stream_manager->VideoDeviceIdToSessionId(source_id);
52   if (session_id.is_empty())
53     return;
54   media_stream_manager->video_capture_manager()->SetPhotoOptions(
55       session_id, std::move(settings), std::move(callback));
56 }
57 
TakePhotoOnIOThread(const std::string & source_id,MediaStreamManager * media_stream_manager,ImageCaptureImpl::TakePhotoCallback callback)58 void TakePhotoOnIOThread(const std::string& source_id,
59                          MediaStreamManager* media_stream_manager,
60                          ImageCaptureImpl::TakePhotoCallback callback) {
61   DCHECK_CURRENTLY_ON(BrowserThread::IO);
62   TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
63                        "image_capture_impl.cc::TakePhotoOnIOThread",
64                        TRACE_EVENT_SCOPE_PROCESS);
65 
66   const base::UnguessableToken session_id =
67       media_stream_manager->VideoDeviceIdToSessionId(source_id);
68   if (session_id.is_empty())
69     return;
70 
71   media_stream_manager->video_capture_manager()->TakePhoto(session_id,
72                                                            std::move(callback));
73 }
74 
75 }  // anonymous namespace
76 
ImageCaptureImpl()77 ImageCaptureImpl::ImageCaptureImpl() {}
78 
~ImageCaptureImpl()79 ImageCaptureImpl::~ImageCaptureImpl() {}
80 
81 // static
Create(mojo::PendingReceiver<media::mojom::ImageCapture> receiver)82 void ImageCaptureImpl::Create(
83     mojo::PendingReceiver<media::mojom::ImageCapture> receiver) {
84   mojo::MakeSelfOwnedReceiver(std::make_unique<ImageCaptureImpl>(),
85                               std::move(receiver));
86 }
87 
GetPhotoState(const std::string & source_id,GetPhotoStateCallback callback)88 void ImageCaptureImpl::GetPhotoState(const std::string& source_id,
89                                      GetPhotoStateCallback callback) {
90   DCHECK_CURRENTLY_ON(BrowserThread::UI);
91   TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
92                        "ImageCaptureImpl::GetPhotoState",
93                        TRACE_EVENT_SCOPE_PROCESS);
94 
95   GetPhotoStateCallback scoped_callback =
96       mojo::WrapCallbackWithDefaultInvokeIfNotRun(
97           media::BindToCurrentLoop(std::move(callback)),
98           mojo::CreateEmptyPhotoState());
99   base::PostTask(
100       FROM_HERE, {BrowserThread::IO},
101       base::BindOnce(&GetPhotoStateOnIOThread, source_id,
102                      BrowserMainLoop::GetInstance()->media_stream_manager(),
103                      std::move(scoped_callback)));
104 }
105 
SetOptions(const std::string & source_id,media::mojom::PhotoSettingsPtr settings,SetOptionsCallback callback)106 void ImageCaptureImpl::SetOptions(const std::string& source_id,
107                                   media::mojom::PhotoSettingsPtr settings,
108                                   SetOptionsCallback callback) {
109   DCHECK_CURRENTLY_ON(BrowserThread::UI);
110   TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
111                        "ImageCaptureImpl::SetOptions",
112                        TRACE_EVENT_SCOPE_PROCESS);
113 
114   SetOptionsCallback scoped_callback =
115       mojo::WrapCallbackWithDefaultInvokeIfNotRun(
116           media::BindToCurrentLoop(std::move(callback)), false);
117   base::PostTask(
118       FROM_HERE, {BrowserThread::IO},
119       base::BindOnce(&SetOptionsOnIOThread, source_id,
120                      BrowserMainLoop::GetInstance()->media_stream_manager(),
121                      std::move(settings), std::move(scoped_callback)));
122 }
123 
TakePhoto(const std::string & source_id,TakePhotoCallback callback)124 void ImageCaptureImpl::TakePhoto(const std::string& source_id,
125                                  TakePhotoCallback callback) {
126   DCHECK_CURRENTLY_ON(BrowserThread::UI);
127   TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
128                        "ImageCaptureImpl::TakePhoto",
129                        TRACE_EVENT_SCOPE_PROCESS);
130 
131   TakePhotoCallback scoped_callback =
132       mojo::WrapCallbackWithDefaultInvokeIfNotRun(
133           media::BindToCurrentLoop(std::move(callback)),
134           media::mojom::Blob::New());
135   base::PostTask(
136       FROM_HERE, {BrowserThread::IO},
137       base::BindOnce(&TakePhotoOnIOThread, source_id,
138                      BrowserMainLoop::GetInstance()->media_stream_manager(),
139                      std::move(scoped_callback)));
140 }
141 
142 }  // namespace content
143