88#include < utility>
99#include < vector>
1010
11- using base::PlatformThreadRef;
12-
1311#include " atom/common/api/atom_api_native_image.h"
1412#include " atom/common/native_mate_converters/gfx_converter.h"
1513#include " base/strings/string_number_conversions.h"
1614#include " base/strings/utf_string_conversions.h"
17- #include " base/task_scheduler/post_task.h"
18- #include " base/threading/thread_task_runner_handle.h"
19- #include " chrome/browser/media/desktop_media_list.h"
20- #include " content/public/browser/browser_thread.h"
15+ #include " base/threading/thread_restrictions.h"
16+ #include " chrome/browser/media/webrtc/desktop_media_list.h"
2117#include " content/public/browser/desktop_capture.h"
2218#include " native_mate/dictionary.h"
2319#include " third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
2420#include " third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
21+
2522#if defined(OS_WIN)
2623#include " third_party/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h"
2724#include " third_party/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
@@ -51,63 +48,121 @@ struct Converter<atom::api::DesktopCapturer::Source> {
5148
5249} // namespace mate
5350
54- namespace {
51+ namespace atom {
5552
56- void EmitFinished (
57- const std::vector<atom::api::DesktopCapturer::Source>& sources,
58- atom::api::DesktopCapturer* cap ) {
59- cap-> Emit ( " finished " , sources );
53+ namespace api {
54+
55+ DesktopCapturer::DesktopCapturer (v8::Isolate* isolate ) {
56+ Init (isolate );
6057}
6158
62- void StartHandlingTask (bool capture_window,
63- bool capture_screen,
64- const gfx::Size& thumbnail_size,
65- atom::api::DesktopCapturer* cap) {
59+ DesktopCapturer::~DesktopCapturer () {}
60+
61+ void DesktopCapturer::StartHandling (bool capture_window,
62+ bool capture_screen,
63+ const gfx::Size& thumbnail_size) {
6664#if defined(OS_WIN)
6765 if (content::desktop_capture::CreateDesktopCaptureOptions ()
6866 .allow_directx_capturer ()) {
6967 // DxgiDuplicatorController should be alive in this scope according to
7068 // screen_capturer_win.cc.
7169 auto duplicator = webrtc::DxgiDuplicatorController::Instance ();
72- cap->using_directx_capturer_ =
73- webrtc::ScreenCapturerWinDirectx::IsSupported ();
70+ using_directx_capturer_ = webrtc::ScreenCapturerWinDirectx::IsSupported ();
7471 }
7572#endif // defined(OS_WIN)
76- std::unique_ptr<webrtc::DesktopCapturer> screen_capturer (
77- capture_screen ? content::desktop_capture::CreateScreenCapturer ()
78- : nullptr );
79- std::unique_ptr<webrtc::DesktopCapturer> window_capturer (
80- capture_window ? content::desktop_capture::CreateWindowCapturer ()
81- : nullptr );
82- cap->media_list_ .reset (new NativeDesktopMediaList (
83- std::move (screen_capturer), std::move (window_capturer)));
84-
85- cap->media_list_ ->SetThumbnailSize (thumbnail_size);
86- cap->media_list_ ->StartUpdating (cap);
73+
74+ // clear any existing captured sources.
75+ captured_sources_.clear ();
76+
77+ // Start listening for captured sources.
78+ capture_window_ = capture_window;
79+ capture_screen_ = capture_screen;
80+
81+ {
82+ // Remove this once
83+ // https://bugs.chromium.org/p/chromium/issues/detail?id=795340 is fixed.
84+ base::ScopedAllowBaseSyncPrimitivesForTesting
85+ scoped_allow_base_sync_primitives;
86+ // Initialize the source list.
87+ // Apply the new thumbnail size and restart capture.
88+ if (capture_window) {
89+ window_capturer_.reset (new NativeDesktopMediaList (
90+ content::DesktopMediaID::TYPE_WINDOW,
91+ content::desktop_capture::CreateWindowCapturer ()));
92+ window_capturer_->SetThumbnailSize (thumbnail_size);
93+ window_capturer_->AddObserver (this );
94+ window_capturer_->StartUpdating ();
95+ }
96+
97+ if (capture_screen) {
98+ screen_capturer_.reset (new NativeDesktopMediaList (
99+ content::DesktopMediaID::TYPE_SCREEN,
100+ content::desktop_capture::CreateScreenCapturer ()));
101+ screen_capturer_->SetThumbnailSize (thumbnail_size);
102+ screen_capturer_->AddObserver (this );
103+ screen_capturer_->StartUpdating ();
104+ }
105+ }
106+ }
107+
108+ void DesktopCapturer::OnSourceAdded (DesktopMediaList* list, int index) {}
109+
110+ void DesktopCapturer::OnSourceRemoved (DesktopMediaList* list, int index) {}
111+
112+ void DesktopCapturer::OnSourceMoved (DesktopMediaList* list,
113+ int old_index,
114+ int new_index) {}
115+
116+ void DesktopCapturer::OnSourceNameChanged (DesktopMediaList* list, int index) {}
117+
118+ void DesktopCapturer::OnSourceThumbnailChanged (DesktopMediaList* list,
119+ int index) {}
120+
121+ void DesktopCapturer::OnSourceUnchanged (DesktopMediaList* list) {
122+ UpdateSourcesList (list);
87123}
88124
89- void OnRefreshFinishedTask (atom::api::DesktopCapturer* cap) {
90- const auto media_list_sources = cap->media_list_ ->GetSources ();
91- std::vector<atom::api::DesktopCapturer::Source> sources;
92- for (const auto & media_list_source : media_list_sources) {
93- sources.emplace_back (
94- atom::api::DesktopCapturer::Source{media_list_source, std::string ()});
125+ bool DesktopCapturer::ShouldScheduleNextRefresh (DesktopMediaList* list) {
126+ UpdateSourcesList (list);
127+ return false ;
128+ }
129+
130+ void DesktopCapturer::UpdateSourcesList (DesktopMediaList* list) {
131+ std::vector<DesktopCapturer::Source> window_sources;
132+ if (capture_window_ &&
133+ list->GetMediaListType () == content::DesktopMediaID::TYPE_WINDOW) {
134+ capture_window_ = false ;
135+ const auto & media_list_sources = list->GetSources ();
136+ for (const auto & media_list_source : media_list_sources) {
137+ window_sources.emplace_back (
138+ DesktopCapturer::Source{media_list_source, std::string ()});
139+ }
140+ std::move (window_sources.begin (), window_sources.end (),
141+ std::back_inserter (captured_sources_));
95142 }
96143
144+ std::vector<DesktopCapturer::Source> screen_sources;
145+ if (capture_screen_ &&
146+ list->GetMediaListType () == content::DesktopMediaID::TYPE_SCREEN) {
147+ capture_screen_ = false ;
148+ const auto & media_list_sources = list->GetSources ();
149+ for (const auto & media_list_source : media_list_sources) {
150+ screen_sources.emplace_back (
151+ DesktopCapturer::Source{media_list_source, std::string ()});
152+ }
97153#if defined(OS_WIN)
98- // Gather the same unique screen IDs used by the electron.screen API in order
99- // to provide an association between it and desktopCapturer/getUserMedia.
100- // This is only required when using the DirectX capturer, otherwise the IDs
101- // across the APIs already match.
102- if (cap->using_directx_capturer_ ) {
103- std::vector<std::string> device_names;
104- // Crucially, this list of device names will be in the same order as
105- // |media_list_sources|.
106- webrtc::DxgiDuplicatorController::Instance ()->GetDeviceNames (&device_names);
107- int device_name_index = 0 ;
108- for (auto & source : sources) {
109- if (source.media_list_source .id .type ==
110- content::DesktopMediaID::TYPE_SCREEN) {
154+ // Gather the same unique screen IDs used by the electron.screen API in
155+ // order to provide an association between it and
156+ // desktopCapturer/getUserMedia. This is only required when using the
157+ // DirectX capturer, otherwise the IDs across the APIs already match.
158+ if (using_directx_capturer_) {
159+ std::vector<std::string> device_names;
160+ // Crucially, this list of device names will be in the same order as
161+ // |media_list_sources|.
162+ webrtc::DxgiDuplicatorController::Instance ()->GetDeviceNames (
163+ &device_names);
164+ int device_name_index = 0 ;
165+ for (auto & source : screen_sources) {
111166 const auto & device_name = device_names[device_name_index++];
112167 std::wstring wide_device_name;
113168 base::UTF8ToWide (device_name.c_str (), device_name.size (),
@@ -118,61 +173,21 @@ void OnRefreshFinishedTask(atom::api::DesktopCapturer* cap) {
118173 source.display_id = base::Int64ToString (device_id);
119174 }
120175 }
121- }
122176#elif defined(OS_MACOSX)
123- // On Mac, the IDs across the APIs match.
124- for (auto & source : sources) {
125- if (source.media_list_source .id .type ==
126- content::DesktopMediaID::TYPE_SCREEN) {
177+ // On Mac, the IDs across the APIs match.
178+ for (auto & source : screen_sources) {
127179 source.display_id = base::Int64ToString (source.media_list_source .id .id );
128180 }
129- }
130181#endif // defined(OS_WIN)
131- // TODO(ajmacd): Add Linux support. The IDs across APIs differ but Chrome only
132- // supports capturing the entire desktop on Linux. Revisit this if individual
133- // screen support is added.
134-
135- content::BrowserThread::PostTask (content::BrowserThread::UI, FROM_HERE,
136- base::Bind (EmitFinished, sources, cap));
137- }
138-
139- } // namespace
140-
141- namespace atom {
142-
143- namespace api {
144-
145- DesktopCapturer::DesktopCapturer (v8::Isolate* isolate) {
146- Init (isolate);
147- capture_thread_ = base::CreateSequencedTaskRunnerWithTraits (
148- {base::WithBaseSyncPrimitives (), base::MayBlock (),
149- base::TaskPriority::USER_VISIBLE});
150- }
151-
152- DesktopCapturer::~DesktopCapturer () {}
153-
154- void DesktopCapturer::StartHandling (bool capture_window,
155- bool capture_screen,
156- const gfx::Size& thumbnail_size) {
157- capture_thread_->PostTask (
158- FROM_HERE, base::BindOnce (StartHandlingTask, capture_window,
159- capture_screen, thumbnail_size, this ));
160- }
161-
162- void DesktopCapturer::OnSourceAdded (int index) {}
163-
164- void DesktopCapturer::OnSourceRemoved (int index) {}
165-
166- void DesktopCapturer::OnSourceMoved (int old_index, int new_index) {}
167-
168- void DesktopCapturer::OnSourceNameChanged (int index) {}
169-
170- void DesktopCapturer::OnSourceThumbnailChanged (int index) {}
182+ // TODO(ajmacd): Add Linux support. The IDs across APIs differ but Chrome
183+ // only supports capturing the entire desktop on Linux. Revisit this if
184+ // individual screen support is added.
185+ std::move (screen_sources.begin (), screen_sources.end (),
186+ std::back_inserter (captured_sources_));
187+ }
171188
172- bool DesktopCapturer::OnRefreshFinished () {
173- capture_thread_->PostTask (FROM_HERE,
174- base::BindOnce (OnRefreshFinishedTask, this ));
175- return false ;
189+ if (!capture_window_ && !capture_screen_)
190+ Emit (" finished" , captured_sources_);
176191}
177192
178193// static
0 commit comments