This source file includes following definitions.
- SetPickerFactoryForTests
- render_view_id_
- DesktopCaptureChooseDesktopMediaFunction
- Cancel
- RunImpl
- WebContentsDestroyed
- OnPickerDialogResults
- request_id
- DesktopCaptureCancelChooseDesktopMediaFunction
- DesktopCaptureCancelChooseDesktopMediaFunction
- RunImpl
- GetInstance
- AddRequest
- RemoveRequest
- CancelRequest
#include "chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/media/desktop_media_list_ash.h"
#include "chrome/browser/media/desktop_streams_registry.h"
#include "chrome/browser/media/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/native_desktop_media_list.h"
#include "chrome/browser/ui/ash/ash_util.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/api/tabs.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "net/base/net_util.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
namespace extensions {
namespace {
const char kInvalidSourceNameError[] = "Invalid source type specified.";
const char kEmptySourcesListError[] =
"At least one source type must be specified.";
const char kTabCaptureNotSupportedError[] = "Tab capture is not supported yet.";
const char kNoTabIdError[] = "targetTab doesn't have id field set.";
const char kNoUrlError[] = "targetTab doesn't have URL field set.";
const char kInvalidTabIdError[] = "Invalid tab specified.";
const char kTabUrlChangedError[] = "URL for the specified tab has changed.";
const char kTabUrlNotSecure[] =
"URL scheme for the specified tab is not secure.";
DesktopCaptureChooseDesktopMediaFunction::PickerFactory* g_picker_factory =
NULL;
}
void DesktopCaptureChooseDesktopMediaFunction::SetPickerFactoryForTests(
PickerFactory* factory) {
g_picker_factory = factory;
}
DesktopCaptureChooseDesktopMediaFunction::
DesktopCaptureChooseDesktopMediaFunction()
: render_process_id_(0),
render_view_id_(0) {
}
DesktopCaptureChooseDesktopMediaFunction::
~DesktopCaptureChooseDesktopMediaFunction() {
if (render_view_host()) {
DesktopCaptureRequestsRegistry::GetInstance()->RemoveRequest(
render_view_host()->GetProcess()->GetID(), request_id_);
}
}
void DesktopCaptureChooseDesktopMediaFunction::Cancel() {
scoped_refptr<DesktopCaptureChooseDesktopMediaFunction> self(this);
if (picker_) {
picker_.reset();
SetResult(new base::StringValue(std::string()));
SendResponse(true);
}
}
bool DesktopCaptureChooseDesktopMediaFunction::RunImpl() {
EXTENSION_FUNCTION_VALIDATE(args_->GetSize() > 0);
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &request_id_));
args_->Remove(0, NULL);
scoped_ptr<api::desktop_capture::ChooseDesktopMedia::Params> params =
api::desktop_capture::ChooseDesktopMedia::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params.get());
DesktopCaptureRequestsRegistry::GetInstance()->AddRequest(
render_view_host()->GetProcess()->GetID(), request_id_, this);
gfx::NativeWindow parent_window;
content::RenderViewHost* render_view;
base::string16 target_name;
if (params->target_tab) {
if (!params->target_tab->url) {
error_ = kNoUrlError;
return false;
}
origin_ = GURL(*(params->target_tab->url)).GetOrigin();
if (!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAllowHttpScreenCapture) &&
!origin_.SchemeIsSecure()) {
error_ = kTabUrlNotSecure;
return false;
}
target_name = base::UTF8ToUTF16(origin_.SchemeIsSecure() ?
net::GetHostAndOptionalPort(origin_) : origin_.spec());
if (!params->target_tab->id) {
error_ = kNoTabIdError;
return false;
}
content::WebContents* web_contents = NULL;
if (!ExtensionTabUtil::GetTabById(*(params->target_tab->id), GetProfile(),
true, NULL, NULL, &web_contents, NULL)) {
error_ = kInvalidTabIdError;
return false;
}
GURL current_origin_ =
web_contents->GetLastCommittedURL().GetOrigin();
if (current_origin_ != origin_) {
error_ = kTabUrlChangedError;
return false;
}
Observe(web_contents);
render_view = web_contents->GetRenderViewHost();
parent_window = web_contents->GetView()->GetTopLevelNativeWindow();
} else {
origin_ = GetExtension()->url();
target_name = base::UTF8ToUTF16(GetExtension()->name());
render_view = render_view_host();
parent_window =
GetAssociatedWebContents()->GetView()->GetTopLevelNativeWindow();
}
render_process_id_ = render_view->GetProcess()->GetID();
render_view_id_ = render_view->GetRoutingID();
bool show_screens = false;
bool show_windows = false;
for (std::vector<api::desktop_capture::DesktopCaptureSourceType>::iterator
it = params->sources.begin(); it != params->sources.end(); ++it) {
switch (*it) {
case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_NONE:
error_ = kInvalidSourceNameError;
return false;
case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_SCREEN:
show_screens = true;
break;
case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_WINDOW:
show_windows = true;
break;
case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_TAB:
error_ = kTabCaptureNotSupportedError;
return false;
}
}
if (!show_screens && !show_windows) {
error_ = kEmptySourcesListError;
return false;
}
scoped_ptr<DesktopMediaList> media_list;
if (g_picker_factory) {
media_list = g_picker_factory->CreateModel(
show_screens, show_windows);
picker_ = g_picker_factory->CreatePicker();
} else {
#if defined(USE_ASH)
if (chrome::IsNativeWindowInAsh(parent_window)) {
media_list.reset(new DesktopMediaListAsh(
(show_screens ? DesktopMediaListAsh::SCREENS : 0) |
(show_windows ? DesktopMediaListAsh::WINDOWS : 0)));
} else
#endif
{
webrtc::DesktopCaptureOptions options =
webrtc::DesktopCaptureOptions::CreateDefault();
options.set_disable_effects(false);
scoped_ptr<webrtc::ScreenCapturer> screen_capturer(
show_screens ? webrtc::ScreenCapturer::Create(options) : NULL);
scoped_ptr<webrtc::WindowCapturer> window_capturer(
show_windows ? webrtc::WindowCapturer::Create(options) : NULL);
media_list.reset(new NativeDesktopMediaList(
screen_capturer.Pass(), window_capturer.Pass()));
}
#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
picker_ = DesktopMediaPicker::Create();
#else
error_ = "Desktop Capture API is not yet implemented for this platform.";
return false;
#endif
}
DesktopMediaPicker::DoneCallback callback = base::Bind(
&DesktopCaptureChooseDesktopMediaFunction::OnPickerDialogResults, this);
picker_->Show(parent_window, parent_window,
base::UTF8ToUTF16(GetExtension()->name()),
target_name,
media_list.Pass(), callback);
return true;
}
void DesktopCaptureChooseDesktopMediaFunction::WebContentsDestroyed(
content::WebContents* web_contents) {
Cancel();
}
void DesktopCaptureChooseDesktopMediaFunction::OnPickerDialogResults(
content::DesktopMediaID source) {
std::string result;
if (source.type != content::DesktopMediaID::TYPE_NONE) {
DesktopStreamsRegistry* registry =
MediaCaptureDevicesDispatcher::GetInstance()->
GetDesktopStreamsRegistry();
result = registry->RegisterStream(
render_process_id_,
render_view_id_,
origin_,
source,
GetExtension()->name());
}
SetResult(new base::StringValue(result));
SendResponse(true);
}
DesktopCaptureRequestsRegistry::RequestId::RequestId(int process_id,
int request_id)
: process_id(process_id),
request_id(request_id) {
}
bool DesktopCaptureRequestsRegistry::RequestId::operator<(
const RequestId& other) const {
if (process_id != other.process_id) {
return process_id < other.process_id;
} else {
return request_id < other.request_id;
}
}
DesktopCaptureCancelChooseDesktopMediaFunction::
DesktopCaptureCancelChooseDesktopMediaFunction() {}
DesktopCaptureCancelChooseDesktopMediaFunction::
~DesktopCaptureCancelChooseDesktopMediaFunction() {}
bool DesktopCaptureCancelChooseDesktopMediaFunction::RunImpl() {
int request_id;
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &request_id));
DesktopCaptureRequestsRegistry::GetInstance()->CancelRequest(
render_view_host()->GetProcess()->GetID(), request_id);
return true;
}
DesktopCaptureRequestsRegistry::DesktopCaptureRequestsRegistry() {}
DesktopCaptureRequestsRegistry::~DesktopCaptureRequestsRegistry() {}
DesktopCaptureRequestsRegistry* DesktopCaptureRequestsRegistry::GetInstance() {
return Singleton<DesktopCaptureRequestsRegistry>::get();
}
void DesktopCaptureRequestsRegistry::AddRequest(
int process_id,
int request_id,
DesktopCaptureChooseDesktopMediaFunction* handler) {
requests_.insert(
RequestsMap::value_type(RequestId(process_id, request_id), handler));
}
void DesktopCaptureRequestsRegistry::RemoveRequest(int process_id,
int request_id) {
requests_.erase(RequestId(process_id, request_id));
}
void DesktopCaptureRequestsRegistry::CancelRequest(int process_id,
int request_id) {
RequestsMap::iterator it = requests_.find(RequestId(process_id, request_id));
if (it != requests_.end())
it->second->Cancel();
}
}