2012-04-03 03:34:16 +02:00
|
|
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "libcef/browser/content_browser_client.h"
|
2012-09-11 00:19:19 +02:00
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2012-04-03 03:34:16 +02:00
|
|
|
#include "libcef/browser/browser_context.h"
|
|
|
|
#include "libcef/browser/browser_host_impl.h"
|
|
|
|
#include "libcef/browser/browser_main.h"
|
|
|
|
#include "libcef/browser/browser_message_filter.h"
|
|
|
|
#include "libcef/browser/browser_settings.h"
|
2012-10-08 19:47:37 +02:00
|
|
|
#include "libcef/browser/chrome_scheme_handler.h"
|
2012-04-03 03:34:16 +02:00
|
|
|
#include "libcef/browser/context.h"
|
2012-06-25 23:21:27 +02:00
|
|
|
#include "libcef/browser/resource_dispatcher_host_delegate.h"
|
2012-04-03 03:34:16 +02:00
|
|
|
#include "libcef/browser/thread_util.h"
|
2012-09-28 22:14:02 +02:00
|
|
|
#include "libcef/browser/web_plugin_impl.h"
|
2012-04-03 03:34:16 +02:00
|
|
|
#include "libcef/common/cef_switches.h"
|
2012-09-27 19:07:31 +02:00
|
|
|
#include "libcef/common/command_line_impl.h"
|
2012-04-03 03:34:16 +02:00
|
|
|
|
|
|
|
#include "base/command_line.h"
|
|
|
|
#include "base/file_path.h"
|
2012-09-11 00:19:19 +02:00
|
|
|
#include "base/path_service.h"
|
2012-09-28 22:14:02 +02:00
|
|
|
#include "content/browser/plugin_service_impl.h"
|
2012-04-03 03:34:16 +02:00
|
|
|
#include "content/public/browser/access_token_store.h"
|
2012-10-08 19:47:37 +02:00
|
|
|
#include "content/public/browser/browser_url_handler.h"
|
2012-04-03 03:34:16 +02:00
|
|
|
#include "content/public/browser/media_observer.h"
|
2012-09-28 22:14:02 +02:00
|
|
|
#include "content/public/browser/plugin_service_filter.h"
|
2012-09-28 00:52:15 +02:00
|
|
|
#include "content/public/browser/quota_permission_context.h"
|
2012-04-04 20:18:09 +02:00
|
|
|
#include "content/public/browser/render_process_host.h"
|
2012-06-25 23:21:27 +02:00
|
|
|
#include "content/public/browser/resource_dispatcher_host.h"
|
2012-04-03 03:34:16 +02:00
|
|
|
#include "content/public/common/content_switches.h"
|
|
|
|
#include "googleurl/src/gurl.h"
|
2012-10-22 22:56:38 +02:00
|
|
|
#include "ui/base/ui_base_switches.h"
|
2012-04-03 03:34:16 +02:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
// In-memory store for access tokens used by geolocation.
|
|
|
|
class CefAccessTokenStore : public content::AccessTokenStore {
|
|
|
|
public:
|
|
|
|
CefAccessTokenStore() {}
|
|
|
|
|
|
|
|
virtual void LoadAccessTokens(
|
|
|
|
const LoadAccessTokensCallbackType& callback) OVERRIDE {
|
|
|
|
callback.Run(access_token_set_,
|
|
|
|
_Context->browser_context()->GetRequestContext());
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void SaveAccessToken(
|
|
|
|
const GURL& server_url, const string16& access_token) OVERRIDE {
|
|
|
|
access_token_set_[server_url] = access_token;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
AccessTokenSet access_token_set_;
|
|
|
|
};
|
|
|
|
|
2012-09-28 00:52:15 +02:00
|
|
|
class CefQuotaCallbackImpl : public CefQuotaCallback {
|
|
|
|
public:
|
|
|
|
explicit CefQuotaCallbackImpl(
|
|
|
|
const content::QuotaPermissionContext::PermissionCallback& callback)
|
|
|
|
: callback_(callback) {
|
|
|
|
}
|
|
|
|
~CefQuotaCallbackImpl() {
|
|
|
|
if (!callback_.is_null()) {
|
|
|
|
// The callback is still pending. Cancel it now.
|
|
|
|
if (CEF_CURRENTLY_ON_IOT()) {
|
|
|
|
CancelNow(callback_);
|
|
|
|
} else {
|
|
|
|
CEF_POST_TASK(CEF_IOT,
|
|
|
|
base::Bind(&CefQuotaCallbackImpl::CancelNow, callback_));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Continue(bool allow) OVERRIDE {
|
|
|
|
if (CEF_CURRENTLY_ON_IOT()) {
|
|
|
|
if (!callback_.is_null()) {
|
|
|
|
callback_.Run(allow ?
|
|
|
|
content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW :
|
|
|
|
content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_DISALLOW);
|
|
|
|
callback_.Reset();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
CEF_POST_TASK(CEF_IOT,
|
|
|
|
base::Bind(&CefQuotaCallbackImpl::Continue, this, allow));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Cancel() OVERRIDE {
|
|
|
|
if (CEF_CURRENTLY_ON_IOT()) {
|
|
|
|
if (!callback_.is_null()) {
|
|
|
|
CancelNow(callback_);
|
|
|
|
callback_.Reset();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
CEF_POST_TASK(CEF_IOT, base::Bind(&CefQuotaCallbackImpl::Cancel, this));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Disconnect() {
|
|
|
|
callback_.Reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static void CancelNow(
|
|
|
|
const content::QuotaPermissionContext::PermissionCallback& callback) {
|
|
|
|
CEF_REQUIRE_IOT();
|
|
|
|
callback.Run(
|
|
|
|
content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED);
|
|
|
|
}
|
|
|
|
|
|
|
|
content::QuotaPermissionContext::PermissionCallback callback_;
|
|
|
|
|
|
|
|
IMPLEMENT_REFCOUNTING(CefQuotaCallbackImpl);
|
|
|
|
};
|
|
|
|
|
|
|
|
class CefQuotaPermissionContext : public content::QuotaPermissionContext {
|
|
|
|
public:
|
|
|
|
CefQuotaPermissionContext() {
|
|
|
|
}
|
|
|
|
|
|
|
|
// The callback will be dispatched on the IO thread.
|
|
|
|
virtual void RequestQuotaPermission(
|
|
|
|
const GURL& origin_url,
|
|
|
|
quota::StorageType type,
|
|
|
|
int64 new_quota,
|
|
|
|
int render_process_id,
|
|
|
|
int render_view_id,
|
|
|
|
const PermissionCallback& callback) OVERRIDE {
|
|
|
|
if (type != quota::kStorageTypePersistent) {
|
|
|
|
// To match Chrome behavior we only support requesting quota with this
|
|
|
|
// interface for Persistent storage type.
|
|
|
|
callback.Run(QUOTA_PERMISSION_RESPONSE_DISALLOW);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool handled = false;
|
|
|
|
|
|
|
|
CefRefPtr<CefBrowserHostImpl> browser =
|
|
|
|
CefBrowserHostImpl::GetBrowserByRoutingID(render_process_id,
|
|
|
|
render_view_id);
|
|
|
|
if (browser.get()) {
|
|
|
|
CefRefPtr<CefClient> client = browser->GetClient();
|
|
|
|
if (client.get()) {
|
|
|
|
CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
|
|
|
|
if (handler.get()) {
|
|
|
|
CefRefPtr<CefQuotaCallbackImpl> callbackImpl(
|
|
|
|
new CefQuotaCallbackImpl(callback));
|
|
|
|
handled = handler->OnQuotaRequest(browser.get(), origin_url.spec(),
|
|
|
|
new_quota, callbackImpl.get());
|
|
|
|
if (!handled)
|
|
|
|
callbackImpl->Disconnect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!handled) {
|
|
|
|
// Disallow the request by default.
|
|
|
|
callback.Run(QUOTA_PERMISSION_RESPONSE_DISALLOW);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual ~CefQuotaPermissionContext() {
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-09-28 22:14:02 +02:00
|
|
|
class CefPluginServiceFilter : public content::PluginServiceFilter {
|
|
|
|
public:
|
|
|
|
CefPluginServiceFilter() {}
|
|
|
|
virtual ~CefPluginServiceFilter() {}
|
|
|
|
|
|
|
|
virtual bool ShouldUsePlugin(int render_process_id,
|
|
|
|
int render_view_id,
|
|
|
|
const void* context,
|
|
|
|
const GURL& url,
|
|
|
|
const GURL& policy_url,
|
|
|
|
webkit::WebPluginInfo* plugin) OVERRIDE {
|
|
|
|
bool allowed = true;
|
|
|
|
|
|
|
|
CefRefPtr<CefBrowserHostImpl> browser =
|
|
|
|
CefBrowserHostImpl::GetBrowserByRoutingID(render_process_id,
|
|
|
|
render_view_id);
|
|
|
|
if (browser.get()) {
|
|
|
|
CefRefPtr<CefClient> client = browser->GetClient();
|
|
|
|
if (client.get()) {
|
|
|
|
CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
|
|
|
|
if (handler.get()) {
|
|
|
|
CefRefPtr<CefWebPluginInfoImpl> pluginInfo(
|
|
|
|
new CefWebPluginInfoImpl(*plugin));
|
|
|
|
allowed =
|
|
|
|
!handler->OnBeforePluginLoad(browser.get(),
|
|
|
|
url.possibly_invalid_spec(),
|
|
|
|
policy_url.possibly_invalid_spec(),
|
|
|
|
pluginInfo.get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return allowed;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-04-03 03:34:16 +02:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
|
|
class CefMediaObserver : public content::MediaObserver {
|
|
|
|
public:
|
|
|
|
CefMediaObserver() {}
|
|
|
|
virtual ~CefMediaObserver() {}
|
|
|
|
|
|
|
|
virtual void OnDeleteAudioStream(void* host, int stream_id) OVERRIDE {}
|
|
|
|
|
|
|
|
virtual void OnSetAudioStreamPlaying(void* host, int stream_id,
|
|
|
|
bool playing) OVERRIDE {}
|
|
|
|
virtual void OnSetAudioStreamStatus(void* host, int stream_id,
|
|
|
|
const std::string& status) OVERRIDE {}
|
|
|
|
virtual void OnSetAudioStreamVolume(void* host, int stream_id,
|
|
|
|
double volume) OVERRIDE {}
|
|
|
|
virtual void OnMediaEvent(int render_process_id,
|
|
|
|
const media::MediaLogEvent& event) OVERRIDE {}
|
2012-05-18 17:04:56 +02:00
|
|
|
virtual void OnCaptureDevicesOpened(
|
|
|
|
int render_process_id,
|
|
|
|
int render_view_id,
|
|
|
|
const content::MediaStreamDevices& devices) OVERRIDE {}
|
|
|
|
virtual void OnCaptureDevicesClosed(
|
|
|
|
int render_process_id,
|
|
|
|
int render_view_id,
|
|
|
|
const content::MediaStreamDevices& devices) OVERRIDE {}
|
2012-11-05 21:18:20 +01:00
|
|
|
virtual void OnMediaRequestStateChanged(
|
|
|
|
int render_process_id,
|
|
|
|
int render_view_id,
|
|
|
|
const content::MediaStreamDevice& device,
|
|
|
|
content::MediaRequestState state) OVERRIDE {}
|
2012-04-03 03:34:16 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
CefContentBrowserClient::CefContentBrowserClient()
|
|
|
|
: browser_main_parts_(NULL) {
|
2012-09-28 22:14:02 +02:00
|
|
|
plugin_service_filter_.reset(new CefPluginServiceFilter);
|
2012-11-05 21:18:20 +01:00
|
|
|
content::PluginServiceImpl::GetInstance()->SetFilter(
|
|
|
|
plugin_service_filter_.get());
|
2012-04-03 03:34:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CefContentBrowserClient::~CefContentBrowserClient() {
|
|
|
|
}
|
|
|
|
|
2012-11-20 21:08:36 +01:00
|
|
|
// static
|
|
|
|
CefContentBrowserClient* CefContentBrowserClient::Get() {
|
|
|
|
return static_cast<CefContentBrowserClient*>(
|
|
|
|
content::GetContentClient()->browser());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CefContentBrowserClient::GetNewPopupBrowserInfo(
|
|
|
|
int render_process_id, int render_view_id, NewPopupBrowserInfo* info) {
|
|
|
|
base::AutoLock lock_scope(new_popup_browser_lock_);
|
|
|
|
|
|
|
|
NewPopupBrowserInfoMap::const_iterator it =
|
|
|
|
new_popup_browser_info_map_.find(
|
|
|
|
std::make_pair(render_process_id, render_view_id));
|
|
|
|
if (it != new_popup_browser_info_map_.end()) {
|
|
|
|
*info = it->second;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the info now.
|
|
|
|
NewPopupBrowserInfo new_info;
|
|
|
|
new_info.browser_id = _Context->GetNextBrowserID();
|
|
|
|
new_popup_browser_info_map_.insert(
|
|
|
|
std::make_pair(
|
|
|
|
std::make_pair(render_process_id, render_view_id), new_info));
|
|
|
|
*info = new_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CefContentBrowserClient::ClearNewPopupBrowserInfo(int render_process_id,
|
|
|
|
int render_view_id) {
|
|
|
|
base::AutoLock lock_scope(new_popup_browser_lock_);
|
|
|
|
|
|
|
|
NewPopupBrowserInfoMap::iterator it =
|
|
|
|
new_popup_browser_info_map_.find(
|
|
|
|
std::make_pair(render_process_id, render_view_id));
|
|
|
|
if (it != new_popup_browser_info_map_.end())
|
|
|
|
new_popup_browser_info_map_.erase(it);
|
|
|
|
}
|
|
|
|
|
2012-04-03 03:34:16 +02:00
|
|
|
content::BrowserMainParts* CefContentBrowserClient::CreateBrowserMainParts(
|
|
|
|
const content::MainFunctionParams& parameters) {
|
2012-04-11 20:00:55 +02:00
|
|
|
browser_main_parts_ = new CefBrowserMainParts(parameters);
|
|
|
|
return browser_main_parts_;
|
2012-04-03 03:34:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CefContentBrowserClient::RenderProcessHostCreated(
|
|
|
|
content::RenderProcessHost* host) {
|
|
|
|
host->GetChannel()->AddFilter(new CefBrowserMessageFilter(host));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CefContentBrowserClient::AppendExtraCommandLineSwitches(
|
|
|
|
CommandLine* command_line, int child_process_id) {
|
2012-09-10 18:13:51 +02:00
|
|
|
const CommandLine& browser_cmd = *CommandLine::ForCurrentProcess();
|
|
|
|
|
|
|
|
{
|
|
|
|
// Propagate the following switches to all command lines (along with any
|
|
|
|
// associated values) if present in the browser command line.
|
|
|
|
static const char* const kSwitchNames[] = {
|
2012-10-25 23:19:20 +02:00
|
|
|
switches::kLang,
|
|
|
|
switches::kLocalesDirPath,
|
2012-09-10 18:13:51 +02:00
|
|
|
switches::kLogFile,
|
|
|
|
switches::kLogSeverity,
|
2012-10-25 23:19:20 +02:00
|
|
|
switches::kPackLoadingDisabled,
|
|
|
|
switches::kResourcesDirPath,
|
2012-09-10 18:13:51 +02:00
|
|
|
};
|
|
|
|
command_line->CopySwitchesFrom(browser_cmd, kSwitchNames,
|
|
|
|
arraysize(kSwitchNames));
|
|
|
|
}
|
|
|
|
|
2012-04-03 03:34:16 +02:00
|
|
|
std::string process_type =
|
|
|
|
command_line->GetSwitchValueASCII(switches::kProcessType);
|
|
|
|
if (process_type == switches::kRendererProcess) {
|
2012-09-10 18:13:51 +02:00
|
|
|
// Propagate the following switches to the renderer command line (along with
|
|
|
|
// any associated values) if present in the browser command line.
|
|
|
|
static const char* const kSwitchNames[] = {
|
2012-10-29 22:46:02 +01:00
|
|
|
switches::kContextSafetyImplementation,
|
2012-09-10 18:13:51 +02:00
|
|
|
switches::kProductVersion,
|
2012-11-02 19:16:28 +01:00
|
|
|
switches::kUncaughtExceptionStackSize,
|
2012-09-10 18:13:51 +02:00
|
|
|
};
|
|
|
|
command_line->CopySwitchesFrom(browser_cmd, kSwitchNames,
|
|
|
|
arraysize(kSwitchNames));
|
2012-04-03 03:34:16 +02:00
|
|
|
}
|
2012-09-27 19:07:31 +02:00
|
|
|
|
|
|
|
CefRefPtr<CefApp> app = _Context->application();
|
|
|
|
if (app.get()) {
|
|
|
|
CefRefPtr<CefBrowserProcessHandler> handler =
|
|
|
|
app->GetBrowserProcessHandler();
|
|
|
|
if (handler.get()) {
|
|
|
|
CefRefPtr<CefCommandLineImpl> commandLinePtr(
|
|
|
|
new CefCommandLineImpl(command_line, false, false));
|
|
|
|
handler->OnBeforeChildProcessLaunch(commandLinePtr.get());
|
|
|
|
commandLinePtr->Detach(NULL);
|
|
|
|
}
|
|
|
|
}
|
2012-04-03 03:34:16 +02:00
|
|
|
}
|
|
|
|
|
2012-09-28 00:52:15 +02:00
|
|
|
content::QuotaPermissionContext*
|
|
|
|
CefContentBrowserClient::CreateQuotaPermissionContext() {
|
|
|
|
return new CefQuotaPermissionContext();
|
|
|
|
}
|
|
|
|
|
2012-04-03 03:34:16 +02:00
|
|
|
content::MediaObserver* CefContentBrowserClient::GetMediaObserver() {
|
|
|
|
// TODO(cef): Return NULL once it's supported. See crbug.com/116113.
|
|
|
|
if (!media_observer_.get())
|
|
|
|
media_observer_.reset(new CefMediaObserver());
|
|
|
|
return media_observer_.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
content::AccessTokenStore* CefContentBrowserClient::CreateAccessTokenStore() {
|
|
|
|
return new CefAccessTokenStore;
|
|
|
|
}
|
|
|
|
|
2012-06-25 23:21:27 +02:00
|
|
|
void CefContentBrowserClient::ResourceDispatcherHostCreated() {
|
|
|
|
resource_dispatcher_host_delegate_.reset(
|
|
|
|
new CefResourceDispatcherHostDelegate());
|
|
|
|
content::ResourceDispatcherHost::Get()->SetDelegate(
|
|
|
|
resource_dispatcher_host_delegate_.get());
|
|
|
|
}
|
|
|
|
|
2012-04-03 03:34:16 +02:00
|
|
|
void CefContentBrowserClient::OverrideWebkitPrefs(
|
|
|
|
content::RenderViewHost* rvh,
|
|
|
|
const GURL& url,
|
2012-05-18 17:04:56 +02:00
|
|
|
webkit_glue::WebPreferences* prefs) {
|
|
|
|
CefRefPtr<CefBrowserHostImpl> browser =
|
|
|
|
CefBrowserHostImpl::GetBrowserForHost(rvh);
|
2012-04-03 03:34:16 +02:00
|
|
|
DCHECK(browser.get());
|
|
|
|
|
|
|
|
// Populate WebPreferences based on CefBrowserSettings.
|
|
|
|
BrowserToWebSettings(browser->settings(), *prefs);
|
|
|
|
}
|
|
|
|
|
2012-10-08 19:47:37 +02:00
|
|
|
void CefContentBrowserClient::BrowserURLHandlerCreated(
|
|
|
|
content::BrowserURLHandler* handler) {
|
|
|
|
// Used to redirect about: URLs to chrome: URLs.
|
|
|
|
handler->AddHandlerPair(&scheme::WillHandleBrowserAboutURL,
|
|
|
|
content::BrowserURLHandler::null_handler());
|
|
|
|
}
|
|
|
|
|
2012-04-03 03:34:16 +02:00
|
|
|
std::string CefContentBrowserClient::GetDefaultDownloadName() {
|
|
|
|
return "download";
|
|
|
|
}
|
2012-09-11 00:19:19 +02:00
|
|
|
|
|
|
|
#if defined(OS_WIN)
|
|
|
|
const wchar_t* CefContentBrowserClient::GetResourceDllName() {
|
|
|
|
static wchar_t file_path[MAX_PATH+1] = {0};
|
|
|
|
|
|
|
|
if (file_path[0] == 0) {
|
|
|
|
// Retrieve the module path (usually libcef.dll).
|
|
|
|
FilePath module;
|
|
|
|
PathService::Get(base::FILE_MODULE, &module);
|
|
|
|
const std::wstring wstr = module.value();
|
|
|
|
size_t count = std::min(static_cast<size_t>(MAX_PATH), wstr.size());
|
|
|
|
wcsncpy(file_path, wstr.c_str(), count);
|
|
|
|
file_path[count] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return file_path;
|
|
|
|
}
|
|
|
|
#endif // defined(OS_WIN)
|