Update to Chromium version 122.0.6261.0 (#1250580)

Frame identifiers have changed from int64_t to string type. This is due
to https://crbug.com/1502660 which removes access to frame routing IDs
in the renderer process. New cross-process frame identifiers are 160-bit
values (32-bit child process ID + 128-bit local frame token) and most
easily represented as strings. All other frame-related expectations and
behaviors remain the same.
This commit is contained in:
Marshall Greenblatt
2024-01-25 21:12:43 -05:00
parent 2a86a02bdd
commit 2f1e782f62
156 changed files with 1452 additions and 1436 deletions

View File

@@ -290,7 +290,7 @@ void AlloyContentRendererClient::RenderFrameCreated(
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(switches::kDisableSpellChecking)) {
new SpellCheckProvider(render_frame, spellcheck_.get(), this);
new SpellCheckProvider(render_frame, spellcheck_.get());
}
bool browser_created;
@@ -412,9 +412,9 @@ void AlloyContentRendererClient::WillSendRequest(
}
}
uint64_t AlloyContentRendererClient::VisitedLinkHash(const char* canonical_url,
size_t length) {
return visited_link_slave_->ComputeURLFingerprint(canonical_url, length);
uint64_t AlloyContentRendererClient::VisitedLinkHash(
std::string_view canonical_url) {
return visited_link_slave_->ComputeURLFingerprint(canonical_url);
}
bool AlloyContentRendererClient::IsLinkVisited(uint64_t link_hash) {

View File

@@ -97,7 +97,7 @@ class AlloyContentRendererClient
const net::SiteForCookies& site_for_cookies,
const url::Origin* initiator_origin,
GURL* new_url) override;
uint64_t VisitedLinkHash(const char* canonical_url, size_t length) override;
uint64_t VisitedLinkHash(std::string_view canonical_url) override;
bool IsLinkVisited(uint64_t link_hash) override;
bool IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path) override;
void GetSupportedKeySystems(media::GetSupportedKeySystemsCB cb) override;

View File

@@ -47,18 +47,15 @@ CefURLLoaderThrottleProviderImpl::Clone() {
blink::WebVector<std::unique_ptr<blink::URLLoaderThrottle>>
CefURLLoaderThrottleProviderImpl::CreateThrottles(
base::optional_ref<const blink::LocalFrameToken> local_frame_token,
const blink::WebURLRequest& request) {
const network::ResourceRequest& request) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
blink::WebVector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
const network::mojom::RequestDestination request_destination =
request.GetRequestDestination();
// Some throttles have already been added in the browser for frame resources.
// Don't add them for frame requests.
bool is_frame_resource =
blink::IsRequestDestinationFrame(request_destination);
blink::IsRequestDestinationFrame(request.destination);
DCHECK(!is_frame_resource ||
type_ == blink::URLLoaderThrottleProviderType::kFrame);

View File

@@ -31,7 +31,7 @@ class CefURLLoaderThrottleProviderImpl
std::unique_ptr<blink::URLLoaderThrottleProvider> Clone() override;
blink::WebVector<std::unique_ptr<blink::URLLoaderThrottle>> CreateThrottles(
base::optional_ref<const blink::LocalFrameToken> local_frame_token,
const blink::WebURLRequest& request) override;
const network::ResourceRequest& request) override;
void SetOnline(bool is_online) override;
private:

View File

@@ -56,8 +56,6 @@ blink::ExecutionContext* GetExecutionContext(v8::Local<v8::Context> context) {
} // namespace
const int64_t kInvalidFrameId = -1;
bool CanGoBack(blink::WebView* view) {
if (!view) {
return false;

View File

@@ -29,8 +29,6 @@ class WebView;
namespace blink_glue {
BLINK_EXPORT extern const int64_t kInvalidFrameId;
BLINK_EXPORT bool CanGoBack(blink::WebView* view);
BLINK_EXPORT bool CanGoForward(blink::WebView* view);
BLINK_EXPORT void GoBack(blink::WebView* view);

View File

@@ -181,13 +181,14 @@ CefRefPtr<CefFrame> CefBrowserImpl::GetFocusedFrame() {
return nullptr;
}
CefRefPtr<CefFrame> CefBrowserImpl::GetFrame(int64_t identifier) {
CefRefPtr<CefFrame> CefBrowserImpl::GetFrameByIdentifier(
const CefString& identifier) {
CEF_REQUIRE_RT_RETURN(nullptr);
return GetWebFrameImpl(identifier).get();
}
CefRefPtr<CefFrame> CefBrowserImpl::GetFrame(const CefString& name) {
CefRefPtr<CefFrame> CefBrowserImpl::GetFrameByName(const CefString& name) {
CEF_REQUIRE_RT_RETURN(nullptr);
blink::WebView* web_view = GetWebView();
@@ -235,7 +236,7 @@ size_t CefBrowserImpl::GetFrameCount() {
return count;
}
void CefBrowserImpl::GetFrameIdentifiers(std::vector<int64_t>& identifiers) {
void CefBrowserImpl::GetFrameIdentifiers(std::vector<CefString>& identifiers) {
CEF_REQUIRE_RT_RETURN_VOID();
if (identifiers.size() > 0) {
@@ -287,71 +288,45 @@ CefBrowserImpl::~CefBrowserImpl() = default;
CefRefPtr<CefFrameImpl> CefBrowserImpl::GetWebFrameImpl(
blink::WebLocalFrame* frame) {
DCHECK(frame);
int64_t frame_id = render_frame_util::GetIdentifier(frame);
const auto& frame_token = frame->GetLocalFrameToken();
// Frames are re-used between page loads. Only add the frame to the map once.
FrameMap::const_iterator it = frames_.find(frame_id);
FrameMap::const_iterator it = frames_.find(frame_token);
if (it != frames_.end()) {
return it->second;
}
CefRefPtr<CefFrameImpl> framePtr(new CefFrameImpl(this, frame, frame_id));
frames_.insert(std::make_pair(frame_id, framePtr));
CefRefPtr<CefFrameImpl> framePtr(new CefFrameImpl(this, frame));
frames_.insert(std::make_pair(frame_token, framePtr));
return framePtr;
}
CefRefPtr<CefFrameImpl> CefBrowserImpl::GetWebFrameImpl(int64_t frame_id) {
if (frame_id == blink_glue::kInvalidFrameId) {
if (GetWebView()) {
blink::WebFrame* main_frame = GetWebView()->MainFrame();
if (main_frame && main_frame->IsWebLocalFrame()) {
return GetWebFrameImpl(main_frame->ToWebLocalFrame());
}
}
CefRefPtr<CefFrameImpl> CefBrowserImpl::GetWebFrameImpl(
const std::string& identifier) {
const auto& frame_token =
render_frame_util::ParseFrameTokenFromIdentifier(identifier);
if (!frame_token) {
return nullptr;
}
// Check if we already know about the frame.
FrameMap::const_iterator it = frames_.find(frame_id);
FrameMap::const_iterator it = frames_.find(*frame_token);
if (it != frames_.end()) {
return it->second;
}
if (GetWebView()) {
// Check if the frame exists but we don't know about it yet.
for (blink::WebFrame* frame = GetWebView()->MainFrame(); frame;
frame = frame->TraverseNext()) {
if (frame->IsWebLocalFrame() &&
render_frame_util::GetIdentifier(frame->ToWebLocalFrame()) ==
frame_id) {
return GetWebFrameImpl(frame->ToWebLocalFrame());
}
if (auto* local_frame =
blink::WebLocalFrame::FromFrameToken(*frame_token)) {
return GetWebFrameImpl(local_frame);
}
}
return nullptr;
}
void CefBrowserImpl::AddFrameObject(int64_t frame_id,
CefTrackNode* tracked_object) {
CefRefPtr<CefTrackManager> manager;
if (!frame_objects_.empty()) {
FrameObjectMap::const_iterator it = frame_objects_.find(frame_id);
if (it != frame_objects_.end()) {
manager = it->second;
}
}
if (!manager.get()) {
manager = new CefTrackManager();
frame_objects_.insert(std::make_pair(frame_id, manager));
}
manager->Add(tracked_object);
}
// RenderViewObserver methods.
// -----------------------------------------------------------------------------
@@ -368,22 +343,8 @@ void CefBrowserImpl::OnDestruct() {
CefRenderManager::Get()->OnBrowserDestroyed(this);
}
void CefBrowserImpl::FrameDetached(int64_t frame_id) {
if (!frames_.empty()) {
// Remove the frame from the map.
FrameMap::iterator it = frames_.find(frame_id);
if (it != frames_.end()) {
frames_.erase(it);
}
}
if (!frame_objects_.empty()) {
// Remove any tracked objects associated with the frame.
FrameObjectMap::iterator it = frame_objects_.find(frame_id);
if (it != frame_objects_.end()) {
frame_objects_.erase(it);
}
}
void CefBrowserImpl::FrameDetached(blink::WebLocalFrame* frame) {
frames_.erase(frame->GetLocalFrameToken());
}
void CefBrowserImpl::OnLoadingStateChange(bool isLoading) {

View File

@@ -16,9 +16,9 @@
#include "include/cef_browser.h"
#include "include/cef_client.h"
#include "libcef/common/tracker.h"
#include "libcef/renderer/frame_impl.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/web/web_view_observer.h"
namespace blink {
@@ -57,10 +57,11 @@ class CefBrowserImpl : public CefBrowser, public blink::WebViewObserver {
bool HasDocument() override;
CefRefPtr<CefFrame> GetMainFrame() override;
CefRefPtr<CefFrame> GetFocusedFrame() override;
CefRefPtr<CefFrame> GetFrame(int64_t identifier) override;
CefRefPtr<CefFrame> GetFrame(const CefString& name) override;
CefRefPtr<CefFrame> GetFrameByIdentifier(
const CefString& identifier) override;
CefRefPtr<CefFrame> GetFrameByName(const CefString& name) override;
size_t GetFrameCount() override;
void GetFrameIdentifiers(std::vector<int64_t>& identifiers) override;
void GetFrameIdentifiers(std::vector<CefString>& identifiers) override;
void GetFrameNames(std::vector<CefString>& names) override;
CefBrowserImpl(blink::WebView* web_view,
@@ -75,10 +76,7 @@ class CefBrowserImpl : public CefBrowser, public blink::WebViewObserver {
// Returns the matching CefFrameImpl reference or creates a new one.
CefRefPtr<CefFrameImpl> GetWebFrameImpl(blink::WebLocalFrame* frame);
CefRefPtr<CefFrameImpl> GetWebFrameImpl(int64_t frame_id);
// Frame objects will be deleted immediately before the frame is closed.
void AddFrameObject(int64_t frame_id, CefTrackNode* tracked_object);
CefRefPtr<CefFrameImpl> GetWebFrameImpl(const std::string& identifier);
int browser_id() const { return browser_id_; }
bool is_popup() const { return is_popup_; }
@@ -86,7 +84,7 @@ class CefBrowserImpl : public CefBrowser, public blink::WebViewObserver {
// blink::WebViewObserver methods.
void OnDestruct() override;
void FrameDetached(int64_t frame_id);
void FrameDetached(blink::WebLocalFrame* frame);
void OnLoadingStateChange(bool isLoading);
void OnEnterBFCache();
@@ -99,18 +97,13 @@ class CefBrowserImpl : public CefBrowser, public blink::WebViewObserver {
bool is_popup_;
bool is_windowless_;
// Map of unique frame ids to CefFrameImpl references.
using FrameMap = std::map<int64_t, CefRefPtr<CefFrameImpl>>;
// Map of unique frame tokens to CefFrameImpl references.
using FrameMap = std::map<blink::LocalFrameToken, CefRefPtr<CefFrameImpl>>;
FrameMap frames_;
// True if the browser was in the BFCache.
bool was_in_bfcache_ = false;
// Map of unique frame ids to CefTrackManager objects that need to be cleaned
// up when the frame is deleted.
using FrameObjectMap = std::map<int64_t, CefRefPtr<CefTrackManager>>;
FrameObjectMap frame_objects_;
struct LoadingState {
LoadingState(bool is_loading, bool can_go_back, bool can_go_forward)
: is_loading_(is_loading),

View File

@@ -19,6 +19,7 @@
#include "extensions/renderer/dispatcher.h"
#include "extensions/renderer/extension_frame_helper.h"
#include "extensions/renderer/extensions_render_frame_observer.h"
#include "extensions/renderer/extensions_renderer_api_provider.h"
#include "extensions/renderer/renderer_extension_registry.h"
#include "extensions/renderer/script_context.h"
#include "third_party/blink/public/web/web_document.h"
@@ -82,7 +83,9 @@ void CefExtensionsRendererClient::RenderThreadStarted() {
content::RenderThread* thread = content::RenderThread::Get();
extension_dispatcher_ = std::make_unique<extensions::Dispatcher>(
std::make_unique<extensions::CefExtensionsDispatcherDelegate>());
std::make_unique<extensions::CefExtensionsDispatcherDelegate>(),
std::vector<
std::unique_ptr<extensions::ExtensionsRendererAPIProvider>>());
extension_dispatcher_->OnRenderThreadStarted(thread);
resource_request_policy_ =
std::make_unique<extensions::ResourceRequestPolicy>(

View File

@@ -61,12 +61,16 @@ constexpr auto kConnectionRetryDelay = base::Seconds(1);
// Length of time to wait for the browser connection ACK before timing out.
constexpr auto kConnectionTimeout = base::Seconds(10);
std::string GetDebugString(blink::WebLocalFrame* frame) {
return "frame " + render_frame_util::GetIdentifier(frame);
}
} // namespace
CefFrameImpl::CefFrameImpl(CefBrowserImpl* browser,
blink::WebLocalFrame* frame,
int64_t frame_id)
: browser_(browser), frame_(frame), frame_id_(frame_id) {}
CefFrameImpl::CefFrameImpl(CefBrowserImpl* browser, blink::WebLocalFrame* frame)
: browser_(browser),
frame_(frame),
frame_debug_str_(GetDebugString(frame)) {}
CefFrameImpl::~CefFrameImpl() = default;
@@ -185,10 +189,14 @@ CefString CefFrameImpl::GetName() {
return name;
}
int64_t CefFrameImpl::GetIdentifier() {
CEF_REQUIRE_RT_RETURN(0);
CefString CefFrameImpl::GetIdentifier() {
CefString identifier;
CEF_REQUIRE_RT_RETURN(identifier);
return frame_id_;
if (frame_) {
identifier = render_frame_util::GetIdentifier(frame_);
}
return identifier;
}
CefRefPtr<CefFrame> CefFrameImpl::GetParent() {
@@ -406,10 +414,9 @@ void CefFrameImpl::OnDetached() {
// keep |this| alive until after this method returns.
CefRefPtr<CefFrameImpl> self = this;
browser_->FrameDetached(frame_);
frame_ = nullptr;
browser_->FrameDetached(frame_id_);
OnDisconnect(DisconnectReason::DETACHED);
browser_ = nullptr;
@@ -417,7 +424,7 @@ void CefFrameImpl::OnDetached() {
// In case we never attached.
while (!queued_browser_actions_.empty()) {
auto& action = queued_browser_actions_.front();
LOG(WARNING) << action.first << " sent to detached " << GetDebugString()
LOG(WARNING) << action.first << " sent to detached " << frame_debug_str_
<< " will be ignored";
queued_browser_actions_.pop();
}
@@ -425,7 +432,7 @@ void CefFrameImpl::OnDetached() {
// In case we're destroyed without the context being created.
while (!queued_context_actions_.empty()) {
auto& action = queued_context_actions_.front();
LOG(WARNING) << action.first << " sent to detached " << GetDebugString()
LOG(WARNING) << action.first << " sent to detached " << frame_debug_str_
<< " will be ignored";
queued_context_actions_.pop();
}
@@ -444,7 +451,7 @@ void CefFrameImpl::ExecuteOnLocalFrame(const std::string& function_name,
if (frame_) {
std::move(action).Run(frame_);
} else {
LOG(WARNING) << function_name << " sent to detached " << GetDebugString()
LOG(WARNING) << function_name << " sent to detached " << frame_debug_str_
<< " will be ignored";
}
}
@@ -467,7 +474,7 @@ void CefFrameImpl::ConnectBrowserFrame(ConnectReason reason) {
"RETRY %zu/%zu", browser_connect_retry_ct_, kConnectionRetryMaxCt);
break;
}
VLOG(1) << GetDebugString() << " connection request (reason=" << reason_str
VLOG(1) << frame_debug_str_ << " connection request (reason=" << reason_str
<< ")";
}
@@ -477,7 +484,7 @@ void CefFrameImpl::ConnectBrowserFrame(ConnectReason reason) {
if (!frame_ || blink_glue::IsInBackForwardCache(frame_)) {
browser_connection_state_ = ConnectionState::DISCONNECTED;
browser_connect_timer_.Stop();
VLOG(1) << GetDebugString() << " connection retry canceled (reason="
VLOG(1) << frame_debug_str_ << " connection retry canceled (reason="
<< (frame_ ? "BFCACHED" : "INVALID") << ")";
return;
}
@@ -524,7 +531,7 @@ const mojo::Remote<cef::mojom::BrowserFrame>& CefFrameImpl::GetBrowserFrame(
}
void CefFrameImpl::OnBrowserFrameTimeout() {
LOG(ERROR) << GetDebugString() << " connection timeout";
LOG(ERROR) << frame_debug_str_ << " connection timeout";
OnDisconnect(DisconnectReason::CONNECT_TIMEOUT);
}
@@ -577,7 +584,7 @@ void CefFrameImpl::OnDisconnect(DisconnectReason reason) {
state_str += ", FRAME_INVALID";
}
VLOG(1) << GetDebugString() << " disconnected (reason=" << reason_str
VLOG(1) << frame_debug_str_ << " disconnected (reason=" << reason_str
<< ", current_state=" << state_str << ")";
}
@@ -590,7 +597,7 @@ void CefFrameImpl::OnDisconnect(DisconnectReason reason) {
// intentionally detached.
if (frame_ && reason != DisconnectReason::BROWSER_FRAME_DETACHED) {
if (browser_connect_retry_ct_++ < kConnectionRetryMaxCt) {
VLOG(1) << GetDebugString() << " connection retry scheduled";
VLOG(1) << frame_debug_str_ << " connection retry scheduled";
// Retry after a delay in case the frame is currently navigating, being
// destroyed, or entering the bfcache. In the navigation case the retry
@@ -605,7 +612,7 @@ void CefFrameImpl::OnDisconnect(DisconnectReason reason) {
ConnectReason::RETRY));
} else {
// Trigger a crash in official builds.
LOG(FATAL) << GetDebugString() << " connection retry failed";
LOG(FATAL) << frame_debug_str_ << " connection retry failed";
}
}
}
@@ -614,7 +621,7 @@ void CefFrameImpl::SendToBrowserFrame(const std::string& function_name,
BrowserFrameAction action) {
if (!frame_) {
// We've been detached.
LOG(WARNING) << function_name << " sent to detached " << GetDebugString()
LOG(WARNING) << function_name << " sent to detached " << frame_debug_str_
<< " will be ignored";
return;
}
@@ -798,10 +805,6 @@ void CefFrameImpl::ContextLifecycleStateChanged(
}
}
std::string CefFrameImpl::GetDebugString() const {
return "frame " + frame_util::GetFrameDebugString(frame_id_);
}
// Enable deprecation warnings on Windows. See http://crbug.com/585142.
#if BUILDFLAG(IS_WIN)
#if defined(__clang__)

View File

@@ -41,9 +41,7 @@ class CefFrameImpl
public cef::mojom::RenderFrame,
public blink_glue::CefExecutionContextLifecycleStateObserver {
public:
CefFrameImpl(CefBrowserImpl* browser,
blink::WebLocalFrame* frame,
int64_t frame_id);
CefFrameImpl(CefBrowserImpl* browser, blink::WebLocalFrame* frame);
CefFrameImpl(const CefFrameImpl&) = delete;
CefFrameImpl& operator=(const CefFrameImpl&) = delete;
@@ -70,7 +68,7 @@ class CefFrameImpl
bool IsMain() override;
bool IsFocused() override;
CefString GetName() override;
int64_t GetIdentifier() override;
CefString GetIdentifier() override;
CefRefPtr<CefFrame> GetParent() override;
CefString GetURL() override;
CefRefPtr<CefBrowser> GetBrowser() override;
@@ -162,11 +160,9 @@ class CefFrameImpl
void ContextLifecycleStateChanged(
blink::mojom::blink::FrameLifecycleState state) override;
std::string GetDebugString() const;
CefBrowserImpl* browser_;
blink::WebLocalFrame* frame_;
const int64_t frame_id_;
const std::string frame_debug_str_;
bool did_commit_provisional_load_ = false;
bool did_initialize_script_context_ = false;

View File

@@ -15,13 +15,12 @@
namespace render_frame_util {
int64_t GetIdentifier(blink::WebLocalFrame* frame) {
std::string GetIdentifier(blink::WebLocalFrame* frame) {
// Each WebFrame will have an associated RenderFrame. The RenderFrame
// routing IDs are unique within a given renderer process.
content::RenderFrame* render_frame =
content::RenderFrame::FromWebFrame(frame);
return frame_util::MakeFrameId(content::RenderThread::Get()->GetClientId(),
render_frame->GetRoutingID());
return frame_util::MakeFrameIdentifier(content::GlobalRenderFrameHostToken(
content::RenderThread::Get()->GetClientId(),
frame->GetLocalFrameToken()));
}
std::string GetName(blink::WebLocalFrame* frame) {
@@ -42,4 +41,14 @@ std::string GetName(blink::WebLocalFrame* frame) {
return std::string();
}
std::optional<blink::LocalFrameToken> ParseFrameTokenFromIdentifier(
const std::string& identifier) {
const auto& global_token = frame_util::ParseFrameIdentifier(identifier);
if (!global_token ||
global_token->child_id != content::RenderThread::Get()->GetClientId()) {
return std::nullopt;
}
return global_token->frame_token;
}
} // namespace render_frame_util

View File

@@ -6,19 +6,25 @@
#ifndef CEF_LIBCEF_RENDERER_RENDER_FRAME_UTIL_H_
#define CEF_LIBCEF_RENDERER_RENDER_FRAME_UTIL_H_
#include <stdint.h>
#include <optional>
#include <string>
#include "third_party/blink/public/common/tokens/tokens.h"
namespace blink {
class WebLocalFrame;
}
} // namespace blink
namespace render_frame_util {
int64_t GetIdentifier(blink::WebLocalFrame* frame);
std::string GetIdentifier(blink::WebLocalFrame* frame);
std::string GetName(blink::WebLocalFrame* frame);
// Parses |identifier| and returns a frame token appropriate to this renderer
// process, or std::nullopt.
std::optional<blink::LocalFrameToken> ParseFrameTokenFromIdentifier(
const std::string& identifier);
} // namespace render_frame_util
#endif // CEF_LIBCEF_RENDERER_RENDER_FRAME_UTIL_H_

View File

@@ -41,6 +41,7 @@
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/web/web_frame.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_security_policy.h"
#include "third_party/blink/public/web/web_view.h"
#include "third_party/blink/public/web/web_view_observer.h"
@@ -112,6 +113,11 @@ void CefRenderManager::RenderFrameCreated(
render_frame_observer->AttachFrame(
browser->GetWebFrameImpl(render_frame->GetWebFrame()).get());
}
// Enable support for draggable regions.
// TODO: This has performance consequences so consider making it configurable
// (e.g. only enabled for frameless windows). See issue #3636.
render_frame->GetWebView()->SetSupportsAppRegion(true);
}
void CefRenderManager::WebViewCreated(blink::WebView* web_view,
@@ -317,8 +323,8 @@ CefRefPtr<CefBrowserImpl> CefRenderManager::MaybeCreateBrowser(
auto params = cef::mojom::NewBrowserInfo::New();
if (!is_pdf) {
// Retrieve browser information synchronously.
GetBrowserManager()->GetNewBrowserInfo(render_frame->GetRoutingID(),
&params);
GetBrowserManager()->GetNewBrowserInfo(
render_frame->GetWebFrame()->GetLocalFrameToken(), &params);
if (params->browser_id == 0) {
// The popup may have been canceled during creation.
return nullptr;

View File

@@ -985,7 +985,7 @@ CefRefPtr<CefFrame> CefV8ContextImpl::GetFrame() {
CefRefPtr<CefBrowserImpl> browser =
CefBrowserImpl::GetBrowserForMainFrame(webframe->Top());
if (browser) {
frame = browser->GetFrame(render_frame_util::GetIdentifier(webframe));
frame = browser->GetWebFrameImpl(webframe).get();
}
}