mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Improve timing of frame attach/detach (see #3664)
- Move frame attachment from RenderFrameCreated to DidCommitProvisionalLoad. This has a number of advantages: - Significantly reduces the frequency of disconnects by avoiding the GetInterface/DidCommitNavigation race condition. - Stops connecting temporary frames (created during cross-origin navigation), making callback behavior more consistent. - Split frame detach and destruction notifications into separate callbacks. OnFrameDetached now reflects a potentially recoverable state. Add a new OnFrameDestroyed callback for the unrecoverable destruction state.
This commit is contained in:
@ -131,6 +131,9 @@ void CefBrowserInfo::MaybeCreateFrame(content::RenderFrameHost* host) {
|
||||
return;
|
||||
}
|
||||
|
||||
DVLOG(1) << __func__ << ": "
|
||||
<< frame_util::GetFrameDebugString(host->GetGlobalFrameToken());
|
||||
|
||||
const auto global_id = host->GetGlobalId();
|
||||
const bool is_main_frame = (host->GetParent() == nullptr);
|
||||
|
||||
@ -160,7 +163,7 @@ void CefBrowserInfo::MaybeCreateFrame(content::RenderFrameHost* host) {
|
||||
#endif
|
||||
|
||||
// Update the associated RFH, which may have changed.
|
||||
info->frame_->MaybeReAttach(this, host, /*require_detached=*/false);
|
||||
info->frame_->MaybeAttach(this, host);
|
||||
|
||||
if (info->is_speculative_ && !is_speculative) {
|
||||
// Upgrade the frame info from speculative to non-speculative.
|
||||
@ -208,17 +211,20 @@ void CefBrowserInfo::FrameHostStateChanged(
|
||||
content::RenderFrameHost::LifecycleState new_state) {
|
||||
CEF_REQUIRE_UIT();
|
||||
|
||||
DVLOG(1) << __func__ << ": "
|
||||
<< frame_util::GetFrameDebugString(host->GetGlobalFrameToken());
|
||||
|
||||
if ((old_state == content::RenderFrameHost::LifecycleState::kPrerendering ||
|
||||
old_state ==
|
||||
content::RenderFrameHost::LifecycleState::kInBackForwardCache) &&
|
||||
new_state == content::RenderFrameHost::LifecycleState::kActive) {
|
||||
if (auto frame = GetFrameForHost(host)) {
|
||||
// Update the associated RFH, which may have changed.
|
||||
frame->MaybeReAttach(this, host, /*require_detached=*/true);
|
||||
frame->MaybeAttach(this, host);
|
||||
|
||||
if (frame->IsMain()) {
|
||||
// Update the main frame object.
|
||||
NotificationStateLock lock_scope(this);
|
||||
// Update the main frame object.
|
||||
SetMainFrame(browser_, frame);
|
||||
}
|
||||
|
||||
@ -251,6 +257,9 @@ void CefBrowserInfo::FrameHostStateChanged(
|
||||
void CefBrowserInfo::RemoveFrame(content::RenderFrameHost* host) {
|
||||
CEF_REQUIRE_UIT();
|
||||
|
||||
DVLOG(1) << __func__ << ": "
|
||||
<< frame_util::GetFrameDebugString(host->GetGlobalFrameToken());
|
||||
|
||||
NotificationStateLock lock_scope(this);
|
||||
|
||||
const auto global_id = host->GetGlobalId();
|
||||
@ -281,12 +290,17 @@ void CefBrowserInfo::RemoveFrame(content::RenderFrameHost* host) {
|
||||
const auto& other_frame_info = *it2;
|
||||
if (other_frame_info->frame_) {
|
||||
const bool is_current_main_frame = other_frame_info->IsCurrentMainFrame();
|
||||
if (other_frame_info->frame_->Detach(
|
||||
const auto [frame_detached, frame_destroyed] =
|
||||
other_frame_info->frame_->Detach(
|
||||
CefFrameHostImpl::DetachReason::RENDER_FRAME_DELETED,
|
||||
is_current_main_frame)) {
|
||||
DCHECK(!is_current_main_frame);
|
||||
is_current_main_frame);
|
||||
if (frame_detached) {
|
||||
MaybeNotifyFrameDetached(browser_, other_frame_info->frame_);
|
||||
}
|
||||
if (frame_destroyed) {
|
||||
DCHECK(!is_current_main_frame);
|
||||
MaybeNotifyFrameDestroyed(browser_, other_frame_info->frame_);
|
||||
}
|
||||
}
|
||||
|
||||
frame_info_set_.erase(it2);
|
||||
@ -477,13 +491,21 @@ void CefBrowserInfo::SetMainFrame(CefRefPtr<CefBrowserHostBase> browser,
|
||||
return;
|
||||
}
|
||||
|
||||
DVLOG(1) << __func__ << ": "
|
||||
<< (frame ? frame->GetIdentifier().ToString() : "null");
|
||||
|
||||
CefRefPtr<CefFrameHostImpl> old_frame;
|
||||
if (main_frame_) {
|
||||
old_frame = main_frame_;
|
||||
if (old_frame->Detach(CefFrameHostImpl::DetachReason::NEW_MAIN_FRAME,
|
||||
/*is_current_main_frame=*/false)) {
|
||||
const auto [frame_detached, frame_destroyed] =
|
||||
old_frame->Detach(CefFrameHostImpl::DetachReason::NEW_MAIN_FRAME,
|
||||
/*is_current_main_frame=*/false);
|
||||
if (frame_detached) {
|
||||
MaybeNotifyFrameDetached(browser, old_frame);
|
||||
}
|
||||
if (frame_destroyed) {
|
||||
MaybeNotifyFrameDestroyed(browser, old_frame);
|
||||
}
|
||||
}
|
||||
|
||||
main_frame_ = frame;
|
||||
@ -526,6 +548,24 @@ void CefBrowserInfo::MaybeNotifyFrameDetached(
|
||||
browser, frame));
|
||||
}
|
||||
|
||||
// Passing in |browser| here because |browser_| may already be cleared.
|
||||
void CefBrowserInfo::MaybeNotifyFrameDestroyed(
|
||||
CefRefPtr<CefBrowserHostBase> browser,
|
||||
CefRefPtr<CefFrameHostImpl> frame) {
|
||||
CEF_REQUIRE_UIT();
|
||||
|
||||
// Never notify for temporary objects.
|
||||
DCHECK(!frame->is_temporary());
|
||||
|
||||
MaybeExecuteFrameNotification(base::BindOnce(
|
||||
[](CefRefPtr<CefBrowserHostBase> browser,
|
||||
CefRefPtr<CefFrameHostImpl> frame,
|
||||
CefRefPtr<CefFrameHandler> handler) {
|
||||
handler->OnFrameDestroyed(browser, frame);
|
||||
},
|
||||
browser, frame));
|
||||
}
|
||||
|
||||
// Passing in |browser| here because |browser_| may already be cleared.
|
||||
void CefBrowserInfo::MaybeNotifyMainFrameChanged(
|
||||
CefRefPtr<CefBrowserHostBase> browser,
|
||||
@ -563,13 +603,13 @@ void CefBrowserInfo::RemoveAllFrames(
|
||||
// Explicitly Detach everything.
|
||||
for (auto& info : frame_info_set_) {
|
||||
if (info->frame_) {
|
||||
const bool is_current_main_frame = info->IsCurrentMainFrame();
|
||||
if (info->frame_->Detach(
|
||||
[[maybe_unused]] const auto [frame_detached, frame_destroyed] =
|
||||
info->frame_->Detach(
|
||||
CefFrameHostImpl::DetachReason::BROWSER_DESTROYED,
|
||||
is_current_main_frame)) {
|
||||
DCHECK(!is_current_main_frame);
|
||||
MaybeNotifyFrameDetached(old_browser, info->frame_);
|
||||
}
|
||||
info->IsCurrentMainFrame());
|
||||
// Shouldn't need to trigger any notifications at this point.
|
||||
DCHECK(!frame_detached);
|
||||
DCHECK(!frame_destroyed);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user