Skip to content

Commit 261f07c

Browse files
committed
[Screen Selection] OSX and Win implementation
Squashed commits: [4606c6c] [Screen Selection] [OSX] initial implementation
1 parent 0ca1642 commit 261f07c

File tree

7 files changed

+420
-14
lines changed

7 files changed

+420
-14
lines changed

nw.gypi

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@
8181
'<(DEPTH)/ui/resources/ui_resources.gyp:ui_resources',
8282
'<(DEPTH)/url/url.gyp:url_lib',
8383
'<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
84+
'<(DEPTH)/third_party/libyuv/libyuv.gyp:libyuv',
85+
'<(DEPTH)/third_party/webrtc/modules/modules.gyp:desktop_capture',
8486
'<(DEPTH)/third_party/zlib/zlib.gyp:minizip',
8587
'<(DEPTH)/third_party/WebKit/public/blink.gyp:blink',
8688
'<(DEPTH)/extensions/browser/api/api_registration.gyp:extensions_api_registration',
@@ -203,6 +205,13 @@
203205
'src/api/dispatcher_host.h',
204206
'src/api/event/event.h',
205207
'src/api/event/event.cc',
208+
'src/api/screen/desktop_capture_api.h',
209+
'src/api/screen/desktop_capture_api.cc',
210+
'<(DEPTH)/chrome/browser/media/desktop_media_list.h',
211+
'<(DEPTH)/chrome/browser/media/desktop_media_list_observer.h',
212+
'<(DEPTH)/chrome/browser/media/desktop_media_picker.h',
213+
'<(DEPTH)/chrome/browser/media/native_desktop_media_list.h',
214+
'<(DEPTH)/chrome/browser/media/native_desktop_media_list.cc',
206215
'src/api/screen/screen.h',
207216
'src/api/screen/screen.cc',
208217
'src/api/window_bindings.cc',
@@ -471,6 +480,8 @@
471480
}],
472481
['use_aura==1', {
473482
'sources': [
483+
'<(DEPTH)/chrome/browser/ui/views/desktop_media_picker_views.cc',
484+
'<(DEPTH)/chrome/browser/ui/views/desktop_media_picker_views.h',
474485
'<(DEPTH)/chrome/browser/ui/views/web_contents_modal_dialog_manager_views.cc',
475486
'src/browser/login_view.cc',
476487
'src/browser/login_view.h',
@@ -536,11 +547,20 @@
536547
],
537548
'sources': [
538549
#'<(DEPTH)/chrome/browser/ui/cocoa/web_contents_modal_dialog_manager_cocoa.mm',
550+
'<(DEPTH)/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_bridge.h',
551+
'<(DEPTH)/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_bridge.mm',
552+
'<(DEPTH)/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.h',
553+
'<(DEPTH)/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.mm',
554+
'<(DEPTH)/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.h',
555+
'<(DEPTH)/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm',
556+
'<(DEPTH)/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.h',
557+
'<(DEPTH)/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.mm',
539558
'src/browser/shell_web_contents_modal_dialog_manager.cc',
540559
],
541560
'dependencies': [
542561
'<(DEPTH)/breakpad/breakpad.gyp:breakpad',
543562
'<(DEPTH)/components/components.gyp:crash_component',
563+
'<(DEPTH)/third_party/google_toolbox_for_mac/google_toolbox_for_mac.gyp:google_toolbox_for_mac',
544564
],
545565
'link_settings': {
546566
'libraries': [
@@ -747,6 +767,7 @@
747767
'action_name': 'repack_nw_pack',
748768
'variables': {
749769
'pak_inputs': [
770+
'<(SHARED_INTERMEDIATE_DIR)/chrome/generated_resources_en-US.pak',
750771
'<(SHARED_INTERMEDIATE_DIR)/content/content_resources.pak',
751772
'<(SHARED_INTERMEDIATE_DIR)/content/nw_resources.pak',
752773
'<(SHARED_INTERMEDIATE_DIR)/content/nw_components.pak',
@@ -1195,6 +1216,13 @@
11951216
'src/shell_content_main.h',
11961217
],
11971218
'xcode_settings': { 'OTHER_LDFLAGS': [ '-Wl,-force_load,libnode.a' ], },
1219+
'link_settings': {
1220+
'xcode_settings': {
1221+
'OTHER_LDFLAGS': [
1222+
'-framework Quartz',
1223+
],
1224+
},
1225+
},
11981226
'copies': [
11991227
{
12001228
# Copy FFmpeg binaries for audio/video support.

src/api/screen/desktop_capture_api.cc

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
// Copyright 2013 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/nw/src/api/screen/desktop_capture_api.h"
6+
7+
#include "base/command_line.h"
8+
#include "base/compiler_specific.h"
9+
#include "base/strings/utf_string_conversions.h"
10+
#include "chrome/browser/media/native_desktop_media_list.h"
11+
#include "content/public/browser/render_frame_host.h"
12+
#include "content/public/browser/render_process_host.h"
13+
#include "content/public/browser/render_view_host.h"
14+
#include "content/public/browser/web_contents.h"
15+
#include "net/base/net_util.h"
16+
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
17+
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
18+
#include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
19+
20+
namespace nwapi {
21+
22+
namespace {
23+
24+
const char kEmptySourcesListError[] =
25+
"At least one source type must be specified.";
26+
27+
DesktopCaptureChooseDesktopMediaFunction::PickerFactory* g_picker_factory =
28+
NULL;
29+
30+
} // namespace
31+
32+
// static
33+
void DesktopCaptureChooseDesktopMediaFunction::SetPickerFactoryForTests(
34+
PickerFactory* factory) {
35+
g_picker_factory = factory;
36+
}
37+
38+
DesktopCaptureChooseDesktopMediaFunction::
39+
DesktopCaptureChooseDesktopMediaFunction() {
40+
}
41+
42+
DesktopCaptureChooseDesktopMediaFunction::
43+
~DesktopCaptureChooseDesktopMediaFunction() {
44+
// RenderViewHost may be already destroyed.
45+
if (render_view_host()) {
46+
DesktopCaptureRequestsRegistry::GetInstance()->RemoveRequest(
47+
render_view_host()->GetProcess()->GetID(), request_id_);
48+
}
49+
}
50+
51+
void DesktopCaptureChooseDesktopMediaFunction::Cancel() {
52+
// Keep reference to |this| to ensure the object doesn't get destroyed before
53+
// we return.
54+
scoped_refptr<DesktopCaptureChooseDesktopMediaFunction> self(this);
55+
if (picker_) {
56+
picker_.reset();
57+
SetResult(new base::StringValue(std::string()));
58+
SendResponse(true);
59+
}
60+
}
61+
62+
bool DesktopCaptureChooseDesktopMediaFunction::RunSync() {
63+
64+
DesktopCaptureRequestsRegistry::GetInstance()->AddRequest(
65+
render_view_host()->GetProcess()->GetID(), request_id_, this);
66+
67+
// |web_contents| is the WebContents for which the stream is created, and will
68+
// also be used to determine where to show the picker's UI.
69+
content::WebContents* web_contents = content::WebContents::FromRenderViewHost(render_view_host());
70+
DCHECK(web_contents);
71+
base::string16 target_name;
72+
73+
// Register to be notified when the tab is closed.
74+
Observe(web_contents);
75+
76+
bool show_screens = false;
77+
bool show_windows = false;
78+
79+
const base::ListValue* capture_param = NULL;
80+
if(args_->GetList(1,&capture_param)) {
81+
for(base::ListValue::const_iterator i = capture_param->begin(); i != capture_param->end(); i++) {
82+
const base::Value* val = static_cast<const base::Value*>(*i);
83+
std::string str;
84+
if(val->GetAsString(&str)) {
85+
if(!str.compare("window")) {
86+
show_windows = true;
87+
continue;
88+
}
89+
90+
if(!str.compare("screen")) {
91+
show_screens = true;
92+
continue;
93+
}
94+
}
95+
}
96+
}
97+
98+
if (!show_screens && !show_windows) {
99+
error_ = kEmptySourcesListError;
100+
return false;
101+
}
102+
103+
const gfx::NativeWindow parent_window =
104+
web_contents->GetTopLevelNativeWindow();
105+
scoped_ptr<DesktopMediaList> media_list;
106+
if (g_picker_factory) {
107+
media_list = g_picker_factory->CreateModel(
108+
show_screens, show_windows);
109+
picker_ = g_picker_factory->CreatePicker();
110+
} else {
111+
{
112+
webrtc::DesktopCaptureOptions options =
113+
webrtc::DesktopCaptureOptions::CreateDefault();
114+
options.set_disable_effects(false);
115+
scoped_ptr<webrtc::ScreenCapturer> screen_capturer(
116+
show_screens ? webrtc::ScreenCapturer::Create(options) : NULL);
117+
scoped_ptr<webrtc::WindowCapturer> window_capturer(
118+
show_windows ? webrtc::WindowCapturer::Create(options) : NULL);
119+
120+
media_list.reset(new NativeDesktopMediaList(
121+
screen_capturer.Pass(), window_capturer.Pass()));
122+
}
123+
124+
// DesktopMediaPicker is implemented only for Windows, OSX and
125+
// Aura Linux builds.
126+
#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
127+
picker_ = DesktopMediaPicker::Create();
128+
#else
129+
error_ = "Desktop Capture API is not yet implemented for this platform.";
130+
return false;
131+
#endif
132+
}
133+
DesktopMediaPicker::DoneCallback callback = base::Bind(
134+
&DesktopCaptureChooseDesktopMediaFunction::OnPickerDialogResults, this);
135+
136+
picker_->Show(web_contents,
137+
parent_window,
138+
parent_window,
139+
target_name,
140+
target_name,
141+
media_list.Pass(),
142+
callback);
143+
return true;
144+
}
145+
146+
void DesktopCaptureChooseDesktopMediaFunction::WebContentsDestroyed() {
147+
Cancel();
148+
}
149+
150+
void DesktopCaptureChooseDesktopMediaFunction::OnPickerDialogResults(
151+
content::DesktopMediaID source) {
152+
std::string result;
153+
if (source.type != content::DesktopMediaID::TYPE_NONE &&
154+
web_contents()) {
155+
result = source.ToString();
156+
}
157+
158+
SetResult(new base::StringValue(result));
159+
SendResponse(true);
160+
}
161+
162+
DesktopCaptureRequestsRegistry::RequestId::RequestId(int process_id,
163+
int request_id)
164+
: process_id(process_id),
165+
request_id(request_id) {
166+
}
167+
168+
bool DesktopCaptureRequestsRegistry::RequestId::operator<(
169+
const RequestId& other) const {
170+
if (process_id != other.process_id) {
171+
return process_id < other.process_id;
172+
} else {
173+
return request_id < other.request_id;
174+
}
175+
}
176+
177+
DesktopCaptureCancelChooseDesktopMediaFunction::
178+
DesktopCaptureCancelChooseDesktopMediaFunction() {}
179+
180+
DesktopCaptureCancelChooseDesktopMediaFunction::
181+
~DesktopCaptureCancelChooseDesktopMediaFunction() {}
182+
183+
bool DesktopCaptureCancelChooseDesktopMediaFunction::RunSync() {
184+
int request_id;
185+
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &request_id));
186+
187+
DesktopCaptureRequestsRegistry::GetInstance()->CancelRequest(
188+
render_view_host()->GetProcess()->GetID(), request_id);
189+
return true;
190+
}
191+
192+
DesktopCaptureRequestsRegistry::DesktopCaptureRequestsRegistry() {}
193+
DesktopCaptureRequestsRegistry::~DesktopCaptureRequestsRegistry() {}
194+
195+
// static
196+
DesktopCaptureRequestsRegistry* DesktopCaptureRequestsRegistry::GetInstance() {
197+
return Singleton<DesktopCaptureRequestsRegistry>::get();
198+
}
199+
200+
void DesktopCaptureRequestsRegistry::AddRequest(
201+
int process_id,
202+
int request_id,
203+
DesktopCaptureChooseDesktopMediaFunction* handler) {
204+
requests_.insert(
205+
RequestsMap::value_type(RequestId(process_id, request_id), handler));
206+
}
207+
208+
void DesktopCaptureRequestsRegistry::RemoveRequest(int process_id,
209+
int request_id) {
210+
requests_.erase(RequestId(process_id, request_id));
211+
}
212+
213+
void DesktopCaptureRequestsRegistry::CancelRequest(int process_id,
214+
int request_id) {
215+
RequestsMap::iterator it = requests_.find(RequestId(process_id, request_id));
216+
if (it != requests_.end())
217+
it->second->Cancel();
218+
}
219+
220+
221+
} // namespace extensions

0 commit comments

Comments
 (0)