mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Move message routing from CefBrowser to CefFrame (see issue #2498).
This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
This commit is contained in:
@@ -65,13 +65,10 @@ scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::CreateBrowserInfo(
|
||||
CefRefPtr<CefDictionaryValue> extra_info) {
|
||||
base::AutoLock lock_scope(browser_info_lock_);
|
||||
|
||||
scoped_refptr<CefBrowserInfo> browser_info =
|
||||
new CefBrowserInfo(++next_browser_id_, is_popup, extra_info);
|
||||
scoped_refptr<CefBrowserInfo> browser_info = new CefBrowserInfo(
|
||||
++next_browser_id_, is_popup, is_windowless, extra_info);
|
||||
browser_info_list_.push_back(browser_info);
|
||||
|
||||
if (is_windowless)
|
||||
browser_info->set_windowless(true);
|
||||
|
||||
return browser_info;
|
||||
}
|
||||
|
||||
@@ -81,32 +78,20 @@ scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::CreatePopupBrowserInfo(
|
||||
CefRefPtr<CefDictionaryValue> extra_info) {
|
||||
base::AutoLock lock_scope(browser_info_lock_);
|
||||
|
||||
content::RenderFrameHost* frame_host = new_contents->GetMainFrame();
|
||||
auto frame_host = new_contents->GetMainFrame();
|
||||
const int render_process_id = frame_host->GetProcess()->GetID();
|
||||
const int render_frame_routing_id = frame_host->GetRoutingID();
|
||||
const auto frame_id = CefFrameHostImpl::MakeFrameId(frame_host);
|
||||
|
||||
scoped_refptr<CefBrowserInfo> browser_info =
|
||||
new CefBrowserInfo(++next_browser_id_, true, extra_info);
|
||||
browser_info->render_id_manager()->add_render_frame_id(
|
||||
render_process_id, render_frame_routing_id);
|
||||
new CefBrowserInfo(++next_browser_id_, true, is_windowless, extra_info);
|
||||
browser_info_list_.push_back(browser_info);
|
||||
|
||||
if (is_windowless)
|
||||
browser_info->set_windowless(true);
|
||||
|
||||
// Continue any pending NewBrowserInfo requests.
|
||||
PendingNewBrowserInfoList::iterator it =
|
||||
pending_new_browser_info_list_.begin();
|
||||
for (; it != pending_new_browser_info_list_.end(); ++it) {
|
||||
PendingNewBrowserInfo* info = it->get();
|
||||
if (info->render_process_id == render_process_id &&
|
||||
info->render_frame_routing_id == render_frame_routing_id) {
|
||||
SendNewBrowserInfoResponse(render_process_id, browser_info, false,
|
||||
info->reply_msg);
|
||||
|
||||
pending_new_browser_info_list_.erase(it);
|
||||
break;
|
||||
}
|
||||
auto it = pending_new_browser_info_map_.find(frame_id);
|
||||
if (it != pending_new_browser_info_map_.end()) {
|
||||
SendNewBrowserInfoResponse(render_process_id, browser_info, false,
|
||||
it->second->reply_msg);
|
||||
pending_new_browser_info_map_.erase(it);
|
||||
}
|
||||
|
||||
return browser_info;
|
||||
@@ -159,8 +144,8 @@ bool CefBrowserInfoManager::CanCreateWindow(
|
||||
|
||||
auto pending_popup = std::make_unique<CefBrowserInfoManager::PendingPopup>();
|
||||
pending_popup->step = CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW;
|
||||
pending_popup->opener_process_id = opener->GetProcess()->GetID();
|
||||
pending_popup->opener_frame_id = opener->GetRoutingID();
|
||||
pending_popup->opener_render_process_id = opener->GetProcess()->GetID();
|
||||
pending_popup->opener_render_routing_id = opener->GetRoutingID();
|
||||
pending_popup->target_url = target_url;
|
||||
pending_popup->target_frame_name = frame_name;
|
||||
|
||||
@@ -171,8 +156,8 @@ bool CefBrowserInfoManager::CanCreateWindow(
|
||||
if (client.get()) {
|
||||
CefRefPtr<CefLifeSpanHandler> handler = client->GetLifeSpanHandler();
|
||||
if (handler.get()) {
|
||||
CefRefPtr<CefFrame> frame =
|
||||
browser->GetFrame(pending_popup->opener_frame_id);
|
||||
CefRefPtr<CefFrame> opener_frame = browser->GetFrameForHost(opener);
|
||||
DCHECK(opener_frame);
|
||||
|
||||
CefPopupFeatures cef_features;
|
||||
TranslatePopupFeatures(features, cef_features);
|
||||
@@ -190,7 +175,7 @@ bool CefBrowserInfoManager::CanCreateWindow(
|
||||
#endif
|
||||
|
||||
allow = !handler->OnBeforePopup(
|
||||
browser.get(), frame, pending_popup->target_url.spec(),
|
||||
browser.get(), opener_frame, pending_popup->target_url.spec(),
|
||||
pending_popup->target_frame_name,
|
||||
static_cast<cef_window_open_disposition_t>(disposition), user_gesture,
|
||||
cef_features, *window_info, pending_popup->client,
|
||||
@@ -229,14 +214,14 @@ bool CefBrowserInfoManager::CanCreateWindow(
|
||||
void CefBrowserInfoManager::GetCustomWebContentsView(
|
||||
const GURL& target_url,
|
||||
int opener_render_process_id,
|
||||
int opener_render_frame_id,
|
||||
int opener_render_routing_id,
|
||||
content::WebContentsView** view,
|
||||
content::RenderViewHostDelegateView** delegate_view) {
|
||||
CEF_REQUIRE_UIT();
|
||||
|
||||
std::unique_ptr<CefBrowserInfoManager::PendingPopup> pending_popup =
|
||||
PopPendingPopup(CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW,
|
||||
opener_render_process_id, opener_render_frame_id,
|
||||
opener_render_process_id, opener_render_routing_id,
|
||||
target_url);
|
||||
DCHECK(pending_popup.get());
|
||||
DCHECK(pending_popup->platform_delegate.get());
|
||||
@@ -254,7 +239,7 @@ void CefBrowserInfoManager::GetCustomWebContentsView(
|
||||
void CefBrowserInfoManager::WebContentsCreated(
|
||||
const GURL& target_url,
|
||||
int opener_render_process_id,
|
||||
int opener_render_frame_id,
|
||||
int opener_render_routing_id,
|
||||
CefBrowserSettings& settings,
|
||||
CefRefPtr<CefClient>& client,
|
||||
std::unique_ptr<CefBrowserPlatformDelegate>& platform_delegate,
|
||||
@@ -264,7 +249,7 @@ void CefBrowserInfoManager::WebContentsCreated(
|
||||
std::unique_ptr<CefBrowserInfoManager::PendingPopup> pending_popup =
|
||||
PopPendingPopup(
|
||||
CefBrowserInfoManager::PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW,
|
||||
opener_render_process_id, opener_render_frame_id, target_url);
|
||||
opener_render_process_id, opener_render_routing_id, target_url);
|
||||
DCHECK(pending_popup.get());
|
||||
DCHECK(pending_popup->platform_delegate.get());
|
||||
|
||||
@@ -275,18 +260,18 @@ void CefBrowserInfoManager::WebContentsCreated(
|
||||
}
|
||||
|
||||
void CefBrowserInfoManager::OnGetNewBrowserInfo(int render_process_id,
|
||||
int render_frame_routing_id,
|
||||
int render_routing_id,
|
||||
IPC::Message* reply_msg) {
|
||||
DCHECK_NE(render_process_id, content::ChildProcessHost::kInvalidUniqueID);
|
||||
DCHECK_GT(render_frame_routing_id, 0);
|
||||
DCHECK_GT(render_routing_id, 0);
|
||||
DCHECK(reply_msg);
|
||||
|
||||
base::AutoLock lock_scope(browser_info_lock_);
|
||||
|
||||
bool is_guest_view = false;
|
||||
|
||||
scoped_refptr<CefBrowserInfo> browser_info = GetBrowserInfo(
|
||||
render_process_id, render_frame_routing_id, &is_guest_view);
|
||||
scoped_refptr<CefBrowserInfo> browser_info =
|
||||
GetBrowserInfo(render_process_id, render_routing_id, &is_guest_view);
|
||||
|
||||
if (browser_info.get()) {
|
||||
// Send the response immediately.
|
||||
@@ -295,27 +280,20 @@ void CefBrowserInfoManager::OnGetNewBrowserInfo(int render_process_id,
|
||||
return;
|
||||
}
|
||||
|
||||
#if DCHECK_IS_ON()
|
||||
const auto frame_id =
|
||||
CefFrameHostImpl::MakeFrameId(render_process_id, render_routing_id);
|
||||
|
||||
// Verify that no request for the same route is currently queued.
|
||||
{
|
||||
PendingNewBrowserInfoList::const_iterator it =
|
||||
pending_new_browser_info_list_.begin();
|
||||
for (; it != pending_new_browser_info_list_.end(); ++it) {
|
||||
PendingNewBrowserInfo* info = it->get();
|
||||
if (info->render_process_id == render_process_id &&
|
||||
info->render_frame_routing_id == render_frame_routing_id) {
|
||||
NOTREACHED();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
DCHECK(pending_new_browser_info_map_.find(frame_id) ==
|
||||
pending_new_browser_info_map_.end());
|
||||
|
||||
// Queue the request.
|
||||
std::unique_ptr<PendingNewBrowserInfo> pending(new PendingNewBrowserInfo());
|
||||
pending->render_process_id = render_process_id;
|
||||
pending->render_frame_routing_id = render_frame_routing_id;
|
||||
pending->render_routing_id = render_routing_id;
|
||||
pending->reply_msg = reply_msg;
|
||||
pending_new_browser_info_list_.push_back(std::move(pending));
|
||||
pending_new_browser_info_map_.insert(
|
||||
std::make_pair(frame_id, std::move(pending)));
|
||||
}
|
||||
|
||||
void CefBrowserInfoManager::RemoveBrowserInfo(
|
||||
@@ -363,26 +341,32 @@ void CefBrowserInfoManager::DestroyAllBrowsers() {
|
||||
#endif
|
||||
}
|
||||
|
||||
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfoForFrame(
|
||||
int render_process_id,
|
||||
int render_routing_id,
|
||||
bool* is_guest_view) {
|
||||
scoped_refptr<CefBrowserInfo>
|
||||
CefBrowserInfoManager::GetBrowserInfoForFrameRoute(int render_process_id,
|
||||
int render_routing_id,
|
||||
bool* is_guest_view) {
|
||||
base::AutoLock lock_scope(browser_info_lock_);
|
||||
return GetBrowserInfo(render_process_id, render_routing_id, is_guest_view);
|
||||
}
|
||||
|
||||
scoped_refptr<CefBrowserInfo>
|
||||
CefBrowserInfoManager::GetBrowserInfoForFrameTreeNode(int frame_tree_node_id) {
|
||||
CefBrowserInfoManager::GetBrowserInfoForFrameTreeNode(int frame_tree_node_id,
|
||||
bool* is_guest_view) {
|
||||
if (is_guest_view)
|
||||
*is_guest_view = false;
|
||||
|
||||
if (frame_tree_node_id < 0)
|
||||
return nullptr;
|
||||
|
||||
base::AutoLock lock_scope(browser_info_lock_);
|
||||
|
||||
BrowserInfoList::const_iterator it = browser_info_list_.begin();
|
||||
for (; it != browser_info_list_.end(); ++it) {
|
||||
const scoped_refptr<CefBrowserInfo>& browser_info = *it;
|
||||
if (browser_info->frame_tree_node_id_manager()->is_frame_tree_node_id_match(
|
||||
frame_tree_node_id)) {
|
||||
for (const auto& browser_info : browser_info_list_) {
|
||||
bool is_guest_view_tmp;
|
||||
auto frame = browser_info->GetFrameForFrameTreeNode(frame_tree_node_id,
|
||||
&is_guest_view_tmp);
|
||||
if (frame || is_guest_view_tmp) {
|
||||
if (is_guest_view)
|
||||
*is_guest_view = is_guest_view_tmp;
|
||||
return browser_info;
|
||||
}
|
||||
}
|
||||
@@ -390,9 +374,12 @@ CefBrowserInfoManager::GetBrowserInfoForFrameTreeNode(int frame_tree_node_id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CefBrowserInfoManager::GetBrowserInfoList(BrowserInfoList& list) {
|
||||
CefBrowserInfoManager::BrowserInfoList
|
||||
CefBrowserInfoManager::GetBrowserInfoList() {
|
||||
base::AutoLock lock_scope(browser_info_lock_);
|
||||
list = browser_info_list_;
|
||||
BrowserInfoList copy;
|
||||
copy.assign(browser_info_list_.begin(), browser_info_list_.end());
|
||||
return copy;
|
||||
}
|
||||
|
||||
void CefBrowserInfoManager::RenderProcessHostDestroyed(
|
||||
@@ -406,12 +393,12 @@ void CefBrowserInfoManager::RenderProcessHostDestroyed(
|
||||
{
|
||||
base::AutoLock lock_scope(browser_info_lock_);
|
||||
|
||||
PendingNewBrowserInfoList::iterator it =
|
||||
pending_new_browser_info_list_.begin();
|
||||
while (it != pending_new_browser_info_list_.end()) {
|
||||
PendingNewBrowserInfo* info = it->get();
|
||||
PendingNewBrowserInfoMap::iterator it =
|
||||
pending_new_browser_info_map_.begin();
|
||||
while (it != pending_new_browser_info_map_.end()) {
|
||||
auto info = it->second.get();
|
||||
if (info->render_process_id == render_process_id)
|
||||
it = pending_new_browser_info_list_.erase(it);
|
||||
it = pending_new_browser_info_map_.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
@@ -422,7 +409,7 @@ void CefBrowserInfoManager::RenderProcessHostDestroyed(
|
||||
PendingPopupList::iterator it = pending_popup_list_.begin();
|
||||
while (it != pending_popup_list_.end()) {
|
||||
PendingPopup* popup = it->get();
|
||||
if (popup->opener_process_id == render_process_id) {
|
||||
if (popup->opener_render_process_id == render_process_id) {
|
||||
it = pending_popup_list_.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
@@ -439,18 +426,19 @@ void CefBrowserInfoManager::PushPendingPopup(
|
||||
|
||||
std::unique_ptr<CefBrowserInfoManager::PendingPopup>
|
||||
CefBrowserInfoManager::PopPendingPopup(PendingPopup::Step step,
|
||||
int opener_process_id,
|
||||
int opener_frame_id,
|
||||
int opener_render_process_id,
|
||||
int opener_render_routing_id,
|
||||
const GURL& target_url) {
|
||||
CEF_REQUIRE_UIT();
|
||||
DCHECK_GT(opener_process_id, 0);
|
||||
DCHECK_GT(opener_frame_id, 0);
|
||||
DCHECK_GT(opener_render_process_id, 0);
|
||||
DCHECK_GT(opener_render_routing_id, 0);
|
||||
|
||||
PendingPopupList::iterator it = pending_popup_list_.begin();
|
||||
for (; it != pending_popup_list_.end(); ++it) {
|
||||
PendingPopup* popup = it->get();
|
||||
if (popup->step == step && popup->opener_process_id == opener_process_id &&
|
||||
popup->opener_frame_id == opener_frame_id &&
|
||||
if (popup->step == step &&
|
||||
popup->opener_render_process_id == opener_render_process_id &&
|
||||
popup->opener_render_routing_id == opener_render_routing_id &&
|
||||
popup->target_url == target_url) {
|
||||
// Transfer ownership of the pointer.
|
||||
it->release();
|
||||
@@ -463,29 +451,24 @@ CefBrowserInfoManager::PopPendingPopup(PendingPopup::Step step,
|
||||
}
|
||||
|
||||
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfo(
|
||||
int render_frame_process_id,
|
||||
int render_frame_routing_id,
|
||||
int render_process_id,
|
||||
int render_routing_id,
|
||||
bool* is_guest_view) {
|
||||
browser_info_lock_.AssertAcquired();
|
||||
|
||||
if (is_guest_view)
|
||||
*is_guest_view = false;
|
||||
|
||||
if (render_frame_process_id < 0 || render_frame_routing_id < 0)
|
||||
if (render_process_id < 0 || render_routing_id < 0)
|
||||
return nullptr;
|
||||
|
||||
BrowserInfoList::const_iterator it = browser_info_list_.begin();
|
||||
for (; it != browser_info_list_.end(); ++it) {
|
||||
const scoped_refptr<CefBrowserInfo>& browser_info = *it;
|
||||
if (browser_info->render_id_manager()->is_render_frame_id_match(
|
||||
render_frame_process_id, render_frame_routing_id)) {
|
||||
return browser_info;
|
||||
}
|
||||
if (extensions::ExtensionsEnabled() &&
|
||||
browser_info->guest_render_id_manager()->is_render_frame_id_match(
|
||||
render_frame_process_id, render_frame_routing_id)) {
|
||||
for (const auto& browser_info : browser_info_list_) {
|
||||
bool is_guest_view_tmp;
|
||||
auto frame = browser_info->GetFrameForRoute(
|
||||
render_process_id, render_routing_id, &is_guest_view_tmp);
|
||||
if (frame || is_guest_view_tmp) {
|
||||
if (is_guest_view)
|
||||
*is_guest_view = true;
|
||||
*is_guest_view = is_guest_view_tmp;
|
||||
return browser_info;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user