- Pass information to the renderer process synchronously on render thread creation and new browser creation to avoid race conditions (issue #744).

- Add the ability to pass extra information to child processes using a new CefBrowserProcessHandler::OnRenderProcessThreadCreated callback (issue #744).
- Fix OnBeforeChildProcessLaunch documentation (issue #754).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@910 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt
2012-11-20 20:08:36 +00:00
parent 8a504d3d25
commit 1e871cc2c8
32 changed files with 957 additions and 234 deletions

View File

@@ -10,6 +10,7 @@
#include "libcef/browser/browser_context.h"
#include "libcef/browser/chrome_scheme_handler.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/context.h"
#include "libcef/browser/devtools_delegate.h"
#include "libcef/browser/navigate_params.h"
@@ -251,8 +252,10 @@ CefRefPtr<CefBrowser> CefBrowserHost::CreateBrowserSync(
return NULL;
}
int browser_id = _Context->GetNextBrowserID();
CefRefPtr<CefBrowserHostImpl> browser =
CefBrowserHostImpl::Create(windowInfo, settings, client, NULL, NULL);
CefBrowserHostImpl::Create(windowInfo, settings, client, NULL, browser_id,
NULL);
if (!url.empty())
browser->LoadURL(CefFrameHostImpl::kMainFrameId, url);
return browser.get();
@@ -268,6 +271,7 @@ CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::Create(
const CefBrowserSettings& settings,
CefRefPtr<CefClient> client,
content::WebContents* web_contents,
int browser_id,
CefWindowHandle opener) {
CEF_REQUIRE_UIT();
@@ -281,7 +285,7 @@ CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::Create(
CefRefPtr<CefBrowserHostImpl> browser =
new CefBrowserHostImpl(window_info, settings, client, web_contents,
opener);
browser_id, opener);
if (!browser->PlatformCreateWindow())
return NULL;
@@ -561,7 +565,7 @@ void CefBrowserHostImpl::StopLoad() {
}
int CefBrowserHostImpl::GetIdentifier() {
return unique_id();
return browser_id();
}
bool CefBrowserHostImpl::IsPopup() {
@@ -669,12 +673,6 @@ bool CefBrowserHostImpl::SendProcessMessage(
// CefBrowserHostImpl public methods.
// -----------------------------------------------------------------------------
void CefBrowserHostImpl::SetUniqueId(int unique_id) {
CEF_REQUIRE_UIT();
unique_id_ = unique_id;
Send(new CefMsg_UpdateBrowserWindowId(routing_id(), unique_id, IsPopup()));
}
void CefBrowserHostImpl::DestroyBrowser() {
CEF_REQUIRE_UIT();
@@ -1218,9 +1216,16 @@ void CefBrowserHostImpl::WebContentsCreated(
if (source_contents)
opener = GetBrowserForContents(source_contents)->GetWindowHandle();
CefContentBrowserClient::NewPopupBrowserInfo info;
CefContentBrowserClient::Get()->GetNewPopupBrowserInfo(
new_contents->GetRenderProcessHost()->GetID(),
new_contents->GetRoutingID(),
&info);
DCHECK_GT(info.browser_id, 0);
CefRefPtr<CefBrowserHostImpl> browser = CefBrowserHostImpl::Create(
pending_window_info_, pending_settings_, pending_client_, new_contents,
opener);
info.browser_id, opener);
pending_client_ = NULL;
}
@@ -1288,6 +1293,12 @@ void CefBrowserHostImpl::RenderViewDeleted(
}
void CefBrowserHostImpl::RenderViewReady() {
if (IsPopup()) {
CefContentBrowserClient::Get()->ClearNewPopupBrowserInfo(
web_contents()->GetRenderProcessHost()->GetID(),
web_contents()->GetRoutingID());
}
// Send the queued messages.
queue_messages_ = false;
while (!queued_messages_.empty()) {
@@ -1511,15 +1522,16 @@ CefBrowserHostImpl::CefBrowserHostImpl(const CefWindowInfo& window_info,
const CefBrowserSettings& settings,
CefRefPtr<CefClient> client,
content::WebContents* web_contents,
int browser_id,
CefWindowHandle opener)
: content::WebContentsObserver(web_contents),
window_info_(window_info),
settings_(settings),
client_(client),
browser_id_(browser_id),
opener_(opener),
render_process_id_(0),
render_view_id_(0),
unique_id_(0),
render_process_id_(MSG_ROUTING_NONE),
render_view_id_(MSG_ROUTING_NONE),
is_loading_(false),
can_go_back_(false),
can_go_forward_(false),

View File

@@ -78,6 +78,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
const CefBrowserSettings& settings,
CefRefPtr<CefClient> client,
content::WebContents* web_contents,
int browser_id,
CefWindowHandle opener);
// Returns the browser associated with the specified RenderViewHost.
@@ -138,9 +139,6 @@ class CefBrowserHostImpl : public CefBrowserHost,
CefProcessId target_process,
CefRefPtr<CefProcessMessage> message) OVERRIDE;
// Set the unique identifier for this browser.
void SetUniqueId(int unique_id);
// Destroy the browser members. This method should only be called after the
// native browser window is not longer processing messages.
void DestroyBrowser();
@@ -198,7 +196,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
// Thread safe accessors.
const CefBrowserSettings& settings() const { return settings_; }
CefRefPtr<CefClient> client() const { return client_; }
int unique_id() const { return unique_id_; }
int browser_id() const { return browser_id_; }
// Returns the URL that is currently loading (or loaded) in the main frame.
GURL GetLoadingURL();
@@ -323,6 +321,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
const CefBrowserSettings& settings,
CefRefPtr<CefClient> client,
content::WebContents* web_contents,
int browser_id,
CefWindowHandle opener);
// Initialize settings based on the specified RenderViewHost.
@@ -398,6 +397,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
CefBrowserSettings settings_;
CefRefPtr<CefClient> client_;
scoped_ptr<content::WebContents> web_contents_;
int browser_id_;
CefWindowHandle opener_;
// Unique ids used for routing communication to/from the renderer. We keep a
@@ -406,9 +406,6 @@ class CefBrowserHostImpl : public CefBrowserHost,
int render_process_id_;
int render_view_id_;
// Unique id for the browser.
int unique_id_;
// Used when creating a new popup window.
CefWindowInfo pending_window_info_;
CefBrowserSettings pending_settings_;

View File

@@ -5,12 +5,17 @@
#include "libcef/browser/browser_message_filter.h"
#include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/context.h"
#include "libcef/browser/origin_whitelist_impl.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/cef_messages.h"
#include "libcef/common/values_impl.h"
#include "base/compiler_specific.h"
#include "base/bind.h"
#include "content/public/browser/render_process_host.h"
CefBrowserMessageFilter::CefBrowserMessageFilter(
content::RenderProcessHost* host)
@@ -31,22 +36,50 @@ void CefBrowserMessageFilter::OnFilterRemoved() {
bool CefBrowserMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(CefBrowserMessageFilter, message)
IPC_MESSAGE_HANDLER(CefProcessHostMsg_RenderThreadStarted,
OnRenderThreadStarted)
IPC_MESSAGE_HANDLER(CefProcessHostMsg_GetNewRenderThreadInfo,
OnGetNewRenderThreadInfo)
IPC_MESSAGE_HANDLER(CefProcessHostMsg_GetNewBrowserInfo,
OnGetNewBrowserInfo)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void CefBrowserMessageFilter::OnRenderThreadStarted() {
// Execute registration on the UI thread.
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserMessageFilter::RegisterOnUIThread, this));
bool CefBrowserMessageFilter::Send(IPC::Message* message) {
return host_->Send(message);
}
void CefBrowserMessageFilter::RegisterOnUIThread() {
CEF_REQUIRE_UIT();
// Send existing registrations to the new render process.
RegisterCrossOriginWhitelistEntriesWithHost(host_);
void CefBrowserMessageFilter::OnGetNewRenderThreadInfo(
CefProcessHostMsg_GetNewRenderThreadInfo_Params* params) {
GetCrossOriginWhitelistEntries(&params->cross_origin_whitelist_entries);
CefRefPtr<CefApp> app = _Context->application();
if (app.get()) {
CefRefPtr<CefBrowserProcessHandler> handler =
app->GetBrowserProcessHandler();
if (handler.get()) {
CefRefPtr<CefListValueImpl> listValuePtr(
new CefListValueImpl(&params->extra_info, false, false));
handler->OnRenderProcessThreadCreated(listValuePtr.get());
listValuePtr->Detach(NULL);
}
}
}
void CefBrowserMessageFilter::OnGetNewBrowserInfo(
int routing_id, CefProcessHostMsg_GetNewBrowserInfo_Params* params) {
CefRefPtr<CefBrowserHostImpl> browser =
CefBrowserHostImpl::GetBrowserByRoutingID(host_->GetID(), routing_id);
if (browser.get()) {
params->browser_id = browser->GetIdentifier();
params->is_popup = browser->IsPopup();
} else {
CefContentBrowserClient::NewPopupBrowserInfo info;
CefContentBrowserClient::Get()->GetNewPopupBrowserInfo(host_->GetID(),
routing_id,
&info);
DCHECK_GT(info.browser_id, 0);
params->browser_id = info.browser_id;
params->is_popup = true;
}
}

View File

@@ -13,6 +13,9 @@ namespace content {
class RenderProcessHost;
}
struct CefProcessHostMsg_GetNewBrowserInfo_Params;
struct CefProcessHostMsg_GetNewRenderThreadInfo_Params;
// This class sends and receives control messages on the browser process.
class CefBrowserMessageFilter : public IPC::ChannelProxy::MessageFilter {
public:
@@ -24,11 +27,14 @@ class CefBrowserMessageFilter : public IPC::ChannelProxy::MessageFilter {
virtual void OnFilterRemoved() OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
bool Send(IPC::Message* message);
private:
// Message handlers.
void OnRenderThreadStarted();
void RegisterOnUIThread();
void OnGetNewRenderThreadInfo(
CefProcessHostMsg_GetNewRenderThreadInfo_Params* params);
void OnGetNewBrowserInfo(int routing_id,
CefProcessHostMsg_GetNewBrowserInfo_Params* params);
content::RenderProcessHost* host_;
IPC::Channel* channel_;

View File

@@ -247,6 +247,44 @@ CefContentBrowserClient::CefContentBrowserClient()
CefContentBrowserClient::~CefContentBrowserClient() {
}
// 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);
}
content::BrowserMainParts* CefContentBrowserClient::CreateBrowserMainParts(
const content::MainFunctionParams& parameters) {
browser_main_parts_ = new CefBrowserMainParts(parameters);

View File

@@ -6,12 +6,14 @@
#define CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_
#pragma once
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "content/public/browser/content_browser_client.h"
class CefBrowserMainParts;
@@ -28,10 +30,29 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
CefContentBrowserClient();
virtual ~CefContentBrowserClient();
// Returns the singleton CefContentBrowserClient instance.
static CefContentBrowserClient* Get();
CefBrowserMainParts* browser_main_parts() const {
return browser_main_parts_;
}
// During popup window creation there is a race between the call to
// CefBrowserMessageFilter::OnGetNewBrowserInfo on the IO thread and the call
// to CefBrowserHostImpl::WebContentsCreated on the UI thread. To resolve this
// race we create the info when requested for the first time.
class NewPopupBrowserInfo {
public:
NewPopupBrowserInfo()
: browser_id(0) {}
int browser_id;
};
void GetNewPopupBrowserInfo(int render_process_id,
int render_view_id,
NewPopupBrowserInfo* info);
void ClearNewPopupBrowserInfo(int render_process_id,
int render_view_id);
virtual content::BrowserMainParts* CreateBrowserMainParts(
const content::MainFunctionParams& parameters) OVERRIDE;
virtual void RenderProcessHostCreated(
@@ -60,6 +81,14 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
scoped_ptr<content::PluginServiceFilter> plugin_service_filter_;
scoped_ptr<CefResourceDispatcherHostDelegate>
resource_dispatcher_host_delegate_;
base::Lock new_popup_browser_lock_;
// Map of (render_process_id, render_view_id) to info. Access must be
// protected by |new_popup_browser_lock_|.
typedef std::map<std::pair<int, int>, NewPopupBrowserInfo>
NewPopupBrowserInfoMap;
NewPopupBrowserInfoMap new_popup_browser_info_map_;
};
#endif // CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_

View File

@@ -167,8 +167,7 @@ void CefQuitMessageLoop() {
CefContext::CefContext()
: initialized_(false),
shutting_down_(false),
init_thread_id_(0),
next_browser_id_(kNextBrowserIdReset) {
init_thread_id_(0) {
}
CefContext::~CefContext() {
@@ -271,48 +270,26 @@ bool CefContext::OnInitThread() {
return (base::PlatformThread::CurrentId() == init_thread_id_);
}
bool CefContext::AddBrowser(CefRefPtr<CefBrowserHostImpl> browser) {
bool found = false;
int CefContext::GetNextBrowserID() {
return next_browser_id_.GetNext() + 1;
}
void CefContext::AddBrowser(CefRefPtr<CefBrowserHostImpl> browser) {
AutoLock lock_scope(this);
// check that the browser isn't already in the list before adding
BrowserList::const_iterator it = browserlist_.begin();
browserlist_.push_back(browser);
}
void CefContext::RemoveBrowser(CefRefPtr<CefBrowserHostImpl> browser) {
AutoLock lock_scope(this);
BrowserList::iterator it = browserlist_.begin();
for (; it != browserlist_.end(); ++it) {
if (it->get() == browser.get()) {
found = true;
browserlist_.erase(it);
break;
}
}
if (!found) {
browser->SetUniqueId(next_browser_id_++);
browserlist_.push_back(browser);
}
return !found;
}
bool CefContext::RemoveBrowser(CefRefPtr<CefBrowserHostImpl> browser) {
bool deleted = false;
{
AutoLock lock_scope(this);
BrowserList::iterator it = browserlist_.begin();
for (; it != browserlist_.end(); ++it) {
if (it->get() == browser.get()) {
browserlist_.erase(it);
deleted = true;
break;
}
}
if (browserlist_.empty())
next_browser_id_ = kNextBrowserIdReset;
}
return deleted;
}
CefRefPtr<CefBrowserHostImpl> CefContext::GetBrowserByID(int id) {
@@ -320,7 +297,7 @@ CefRefPtr<CefBrowserHostImpl> CefContext::GetBrowserByID(int id) {
BrowserList::const_iterator it = browserlist_.begin();
for (; it != browserlist_.end(); ++it) {
if (it->get()->unique_id() == id)
if (it->get()->browser_id() == id)
return it->get();
}

View File

@@ -13,6 +13,7 @@
#include "include/cef_app.h"
#include "include/cef_base.h"
#include "base/atomic_sequence_num.h"
#include "base/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/scoped_temp_dir.h"
@@ -54,8 +55,9 @@ class CefContext : public CefBase {
// Returns true if the context is shutting down.
bool shutting_down() { return shutting_down_; }
bool AddBrowser(CefRefPtr<CefBrowserHostImpl> browser);
bool RemoveBrowser(CefRefPtr<CefBrowserHostImpl> browser);
int GetNextBrowserID();
void AddBrowser(CefRefPtr<CefBrowserHostImpl> browser);
void RemoveBrowser(CefRefPtr<CefBrowserHostImpl> browser);
CefRefPtr<CefBrowserHostImpl> GetBrowserByID(int id);
CefRefPtr<CefBrowserHostImpl> GetBrowserByRoutingID(int render_process_id,
int render_view_id);
@@ -97,7 +99,7 @@ class CefContext : public CefBase {
BrowserList browserlist_;
// Used for assigning unique IDs to browser instances.
int next_browser_id_;
base::AtomicSequenceNumber next_browser_id_;
scoped_ptr<CefMainDelegate> main_delegate_;
scoped_ptr<content::ContentMainRunner> main_runner_;

View File

@@ -5,7 +5,7 @@
#include "libcef/browser/origin_whitelist_impl.h"
#include <string>
#include <list>
#include <vector>
#include "include/cef_origin_whitelist.h"
#include "libcef/browser/context.h"
@@ -14,6 +14,7 @@
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/synchronization/lock.h"
#include "content/public/browser/render_process_host.h"
#include "googleurl/src/gurl.h"
@@ -31,25 +32,26 @@ class CefOriginWhitelistManager {
const std::string& target_protocol,
const std::string& target_domain,
bool allow_target_subdomains) {
CEF_REQUIRE_UIT();
OriginInfo info;
Cef_CrossOriginWhiteListEntry_Params info;
info.source_origin = source_origin;
info.target_protocol = target_protocol;
info.target_domain = target_domain;
info.allow_target_subdomains = allow_target_subdomains;
// Verify that the origin entry doesn't already exist.
OriginList::const_iterator it = origin_list_.begin();
for (; it != origin_list_.end(); ++it) {
if (it->Equals(info))
return false;
{
base::AutoLock lock_scope(lock_);
// Verify that the origin entry doesn't already exist.
OriginList::const_iterator it = origin_list_.begin();
for (; it != origin_list_.end(); ++it) {
if (IsEqual(*it, info))
return false;
}
origin_list_.push_back(info);
}
origin_list_.push_back(info);
SendModifyCrossOriginWhitelistEntry(true, source_origin, target_protocol,
target_domain, allow_target_subdomains);
SendModifyCrossOriginWhitelistEntry(true, info);
return true;
}
@@ -57,9 +59,7 @@ class CefOriginWhitelistManager {
const std::string& target_protocol,
const std::string& target_domain,
bool allow_target_subdomains) {
CEF_REQUIRE_UIT();
OriginInfo info;
Cef_CrossOriginWhiteListEntry_Params info;
info.source_origin = source_origin;
info.target_protocol = target_protocol;
info.target_domain = target_domain;
@@ -67,70 +67,63 @@ class CefOriginWhitelistManager {
bool found = false;
OriginList::iterator it = origin_list_.begin();
for (; it != origin_list_.end(); ++it) {
if (it->Equals(info)) {
origin_list_.erase(it);
found = true;
break;
{
base::AutoLock lock_scope(lock_);
OriginList::iterator it = origin_list_.begin();
for (; it != origin_list_.end(); ++it) {
if (IsEqual(*it, info)) {
origin_list_.erase(it);
found = true;
break;
}
}
}
if (!found)
return false;
SendModifyCrossOriginWhitelistEntry(false, source_origin, target_protocol,
target_domain, allow_target_subdomains);
SendModifyCrossOriginWhitelistEntry(false, info);
return true;
}
void ClearOrigins() {
CEF_REQUIRE_UIT();
origin_list_.clear();
{
base::AutoLock lock_scope(lock_);
origin_list_.clear();
}
SendClearCrossOriginWhitelist();
}
// Send all existing cross-origin registrations to the specified host.
void RegisterOriginsWithHost(content::RenderProcessHost* host) {
CEF_REQUIRE_UIT();
void GetCrossOriginWhitelistEntries(
std::vector<Cef_CrossOriginWhiteListEntry_Params>* entries) {
base::AutoLock lock_scope(lock_);
if (origin_list_.empty())
return;
OriginList::const_iterator it = origin_list_.begin();
for (; it != origin_list_.end(); ++it) {
host->Send(
new CefProcessMsg_ModifyCrossOriginWhitelistEntry(
true, it->source_origin, it->target_protocol, it->target_domain,
it->allow_target_subdomains));
}
entries->insert(entries->end(), origin_list_.begin(), origin_list_.end());
}
private:
// Send the modify cross-origin whitelist entry message to all currently
// existing hosts.
void SendModifyCrossOriginWhitelistEntry(bool add,
const std::string& source_origin,
const std::string& target_protocol,
const std::string& target_domain,
bool allow_target_subdomains) {
static void SendModifyCrossOriginWhitelistEntry(
bool add,
Cef_CrossOriginWhiteListEntry_Params& params) {
CEF_REQUIRE_UIT();
content::RenderProcessHost::iterator i(
content::RenderProcessHost::AllHostsIterator());
for (; !i.IsAtEnd(); i.Advance()) {
i.GetCurrentValue()->Send(
new CefProcessMsg_ModifyCrossOriginWhitelistEntry(
add, source_origin, target_protocol, target_domain,
allow_target_subdomains));
new CefProcessMsg_ModifyCrossOriginWhitelistEntry(add, params));
}
}
// Send the clear cross-origin whitelists message to all currently existing
// hosts.
void SendClearCrossOriginWhitelist() {
static void SendClearCrossOriginWhitelist() {
CEF_REQUIRE_UIT();
content::RenderProcessHost::iterator i(
@@ -140,22 +133,18 @@ class CefOriginWhitelistManager {
}
}
struct OriginInfo {
std::string source_origin;
std::string target_protocol;
std::string target_domain;
bool allow_target_subdomains;
static bool IsEqual(const Cef_CrossOriginWhiteListEntry_Params& param1,
const Cef_CrossOriginWhiteListEntry_Params& param2) {
return (param1.source_origin == param2.source_origin &&
param1.target_protocol == param2.target_protocol &&
param1.target_domain == param2.target_domain &&
param1.allow_target_subdomains == param2.allow_target_subdomains);
}
bool Equals(const OriginInfo& info) const {
return (source_origin == info.source_origin &&
target_protocol == info.target_protocol &&
target_domain == info.target_domain &&
allow_target_subdomains == info.allow_target_subdomains);
}
};
base::Lock lock_;
// List of registered origins.
typedef std::list<OriginInfo> OriginList;
// List of registered origins. Access must be protected by |lock_|.
typedef std::vector<Cef_CrossOriginWhiteListEntry_Params> OriginList;
OriginList origin_list_;
DISALLOW_EVIL_CONSTRUCTORS(CefOriginWhitelistManager);
@@ -247,8 +236,8 @@ bool CefClearCrossOriginWhitelist() {
return true;
}
void RegisterCrossOriginWhitelistEntriesWithHost(
content::RenderProcessHost* host) {
CEF_REQUIRE_UIT();
CefOriginWhitelistManager::GetInstance()->RegisterOriginsWithHost(host);
void GetCrossOriginWhitelistEntries(
std::vector<Cef_CrossOriginWhiteListEntry_Params>* entries) {
CefOriginWhitelistManager::GetInstance()->GetCrossOriginWhitelistEntries(
entries);
}

View File

@@ -5,13 +5,17 @@
#ifndef CEF_LIBCEF_BROWSER_ORIGIN_WHITELIST_IMPL_H_
#define CEF_LIBCEF_BROWSER_ORIGIN_WHITELIST_IMPL_H_
#include <vector>
namespace content {
class RenderProcessHost;
}
// Called when a new RenderProcessHost is created to send existing cross-origin
// whitelist entry information.
void RegisterCrossOriginWhitelistEntriesWithHost(
content::RenderProcessHost* host);
struct Cef_CrossOriginWhiteListEntry_Params;
// Called to retrieve the current list of cross-origin white list entries. This
// method is thread safe.
void GetCrossOriginWhitelistEntries(
std::vector<Cef_CrossOriginWhiteListEntry_Params>* entries);
#endif // CEF_LIBCEF_BROWSER_ORIGIN_WHITELIST_IMPL_H_

View File

@@ -58,15 +58,17 @@ IPC_STRUCT_BEGIN(Cef_Response_Params)
IPC_STRUCT_MEMBER(std::string, response)
IPC_STRUCT_END()
// Parameters structure for a cross-origin white list entry.
IPC_STRUCT_BEGIN(Cef_CrossOriginWhiteListEntry_Params)
IPC_STRUCT_MEMBER(std::string, source_origin)
IPC_STRUCT_MEMBER(std::string, target_protocol)
IPC_STRUCT_MEMBER(std::string, target_domain)
IPC_STRUCT_MEMBER(bool, allow_target_subdomains)
IPC_STRUCT_END()
// Messages sent from the browser to the renderer.
// Tell the renderer which browser window it's being attached to.
IPC_MESSAGE_ROUTED2(CefMsg_UpdateBrowserWindowId,
int /* browser_id */,
bool /* is_popup */)
// Parameters for a resource request.
IPC_STRUCT_BEGIN(CefMsg_LoadRequest_Params)
// The request method: GET, POST, etc.
@@ -121,12 +123,9 @@ IPC_MESSAGE_ROUTED1(CefMsg_ResponseAck,
int /* request_id */)
// Sent to child processes to add or remove a cross-origin whitelist entry.
IPC_MESSAGE_CONTROL5(CefProcessMsg_ModifyCrossOriginWhitelistEntry,
IPC_MESSAGE_CONTROL2(CefProcessMsg_ModifyCrossOriginWhitelistEntry,
bool /* add */,
std::string /* source_origin */,
std::string /* target_protocol */,
std::string /* target_domain */,
bool /* allow_target_subdomains */)
Cef_CrossOriginWhiteListEntry_Params /* params */)
// Sent to child processes to clear the cross-origin whitelist.
IPC_MESSAGE_CONTROL0(CefProcessMsg_ClearCrossOriginWhitelist)
@@ -134,8 +133,30 @@ IPC_MESSAGE_CONTROL0(CefProcessMsg_ClearCrossOriginWhitelist)
// Messages sent from the renderer to the browser.
// Sent when the render thread has started and all filters are attached.
IPC_MESSAGE_CONTROL0(CefProcessHostMsg_RenderThreadStarted)
// Parameters for a newly created render thread.
IPC_STRUCT_BEGIN(CefProcessHostMsg_GetNewRenderThreadInfo_Params)
IPC_STRUCT_MEMBER(std::vector<Cef_CrossOriginWhiteListEntry_Params>,
cross_origin_whitelist_entries)
IPC_STRUCT_MEMBER(ListValue, extra_info)
IPC_STRUCT_END()
// Retrieve information about a newly created render thread.
IPC_SYNC_MESSAGE_CONTROL0_1(
CefProcessHostMsg_GetNewRenderThreadInfo,
CefProcessHostMsg_GetNewRenderThreadInfo_Params /* params*/)
// Parameters for a newly created browser window.
IPC_STRUCT_BEGIN(CefProcessHostMsg_GetNewBrowserInfo_Params)
IPC_STRUCT_MEMBER(int, browser_id)
IPC_STRUCT_MEMBER(bool, is_popup)
IPC_STRUCT_END()
// Retrieve information about a newly created browser window.
IPC_SYNC_MESSAGE_CONTROL1_1(
CefProcessHostMsg_GetNewBrowserInfo,
int /* routing_id */,
CefProcessHostMsg_GetNewBrowserInfo_Params /* params*/)
// Sent when a frame is identified for the first time.
IPC_MESSAGE_ROUTED3(CefHostMsg_FrameIdentified,

View File

@@ -38,6 +38,14 @@ CefRefPtr<CefBinaryValue> CefBinaryValueImpl::GetOrCreateRef(
CefBinaryValueImpl::kReference, controller);
}
CefBinaryValueImpl::CefBinaryValueImpl(base::BinaryValue* value,
bool will_delete,
bool read_only)
: CefValueBase<CefBinaryValue, base::BinaryValue>(
value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete,
read_only, NULL) {
}
base::BinaryValue* CefBinaryValueImpl::CopyValue() {
CEF_VALUE_VERIFY_RETURN(false, NULL);
return const_value().DeepCopy();
@@ -139,6 +147,14 @@ CefRefPtr<CefDictionaryValue> CefDictionaryValueImpl::GetOrCreateRef(
CefDictionaryValueImpl::kReference, read_only, controller);
}
CefDictionaryValueImpl::CefDictionaryValueImpl(base::DictionaryValue* value,
bool will_delete,
bool read_only)
: CefValueBase<CefDictionaryValue, base::DictionaryValue>(
value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete,
read_only, NULL) {
}
base::DictionaryValue* CefDictionaryValueImpl::CopyValue() {
CEF_VALUE_VERIFY_RETURN(false, NULL);
return const_value().DeepCopy();
@@ -487,6 +503,14 @@ CefRefPtr<CefListValue> CefListValueImpl::GetOrCreateRef(
CefListValueImpl::kReference, read_only, controller);
}
CefListValueImpl::CefListValueImpl(base::ListValue* value,
bool will_delete,
bool read_only)
: CefValueBase<CefListValue, base::ListValue>(
value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete,
read_only, NULL) {
}
base::ListValue* CefListValueImpl::CopyValue() {
CEF_VALUE_VERIFY_RETURN(false, NULL);
return const_value().DeepCopy();

View File

@@ -25,6 +25,11 @@ class CefBinaryValueImpl
void* parent_value,
CefValueController* controller);
// Simple constructor for referencing existing value objects.
CefBinaryValueImpl(base::BinaryValue* value,
bool will_delete,
bool read_only);
// Return a copy of the value.
base::BinaryValue* CopyValue();
@@ -72,6 +77,11 @@ class CefDictionaryValueImpl
bool read_only,
CefValueController* controller);
// Simple constructor for referencing existing value objects.
CefDictionaryValueImpl(base::DictionaryValue* value,
bool will_delete,
bool read_only);
// Return a copy of the value.
base::DictionaryValue* CopyValue();
@@ -140,6 +150,11 @@ class CefListValueImpl
bool read_only,
CefValueController* controller);
// Simple constructor for referencing existing value objects.
CefListValueImpl(base::ListValue* value,
bool will_delete,
bool read_only);
// Return a copy of the value.
base::ListValue* CopyValue();

View File

@@ -250,10 +250,12 @@ bool CefBrowserImpl::SendProcessMessage(CefProcessId target_process,
// CefBrowserImpl public methods.
// -----------------------------------------------------------------------------
CefBrowserImpl::CefBrowserImpl(content::RenderView* render_view)
CefBrowserImpl::CefBrowserImpl(content::RenderView* render_view,
int browser_id,
bool is_popup)
: content::RenderViewObserver(render_view),
browser_window_id_(kInvalidBrowserId),
is_popup_(false),
browser_window_id_(browser_id),
is_popup_(is_popup),
last_focused_frame_id_(kInvalidFrameId) {
response_manager_.reset(new CefResponseManager);
}
@@ -547,8 +549,6 @@ void CefBrowserImpl::DidCreateDataSource(WebKit::WebFrame* frame,
bool CefBrowserImpl::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(CefBrowserImpl, message)
IPC_MESSAGE_HANDLER(CefMsg_UpdateBrowserWindowId,
OnUpdateBrowserWindowId)
IPC_MESSAGE_HANDLER(CefMsg_Request, OnRequest)
IPC_MESSAGE_HANDLER(CefMsg_Response, OnResponse)
IPC_MESSAGE_HANDLER(CefMsg_ResponseAck, OnResponseAck)
@@ -562,23 +562,6 @@ bool CefBrowserImpl::OnMessageReceived(const IPC::Message& message) {
// RenderViewObserver::OnMessageReceived message handlers.
// -----------------------------------------------------------------------------
void CefBrowserImpl::OnUpdateBrowserWindowId(int window_id, bool is_popup) {
// This message should only be sent one time.
DCHECK(browser_window_id_ == kInvalidBrowserId);
browser_window_id_ = window_id;
is_popup_ = is_popup;
// Notify that the browser window has been created.
CefRefPtr<CefApp> app = CefContentClient::Get()->application();
if (app.get()) {
CefRefPtr<CefRenderProcessHandler> handler =
app->GetRenderProcessHandler();
if (handler.get())
handler->OnBrowserCreated(this);
}
}
void CefBrowserImpl::OnRequest(const Cef_Request_Params& params) {
bool success = false;
std::string response;

View File

@@ -76,7 +76,9 @@ class CefBrowserImpl : public CefBrowser,
CefProcessId target_process,
CefRefPtr<CefProcessMessage> message) OVERRIDE;
explicit CefBrowserImpl(content::RenderView* render_view);
CefBrowserImpl(content::RenderView* render_view,
int browser_id,
bool is_popup);
virtual ~CefBrowserImpl();
void LoadRequest(const CefMsg_LoadRequest_Params& params);
@@ -110,7 +112,6 @@ class CefBrowserImpl : public CefBrowser,
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
// RenderViewObserver::OnMessageReceived message handlers.
void OnUpdateBrowserWindowId(int window_id, bool is_popup);
void OnRequest(const Cef_Request_Params& params);
void OnResponse(const Cef_Response_Params& params);
void OnResponseAck(int request_id);

View File

@@ -16,6 +16,7 @@ MSVC_POP_WARNING();
#include "libcef/common/cef_messages.h"
#include "libcef/common/content_client.h"
#include "libcef/common/request_impl.h"
#include "libcef/common/values_impl.h"
#include "libcef/renderer/browser_impl.h"
#include "libcef/renderer/chrome_bindings.h"
#include "libcef/renderer/render_message_filter.h"
@@ -182,7 +183,44 @@ void CefContentRendererClient::RenderThreadStarted() {
WebKit::WebPrerenderingSupport::initialize(new CefPrerenderingSupport());
thread->Send(new CefProcessHostMsg_RenderThreadStarted);
// Retrieve the new render thread information synchronously.
CefProcessHostMsg_GetNewRenderThreadInfo_Params params;
thread->Send(new CefProcessHostMsg_GetNewRenderThreadInfo(&params));
if (params.cross_origin_whitelist_entries.size() > 0) {
// Cross-origin entries need to be added after WebKit is initialized.
observer_->set_pending_cross_origin_whitelist_entries(
params.cross_origin_whitelist_entries);
}
// Notify the render process handler.
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
if (application.get()) {
CefRefPtr<CefRenderProcessHandler> handler =
application->GetRenderProcessHandler();
if (handler.get()) {
CefRefPtr<CefListValueImpl> listValuePtr(
new CefListValueImpl(&params.extra_info, false, true));
handler->OnRenderThreadCreated(listValuePtr.get());
listValuePtr->Detach(NULL);
}
}
}
void CefContentRendererClient::RenderViewCreated(
content::RenderView* render_view) {
// Retrieve the new browser information synchronously.
CefProcessHostMsg_GetNewBrowserInfo_Params params;
content::RenderThread::Get()->Send(
new CefProcessHostMsg_GetNewBrowserInfo(render_view->GetRoutingID(),
&params));
DCHECK_GT(params.browser_id, 0);
CefRefPtr<CefBrowserImpl> browser =
new CefBrowserImpl(render_view, params.browser_id, params.is_popup);
browsers_.insert(std::make_pair(render_view, browser));
new CefPrerendererClient(render_view);
// Notify the render process handler.
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
@@ -190,18 +228,10 @@ void CefContentRendererClient::RenderThreadStarted() {
CefRefPtr<CefRenderProcessHandler> handler =
application->GetRenderProcessHandler();
if (handler.get())
handler->OnRenderThreadCreated();
handler->OnBrowserCreated(browser.get());
}
}
void CefContentRendererClient::RenderViewCreated(
content::RenderView* render_view) {
CefRefPtr<CefBrowserImpl> browser = new CefBrowserImpl(render_view);
browsers_.insert(std::make_pair(render_view, browser));
new CefPrerendererClient(render_view);
}
bool CefContentRendererClient::HandleNavigation(
WebKit::WebFrame* frame,
const WebKit::WebURLRequest& request,

View File

@@ -57,6 +57,22 @@ void CefRenderProcessObserver::WebKitInitialized() {
// Register any custom schemes with WebKit.
CefContentRendererClient::Get()->RegisterCustomSchemes();
if (pending_cross_origin_whitelist_entries_.size() > 0) {
// Add pending cross-origin white list entries.
for (size_t i = 0;
i < pending_cross_origin_whitelist_entries_.size(); ++i) {
const Cef_CrossOriginWhiteListEntry_Params& entry =
pending_cross_origin_whitelist_entries_[i];
GURL gurl = GURL(entry.source_origin);
WebKit::WebSecurityPolicy::addOriginAccessWhitelistEntry(
gurl,
WebKit::WebString::fromUTF8(entry.target_protocol),
WebKit::WebString::fromUTF8(entry.target_domain),
entry.allow_target_subdomains);
}
pending_cross_origin_whitelist_entries_.clear();
}
// The number of stack trace frames to capture for uncaught exceptions.
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kUncaughtExceptionStackSize)) {
@@ -86,23 +102,20 @@ void CefRenderProcessObserver::WebKitInitialized() {
void CefRenderProcessObserver::OnModifyCrossOriginWhitelistEntry(
bool add,
const std::string& source_origin,
const std::string& target_protocol,
const std::string& target_domain,
bool allow_target_subdomains) {
GURL gurl = GURL(source_origin);
const Cef_CrossOriginWhiteListEntry_Params& params) {
GURL gurl = GURL(params.source_origin);
if (add) {
WebKit::WebSecurityPolicy::addOriginAccessWhitelistEntry(
gurl,
WebKit::WebString::fromUTF8(target_protocol),
WebKit::WebString::fromUTF8(target_domain),
allow_target_subdomains);
WebKit::WebString::fromUTF8(params.target_protocol),
WebKit::WebString::fromUTF8(params.target_domain),
params.allow_target_subdomains);
} else {
WebKit::WebSecurityPolicy::removeOriginAccessWhitelistEntry(
gurl,
WebKit::WebString::fromUTF8(target_protocol),
WebKit::WebString::fromUTF8(target_domain),
allow_target_subdomains);
WebKit::WebString::fromUTF8(params.target_protocol),
WebKit::WebString::fromUTF8(params.target_domain),
params.allow_target_subdomains);
}
}

View File

@@ -7,28 +7,37 @@
#define CEF_LIBCEF_RENDERER_RENDER_PROCESS_OBSERVER_H_
#include <string>
#include <vector>
#include "base/memory/ref_counted.h"
#include "content/public/renderer/render_process_observer.h"
struct Cef_CrossOriginWhiteListEntry_Params;
// This class sends and receives control messages on the renderer process.
class CefRenderProcessObserver : public content::RenderProcessObserver {
public:
CefRenderProcessObserver();
virtual ~CefRenderProcessObserver();
void set_pending_cross_origin_whitelist_entries(
const std::vector<Cef_CrossOriginWhiteListEntry_Params>& entries) {
pending_cross_origin_whitelist_entries_ = entries;
}
// RenderProcessObserver implementation.
virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
virtual void WebKitInitialized() OVERRIDE;
private:
// Message handlers called on the render thread.
void OnModifyCrossOriginWhitelistEntry(bool add,
const std::string& source_origin,
const std::string& target_protocol,
const std::string& target_domain,
bool allow_target_subdomains);
void OnModifyCrossOriginWhitelistEntry(
bool add,
const Cef_CrossOriginWhiteListEntry_Params& params);
void OnClearCrossOriginWhitelist();
typedef std::vector<Cef_CrossOriginWhiteListEntry_Params> CrossOriginList;
CrossOriginList pending_cross_origin_whitelist_entries_;
DISALLOW_COPY_AND_ASSIGN(CefRenderProcessObserver);
};