[bfcache] Remove BackForwardCache specific IPC and use mojo
This CL removes PutPageIntoBackForwardCache and RestoreFromBackForward
Cache IPCs and use mojo instead.
Now the page state is managed by PageLifecycleStateManager, which is
responsible for sending updates to renderer via mojo messages.
Bug:1057506
Change-Id: I2e1fafe79c758f8d6d56eabd9ee13f288f370bf1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2192540
Commit-Queue: Yuzu Saijo <[email protected]>
Reviewed-by: Kinuko Yasuda <[email protected]>
Reviewed-by: Kentaro Hara <[email protected]>
Reviewed-by: Alexander Timin <[email protected]>
Cr-Commit-Position: refs/heads/master@{#773075}
diff --git a/content/browser/renderer_host/page_lifecycle_state_manager.cc b/content/browser/renderer_host/page_lifecycle_state_manager.cc
index 50acabe..5e3903d 100644
--- a/content/browser/renderer_host/page_lifecycle_state_manager.cc
+++ b/content/browser/renderer_host/page_lifecycle_state_manager.cc
@@ -12,46 +12,77 @@
PageLifecycleStateManager::PageLifecycleStateManager(
RenderViewHostImpl* render_view_host_impl,
- blink::mojom::PageVisibilityState visibility_state)
- : is_frozen_(false),
- render_view_host_impl_(render_view_host_impl),
- visibility_(visibility_state) {}
+ blink::mojom::PageVisibilityState web_contents_visibility_state)
+ : web_contents_visibility_(web_contents_visibility_state),
+ render_view_host_impl_(render_view_host_impl) {
+ last_state_sent_to_renderer_ = CalculatePageLifecycleState();
+}
PageLifecycleStateManager::~PageLifecycleStateManager() = default;
void PageLifecycleStateManager::SetIsFrozen(bool frozen) {
- if (is_frozen_ == frozen)
+ if (is_set_frozen_called_ == frozen)
return;
- is_frozen_ = frozen;
- SendUpdatesToRenderer();
+ is_set_frozen_called_ = frozen;
+
+ SendUpdatesToRendererIfNeeded(base::nullopt);
}
-void PageLifecycleStateManager::SetVisibility(
+void PageLifecycleStateManager::SetWebContentsVisibility(
blink::mojom::PageVisibilityState visibility) {
- if (visibility_ == visibility)
+ if (web_contents_visibility_ == visibility)
return;
- visibility_ = visibility;
- SendUpdatesToRenderer();
+
+ web_contents_visibility_ = visibility;
+ SendUpdatesToRendererIfNeeded(base::nullopt);
+
// TODO(yuzus): When a page is frozen and made visible, the page should
// automatically resume.
}
-void PageLifecycleStateManager::SendUpdatesToRenderer() {
+void PageLifecycleStateManager::SetIsInBackForwardCache(
+ bool is_in_back_forward_cache,
+ base::Optional<base::TimeTicks> navigation_start) {
+ if (is_in_back_forward_cache_ == is_in_back_forward_cache)
+ return;
+ is_in_back_forward_cache_ = is_in_back_forward_cache;
+ SendUpdatesToRendererIfNeeded(navigation_start);
+}
+
+void PageLifecycleStateManager::SendUpdatesToRendererIfNeeded(
+ base::Optional<base::TimeTicks> navigation_start) {
if (!render_view_host_impl_->GetAssociatedPageBroadcast()) {
// For some tests, |render_view_host_impl_| does not have the associated
// page.
return;
}
- auto state = blink::mojom::PageLifecycleState::New();
- state->is_frozen = is_frozen_;
- state->visibility = visibility_;
+
+ auto new_state = CalculatePageLifecycleState();
+ if (last_state_sent_to_renderer_.Equals(new_state)) {
+ // TODO(yuzus): Send updates to renderer only when the effective state (per
+ // page lifecycle state) has changed. It is possible that the web contents
+ // state has changed but the effective state has not.
+ }
+
+ last_state_sent_to_renderer_ = new_state.Clone();
render_view_host_impl_->GetAssociatedPageBroadcast()->SetPageLifecycleState(
- std::move(state),
+ std::move(new_state), std::move(navigation_start),
base::BindOnce(&PageLifecycleStateManager::OnLifecycleChangedAck,
weak_ptr_factory_.GetWeakPtr()));
}
+blink::mojom::PageLifecycleStatePtr
+PageLifecycleStateManager::CalculatePageLifecycleState() {
+ auto state = blink::mojom::PageLifecycleState::New();
+ state->is_in_back_forward_cache = is_in_back_forward_cache_;
+ state->is_frozen = is_in_back_forward_cache_ ? true : is_set_frozen_called_;
+ state->visibility = is_in_back_forward_cache_
+ ? blink::mojom::PageVisibilityState::kHidden
+ : web_contents_visibility_;
+ return state;
+}
+
void PageLifecycleStateManager::OnLifecycleChangedAck() {
// TODO(yuzus): Implement OnLifecycleChangedAck and send changes to the
// observers.
diff --git a/content/browser/renderer_host/page_lifecycle_state_manager.h b/content/browser/renderer_host/page_lifecycle_state_manager.h
index 1203a1b..5d4c2610 100644
--- a/content/browser/renderer_host/page_lifecycle_state_manager.h
+++ b/content/browser/renderer_host/page_lifecycle_state_manager.h
@@ -20,19 +20,49 @@
public:
explicit PageLifecycleStateManager(
RenderViewHostImpl* render_view_host_impl,
- blink::mojom::PageVisibilityState visibility_state);
+ blink::mojom::PageVisibilityState web_contents_visibility_state);
~PageLifecycleStateManager();
void SetIsFrozen(bool frozen);
- void SetVisibility(blink::mojom::PageVisibilityState visibility_state);
+ void SetWebContentsVisibility(
+ blink::mojom::PageVisibilityState visibility_state);
+ void SetIsInBackForwardCache(
+ bool is_in_back_forward_cache,
+ base::Optional<base::TimeTicks> navigation_start);
private:
- void SendUpdatesToRenderer();
+ // Send mojo message to renderer if the effective (page) lifecycle state has
+ // changed.
+ void SendUpdatesToRendererIfNeeded(
+ base::Optional<base::TimeTicks> navigation_start);
+
+ // Calculates the per-page lifecycle state based on the per-tab / web contents
+ // lifecycle state saved in this instance.
+ blink::mojom::PageLifecycleStatePtr CalculatePageLifecycleState();
+
void OnLifecycleChangedAck();
- bool is_frozen_;
+ // This represents the frozen state set by |SetIsFrozen|, which corresponds to
+ // WebContents::SetPageFrozen. Effective frozen state, i.e. per-page frozen
+ // state is computed based on |is_in_back_forward_cache_| and
+ // |is_set_frozen_called_|.
+ bool is_set_frozen_called_ = false;
+
+ bool is_in_back_forward_cache_ = false;
+
+ // This represents the visibility set by |SetVisibility|, which is web
+ // contents visibility state. Effective visibility, i.e. per-page visibility
+ // is computed based on |is_in_back_forward_cache_| and
+ // |web_contents_visibility_|.
+ blink::mojom::PageVisibilityState web_contents_visibility_;
+
RenderViewHostImpl* render_view_host_impl_;
- blink::mojom::PageVisibilityState visibility_;
+
+ // This is the per-page state computed based on web contents / tab lifecycle
+ // states, i.e. |is_set_frozen_called_|, |is_in_back_forward_cache_| and
+ // |web_contents_visibility_|. This should be only set in
+ // |SendUpdatesToRendererIfNeeded|.
+ blink::mojom::PageLifecycleStatePtr last_state_sent_to_renderer_;
// NOTE: This must be the last member.
base::WeakPtrFactory<PageLifecycleStateManager> weak_ptr_factory_{this};
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 396ef8a5..938ff3a 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -457,8 +457,8 @@
FrameTree* frame_tree = GetDelegate()->GetFrameTree();
frame_tree->UnregisterRenderViewHost(this);
is_in_back_forward_cache_ = true;
- // TODO(altimin, dcheng): This should be a ViewMsg.
- Send(new PageMsg_PutPageIntoBackForwardCache(GetRoutingID()));
+ page_lifecycle_state_manager_->SetIsInBackForwardCache(
+ is_in_back_forward_cache_, /*navigation_start=*/base::nullopt);
}
void RenderViewHostImpl::LeaveBackForwardCache(
@@ -469,17 +469,17 @@
// guaranteed to be committed, so it should be reused going forward.
frame_tree->RegisterRenderViewHost(this);
is_in_back_forward_cache_ = false;
- Send(new PageMsg_RestorePageFromBackForwardCache(GetRoutingID(),
- navigation_start));
-}
-
-void RenderViewHostImpl::SetIsFrozen(bool frozen) {
- page_lifecycle_state_manager_->SetIsFrozen(frozen);
+ page_lifecycle_state_manager_->SetIsInBackForwardCache(false,
+ navigation_start);
}
void RenderViewHostImpl::SetVisibility(
blink::mojom::PageVisibilityState visibility) {
- page_lifecycle_state_manager_->SetVisibility(visibility);
+ page_lifecycle_state_manager_->SetWebContentsVisibility(visibility);
+}
+
+void RenderViewHostImpl::SetIsFrozen(bool frozen) {
+ page_lifecycle_state_manager_->SetIsFrozen(frozen);
}
bool RenderViewHostImpl::IsRenderViewLive() {
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index c3bab2f..dd5cf082 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -226,9 +226,10 @@
// to allow it to record the latency of this navigation.
void LeaveBackForwardCache(base::TimeTicks navigation_start);
- void SetIsFrozen(bool frozen);
void SetVisibility(blink::mojom::PageVisibilityState visibility);
+ void SetIsFrozen(bool frozen);
+
// Called during frame eviction to return all SurfaceIds in the frame tree.
// Marks all views in the frame tree as evicted.
std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction();
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index eae4849..07b8cb1 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2619,11 +2619,8 @@
// as soon as they are shown. But the Page and other classes do not expect
// to be producing frames when the Page is hidden. So we make sure the Page
// is shown first.
- // TODO(yuzus): We should include RenderViewHosts in BackForwardCache in
- // this iteration. Add a special method to get all RenderViewHosts in
- // BackForwardCache in WebContentsImpl.
- for (auto& entry : frame_tree_.render_view_hosts()) {
- entry.second->SetVisibility(page_visibility);
+ for (auto* rvh : GetRenderViewHostsIncludingBackForwardCached()) {
+ rvh->SetVisibility(page_visibility);
}
}
@@ -2655,8 +2652,8 @@
if (page_visibility == PageVisibilityState::kHidden) {
// Similar to when showing the page, we only hide the page after
// hiding the individual RenderWidgets.
- for (auto& entry : frame_tree_.render_view_hosts()) {
- entry.second->SetVisibility(page_visibility);
+ for (auto* rvh : GetRenderViewHostsIncludingBackForwardCached()) {
+ rvh->SetVisibility(page_visibility);
}
} else {
@@ -7412,4 +7409,23 @@
return GetMainFrame()->GetPageUkmSourceId();
}
+std::set<RenderViewHostImpl*>
+WebContentsImpl::GetRenderViewHostsIncludingBackForwardCached() {
+ std::set<RenderViewHostImpl*> render_view_hosts;
+
+ // Add RenderViewHostImpls outside of BackForwardCache.
+ for (auto& render_view_host : frame_tree_.render_view_hosts()) {
+ render_view_hosts.insert(render_view_host.second);
+ }
+
+ // Add RenderViewHostImpls in BackForwardCache.
+ const auto& entries = GetController().GetBackForwardCache().GetEntries();
+ for (const auto& entry : entries) {
+ std::set<RenderViewHostImpl*> bfcached_hosts = entry->render_view_hosts;
+ render_view_hosts.insert(bfcached_hosts.begin(), bfcached_hosts.end());
+ }
+
+ return render_view_hosts;
+}
+
} // namespace content
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index aed47a4..5e74495 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -1641,6 +1641,8 @@
// if you don't.
ukm::SourceId GetCurrentPageUkmSourceId() override;
+ std::set<RenderViewHostImpl*> GetRenderViewHostsIncludingBackForwardCached();
+
// Data for core operation ---------------------------------------------------
// Delegate for notifying our owner about stuff. Not owned by us.