Disable TabDragController tests that fail with a real compositor.
[chromium-blink-merge.git] / chrome / browser / extensions / api / desktop_capture / desktop_capture_api.cc
blobc0502193ebcdecff2902873f0f184addd5155287
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.
5 #include "chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h"
7 #include "base/compiler_specific.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/extensions/extension_tab_util.h"
10 #include "chrome/browser/media/desktop_media_list_ash.h"
11 #include "chrome/browser/media/desktop_streams_registry.h"
12 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
13 #include "chrome/browser/media/native_desktop_media_list.h"
14 #include "chrome/browser/ui/ash/ash_util.h"
15 #include "chrome/common/extensions/api/tabs.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/browser/render_view_host.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/browser/web_contents_view.h"
21 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
22 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
23 #include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
25 namespace extensions {
27 namespace {
29 const char kInvalidSourceNameError[] = "Invalid source type specified.";
30 const char kEmptySourcesListError[] =
31 "At least one source type must be specified.";
32 const char kTabCaptureNotSupportedError[] = "Tab capture is not supported yet.";
33 const char kNoTabIdError[] = "targetTab doesn't have id field set.";
34 const char kNoUrlError[] = "targetTab doesn't have URL field set.";
35 const char kInvalidTabIdError[] = "Invalid tab specified.";
36 const char kTabUrlChangedError[] = "URL for the specified tab has changed.";
38 DesktopCaptureChooseDesktopMediaFunction::PickerFactory* g_picker_factory =
39 NULL;
41 } // namespace
43 // static
44 void DesktopCaptureChooseDesktopMediaFunction::SetPickerFactoryForTests(
45 PickerFactory* factory) {
46 g_picker_factory = factory;
49 DesktopCaptureChooseDesktopMediaFunction::
50 DesktopCaptureChooseDesktopMediaFunction()
51 : render_process_id_(0),
52 render_view_id_(0) {
55 DesktopCaptureChooseDesktopMediaFunction::
56 ~DesktopCaptureChooseDesktopMediaFunction() {
57 // RenderViewHost may be already destroyed.
58 if (render_view_host()) {
59 DesktopCaptureRequestsRegistry::GetInstance()->RemoveRequest(
60 render_view_host()->GetProcess()->GetID(), request_id_);
64 void DesktopCaptureChooseDesktopMediaFunction::Cancel() {
65 // Keep reference to |this| to ensure the object doesn't get destroyed before
66 // we return.
67 scoped_refptr<DesktopCaptureChooseDesktopMediaFunction> self(this);
68 if (picker_) {
69 picker_.reset();
70 SetResult(new base::StringValue(std::string()));
71 SendResponse(true);
75 bool DesktopCaptureChooseDesktopMediaFunction::RunImpl() {
76 EXTENSION_FUNCTION_VALIDATE(args_->GetSize() > 0);
78 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &request_id_));
79 args_->Remove(0, NULL);
81 scoped_ptr<api::desktop_capture::ChooseDesktopMedia::Params> params =
82 api::desktop_capture::ChooseDesktopMedia::Params::Create(*args_);
83 EXTENSION_FUNCTION_VALIDATE(params.get());
85 DesktopCaptureRequestsRegistry::GetInstance()->AddRequest(
86 render_view_host()->GetProcess()->GetID(), request_id_, this);
88 gfx::NativeWindow parent_window;
89 content::RenderViewHost* render_view;
90 if (params->target_tab) {
91 if (!params->target_tab->url) {
92 error_ = kNoUrlError;
93 return false;
95 origin_ = GURL(*(params->target_tab->url)).GetOrigin();
97 if (!params->target_tab->id) {
98 error_ = kNoTabIdError;
99 return false;
102 content::WebContents* web_contents = NULL;
103 if (!ExtensionTabUtil::GetTabById(*(params->target_tab->id), GetProfile(),
104 true, NULL, NULL, &web_contents, NULL)) {
105 error_ = kInvalidTabIdError;
106 return false;
109 GURL current_origin_ =
110 web_contents->GetLastCommittedURL().GetOrigin();
111 if (current_origin_ != origin_) {
112 error_ = kTabUrlChangedError;
113 return false;
116 render_view = web_contents->GetRenderViewHost();
117 parent_window = web_contents->GetView()->GetTopLevelNativeWindow();
118 } else {
119 origin_ = GetExtension()->url();
120 render_view = render_view_host();
121 parent_window =
122 GetAssociatedWebContents()->GetView()->GetTopLevelNativeWindow();
124 render_process_id_ = render_view->GetProcess()->GetID();
125 render_view_id_ = render_view->GetRoutingID();
128 bool show_screens = false;
129 bool show_windows = false;
131 for (std::vector<api::desktop_capture::DesktopCaptureSourceType>::iterator
132 it = params->sources.begin(); it != params->sources.end(); ++it) {
133 switch (*it) {
134 case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_NONE:
135 error_ = kInvalidSourceNameError;
136 return false;
138 case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_SCREEN:
139 show_screens = true;
140 break;
142 case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_WINDOW:
143 show_windows = true;
144 break;
146 case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_TAB:
147 error_ = kTabCaptureNotSupportedError;
148 return false;
152 if (!show_screens && !show_windows) {
153 error_ = kEmptySourcesListError;
154 return false;
157 scoped_ptr<DesktopMediaList> media_list;
158 if (g_picker_factory) {
159 media_list = g_picker_factory->CreateModel(
160 show_screens, show_windows);
161 picker_ = g_picker_factory->CreatePicker();
162 } else {
163 #if defined(USE_ASH)
164 if (chrome::IsNativeWindowInAsh(parent_window)) {
165 media_list.reset(new DesktopMediaListAsh(
166 (show_screens ? DesktopMediaListAsh::SCREENS : 0) |
167 (show_windows ? DesktopMediaListAsh::WINDOWS : 0)));
168 } else
169 #endif
171 webrtc::DesktopCaptureOptions options =
172 webrtc::DesktopCaptureOptions::CreateDefault();
173 options.set_disable_effects(false);
174 scoped_ptr<webrtc::ScreenCapturer> screen_capturer(
175 show_screens ? webrtc::ScreenCapturer::Create(options) : NULL);
176 scoped_ptr<webrtc::WindowCapturer> window_capturer(
177 show_windows ? webrtc::WindowCapturer::Create(options) : NULL);
179 media_list.reset(new NativeDesktopMediaList(
180 screen_capturer.Pass(), window_capturer.Pass()));
183 // DesktopMediaPicker is implemented only for Windows, OSX and
184 // Aura Linux builds.
185 #if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
186 picker_ = DesktopMediaPicker::Create();
187 #else
188 error_ = "Desktop Capture API is not yet implemented for this platform.";
189 return false;
190 #endif
192 DesktopMediaPicker::DoneCallback callback = base::Bind(
193 &DesktopCaptureChooseDesktopMediaFunction::OnPickerDialogResults, this);
195 picker_->Show(parent_window, parent_window,
196 base::UTF8ToUTF16(GetExtension()->name()),
197 media_list.Pass(), callback);
198 return true;
201 void DesktopCaptureChooseDesktopMediaFunction::OnPickerDialogResults(
202 content::DesktopMediaID source) {
203 std::string result;
204 if (source.type != content::DesktopMediaID::TYPE_NONE) {
205 DesktopStreamsRegistry* registry =
206 MediaCaptureDevicesDispatcher::GetInstance()->
207 GetDesktopStreamsRegistry();
208 result = registry->RegisterStream(
209 render_process_id_, render_view_id_, origin_, source);
212 SetResult(new base::StringValue(result));
213 SendResponse(true);
216 DesktopCaptureRequestsRegistry::RequestId::RequestId(int process_id,
217 int request_id)
218 : process_id(process_id),
219 request_id(request_id) {
222 bool DesktopCaptureRequestsRegistry::RequestId::operator<(
223 const RequestId& other) const {
224 if (process_id != other.process_id) {
225 return process_id < other.process_id;
226 } else {
227 return request_id < other.request_id;
231 DesktopCaptureCancelChooseDesktopMediaFunction::
232 DesktopCaptureCancelChooseDesktopMediaFunction() {}
234 DesktopCaptureCancelChooseDesktopMediaFunction::
235 ~DesktopCaptureCancelChooseDesktopMediaFunction() {}
237 bool DesktopCaptureCancelChooseDesktopMediaFunction::RunImpl() {
238 int request_id;
239 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &request_id));
241 DesktopCaptureRequestsRegistry::GetInstance()->CancelRequest(
242 render_view_host()->GetProcess()->GetID(), request_id);
243 return true;
246 DesktopCaptureRequestsRegistry::DesktopCaptureRequestsRegistry() {}
247 DesktopCaptureRequestsRegistry::~DesktopCaptureRequestsRegistry() {}
249 // static
250 DesktopCaptureRequestsRegistry* DesktopCaptureRequestsRegistry::GetInstance() {
251 return Singleton<DesktopCaptureRequestsRegistry>::get();
254 void DesktopCaptureRequestsRegistry::AddRequest(
255 int process_id,
256 int request_id,
257 DesktopCaptureChooseDesktopMediaFunction* handler) {
258 requests_.insert(
259 RequestsMap::value_type(RequestId(process_id, request_id), handler));
262 void DesktopCaptureRequestsRegistry::RemoveRequest(int process_id,
263 int request_id) {
264 requests_.erase(RequestId(process_id, request_id));
267 void DesktopCaptureRequestsRegistry::CancelRequest(int process_id,
268 int request_id) {
269 RequestsMap::iterator it = requests_.find(RequestId(process_id, request_id));
270 if (it != requests_.end())
271 it->second->Cancel();
275 } // namespace extensions