Remove usage of FrameTreeNode IDs (see issue #2421)

With the introduction of prerendering in Chromium it is now possible for
RenderFrameHosts (RFH) to move between FrameTrees. As a consequence we can no
longer rely on FrameTreeNode IDs to uniquely identify a RFH over its lifespan.
We must now switch to using GlobalRenderFrameHostId (child_id, frame_routing_id)
instead for that purpose. Additionally, we simplify existing code by using the
GlobalRenderFrameHostId struct in all places that previously used a
(render_process_id, render_frame_id) pair, since these concepts are equivalent.

See https://crbug.com/1179502#c8 for additional background.
This commit is contained in:
Marshall Greenblatt 2021-08-19 17:07:44 -04:00
parent cfdec92624
commit 955097ea77
33 changed files with 506 additions and 781 deletions

View File

@ -23,6 +23,7 @@
#include "libcef/browser/thread_util.h"
#include "libcef/common/cef_switches.h"
#include "libcef/common/drag_data_impl.h"
#include "libcef/common/frame_util.h"
#include "libcef/common/net/url_util.h"
#include "libcef/common/request_impl.h"
#include "libcef/common/values_impl.h"
@ -288,21 +289,10 @@ CefRefPtr<AlloyBrowserHostImpl> AlloyBrowserHostImpl::GetBrowserForContents(
}
// static
CefRefPtr<AlloyBrowserHostImpl>
AlloyBrowserHostImpl::GetBrowserForFrameTreeNode(int frame_tree_node_id) {
CefRefPtr<AlloyBrowserHostImpl> AlloyBrowserHostImpl::GetBrowserForGlobalId(
const content::GlobalRenderFrameHostId& global_id) {
REQUIRE_ALLOY_RUNTIME();
auto browser =
CefBrowserHostBase::GetBrowserForFrameTreeNode(frame_tree_node_id);
return static_cast<AlloyBrowserHostImpl*>(browser.get());
}
// static
CefRefPtr<AlloyBrowserHostImpl> AlloyBrowserHostImpl::GetBrowserForFrameRoute(
int render_process_id,
int render_routing_id) {
REQUIRE_ALLOY_RUNTIME();
auto browser = CefBrowserHostBase::GetBrowserForFrameRoute(render_process_id,
render_routing_id);
auto browser = CefBrowserHostBase::GetBrowserForGlobalId(global_id);
return static_cast<AlloyBrowserHostImpl*>(browser.get());
}
@ -1279,8 +1269,10 @@ void AlloyBrowserHostImpl::GetCustomWebContentsView(
content::WebContentsView** view,
content::RenderViewHostDelegateView** delegate_view) {
CefBrowserInfoManager::GetInstance()->GetCustomWebContentsView(
target_url, opener_render_process_id, opener_render_frame_id, view,
delegate_view);
target_url,
frame_util::MakeGlobalId(opener_render_process_id,
opener_render_frame_id),
view, delegate_view);
}
void AlloyBrowserHostImpl::WebContentsCreated(
@ -1296,8 +1288,10 @@ void AlloyBrowserHostImpl::WebContentsCreated(
CefRefPtr<CefDictionaryValue> extra_info;
CefBrowserInfoManager::GetInstance()->WebContentsCreated(
target_url, opener_render_process_id, opener_render_frame_id, settings,
client, platform_delegate, extra_info);
target_url,
frame_util::MakeGlobalId(opener_render_process_id,
opener_render_frame_id),
settings, client, platform_delegate, extra_info);
scoped_refptr<CefBrowserInfo> info =
CefBrowserInfoManager::GetInstance()->CreatePopupBrowserInfo(

View File

@ -72,13 +72,9 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
// Returns the browser associated with the specified WebContents.
static CefRefPtr<AlloyBrowserHostImpl> GetBrowserForContents(
const content::WebContents* contents);
// Returns the browser associated with the specified FrameTreeNode ID.
static CefRefPtr<AlloyBrowserHostImpl> GetBrowserForFrameTreeNode(
int frame_tree_node_id);
// Returns the browser associated with the specified frame routing IDs.
static CefRefPtr<AlloyBrowserHostImpl> GetBrowserForFrameRoute(
int render_process_id,
int render_routing_id);
// Returns the browser associated with the specified global ID.
static CefRefPtr<AlloyBrowserHostImpl> GetBrowserForGlobalId(
const content::GlobalRenderFrameHostId& global_id);
// CefBrowserHost methods.
void CloseBrowser(bool force_close) override;

View File

@ -39,6 +39,7 @@
#include "libcef/common/cef_switches.h"
#include "libcef/common/command_line_impl.h"
#include "libcef/common/extensions/extensions_util.h"
#include "libcef/common/frame_util.h"
#include "libcef/common/net/scheme_registration.h"
#include "libcef/common/request_impl.h"
@ -346,13 +347,11 @@ class CefQuotaPermissionContext : public content::QuotaPermissionContext {
bool handled = false;
CefRefPtr<AlloyBrowserHostImpl> browser =
AlloyBrowserHostImpl::GetBrowserForFrameRoute(render_process_id,
params.render_frame_id);
if (browser.get()) {
CefRefPtr<CefClient> client = browser->GetClient();
if (client.get()) {
CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
if (handler.get()) {
AlloyBrowserHostImpl::GetBrowserForGlobalId(frame_util::MakeGlobalId(
render_process_id, params.render_frame_id));
if (browser) {
if (auto client = browser->GetClient()) {
if (auto handler = client->GetRequestHandler()) {
CefRefPtr<CefQuotaCallbackImpl> callbackImpl(
new CefQuotaCallbackImpl(std::move(callback)));
handled = handler->OnQuotaRequest(

View File

@ -7,6 +7,7 @@
#include "libcef/browser/browser_host_base.h"
#include "libcef/browser/browser_platform_delegate.h"
#include "libcef/browser/browser_util.h"
#include "libcef/common/frame_util.h"
#include "content/public/browser/focused_node_details.h"
#include "content/public/browser/keyboard_event_processing_result.h"
@ -252,7 +253,8 @@ void CefBrowserContentsDelegate::RenderFrameHostStateChanged(
void CefBrowserContentsDelegate::RenderFrameDeleted(
content::RenderFrameHost* render_frame_host) {
const auto frame_id = CefFrameHostImpl::MakeFrameId(render_frame_host);
const auto frame_id =
frame_util::MakeFrameId(render_frame_host->GetGlobalId());
browser_info_->RemoveFrame(render_frame_host);
if (focused_frame_ && focused_frame_->GetIdentifier() == frame_id) {
@ -358,6 +360,7 @@ void CefBrowserContentsDelegate::DidFinishNavigation(
return;
const bool is_main_frame = navigation_handle->IsInMainFrame();
const auto global_id = frame_util::GetGlobalId(navigation_handle);
const GURL& url =
(error_code == net::OK ? navigation_handle->GetURL() : GURL());
@ -365,14 +368,13 @@ void CefBrowserContentsDelegate::DidFinishNavigation(
// May return NULL when starting a new navigation if the previous navigation
// caused the renderer process to crash during load.
CefRefPtr<CefFrameHostImpl> frame = browser_info->GetFrameForFrameTreeNode(
navigation_handle->GetFrameTreeNodeId());
CefRefPtr<CefFrameHostImpl> frame =
browser_info->GetFrameForGlobalId(global_id);
if (!frame) {
if (is_main_frame) {
frame = browser_info->GetMainFrame();
} else {
frame =
browser_info->CreateTempSubFrame(CefFrameHostImpl::kInvalidFrameId);
frame = browser_info->CreateTempSubFrame(frame_util::InvalidGlobalId());
}
}
frame->RefreshAttributes();

View File

@ -12,6 +12,7 @@
#include "libcef/browser/request_context_impl.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/cef_switches.h"
#include "libcef/common/frame_util.h"
#include "libcef/features/runtime.h"
#include "base/files/file_util.h"
@ -67,15 +68,12 @@ class ImplManager {
return GetImplPos(impl) != all_.end();
}
CefBrowserContext* GetImplFromIDs(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
bool require_frame_match) {
CefBrowserContext* GetImplFromGlobalId(
const content::GlobalRenderFrameHostId& global_id,
bool require_frame_match) {
CEF_REQUIRE_UIT();
for (const auto& context : all_) {
if (context->IsAssociatedContext(render_process_id, render_frame_id,
frame_tree_node_id,
require_frame_match)) {
if (context->IsAssociatedContext(global_id, require_frame_match)) {
return context;
}
}
@ -242,13 +240,10 @@ CefBrowserContext* CefBrowserContext::FromCachePath(
}
// static
CefBrowserContext* CefBrowserContext::FromIDs(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
bool require_frame_match) {
return g_manager.Get().GetImplFromIDs(render_process_id, render_frame_id,
frame_tree_node_id,
require_frame_match);
CefBrowserContext* CefBrowserContext::FromGlobalId(
const content::GlobalRenderFrameHostId& global_id,
bool require_frame_match) {
return g_manager.Get().GetImplFromGlobalId(global_id, require_frame_match);
}
// static
@ -283,100 +278,70 @@ std::vector<CefBrowserContext*> CefBrowserContext::GetAll() {
void CefBrowserContext::OnRenderFrameCreated(
CefRequestContextImpl* request_context,
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
bool is_main_frame,
bool is_guest_view) {
CEF_REQUIRE_UIT();
DCHECK_GE(render_process_id, 0);
DCHECK_GE(render_frame_id, 0);
DCHECK_GE(frame_tree_node_id, 0);
DCHECK(frame_util::IsValidGlobalId(global_id));
render_id_set_.insert(std::make_pair(render_process_id, render_frame_id));
node_id_set_.insert(frame_tree_node_id);
render_id_set_.insert(global_id);
CefRefPtr<CefRequestContextHandler> handler = request_context->GetHandler();
if (handler) {
handler_map_.AddHandler(render_process_id, render_frame_id,
frame_tree_node_id, handler);
handler_map_.AddHandler(global_id, handler);
CEF_POST_TASK(CEF_IOT,
base::BindOnce(&CefIOThreadState::AddHandler, iothread_state_,
render_process_id, render_frame_id,
frame_tree_node_id, handler));
CEF_POST_TASK(CEF_IOT, base::BindOnce(&CefIOThreadState::AddHandler,
iothread_state_, global_id, handler));
}
}
void CefBrowserContext::OnRenderFrameDeleted(
CefRequestContextImpl* request_context,
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
bool is_main_frame,
bool is_guest_view) {
CEF_REQUIRE_UIT();
DCHECK_GE(render_process_id, 0);
DCHECK_GE(render_frame_id, 0);
DCHECK_GE(frame_tree_node_id, 0);
DCHECK(frame_util::IsValidGlobalId(global_id));
auto it1 =
render_id_set_.find(std::make_pair(render_process_id, render_frame_id));
auto it1 = render_id_set_.find(global_id);
if (it1 != render_id_set_.end())
render_id_set_.erase(it1);
auto it2 = node_id_set_.find(frame_tree_node_id);
if (it2 != node_id_set_.end())
node_id_set_.erase(it2);
CefRefPtr<CefRequestContextHandler> handler = request_context->GetHandler();
if (handler) {
handler_map_.RemoveHandler(render_process_id, render_frame_id,
frame_tree_node_id);
handler_map_.RemoveHandler(global_id);
CEF_POST_TASK(CEF_IOT, base::BindOnce(&CefIOThreadState::RemoveHandler,
iothread_state_, render_process_id,
render_frame_id, frame_tree_node_id));
iothread_state_, global_id));
}
if (is_main_frame) {
ClearPluginLoadDecision(render_process_id);
ClearPluginLoadDecision(global_id.child_id);
}
}
CefRefPtr<CefRequestContextHandler> CefBrowserContext::GetHandler(
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
bool require_frame_match) const {
CEF_REQUIRE_UIT();
return handler_map_.GetHandler(render_process_id, render_frame_id,
frame_tree_node_id, require_frame_match);
return handler_map_.GetHandler(global_id, require_frame_match);
}
bool CefBrowserContext::IsAssociatedContext(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
bool require_frame_match) const {
bool CefBrowserContext::IsAssociatedContext(
const content::GlobalRenderFrameHostId& global_id,
bool require_frame_match) const {
CEF_REQUIRE_UIT();
if (render_process_id >= 0 && render_frame_id >= 0) {
const auto it1 =
render_id_set_.find(std::make_pair(render_process_id, render_frame_id));
if (frame_util::IsValidGlobalId(global_id)) {
const auto it1 = render_id_set_.find(global_id);
if (it1 != render_id_set_.end())
return true;
}
if (frame_tree_node_id >= 0) {
const auto it2 = node_id_set_.find(frame_tree_node_id);
if (it2 != node_id_set_.end())
return true;
}
if (render_process_id >= 0 && !require_frame_match) {
if (frame_util::IsValidChildId(global_id.child_id) && !require_frame_match) {
// Choose an arbitrary handler for the same process.
for (const auto& render_ids : render_id_set_) {
if (render_ids.first == render_process_id)
if (render_ids.child_id == global_id.child_id)
return true;
}
}
@ -407,7 +372,7 @@ bool CefBrowserContext::HasPluginLoadDecision(
const url::Origin& main_frame_origin,
chrome::mojom::PluginStatus* status) const {
CEF_REQUIRE_UIT();
DCHECK_GE(render_process_id, 0);
DCHECK(frame_util::IsValidChildId(render_process_id));
DCHECK(!plugin_path.empty());
PluginLoadDecisionMap::const_iterator it = plugin_load_decision_map_.find(
@ -423,7 +388,7 @@ bool CefBrowserContext::HasPluginLoadDecision(
void CefBrowserContext::ClearPluginLoadDecision(int render_process_id) {
CEF_REQUIRE_UIT();
if (render_process_id == -1) {
if (!frame_util::IsValidChildId(render_process_id)) {
plugin_load_decision_map_.clear();
} else {
PluginLoadDecisionMap::iterator it = plugin_load_decision_map_.begin();

View File

@ -78,7 +78,8 @@
namespace content {
class BrowserContext;
}
struct GlobalRenderFrameHostId;
} // namespace content
class CefMediaRouterManager;
class CefRequestContextImpl;
@ -96,10 +97,9 @@ class CefBrowserContext {
// Returns the existing instance, if any, associated with the specified IDs.
// See comments on IsAssociatedContext() for usage.
static CefBrowserContext* FromIDs(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
bool require_frame_match);
static CefBrowserContext* FromGlobalId(
const content::GlobalRenderFrameHostId& global_id,
bool require_frame_match);
// Returns the underlying CefBrowserContext if any.
static CefBrowserContext* FromBrowserContext(
@ -127,17 +127,13 @@ class CefBrowserContext {
// Called from CefRequestContextImpl::OnRenderFrameCreated.
void OnRenderFrameCreated(CefRequestContextImpl* request_context,
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
bool is_main_frame,
bool is_guest_view);
// Called from CefRequestContextImpl::OnRenderFrameDeleted.
void OnRenderFrameDeleted(CefRequestContextImpl* request_context,
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
bool is_main_frame,
bool is_guest_view);
@ -147,18 +143,14 @@ class CefBrowserContext {
// match, then the first handler for the same |render_process_id| will be
// returned.
CefRefPtr<CefRequestContextHandler> GetHandler(
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
bool require_frame_match) const;
// Returns true if this context is associated with the specified IDs. Pass -1
// for unknown values. If |require_frame_match| is true only exact matches
// will qualify. If |require_frame_match| is false, and there is not an exact
// match, then any match for |render_process_id| will qualify.
bool IsAssociatedContext(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
bool IsAssociatedContext(const content::GlobalRenderFrameHostId& global_id,
bool require_frame_match) const;
// Remember the plugin load decision for plugin status requests that arrive
@ -175,7 +167,8 @@ class CefBrowserContext {
chrome::mojom::PluginStatus* status) const;
// Clear the plugin load decisions associated with |render_process_id|, or all
// plugin load decisions if |render_process_id| is -1.
// plugin load decisions if |render_process_id| is
// content::ChildProcessHost::kInvalidUniqueID.
void ClearPluginLoadDecision(int render_process_id);
// Called from CefRequestContextImpl methods of the same name.
@ -258,18 +251,10 @@ class CefBrowserContext {
PluginLoadDecisionMap;
PluginLoadDecisionMap plugin_load_decision_map_;
// Set of (render_process_id, render_frame_id) associated with this context.
typedef std::set<std::pair<int, int>> RenderIdSet;
// Set of global IDs associated with this context.
typedef std::set<content::GlobalRenderFrameHostId> RenderIdSet;
RenderIdSet render_id_set_;
// Set of frame_tree_node_id associated with this context. Keeping this list
// is necessary because, when navigating the main frame, a new (pre-commit)
// network request will be created before the RenderFrameHost. Consequently we
// can't rely on valid render IDs. See https://crbug.com/776884 for
// background.
typedef std::set<int> NodeIdSet;
NodeIdSet node_id_set_;
#if DCHECK_IS_ON()
bool is_shutdown_ = false;
#endif

View File

@ -10,6 +10,7 @@
#include "libcef/browser/image_impl.h"
#include "libcef/browser/navigation_entry_impl.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/frame_util.h"
#include "libcef/common/net/url_util.h"
#include "base/logging.h"
@ -101,52 +102,30 @@ CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForContents(
}
// static
CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForFrameTreeNode(
int frame_tree_node_id) {
// Use the thread-safe approach.
auto info =
CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameTreeNode(
frame_tree_node_id);
if (info) {
auto browser = info->browser();
if (!browser) {
LOG(WARNING) << "Found browser id " << info->browser_id()
<< " but no browser object matching frame tree node id "
<< frame_tree_node_id;
}
return browser;
}
return nullptr;
}
// static
CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForFrameRoute(
int render_process_id,
int render_routing_id) {
if (render_process_id == -1 || render_routing_id == MSG_ROUTING_NONE)
CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForGlobalId(
const content::GlobalRenderFrameHostId& global_id) {
if (!frame_util::IsValidGlobalId(global_id)) {
return nullptr;
}
if (CEF_CURRENTLY_ON_UIT()) {
// Use the non-thread-safe but potentially faster approach.
content::RenderFrameHost* render_frame_host =
content::RenderFrameHost::FromID(render_process_id, render_routing_id);
content::RenderFrameHost::FromID(global_id);
if (!render_frame_host)
return nullptr;
return GetBrowserForHost(render_frame_host);
} else {
// Use the thread-safe approach.
bool is_guest_view = false;
auto info =
CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameRoute(
render_process_id, render_routing_id, &is_guest_view);
auto info = CefBrowserInfoManager::GetInstance()->GetBrowserInfo(
global_id, &is_guest_view);
if (info && !is_guest_view) {
auto browser = info->browser();
if (!browser) {
LOG(WARNING) << "Found browser id " << info->browser_id()
<< " but no browser object matching frame process id "
<< render_process_id << " and routing id "
<< render_routing_id;
<< " but no browser object matching frame "
<< frame_util::GetFrameDebugString(global_id);
}
return browser;
}
@ -644,7 +623,8 @@ CefRefPtr<CefFrame> CefBrowserHostBase::GetFrame(int64 identifier) {
return focused_frame_;
}
return browser_info_->GetFrameForId(identifier);
return browser_info_->GetFrameForGlobalId(
frame_util::MakeGlobalId(identifier));
}
CefRefPtr<CefFrame> CefBrowserHostBase::GetFrame(const CefString& name) {
@ -723,9 +703,9 @@ CefRefPtr<CefFrame> CefBrowserHostBase::GetFrameForHost(
return browser_info_->GetFrameForHost(host);
}
CefRefPtr<CefFrame> CefBrowserHostBase::GetFrameForFrameTreeNode(
int frame_tree_node_id) {
return browser_info_->GetFrameForFrameTreeNode(frame_tree_node_id, nullptr);
CefRefPtr<CefFrame> CefBrowserHostBase::GetFrameForGlobalId(
const content::GlobalRenderFrameHostId& global_id) {
return browser_info_->GetFrameForGlobalId(global_id, nullptr);
}
void CefBrowserHostBase::AddObserver(Observer* observer) {

View File

@ -123,13 +123,9 @@ class CefBrowserHostBase : public CefBrowserHost,
// Returns the browser associated with the specified WebContents.
static CefRefPtr<CefBrowserHostBase> GetBrowserForContents(
const content::WebContents* contents);
// Returns the browser associated with the specified FrameTreeNode ID.
static CefRefPtr<CefBrowserHostBase> GetBrowserForFrameTreeNode(
int frame_tree_node_id);
// Returns the browser associated with the specified frame routing IDs.
static CefRefPtr<CefBrowserHostBase> GetBrowserForFrameRoute(
int render_process_id,
int render_routing_id);
// Returns the browser associated with the specified global ID.
static CefRefPtr<CefBrowserHostBase> GetBrowserForGlobalId(
const content::GlobalRenderFrameHostId& global_id);
CefBrowserHostBase(
const CefBrowserSettings& settings,
@ -212,8 +208,11 @@ class CefBrowserHostBase : public CefBrowserHost,
// Returns the frame associated with the specified RenderFrameHost.
CefRefPtr<CefFrame> GetFrameForHost(const content::RenderFrameHost* host);
// Returns the frame associated with the specified FrameTreeNode ID.
CefRefPtr<CefFrame> GetFrameForFrameTreeNode(int frame_tree_node_id);
// Returns the frame associated with the specified global ID. See
// documentation on RenderFrameHost::GetFrameTreeNodeId() for why the global
// ID is preferred.
CefRefPtr<CefFrame> GetFrameForGlobalId(
const content::GlobalRenderFrameHostId& global_id);
// Manage observer objects. The observer must either outlive this object or
// be removed before destruction. Must be called on the UI thread.

View File

@ -6,6 +6,7 @@
#include "libcef/browser/browser_host_base.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/frame_util.h"
#include "libcef/common/values_impl.h"
#include "base/logging.h"
@ -74,8 +75,7 @@ void CefBrowserInfo::MaybeCreateFrame(content::RenderFrameHost* host,
bool is_guest_view) {
CEF_REQUIRE_UIT();
const auto frame_id = CefFrameHostImpl::MakeFrameId(host);
const int frame_tree_node_id = host->GetFrameTreeNodeId();
const auto global_id = host->GetGlobalId();
const bool is_main_frame = (host->GetParent() == nullptr);
// A speculative RFH will be created in response to a browser-initiated
@ -93,14 +93,13 @@ void CefBrowserInfo::MaybeCreateFrame(content::RenderFrameHost* host,
NotificationStateLock lock_scope(this);
DCHECK(browser_);
const auto it = frame_id_map_.find(frame_id);
const auto it = frame_id_map_.find(global_id);
if (it != frame_id_map_.end()) {
auto info = it->second;
#if DCHECK_IS_ON()
// Check that the frame info hasn't changed unexpectedly.
DCHECK_EQ(info->frame_id_, frame_id);
DCHECK_EQ(info->frame_tree_node_id_, frame_tree_node_id);
DCHECK_EQ(info->global_id_, global_id);
DCHECK_EQ(info->is_guest_view_, is_guest_view);
DCHECK_EQ(info->is_main_frame_, is_main_frame);
#endif
@ -112,15 +111,13 @@ void CefBrowserInfo::MaybeCreateFrame(content::RenderFrameHost* host,
SetMainFrame(browser_, info->frame_);
}
info->is_speculative_ = false;
MaybeUpdateFrameTreeNodeIdMap(info);
}
return;
}
auto frame_info = new FrameInfo;
frame_info->host_ = host;
frame_info->frame_id_ = frame_id;
frame_info->frame_tree_node_id_ = frame_tree_node_id;
frame_info->global_id_ = global_id;
frame_info->is_guest_view_ = is_guest_view;
frame_info->is_main_frame_ = is_main_frame;
frame_info->is_speculative_ = is_speculative;
@ -136,18 +133,17 @@ void CefBrowserInfo::MaybeCreateFrame(content::RenderFrameHost* host,
#if DCHECK_IS_ON()
// Check that the frame info hasn't changed unexpectedly.
DCHECK_EQ(frame_id, frame_info->frame_->GetIdentifier());
DCHECK_EQ(frame_util::MakeFrameId(global_id),
frame_info->frame_->GetIdentifier());
DCHECK_EQ(frame_info->is_main_frame_, frame_info->frame_->IsMain());
#endif
}
browser_->request_context()->OnRenderFrameCreated(
host->GetProcess()->GetID(), host->GetRoutingID(), frame_tree_node_id,
is_main_frame, is_guest_view);
browser_->request_context()->OnRenderFrameCreated(global_id, is_main_frame,
is_guest_view);
// Populate the lookup maps.
frame_id_map_.insert(std::make_pair(frame_id, frame_info));
MaybeUpdateFrameTreeNodeIdMap(frame_info);
frame_id_map_.insert(std::make_pair(global_id, frame_info));
// And finally set the ownership.
frame_info_set_.insert(base::WrapUnique(frame_info));
@ -171,8 +167,7 @@ void CefBrowserInfo::FrameHostStateChanged(
base::AutoLock lock_scope(lock_);
const auto frame_id = CefFrameHostImpl::MakeFrameId(host);
auto it = frame_id_map_.find(frame_id);
auto it = frame_id_map_.find(host->GetGlobalId());
DCHECK(it != frame_id_map_.end());
DCHECK((!it->second->is_in_bfcache_ && added_to_bfcache) ||
(it->second->is_in_bfcache_ && removed_from_bfcache));
@ -184,31 +179,18 @@ void CefBrowserInfo::RemoveFrame(content::RenderFrameHost* host) {
NotificationStateLock lock_scope(this);
const auto frame_id = CefFrameHostImpl::MakeFrameId(host);
auto it = frame_id_map_.find(frame_id);
const auto global_id = host->GetGlobalId();
auto it = frame_id_map_.find(global_id);
DCHECK(it != frame_id_map_.end());
auto frame_info = it->second;
browser_->request_context()->OnRenderFrameDeleted(
host->GetProcess()->GetID(), host->GetRoutingID(),
frame_info->frame_tree_node_id_, frame_info->is_main_frame_,
frame_info->is_guest_view_);
global_id, frame_info->is_main_frame_, frame_info->is_guest_view_);
// Remove from the lookup maps.
frame_id_map_.erase(it);
// A new RFH with the same node ID may be added before the old RFH is deleted,
// or this might be a speculative RFH. Therefore only delete the map entry if
// it's currently pointing to the to-be-deleted frame info object.
{
auto it2 = frame_tree_node_id_map_.find(frame_info->frame_tree_node_id_);
if (it2 != frame_tree_node_id_map_.end() && it2->second == frame_info) {
frame_tree_node_id_map_.erase(frame_info->frame_tree_node_id_);
}
}
// And finally delete the frame info.
{
auto it2 = frame_info_set_.find(frame_info);
@ -235,8 +217,8 @@ CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetMainFrame() {
}
CefRefPtr<CefFrameHostImpl> CefBrowserInfo::CreateTempSubFrame(
int64_t parent_frame_id) {
CefRefPtr<CefFrameHostImpl> parent = GetFrameForId(parent_frame_id);
const content::GlobalRenderFrameHostId& parent_global_id) {
CefRefPtr<CefFrameHostImpl> parent = GetFrameForGlobalId(parent_global_id);
if (!parent)
parent = GetMainFrame();
// Intentionally not notifying for temporary frames.
@ -253,39 +235,24 @@ CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForHost(
if (!host)
return nullptr;
return GetFrameForId(CefFrameHostImpl::MakeFrameId(host), is_guest_view,
prefer_speculative);
return GetFrameForGlobalId(
const_cast<content::RenderFrameHost*>(host)->GetGlobalId(), is_guest_view,
prefer_speculative);
}
CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForRoute(
int32_t render_process_id,
int32_t render_routing_id,
CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForGlobalId(
const content::GlobalRenderFrameHostId& global_id,
bool* is_guest_view,
bool prefer_speculative) const {
if (is_guest_view)
*is_guest_view = false;
if (render_process_id < 0 || render_routing_id < 0)
return nullptr;
return GetFrameForId(
CefFrameHostImpl::MakeFrameId(render_process_id, render_routing_id),
is_guest_view, prefer_speculative);
}
CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForId(
int64_t frame_id,
bool* is_guest_view,
bool prefer_speculative) const {
if (is_guest_view)
*is_guest_view = false;
if (frame_id < 0)
if (!frame_util::IsValidGlobalId(global_id))
return nullptr;
base::AutoLock lock_scope(lock_);
const auto it = frame_id_map_.find(frame_id);
const auto it = frame_id_map_.find(global_id);
if (it != frame_id_map_.end()) {
const auto info = it->second;
@ -299,21 +266,10 @@ CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForId(
if (info->is_main_frame_ && main_frame_) {
// Always prefer the non-speculative main frame.
return main_frame_;
} else {
// Always prefer an existing non-speculative frame for the same node ID.
bool is_guest_view_tmp;
auto frame = GetFrameForFrameTreeNodeInternal(info->frame_tree_node_id_,
&is_guest_view_tmp);
if (is_guest_view_tmp) {
if (is_guest_view)
*is_guest_view = true;
return nullptr;
}
if (frame)
return frame;
}
LOG(WARNING) << "Returning a speculative frame for frame id " << frame_id;
LOG(WARNING) << "Returning a speculative frame for "
<< frame_util::GetFrameDebugString(global_id);
}
DCHECK(info->frame_);
@ -323,19 +279,6 @@ CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForId(
return nullptr;
}
CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForFrameTreeNode(
int frame_tree_node_id,
bool* is_guest_view) const {
if (is_guest_view)
*is_guest_view = false;
if (frame_tree_node_id < 0)
return nullptr;
base::AutoLock lock_scope(lock_);
return GetFrameForFrameTreeNodeInternal(frame_tree_node_id, is_guest_view);
}
CefBrowserInfo::FrameHostList CefBrowserInfo::GetAllFrames() const {
base::AutoLock lock_scope(lock_);
FrameHostList frames;
@ -402,59 +345,6 @@ void CefBrowserInfo::MaybeExecuteFrameNotification(
std::move(pending_action).Run(frame_handler);
}
void CefBrowserInfo::MaybeUpdateFrameTreeNodeIdMap(FrameInfo* info) {
lock_.AssertAcquired();
auto it = frame_tree_node_id_map_.find(info->frame_tree_node_id_);
const bool has_entry = (it != frame_tree_node_id_map_.end());
if (has_entry && it->second == info) {
// Already mapping to |info|.
return;
}
// Don't replace an existing node ID entry with a speculative RFH, but do
// add an entry if one doesn't already exist.
if (!info->is_speculative_ || !has_entry) {
// A new RFH with the same node ID may be added before the old RFH is
// deleted. To avoid duplicate entries in the map remove the old entry, if
// any, before adding the new entry.
if (has_entry)
frame_tree_node_id_map_.erase(it);
frame_tree_node_id_map_.insert(
std::make_pair(info->frame_tree_node_id_, info));
}
}
CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForFrameTreeNodeInternal(
int frame_tree_node_id,
bool* is_guest_view) const {
if (is_guest_view)
*is_guest_view = false;
lock_.AssertAcquired();
const auto it = frame_tree_node_id_map_.find(frame_tree_node_id);
if (it != frame_tree_node_id_map_.end()) {
const auto info = it->second;
LOG_IF(WARNING, info->is_speculative_)
<< "Returning a speculative frame for node id " << frame_tree_node_id;
if (info->is_guest_view_) {
if (is_guest_view)
*is_guest_view = true;
return nullptr;
}
DCHECK(info->frame_);
return info->frame_;
}
return nullptr;
}
// Passing in |browser| here because |browser_| may already be cleared.
void CefBrowserInfo::SetMainFrame(CefRefPtr<CefBrowserHostBase> browser,
CefRefPtr<CefFrameHostImpl> frame) {
@ -542,7 +432,6 @@ void CefBrowserInfo::RemoveAllFrames(
// Clear the lookup maps.
frame_id_map_.clear();
frame_tree_node_id_map_.clear();
// Explicitly Detach everything but the current main frame.
for (auto& info : frame_info_set_) {

View File

@ -19,6 +19,7 @@
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "base/values.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/render_frame_host.h"
class CefBrowserHostBase;
@ -85,7 +86,8 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
// is invalid the current main frame will be specified as the parent.
// Temporary frame objects are not tracked but will be implicitly detached
// on browser destruction.
CefRefPtr<CefFrameHostImpl> CreateTempSubFrame(int64_t parent_frame_id);
CefRefPtr<CefFrameHostImpl> CreateTempSubFrame(
const content::GlobalRenderFrameHostId& parent_global_id);
// Returns the frame object matching the specified host or nullptr if no match
// is found. Nullptr will also be returned if a guest view match is found
@ -97,36 +99,16 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
bool* is_guest_view = nullptr,
bool prefer_speculative = false) const;
// Returns the frame object matching the specified IDs or nullptr if no match
// is found. Nullptr will also be returned if a guest view match is found
// because we don't create frame objects for guest views. If |is_guest_view|
// is non-nullptr it will be set to true in this case. Safe to call from any
// thread.
CefRefPtr<CefFrameHostImpl> GetFrameForRoute(
int32_t render_process_id,
int32_t render_routing_id,
bool* is_guest_view = nullptr,
bool prefer_speculative = false) const;
// Returns the frame object matching the specified ID or nullptr if no match
// is found. Nullptr will also be returned if a guest view match is found
// because we don't create frame objects for guest views. If |is_guest_view|
// is non-nullptr it will be set to true in this case. Safe to call from any
// thread.
CefRefPtr<CefFrameHostImpl> GetFrameForId(
int64_t frame_id,
CefRefPtr<CefFrameHostImpl> GetFrameForGlobalId(
const content::GlobalRenderFrameHostId& global_id,
bool* is_guest_view = nullptr,
bool prefer_speculative = false) const;
// Returns the frame object matching the specified ID or nullptr if no match
// is found. Nullptr will also be returned if a guest view match is found
// because we don't create frame objects for guest views. If |is_guest_view|
// is non-nullptr it will be set to true in this case. Safe to call from any
// thread.
CefRefPtr<CefFrameHostImpl> GetFrameForFrameTreeNode(
int frame_tree_node_id,
bool* is_guest_view = nullptr) const;
// Returns all non-speculative frame objects that currently exist. Guest views
// will be excluded because they don't have a frame object. Safe to call from
// any thread.
@ -178,8 +160,7 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
}
content::RenderFrameHost* host_;
int64_t frame_id_; // Combination of render_process_id + render_routing_id.
int frame_tree_node_id_;
content::GlobalRenderFrameHostId global_id_;
bool is_guest_view_;
bool is_main_frame_;
bool is_speculative_;
@ -187,12 +168,6 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
CefRefPtr<CefFrameHostImpl> frame_;
};
void MaybeUpdateFrameTreeNodeIdMap(FrameInfo* info);
CefRefPtr<CefFrameHostImpl> GetFrameForFrameTreeNodeInternal(
int frame_tree_node_id,
bool* is_guest_view = nullptr) const;
void SetMainFrame(CefRefPtr<CefBrowserHostBase> browser,
CefRefPtr<CefFrameHostImpl> frame);
@ -244,18 +219,18 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
CefRefPtr<CefBrowserHostBase> browser_;
// Owner of FrameInfo structs.
typedef std::set<std::unique_ptr<FrameInfo>, base::UniquePtrComparator>
FrameInfoSet;
using FrameInfoSet =
std::set<std::unique_ptr<FrameInfo>, base::UniquePtrComparator>;
FrameInfoSet frame_info_set_;
// Map a frame ID (e.g. MakeFrameId(process_id, routing_id)) to one frame.
typedef std::unordered_map<int64_t, FrameInfo*> FrameIDMap;
// Map a global ID to one frame. These IDs are guaranteed to uniquely
// identify a RFH for its complete lifespan. See documentation on
// RenderFrameHost::GetFrameTreeNodeId() for background.
using FrameIDMap = std::unordered_map<content::GlobalRenderFrameHostId,
FrameInfo*,
content::GlobalRenderFrameHostIdHasher>;
FrameIDMap frame_id_map_;
// Map a frame_tree_node_id to one frame.
typedef std::unordered_map<int, FrameInfo*> FrameTreeNodeIDMap;
FrameTreeNodeIDMap frame_tree_node_id_map_;
// The current main frame.
CefRefPtr<CefFrameHostImpl> main_frame_;

View File

@ -12,6 +12,7 @@
#include "libcef/browser/thread_util.h"
#include "libcef/common/cef_switches.h"
#include "libcef/common/extensions/extensions_util.h"
#include "libcef/common/frame_util.h"
#include "libcef/common/values_impl.h"
#include "libcef/features/runtime_checks.h"
@ -85,19 +86,17 @@ scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::CreatePopupBrowserInfo(
base::AutoLock lock_scope(browser_info_lock_);
auto frame_host = new_contents->GetMainFrame();
const int render_process_id = frame_host->GetProcess()->GetID();
const auto frame_id = CefFrameHostImpl::MakeFrameId(frame_host);
scoped_refptr<CefBrowserInfo> browser_info =
new CefBrowserInfo(++next_browser_id_, true, is_windowless, extra_info);
browser_info_list_.push_back(browser_info);
// Continue any pending NewBrowserInfo request.
auto it = pending_new_browser_info_map_.find(frame_id);
auto it = pending_new_browser_info_map_.find(frame_host->GetGlobalId());
if (it != pending_new_browser_info_map_.end()) {
SendNewBrowserInfoResponse(
render_process_id, browser_info, /*is_guest_view=*/false,
std::move(it->second->callback), it->second->callback_runner);
SendNewBrowserInfoResponse(browser_info, /*is_guest_view=*/false,
std::move(it->second->callback),
it->second->callback_runner);
pending_new_browser_info_map_.erase(it);
}
@ -138,8 +137,7 @@ bool CefBrowserInfoManager::CanCreateWindow(
auto pending_popup = std::make_unique<CefBrowserInfoManager::PendingPopup>();
pending_popup->step = CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW;
pending_popup->opener_render_process_id = opener->GetProcess()->GetID();
pending_popup->opener_render_routing_id = opener->GetRoutingID();
pending_popup->opener_global_id = opener->GetGlobalId();
pending_popup->target_url = target_url;
pending_popup->target_frame_name = frame_name;
@ -210,8 +208,7 @@ bool CefBrowserInfoManager::CanCreateWindow(
void CefBrowserInfoManager::GetCustomWebContentsView(
const GURL& target_url,
int opener_render_process_id,
int opener_render_routing_id,
const content::GlobalRenderFrameHostId& opener_global_id,
content::WebContentsView** view,
content::RenderViewHostDelegateView** delegate_view) {
CEF_REQUIRE_UIT();
@ -219,8 +216,7 @@ void CefBrowserInfoManager::GetCustomWebContentsView(
std::unique_ptr<CefBrowserInfoManager::PendingPopup> pending_popup =
PopPendingPopup(CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW,
opener_render_process_id, opener_render_routing_id,
target_url);
opener_global_id, target_url);
DCHECK(pending_popup.get());
DCHECK(pending_popup->platform_delegate.get());
@ -236,8 +232,7 @@ void CefBrowserInfoManager::GetCustomWebContentsView(
void CefBrowserInfoManager::WebContentsCreated(
const GURL& target_url,
int opener_render_process_id,
int opener_render_routing_id,
const content::GlobalRenderFrameHostId& opener_global_id,
CefBrowserSettings& settings,
CefRefPtr<CefClient>& client,
std::unique_ptr<CefBrowserPlatformDelegate>& platform_delegate,
@ -251,8 +246,7 @@ void CefBrowserInfoManager::WebContentsCreated(
: CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW;
std::unique_ptr<CefBrowserInfoManager::PendingPopup> pending_popup =
PopPendingPopup(previous_step, opener_render_process_id,
opener_render_routing_id, target_url);
PopPendingPopup(previous_step, opener_global_id, target_url);
DCHECK(pending_popup.get());
DCHECK(pending_popup->platform_delegate.get());
@ -263,11 +257,9 @@ void CefBrowserInfoManager::WebContentsCreated(
}
void CefBrowserInfoManager::OnGetNewBrowserInfo(
int render_process_id,
int render_routing_id,
const content::GlobalRenderFrameHostId& global_id,
cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback) {
DCHECK_NE(render_process_id, content::ChildProcessHost::kInvalidUniqueID);
DCHECK_GT(render_routing_id, 0);
DCHECK(frame_util::IsValidGlobalId(global_id));
DCHECK(callback);
auto callback_runner = base::SequencedTaskRunnerHandle::Get();
@ -277,33 +269,29 @@ void CefBrowserInfoManager::OnGetNewBrowserInfo(
bool is_guest_view = false;
scoped_refptr<CefBrowserInfo> browser_info =
GetBrowserInfo(render_process_id, render_routing_id, &is_guest_view);
GetBrowserInfoInternal(global_id, &is_guest_view);
if (browser_info.get()) {
if (browser_info) {
// Send the response immediately.
SendNewBrowserInfoResponse(render_process_id, browser_info, is_guest_view,
std::move(callback), callback_runner);
SendNewBrowserInfoResponse(browser_info, is_guest_view, std::move(callback),
callback_runner);
return;
}
const auto frame_id =
CefFrameHostImpl::MakeFrameId(render_process_id, render_routing_id);
// Verify that no request for the same route is currently queued.
DCHECK(pending_new_browser_info_map_.find(frame_id) ==
DCHECK(pending_new_browser_info_map_.find(global_id) ==
pending_new_browser_info_map_.end());
const int timeout_id = ++next_timeout_id_;
// Queue the request.
std::unique_ptr<PendingNewBrowserInfo> pending(new PendingNewBrowserInfo());
pending->render_process_id = render_process_id;
pending->render_routing_id = render_routing_id;
pending->global_id = global_id;
pending->timeout_id = timeout_id;
pending->callback = std::move(callback);
pending->callback_runner = callback_runner;
pending_new_browser_info_map_.insert(
std::make_pair(frame_id, std::move(pending)));
std::make_pair(global_id, std::move(pending)));
// Register a timeout for the pending response so that the renderer process
// doesn't hang forever.
@ -312,7 +300,7 @@ void CefBrowserInfoManager::OnGetNewBrowserInfo(
CEF_POST_DELAYED_TASK(
CEF_UIT,
base::BindOnce(&CefBrowserInfoManager::TimeoutNewBrowserInfoResponse,
frame_id, timeout_id),
global_id, timeout_id),
kNewBrowserInfoResponseTimeoutMs);
}
}
@ -362,12 +350,11 @@ void CefBrowserInfoManager::DestroyAllBrowsers() {
#endif
}
scoped_refptr<CefBrowserInfo>
CefBrowserInfoManager::GetBrowserInfoForFrameRoute(int render_process_id,
int render_routing_id,
bool* is_guest_view) {
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfo(
const content::GlobalRenderFrameHostId& global_id,
bool* is_guest_view) {
base::AutoLock lock_scope(browser_info_lock_);
return GetBrowserInfo(render_process_id, render_routing_id, is_guest_view);
return GetBrowserInfoInternal(global_id, is_guest_view);
}
bool CefBrowserInfoManager::MaybeAllowNavigation(
@ -392,31 +379,6 @@ bool CefBrowserInfoManager::MaybeAllowNavigation(
return true;
}
scoped_refptr<CefBrowserInfo>
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_);
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;
}
}
return nullptr;
}
CefBrowserInfoManager::BrowserInfoList
CefBrowserInfoManager::GetBrowserInfoList() {
base::AutoLock lock_scope(browser_info_lock_);
@ -442,7 +404,7 @@ void CefBrowserInfoManager::RenderProcessHostDestroyed(
pending_new_browser_info_map_.begin();
while (it != pending_new_browser_info_map_.end()) {
const auto& info = it->second;
if (info->render_process_id == render_process_id) {
if (info->global_id.child_id == render_process_id) {
CancelNewBrowserInfoResponse(info.get());
it = pending_new_browser_info_map_.erase(it);
} else {
@ -456,7 +418,7 @@ void CefBrowserInfoManager::RenderProcessHostDestroyed(
PendingPopupList::iterator it = pending_popup_list_.begin();
while (it != pending_popup_list_.end()) {
PendingPopup* popup = it->get();
if (popup->opener_render_process_id == render_process_id) {
if (popup->opener_global_id.child_id == render_process_id) {
it = pending_popup_list_.erase(it);
} else {
++it;
@ -472,20 +434,17 @@ void CefBrowserInfoManager::PushPendingPopup(
}
std::unique_ptr<CefBrowserInfoManager::PendingPopup>
CefBrowserInfoManager::PopPendingPopup(PendingPopup::Step step,
int opener_render_process_id,
int opener_render_routing_id,
const GURL& target_url) {
CefBrowserInfoManager::PopPendingPopup(
PendingPopup::Step step,
const content::GlobalRenderFrameHostId& opener_global_id,
const GURL& target_url) {
CEF_REQUIRE_UIT();
DCHECK_GT(opener_render_process_id, 0);
DCHECK_GT(opener_render_routing_id, 0);
DCHECK(frame_util::IsValidGlobalId(opener_global_id));
PendingPopupList::iterator it = pending_popup_list_.begin();
for (; it != pending_popup_list_.end(); ++it) {
PendingPopup* popup = it->get();
if (popup->step == step &&
popup->opener_render_process_id == opener_render_process_id &&
popup->opener_render_routing_id == opener_render_routing_id &&
if (popup->step == step && popup->opener_global_id == opener_global_id &&
popup->target_url == target_url) {
// Transfer ownership of the pointer.
it->release();
@ -497,22 +456,21 @@ CefBrowserInfoManager::PopPendingPopup(PendingPopup::Step step,
return nullptr;
}
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfo(
int render_process_id,
int render_routing_id,
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfoInternal(
const content::GlobalRenderFrameHostId& global_id,
bool* is_guest_view) {
browser_info_lock_.AssertAcquired();
if (is_guest_view)
*is_guest_view = false;
if (render_process_id < 0 || render_routing_id < 0)
if (!frame_util::IsValidGlobalId(global_id))
return nullptr;
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);
auto frame =
browser_info->GetFrameForGlobalId(global_id, &is_guest_view_tmp);
if (frame || is_guest_view_tmp) {
if (is_guest_view)
*is_guest_view = is_guest_view_tmp;
@ -525,7 +483,6 @@ scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfo(
// static
void CefBrowserInfoManager::SendNewBrowserInfoResponse(
int render_process_id,
scoped_refptr<CefBrowserInfo> browser_info,
bool is_guest_view,
cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback,
@ -534,8 +491,8 @@ void CefBrowserInfoManager::SendNewBrowserInfoResponse(
callback_runner->PostTask(
FROM_HERE,
base::BindOnce(&CefBrowserInfoManager::SendNewBrowserInfoResponse,
render_process_id, browser_info, is_guest_view,
std::move(callback), callback_runner));
browser_info, is_guest_view, std::move(callback),
callback_runner));
return;
}
@ -565,31 +522,30 @@ void CefBrowserInfoManager::SendNewBrowserInfoResponse(
// static
void CefBrowserInfoManager::CancelNewBrowserInfoResponse(
PendingNewBrowserInfo* pending_info) {
SendNewBrowserInfoResponse(pending_info->render_process_id,
/*browser_info=*/nullptr, /*is_guest_view=*/false,
SendNewBrowserInfoResponse(/*browser_info=*/nullptr, /*is_guest_view=*/false,
std::move(pending_info->callback),
pending_info->callback_runner);
}
// static
void CefBrowserInfoManager::TimeoutNewBrowserInfoResponse(int64_t frame_id,
int timeout_id) {
void CefBrowserInfoManager::TimeoutNewBrowserInfoResponse(
const content::GlobalRenderFrameHostId& global_id,
int timeout_id) {
if (!g_info_manager)
return;
base::AutoLock lock_scope(g_info_manager->browser_info_lock_);
// Continue the NewBrowserInfo request if it's still pending.
auto it = g_info_manager->pending_new_browser_info_map_.find(frame_id);
auto it = g_info_manager->pending_new_browser_info_map_.find(global_id);
if (it != g_info_manager->pending_new_browser_info_map_.end()) {
const auto& pending_info = it->second;
// Don't accidentally timeout a new request for the same frame.
if (pending_info->timeout_id != timeout_id)
return;
LOG(ERROR) << "Timeout of new browser info response for frame process id "
<< pending_info->render_process_id << " and routing id "
<< pending_info->render_routing_id;
LOG(ERROR) << "Timeout of new browser info response for frame "
<< frame_util::GetFrameDebugString(global_id);
CancelNewBrowserInfoResponse(pending_info.get());
g_info_manager->pending_new_browser_info_map_.erase(it);

View File

@ -17,6 +17,7 @@
#include "base/sequenced_task_runner.h"
#include "base/synchronization/lock.h"
#include "cef/libcef/common/mojom/cef.mojom.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/render_process_host_observer.h"
#include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
#include "ui/base/window_open_disposition.h"
@ -79,8 +80,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver {
// only). See comments on PendingPopup for more information.
void GetCustomWebContentsView(
const GURL& target_url,
int opener_render_process_id,
int opener_render_routing_id,
const content::GlobalRenderFrameHostId& opener_global_id,
content::WebContentsView** view,
content::RenderViewHostDelegateView** delegate_view);
@ -88,8 +88,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver {
// PendingPopup for more information.
void WebContentsCreated(
const GURL& target_url,
int opener_render_process_id,
int opener_render_routing_id,
const content::GlobalRenderFrameHostId& opener_global_id,
CefBrowserSettings& settings,
CefRefPtr<CefClient>& client,
std::unique_ptr<CefBrowserPlatformDelegate>& platform_delegate,
@ -103,8 +102,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver {
// already exist for traditional popup browsers depending on timing. See
// comments on PendingPopup for more information.
void OnGetNewBrowserInfo(
int render_process_id,
int render_routing_id,
const content::GlobalRenderFrameHostId& global_id,
cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback);
// Called from CefBrowserHostBase::DestroyBrowser() when a browser is
@ -114,25 +112,14 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver {
// Called from CefContext::FinishShutdownOnUIThread() to destroy all browsers.
void DestroyAllBrowsers();
// Returns the CefBrowserInfo matching the specified IDs or nullptr if no
// Returns the CefBrowserInfo matching the specified ID or nullptr if no
// match is found. It is allowed to add new callers of this method but
// consider using CefBrowserHostBase::GetBrowserForFrameRoute() or
// extensions::GetOwnerBrowserForFrameRoute() instead. If |is_guest_view| is
// non-nullptr it will be set to true if the IDs match a guest view associated
// with the returned browser info instead of the browser itself.
scoped_refptr<CefBrowserInfo> GetBrowserInfoForFrameRoute(
int render_process_id,
int render_routing_id,
bool* is_guest_view = nullptr);
// Returns the CefBrowserInfo matching the specified ID or nullptr if no match
// is found. It is allowed to add new callers of this method but consider
// using CefBrowserHostBase::GetBrowserForFrameTreeNode() instead. If
// |is_guest_view| is non-nullptr it will be set to true if the IDs match a
// guest view associated with the returned browser info instead of the browser
// itself.
scoped_refptr<CefBrowserInfo> GetBrowserInfoForFrameTreeNode(
int frame_tree_node_id,
// consider using CefBrowserHostBase::GetBrowserForGlobalId() or
// extensions::GetOwnerBrowserForGlobalId() instead. If |is_guest_view| is
// non-nullptr it will be set to true if the ID matches a guest view
// associated with the returned browser info instead of the browser itself.
scoped_refptr<CefBrowserInfo> GetBrowserInfo(
const content::GlobalRenderFrameHostId& global_id,
bool* is_guest_view = nullptr);
// Returns all existing CefBrowserInfo objects.
@ -176,8 +163,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver {
// Initial state from ViewHostMsg_CreateWindow.
// |target_url| will be empty if a popup is created via window.open() and
// never navigated. For example: javascript:window.open();
int opener_render_process_id;
int opener_render_routing_id;
content::GlobalRenderFrameHostId opener_global_id;
GURL target_url;
std::string target_frame_name;
@ -192,20 +178,18 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver {
// Manage pending popups. Only called on the UI thread.
void PushPendingPopup(std::unique_ptr<PendingPopup> popup);
std::unique_ptr<PendingPopup> PopPendingPopup(PendingPopup::Step step,
int opener_process_id,
int opener_routing_id,
const GURL& target_url);
std::unique_ptr<PendingPopup> PopPendingPopup(
PendingPopup::Step step,
const content::GlobalRenderFrameHostId& opener_global_id,
const GURL& target_url);
// Retrieves the BrowserInfo matching the specified IDs. If both sets are
// valid then this method makes sure both sets have been registered.
scoped_refptr<CefBrowserInfo> GetBrowserInfo(int render_process_id,
int render_routing_id,
bool* is_guest_view);
// Retrieves the BrowserInfo matching the specified ID.
scoped_refptr<CefBrowserInfo> GetBrowserInfoInternal(
const content::GlobalRenderFrameHostId& global_id,
bool* is_guest_view);
// Send the response for a pending OnGetNewBrowserInfo request.
static void SendNewBrowserInfoResponse(
int render_process_id,
scoped_refptr<CefBrowserInfo> browser_info,
bool is_guest_view,
cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback,
@ -213,8 +197,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver {
// Pending request for OnGetNewBrowserInfo.
struct PendingNewBrowserInfo {
int render_process_id;
int render_routing_id;
content::GlobalRenderFrameHostId global_id;
int timeout_id;
cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback;
scoped_refptr<base::SequencedTaskRunner> callback_runner;
@ -224,7 +207,9 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver {
static void CancelNewBrowserInfoResponse(PendingNewBrowserInfo* pending_info);
// Time out a response if it's still pending.
static void TimeoutNewBrowserInfoResponse(int64_t frame_id, int timeout_id);
static void TimeoutNewBrowserInfoResponse(
const content::GlobalRenderFrameHostId& global_id,
int timeout_id);
mutable base::Lock browser_info_lock_;
@ -233,9 +218,12 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver {
BrowserInfoList browser_info_list_;
int next_browser_id_ = 0;
// Map of frame ID to info.
// Map of global ID to info. These IDs are guaranteed to uniquely
// identify a RFH for its complete lifespan. See documentation on
// RenderFrameHost::GetFrameTreeNodeId() for background.
using PendingNewBrowserInfoMap =
std::map<int64_t, std::unique_ptr<PendingNewBrowserInfo>>;
std::map<content::GlobalRenderFrameHostId,
std::unique_ptr<PendingNewBrowserInfo>>;
PendingNewBrowserInfoMap pending_new_browser_info_map_;
// Only accessed on the UI thread.

View File

@ -6,6 +6,7 @@
#include "libcef/browser/browser_info_manager.h"
#include "libcef/browser/origin_whitelist_impl.h"
#include "libcef/common/frame_util.h"
#include "content/public/browser/render_process_host.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@ -52,5 +53,6 @@ void CefBrowserManager::GetNewBrowserInfo(
int32_t render_frame_routing_id,
cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback) {
CefBrowserInfoManager::GetInstance()->OnGetNewBrowserInfo(
render_process_id_, render_frame_routing_id, std::move(callback));
frame_util::MakeGlobalId(render_process_id_, render_frame_routing_id),
std::move(callback));
}

View File

@ -13,10 +13,12 @@
#include "libcef/browser/chrome/chrome_browser_host_impl.h"
#include "libcef/browser/request_context_impl.h"
#include "libcef/common/app_manager.h"
#include "libcef/common/frame_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/native_web_keyboard_event.h"
@ -83,8 +85,10 @@ void ChromeBrowserDelegate::WebContentsCreated(
CefRefPtr<CefDictionaryValue> extra_info;
CefBrowserInfoManager::GetInstance()->WebContentsCreated(
target_url, opener_render_process_id, opener_render_frame_id, settings,
client, platform_delegate, extra_info);
target_url,
frame_util::MakeGlobalId(opener_render_process_id,
opener_render_frame_id),
settings, client, platform_delegate, extra_info);
auto opener = ChromeBrowserHostImpl::GetBrowserForContents(source_contents);
if (!opener) {

View File

@ -86,21 +86,10 @@ CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForContents(
}
// static
CefRefPtr<ChromeBrowserHostImpl>
ChromeBrowserHostImpl::GetBrowserForFrameTreeNode(int frame_tree_node_id) {
CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForGlobalId(
const content::GlobalRenderFrameHostId& global_id) {
REQUIRE_CHROME_RUNTIME();
auto browser =
CefBrowserHostBase::GetBrowserForFrameTreeNode(frame_tree_node_id);
return static_cast<ChromeBrowserHostImpl*>(browser.get());
}
// static
CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForFrameRoute(
int render_process_id,
int render_routing_id) {
REQUIRE_CHROME_RUNTIME();
auto browser = CefBrowserHostBase::GetBrowserForFrameRoute(render_process_id,
render_routing_id);
auto browser = CefBrowserHostBase::GetBrowserForGlobalId(global_id);
return static_cast<ChromeBrowserHostImpl*>(browser.get());
}

View File

@ -44,13 +44,9 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase {
// Returns the browser associated with the specified WebContents.
static CefRefPtr<ChromeBrowserHostImpl> GetBrowserForContents(
const content::WebContents* contents);
// Returns the browser associated with the specified FrameTreeNode ID.
static CefRefPtr<ChromeBrowserHostImpl> GetBrowserForFrameTreeNode(
int frame_tree_node_id);
// Returns the browser associated with the specified frame routing IDs.
static CefRefPtr<ChromeBrowserHostImpl> GetBrowserForFrameRoute(
int render_process_id,
int render_routing_id);
// Returns the browser associated with the specified global ID.
static CefRefPtr<ChromeBrowserHostImpl> GetBrowserForGlobalId(
const content::GlobalRenderFrameHostId& global_id);
~ChromeBrowserHostImpl() override;

View File

@ -10,6 +10,7 @@
#include "libcef/browser/browser_info_manager.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/extensions/extensions_util.h"
#include "libcef/common/frame_util.h"
#include "libcef/features/runtime_checks.h"
#include "chrome/browser/browser_process.h"
@ -73,29 +74,27 @@ content::WebContents* GetOwnerForGuestContents(content::WebContents* guest) {
return print_preview_controller->GetInitiator(guest);
}
CefRefPtr<CefBrowserHostBase> GetOwnerBrowserForFrameRoute(
int render_process_id,
int render_routing_id,
CefRefPtr<CefBrowserHostBase> GetOwnerBrowserForGlobalId(
const content::GlobalRenderFrameHostId& global_id,
bool* is_guest_view) {
if (CEF_CURRENTLY_ON_UIT()) {
// Use the non-thread-safe but potentially faster approach.
content::RenderFrameHost* host =
content::RenderFrameHost::FromID(render_process_id, render_routing_id);
content::RenderFrameHost::FromID(global_id);
if (host)
return GetOwnerBrowserForHost(host, is_guest_view);
return nullptr;
} else {
// Use the thread-safe approach.
scoped_refptr<CefBrowserInfo> info =
CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameRoute(
render_process_id, render_routing_id, is_guest_view);
CefBrowserInfoManager::GetInstance()->GetBrowserInfo(global_id,
is_guest_view);
if (info.get()) {
CefRefPtr<CefBrowserHostBase> browser = info->browser();
if (!browser.get()) {
LOG(WARNING) << "Found browser id " << info->browser_id()
<< " but no browser object matching view process id "
<< render_process_id << " and frame routing id "
<< render_routing_id;
<< " but no browser object matching frame "
<< frame_util::GetFrameDebugString(global_id);
}
return browser;
}

View File

@ -13,6 +13,7 @@
namespace content {
class BrowserContext;
struct GlobalRenderFrameHostId;
class RenderFrameHost;
class RenderViewHost;
class WebContents;
@ -37,12 +38,11 @@ void GetAllGuestsForOwnerContents(content::WebContents* owner,
content::WebContents* GetOwnerForGuestContents(content::WebContents* guest);
// Returns the CefBrowserHostBase that owns the host identified by the specified
// routing IDs, if any. |is_guest_view| will be set to true if the IDs
// match a guest view associated with the returned browser instead of the
// global ID, if any. |is_guest_view| will be set to true if the ID
// matches a guest view associated with the returned browser instead of the
// browser itself.
CefRefPtr<CefBrowserHostBase> GetOwnerBrowserForFrameRoute(
int render_process_id,
int render_routing_id,
CefRefPtr<CefBrowserHostBase> GetOwnerBrowserForGlobalId(
const content::GlobalRenderFrameHostId& global_id,
bool* is_guest_view);
// Returns the CefBrowserHostBase that owns the specified |host|, if any.

View File

@ -68,14 +68,15 @@ CefFrameHostImpl::CefFrameHostImpl(scoped_refptr<CefBrowserInfo> browser_info,
CefFrameHostImpl::CefFrameHostImpl(scoped_refptr<CefBrowserInfo> browser_info,
content::RenderFrameHost* render_frame_host)
: is_main_frame_(render_frame_host->GetParent() == nullptr),
frame_id_(MakeFrameId(render_frame_host)),
frame_id_(frame_util::MakeFrameId(render_frame_host->GetGlobalId())),
browser_info_(browser_info),
is_focused_(is_main_frame_), // The main frame always starts focused.
url_(render_frame_host->GetLastCommittedURL().spec()),
name_(render_frame_host->GetFrameName()),
parent_frame_id_(is_main_frame_
? kInvalidFrameId
: MakeFrameId(render_frame_host->GetParent())),
parent_frame_id_(
is_main_frame_ ? kInvalidFrameId
: frame_util::MakeFrameId(
render_frame_host->GetParent()->GetGlobalId())),
render_frame_host_(render_frame_host) {
DCHECK(browser_info_);
}
@ -276,8 +277,10 @@ void CefFrameHostImpl::RefreshAttributes() {
}
}
if (!is_main_frame_)
parent_frame_id_ = MakeFrameId(render_frame_host_->GetParent());
if (!is_main_frame_) {
parent_frame_id_ =
frame_util::MakeFrameId(render_frame_host_->GetParent()->GetGlobalId());
}
}
void CefFrameHostImpl::NotifyMoveOrResizeStarted() {
@ -457,20 +460,6 @@ bool CefFrameHostImpl::Detach() {
return first_detach;
}
// static
int64_t CefFrameHostImpl::MakeFrameId(const content::RenderFrameHost* host) {
CEF_REQUIRE_UIT();
auto host_nonconst = const_cast<content::RenderFrameHost*>(host);
return MakeFrameId(host_nonconst->GetProcess()->GetID(),
host_nonconst->GetRoutingID());
}
// static
int64_t CefFrameHostImpl::MakeFrameId(int32_t render_process_id,
int32_t render_routing_id) {
return frame_util::MakeFrameId(render_process_id, render_routing_id);
}
// kMainFrameId must be -1 to align with renderer expectations.
const int64_t CefFrameHostImpl::kMainFrameId = -1;
const int64_t CefFrameHostImpl::kFocusedFrameId = -2;

View File

@ -128,10 +128,6 @@ class CefFrameHostImpl : public CefFrame, public cef::mojom::BrowserFrame {
absl::optional<std::vector<cef::mojom::DraggableRegionEntryPtr>> regions)
override;
static int64_t MakeFrameId(const content::RenderFrameHost* host);
static int64_t MakeFrameId(int32_t render_process_id,
int32_t render_routing_id);
static const int64_t kMainFrameId;
static const int64_t kFocusedFrameId;
static const int64_t kUnspecifiedFrameId;

View File

@ -14,6 +14,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/resource_context_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_routing_id.h"
CefIOThreadState::CefIOThreadState() {
// Using base::Unretained() is safe because both this callback and possible
@ -27,31 +28,24 @@ CefIOThreadState::~CefIOThreadState() {
CEF_REQUIRE_IOT();
}
void CefIOThreadState::AddHandler(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
CefRefPtr<CefRequestContextHandler> handler) {
void CefIOThreadState::AddHandler(
const content::GlobalRenderFrameHostId& global_id,
CefRefPtr<CefRequestContextHandler> handler) {
CEF_REQUIRE_IOT();
handler_map_.AddHandler(render_process_id, render_frame_id,
frame_tree_node_id, handler);
handler_map_.AddHandler(global_id, handler);
}
void CefIOThreadState::RemoveHandler(int render_process_id,
int render_frame_id,
int frame_tree_node_id) {
void CefIOThreadState::RemoveHandler(
const content::GlobalRenderFrameHostId& global_id) {
CEF_REQUIRE_IOT();
handler_map_.RemoveHandler(render_process_id, render_frame_id,
frame_tree_node_id);
handler_map_.RemoveHandler(global_id);
}
CefRefPtr<CefRequestContextHandler> CefIOThreadState::GetHandler(
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
bool require_frame_match) const {
CEF_REQUIRE_IOT();
return handler_map_.GetHandler(render_process_id, render_frame_id,
frame_tree_node_id, require_frame_match);
return handler_map_.GetHandler(global_id, require_frame_match);
}
void CefIOThreadState::RegisterSchemeHandlerFactory(

View File

@ -14,6 +14,10 @@
#include "content/public/browser/browser_thread.h"
namespace content {
struct GlobalRenderFrameHostId;
}
class GURL;
// Stores state that will be accessed on the IO thread. Life span is controlled
@ -26,17 +30,11 @@ class CefIOThreadState : public base::RefCountedThreadSafe<
CefIOThreadState();
// See comments in CefRequestContextHandlerMap.
void AddHandler(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
void AddHandler(const content::GlobalRenderFrameHostId& global_id,
CefRefPtr<CefRequestContextHandler> handler);
void RemoveHandler(int render_process_id,
int render_frame_id,
int frame_tree_node_id);
void RemoveHandler(const content::GlobalRenderFrameHostId& global_id);
CefRefPtr<CefRequestContextHandler> GetHandler(
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
bool require_frame_match) const;
// Manage scheme handler factories associated with this context.

View File

@ -7,6 +7,7 @@
#include "libcef/browser/browser_host_base.h"
#include "libcef/browser/browser_info_manager.h"
#include "libcef/browser/frame_host_impl.h"
#include "libcef/common/frame_util.h"
#include "libcef/common/request_impl.h"
#include "components/navigation_interception/intercept_navigation_throttle.h"
@ -25,9 +26,8 @@ namespace {
// |is_main_frame| argument once this problem is fixed.
bool NavigationOnUIThread(
bool is_main_frame,
int64_t frame_id,
int64_t parent_frame_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
const content::GlobalRenderFrameHostId& parent_global_id,
content::WebContents* source,
const navigation_interception::NavigationParams& params) {
CEF_REQUIRE_UIT();
@ -53,16 +53,13 @@ bool NavigationOnUIThread(
CefRefPtr<CefFrame> frame;
if (is_main_frame) {
frame = browser->GetMainFrame();
} else if (frame_id >= 0) {
frame = browser->GetFrame(frame_id);
}
if (!frame && frame_tree_node_id >= 0) {
frame = browser->GetFrameForFrameTreeNode(frame_tree_node_id);
} else {
frame = browser->GetFrameForGlobalId(global_id);
}
if (!frame) {
// Create a temporary frame object for navigation of sub-frames that
// don't yet exist.
frame = browser->browser_info()->CreateTempSubFrame(parent_frame_id);
frame = browser->browser_info()->CreateTempSubFrame(parent_global_id);
}
CefRefPtr<CefRequestImpl> request = new CefRequestImpl();
@ -90,26 +87,20 @@ void CreateThrottlesForNavigation(content::NavigationHandle* navigation_handle,
CEF_REQUIRE_UIT();
const bool is_main_frame = navigation_handle->IsInMainFrame();
const auto global_id = frame_util::GetGlobalId(navigation_handle);
// Identify the RenderFrameHost that originated the navigation.
const int64_t parent_frame_id =
!is_main_frame
? CefFrameHostImpl::MakeFrameId(navigation_handle->GetParentFrame())
: CefFrameHostImpl::kInvalidFrameId;
const int64_t frame_id = !is_main_frame && navigation_handle->HasCommitted()
? CefFrameHostImpl::MakeFrameId(
navigation_handle->GetRenderFrameHost())
: CefFrameHostImpl::kInvalidFrameId;
const auto parent_global_id =
!is_main_frame ? navigation_handle->GetParentFrame()->GetGlobalId()
: frame_util::InvalidGlobalId();
// Must use SynchronyMode::kSync to ensure that OnBeforeBrowse is always
// called before OnBeforeResourceLoad.
std::unique_ptr<content::NavigationThrottle> throttle =
std::make_unique<navigation_interception::InterceptNavigationThrottle>(
navigation_handle,
base::BindRepeating(&NavigationOnUIThread, is_main_frame, frame_id,
parent_frame_id,
navigation_handle->GetFrameTreeNodeId()),
base::BindRepeating(&NavigationOnUIThread, is_main_frame, global_id,
parent_global_id),
navigation_interception::SynchronyMode::kSync);
throttles.push_back(std::move(throttle));
}

View File

@ -22,6 +22,7 @@
#include "chrome/browser/profiles/profile.h"
#include "components/language/core/browser/pref_names.h"
#include "components/prefs/pref_service.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@ -228,8 +229,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
void Initialize(content::BrowserContext* browser_context,
CefRefPtr<CefBrowserHostBase> browser,
CefRefPtr<CefFrame> frame,
int render_process_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
bool is_navigation,
bool is_download,
const url::Origin& request_initiator,
@ -256,8 +256,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
frame_ = frame;
}
render_process_id_ = render_process_id;
frame_tree_node_id_ = frame_tree_node_id;
global_id_ = global_id;
is_navigation_ = is_navigation;
is_download_ = is_download;
request_initiator_ = request_initiator.Serialize();
@ -292,8 +291,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
CefRefPtr<CefFrame> frame_;
scoped_refptr<CefIOThreadState> iothread_state_;
CefBrowserContext::CookieableSchemes cookieable_schemes_;
int render_process_id_ = 0;
int frame_tree_node_id_ = -1;
content::GlobalRenderFrameHostId global_id_;
bool is_navigation_ = true;
bool is_download_ = false;
CefString request_initiator_;
@ -1052,8 +1050,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
// Maybe the request context wants to handle it?
CefRefPtr<CefRequestContextHandler> context_handler =
init_state_->iothread_state_->GetHandler(
init_state_->render_process_id_, MSG_ROUTING_NONE,
init_state_->frame_tree_node_id_, /*require_frame_match=*/false);
init_state_->global_id_, /*require_frame_match=*/false);
if (context_handler) {
if (!requestPtr)
requestPtr = MakeRequest(request, request_id, true);
@ -1174,80 +1171,6 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
DISALLOW_COPY_AND_ASSIGN(InterceptedRequestHandlerWrapper);
};
void InitOnUIThread(
scoped_refptr<InterceptedRequestHandlerWrapper::InitHelper> init_helper,
content::WebContents::Getter web_contents_getter,
int frame_tree_node_id,
const network::ResourceRequest& request,
const base::RepeatingClosure& unhandled_request_callback) {
CEF_REQUIRE_UIT();
// May return nullptr if the WebContents was destroyed while this callback was
// in-flight.
content::WebContents* web_contents = web_contents_getter.Run();
if (!web_contents) {
return;
}
content::BrowserContext* browser_context = web_contents->GetBrowserContext();
DCHECK(browser_context);
const int render_process_id =
web_contents->GetRenderViewHost()->GetProcess()->GetID();
content::RenderFrameHost* frame = nullptr;
if (request.is_main_frame ||
static_cast<blink::mojom::ResourceType>(request.resource_type) ==
blink::mojom::ResourceType::kMainFrame) {
frame = web_contents->GetMainFrame();
DCHECK(frame);
} else {
if (frame_tree_node_id >= 0) {
// May return null for frames in inner WebContents.
frame = web_contents->FindFrameByFrameTreeNodeId(frame_tree_node_id,
render_process_id);
}
if (!frame) {
// Use the main frame for the CefBrowserHost.
frame = web_contents->GetMainFrame();
DCHECK(frame);
}
}
CefRefPtr<CefBrowserHostBase> browserPtr;
CefRefPtr<CefFrame> framePtr;
// |frame| may be null for service worker requests.
if (frame) {
// May return nullptr for requests originating from guest views.
browserPtr = CefBrowserHostBase::GetBrowserForHost(frame);
if (browserPtr) {
framePtr = browserPtr->GetFrameForHost(frame);
if (frame_tree_node_id < 0)
frame_tree_node_id = frame->GetFrameTreeNodeId();
DCHECK(framePtr);
}
}
const bool is_navigation = ui::PageTransitionIsNewNavigation(
static_cast<ui::PageTransition>(request.transition_type));
// TODO(navigation): Can we determine the |is_download| value?
const bool is_download = false;
url::Origin request_initiator;
if (request.request_initiator.has_value())
request_initiator = *request.request_initiator;
auto init_state =
std::make_unique<InterceptedRequestHandlerWrapper::InitState>();
init_state->Initialize(browser_context, browserPtr, framePtr,
render_process_id, frame_tree_node_id, is_navigation,
is_download, request_initiator,
unhandled_request_callback);
init_helper->MaybeSetInitialized(std::move(init_state));
}
} // namespace
std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
@ -1258,27 +1181,31 @@ std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
bool is_download,
const url::Origin& request_initiator) {
CEF_REQUIRE_UIT();
CHECK(browser_context);
CefRefPtr<CefBrowserHostBase> browserPtr;
CefRefPtr<CefFrame> framePtr;
int frame_tree_node_id = -1;
// |frame| may be null for service worker requests.
// Default to handlers for the same process in case |frame| doesn't have an
// associated CefBrowserHost.
content::GlobalRenderFrameHostId global_id(render_process_id,
MSG_ROUTING_NONE);
// |frame| may be nullptr for service worker requests.
if (frame) {
frame_tree_node_id = frame->GetFrameTreeNodeId();
// May return nullptr for requests originating from guest views.
browserPtr = CefBrowserHostBase::GetBrowserForHost(frame);
if (browserPtr) {
framePtr = browserPtr->GetFrameForHost(frame);
DCHECK(framePtr);
CHECK(framePtr);
global_id = frame->GetGlobalId();
}
}
auto init_state =
std::make_unique<InterceptedRequestHandlerWrapper::InitState>();
init_state->Initialize(browser_context, browserPtr, framePtr,
render_process_id, frame_tree_node_id, is_navigation,
is_download, request_initiator,
init_state->Initialize(browser_context, browserPtr, framePtr, global_id,
is_navigation, is_download, request_initiator,
base::RepeatingClosure());
auto wrapper = std::make_unique<InterceptedRequestHandlerWrapper>();
@ -1292,10 +1219,74 @@ std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
int frame_tree_node_id,
const network::ResourceRequest& request,
const base::RepeatingClosure& unhandled_request_callback) {
CEF_REQUIRE_UIT();
content::WebContents* web_contents = web_contents_getter.Run();
CHECK(web_contents);
content::BrowserContext* browser_context = web_contents->GetBrowserContext();
CHECK(browser_context);
content::RenderFrameHost* frame = nullptr;
if (request.is_main_frame ||
static_cast<blink::mojom::ResourceType>(request.resource_type) ==
blink::mojom::ResourceType::kMainFrame) {
frame = web_contents->GetMainFrame();
CHECK(frame);
} else {
// May return nullptr for frames in inner WebContents.
auto node = content::FrameTreeNode::GloballyFindByID(frame_tree_node_id);
if (node) {
frame = node->current_frame_host();
// RFHs can move between FrameTreeNodes. Make sure this one hasn't. See
// documentation on RenderFrameHost::GetFrameTreeNodeId() for background.
if (content::WebContents::FromRenderFrameHost(frame) != web_contents) {
frame = nullptr;
}
}
if (!frame) {
// Use the main frame for the CefBrowserHost.
frame = web_contents->GetMainFrame();
CHECK(frame);
}
}
CefRefPtr<CefBrowserHostBase> browserPtr;
CefRefPtr<CefFrame> framePtr;
// Default to handlers for the same process in case |frame| doesn't have an
// associated CefBrowserHost.
content::GlobalRenderFrameHostId global_id(frame->GetProcess()->GetID(),
MSG_ROUTING_NONE);
// May return nullptr for requests originating from guest views.
browserPtr = CefBrowserHostBase::GetBrowserForHost(frame);
if (browserPtr) {
framePtr = browserPtr->GetFrameForHost(frame);
DCHECK(framePtr);
global_id = frame->GetGlobalId();
}
const bool is_navigation = ui::PageTransitionIsNewNavigation(
static_cast<ui::PageTransition>(request.transition_type));
// TODO(navigation): Can we determine the |is_download| value?
const bool is_download = false;
url::Origin request_initiator;
if (request.request_initiator.has_value())
request_initiator = *request.request_initiator;
auto init_state =
std::make_unique<InterceptedRequestHandlerWrapper::InitState>();
init_state->Initialize(browser_context, browserPtr, framePtr, global_id,
is_navigation, is_download, request_initiator,
unhandled_request_callback);
auto wrapper = std::make_unique<InterceptedRequestHandlerWrapper>();
CEF_POST_TASK(CEF_UIT, base::BindOnce(InitOnUIThread, wrapper->init_helper(),
web_contents_getter, frame_tree_node_id,
request, unhandled_request_callback));
wrapper->init_helper()->MaybeSetInitialized(std::move(init_state));
return wrapper;
}

View File

@ -38,7 +38,7 @@ std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
// Create an InterceptedRequestHandler that will delegate to a
// CefResourceRequestHandler. The resulting object should be passed to
// ProxyURLLoaderFactory::CreateProxy. Called on the IO thread only.
// ProxyURLLoaderFactory::CreateProxy. Called on the UI thread only.
std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
content::WebContents::Getter web_contents_getter,
int frame_tree_node_id,

View File

@ -9,6 +9,7 @@
#include "libcef/browser/thread_util.h"
#include "libcef/browser/web_plugin_impl.h"
#include "libcef/common/alloy/alloy_content_client.h"
#include "libcef/common/frame_util.h"
#include "extensions/common/constants.h"
@ -88,12 +89,12 @@ bool CefPluginServiceFilter::IsPluginAvailable(
return true;
}
auto browser_context =
CefBrowserContext::FromIDs(render_process_id, render_frame_id, -1, false);
const auto global_id = frame_util::MakeGlobalId(
render_process_id, render_frame_id, /*allow_invalid_frame_id=*/true);
auto browser_context = CefBrowserContext::FromGlobalId(global_id, false);
CefRefPtr<CefRequestContextHandler> handler;
if (browser_context) {
handler = browser_context->GetHandler(render_process_id, render_frame_id,
-1, false);
handler = browser_context->GetHandler(global_id, false);
}
if (!handler) {

View File

@ -12,6 +12,7 @@
#include "libcef/browser/print_settings_impl.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/app_manager.h"
#include "libcef/common/frame_util.h"
#include "base/bind.h"
#include "base/files/file_util.h"
@ -19,6 +20,7 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/public/browser/global_routing_id.h"
#include "printing/metafile.h"
#include "printing/print_job_constants.h"
#include "printing/print_settings.h"
@ -106,8 +108,10 @@ gfx::Size CefPrintDialogLinux::GetPdfPaperSize(
gfx::Size size;
auto browser = extensions::GetOwnerBrowserForFrameRoute(
context->render_process_id(), context->render_frame_id(), nullptr);
auto browser = extensions::GetOwnerBrowserForGlobalId(
frame_util::MakeGlobalId(context->render_process_id(),
context->render_frame_id()),
nullptr);
DCHECK(browser);
if (browser && browser->GetClient()) {
if (auto handler = browser->GetClient()->GetPrintHandler()) {
@ -139,8 +143,10 @@ void CefPrintDialogLinux::OnPrintStart(CefRefPtr<CefBrowserHostBase> browser) {
CefPrintDialogLinux::CefPrintDialogLinux(PrintingContextLinux* context)
: context_(context) {
DCHECK(context_);
browser_ = extensions::GetOwnerBrowserForFrameRoute(
context_->render_process_id(), context_->render_frame_id(), nullptr);
browser_ = extensions::GetOwnerBrowserForGlobalId(
frame_util::MakeGlobalId(context_->render_process_id(),
context_->render_frame_id()),
nullptr);
DCHECK(browser_);
}

View File

@ -4,63 +4,42 @@
#include "libcef/browser/request_context_handler_map.h"
#include "libcef/common/frame_util.h"
CefRequestContextHandlerMap::CefRequestContextHandlerMap() = default;
CefRequestContextHandlerMap::~CefRequestContextHandlerMap() = default;
void CefRequestContextHandlerMap::AddHandler(
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
CefRefPtr<CefRequestContextHandler> handler) {
DCHECK_GE(render_process_id, 0);
DCHECK_GE(render_frame_id, 0);
DCHECK_GE(frame_tree_node_id, 0);
DCHECK(frame_util::IsValidGlobalId(global_id));
DCHECK(handler);
render_id_handler_map_.insert(std::make_pair(
std::make_pair(render_process_id, render_frame_id), handler));
node_id_handler_map_.insert(std::make_pair(frame_tree_node_id, handler));
render_id_handler_map_.insert(std::make_pair(global_id, handler));
}
void CefRequestContextHandlerMap::RemoveHandler(int render_process_id,
int render_frame_id,
int frame_tree_node_id) {
DCHECK_GE(render_process_id, 0);
DCHECK_GE(render_frame_id, 0);
DCHECK_GE(frame_tree_node_id, 0);
void CefRequestContextHandlerMap::RemoveHandler(
const content::GlobalRenderFrameHostId& global_id) {
DCHECK(frame_util::IsValidGlobalId(global_id));
auto it1 = render_id_handler_map_.find(
std::make_pair(render_process_id, render_frame_id));
auto it1 = render_id_handler_map_.find(global_id);
if (it1 != render_id_handler_map_.end())
render_id_handler_map_.erase(it1);
auto it2 = node_id_handler_map_.find(frame_tree_node_id);
if (it2 != node_id_handler_map_.end())
node_id_handler_map_.erase(it2);
}
CefRefPtr<CefRequestContextHandler> CefRequestContextHandlerMap::GetHandler(
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
bool require_frame_match) const {
if (render_process_id >= 0 && render_frame_id >= 0) {
const auto it1 = render_id_handler_map_.find(
std::make_pair(render_process_id, render_frame_id));
if (frame_util::IsValidGlobalId(global_id)) {
const auto it1 = render_id_handler_map_.find(global_id);
if (it1 != render_id_handler_map_.end())
return it1->second;
}
if (frame_tree_node_id >= 0) {
const auto it2 = node_id_handler_map_.find(frame_tree_node_id);
if (it2 != node_id_handler_map_.end())
return it2->second;
}
if (render_process_id >= 0 && !require_frame_match) {
if (frame_util::IsValidChildId(global_id.child_id) && !require_frame_match) {
// Choose an arbitrary handler for the same process.
for (auto& kv : render_id_handler_map_) {
if (kv.first.first == render_process_id)
if (kv.first.child_id == global_id.child_id)
return kv.second;
}
}

View File

@ -12,6 +12,7 @@
#include "include/cef_request_context_handler.h"
#include "base/macros.h"
#include "content/public/browser/global_routing_id.h"
// Tracks CefRequestContextHandler associations on a single thread.
class CefRequestContextHandlerMap {
@ -23,38 +24,26 @@ class CefRequestContextHandlerMap {
// originates from frame create/delete notifications in
// CefBrowserContentsDelegate or CefMimeHandlerViewGuestDelegate which are
// forwarded via CefRequestContextImpl and CefBrowserContext.
void AddHandler(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
void AddHandler(const content::GlobalRenderFrameHostId& global_id,
CefRefPtr<CefRequestContextHandler> handler);
void RemoveHandler(int render_process_id,
int render_frame_id,
int frame_tree_node_id);
void RemoveHandler(const content::GlobalRenderFrameHostId& global_id);
// Returns the handler that matches the specified IDs. Pass -1 for unknown
// values. If |require_frame_match| is true only exact matches will be
// returned. If |require_frame_match| is false, and there is not an exact
// match, then the first handler for the same |render_process_id| will be
// returned.
// Returns the handler that matches the specified IDs. If
// |require_frame_match| is true only exact matches will be returned. If
// |require_frame_match| is false, and there is not an exact match, then the
// first handler for the same |global_id.child_id| will be returned.
CefRefPtr<CefRequestContextHandler> GetHandler(
int render_process_id,
int render_frame_id,
int frame_tree_node_id,
const content::GlobalRenderFrameHostId& global_id,
bool require_frame_match) const;
private:
// Map of (render_process_id, render_frame_id) to handler.
typedef std::map<std::pair<int, int>, CefRefPtr<CefRequestContextHandler>>
RenderIdHandlerMap;
// Map of global ID to handler. These IDs are guaranteed to uniquely
// identify a RFH for its complete lifespan. See documentation on
// RenderFrameHost::GetFrameTreeNodeId() for background.
using RenderIdHandlerMap = std::map<content::GlobalRenderFrameHostId,
CefRefPtr<CefRequestContextHandler>>;
RenderIdHandlerMap render_id_handler_map_;
// Map of frame_tree_node_id to handler. Keeping this map is necessary
// because, when navigating the main frame, a new (pre-commit) network request
// will be created before the RenderFrameHost. Consequently we can't rely
// on valid render IDs. See https://crbug.com/776884 for background.
typedef std::map<int, CefRefPtr<CefRequestContextHandler>> NodeIdHandlerMap;
NodeIdHandlerMap node_id_handler_map_;
DISALLOW_COPY_AND_ASSIGN(CefRequestContextHandlerMap);
};

View File

@ -18,6 +18,7 @@
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/ssl_host_state_delegate.h"
#include "content/public/common/child_process_host.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/cpp/resolve_host_client_base.h"
@ -589,24 +590,20 @@ CefRefPtr<CefMediaRouter> CefRequestContextImpl::GetMediaRouter(
return media_router.get();
}
void CefRequestContextImpl::OnRenderFrameCreated(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
bool is_main_frame,
bool is_guest_view) {
browser_context_->OnRenderFrameCreated(this, render_process_id,
render_frame_id, frame_tree_node_id,
is_main_frame, is_guest_view);
void CefRequestContextImpl::OnRenderFrameCreated(
const content::GlobalRenderFrameHostId& global_id,
bool is_main_frame,
bool is_guest_view) {
browser_context_->OnRenderFrameCreated(this, global_id, is_main_frame,
is_guest_view);
}
void CefRequestContextImpl::OnRenderFrameDeleted(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
bool is_main_frame,
bool is_guest_view) {
browser_context_->OnRenderFrameDeleted(this, render_process_id,
render_frame_id, frame_tree_node_id,
is_main_frame, is_guest_view);
void CefRequestContextImpl::OnRenderFrameDeleted(
const content::GlobalRenderFrameHostId& global_id,
bool is_main_frame,
bool is_guest_view) {
browser_context_->OnRenderFrameDeleted(this, global_id, is_main_frame,
is_guest_view);
}
// static
@ -714,7 +711,8 @@ void CefRequestContextImpl::PurgePluginListCacheInternal(
if (!browser_context)
return;
browser_context->ClearPluginLoadDecision(-1);
browser_context->ClearPluginLoadDecision(
content::ChildProcessHost::kInvalidUniqueID);
content::PluginService::GetInstance()->PurgePluginListCache(
browser_context->AsBrowserContext(), false);
}

View File

@ -12,6 +12,10 @@
#include "libcef/browser/net_service/cookie_manager_impl.h"
#include "libcef/browser/thread_util.h"
namespace content {
struct GlobalRenderFrameHostId;
}
class CefBrowserContext;
// Implementation of the CefRequestContext interface. All methods are thread-
@ -95,18 +99,14 @@ class CefRequestContextImpl : public CefRequestContext {
// Called from CefBrowserContentsDelegate::RenderFrameCreated or
// CefMimeHandlerViewGuestDelegate::OnGuestAttached when a render frame is
// created.
void OnRenderFrameCreated(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
void OnRenderFrameCreated(const content::GlobalRenderFrameHostId& global_id,
bool is_main_frame,
bool is_guest_view);
// Called from CefBrowserContentsDelegate::RenderFrameDeleted or
// CefMimeHandlerViewGuestDelegate::OnGuestDetached when a render frame is
// deleted.
void OnRenderFrameDeleted(int render_process_id,
int render_frame_id,
int frame_tree_node_id,
void OnRenderFrameDeleted(const content::GlobalRenderFrameHostId& global_id,
bool is_main_frame,
bool is_guest_view);

View File

@ -4,14 +4,22 @@
#include "libcef/common/frame_util.h"
#include "libcef/browser/thread_util.h"
#include <limits>
#include <sstream>
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
namespace frame_util {
int64_t MakeFrameId(int32_t render_process_id, int32_t render_routing_id) {
return (static_cast<uint64_t>(render_process_id) << 32) |
static_cast<uint64_t>(render_routing_id);
content::GlobalRenderFrameHostId GetGlobalId(
content::NavigationHandle* navigation_handle) {
CEF_REQUIRE_UIT();
return navigation_handle->HasCommitted()
? navigation_handle->GetRenderFrameHost()->GetGlobalId()
: navigation_handle->GetPreviousRenderFrameHostId();
}
std::string GetFrameDebugString(int64_t frame_id) {
@ -23,4 +31,9 @@ std::string GetFrameDebugString(int64_t frame_id) {
return ss.str();
}
std::string GetFrameDebugString(
const content::GlobalRenderFrameHostId& global_id) {
return GetFrameDebugString(MakeFrameId(global_id));
}
} // namespace frame_util

View File

@ -8,14 +8,76 @@
#include <stdint.h>
#include <string>
#include "base/logging.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/common/child_process_host.h"
namespace content {
class NavigationHandle;
}
namespace frame_util {
// Returns the frame ID, which is a 64-bit combination of |render_process_id|
// and |render_routing_id|.
int64_t MakeFrameId(int32_t render_process_id, int32_t render_routing_id);
// Create a frame ID in the format exposed by the CEF API.
inline int64_t MakeFrameId(int child_id, int frame_routing_id) {
return (static_cast<uint64_t>(child_id) << 32) |
static_cast<uint64_t>(frame_routing_id);
}
// Returns a human-readable version of |frame_id|.
// Create a frame ID in the format exposed by the CEF API.
inline int64_t MakeFrameId(const content::GlobalRenderFrameHostId& global_id) {
return MakeFrameId(global_id.child_id, global_id.frame_routing_id);
}
// Returns true if |child_id| is valid.
inline bool IsValidChildId(int child_id) {
// See comments in ChildProcessHostImpl::GenerateChildProcessUniqueId().
return child_id != content::ChildProcessHost::kInvalidUniqueID &&
child_id != 0;
}
// Returns true if |frame_routing_id| is valid.
inline bool IsValidRoutingId(int frame_routing_id) {
return frame_routing_id != MSG_ROUTING_NONE;
}
// Returns true if |global_id| is valid.
inline bool IsValidGlobalId(const content::GlobalRenderFrameHostId& global_id) {
return IsValidChildId(global_id.child_id) &&
IsValidRoutingId(global_id.frame_routing_id);
}
// Create a global ID from components.
inline content::GlobalRenderFrameHostId MakeGlobalId(
int child_id,
int frame_routing_id,
bool allow_invalid_frame_id = false) {
DCHECK(IsValidChildId(child_id));
DCHECK(allow_invalid_frame_id || IsValidRoutingId(frame_routing_id));
return content::GlobalRenderFrameHostId(child_id, frame_routing_id);
}
// Create a global ID from a frame ID.
inline content::GlobalRenderFrameHostId MakeGlobalId(int64_t frame_id) {
uint32_t child_id = frame_id >> 32;
uint32_t frame_routing_id = std::numeric_limits<uint32_t>::max() & frame_id;
return MakeGlobalId(child_id, frame_routing_id);
}
// Returns an invalid global ID value.
inline content::GlobalRenderFrameHostId InvalidGlobalId() {
return content::GlobalRenderFrameHostId();
}
// Returns the best match of global ID for |navigation_handle|. For pre-commit
// navigations this will return the current RFH, if any, or an invalid ID.
content::GlobalRenderFrameHostId GetGlobalId(
content::NavigationHandle* navigation_handle);
// Returns a human-readable version of the ID.
std::string GetFrameDebugString(int64_t frame_id);
std::string GetFrameDebugString(
const content::GlobalRenderFrameHostId& global_id);
} // namespace frame_util