blob: 0a764a3f8818614fd081ad84e741184b12c2ae7f [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/renderer_host/back_forward_cache_throttle.h"
#include "base/barrier_closure.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/time/time.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_controller_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/public/browser/web_contents_observer.h"
namespace content {
// static
std::unique_ptr<BackForwardCacheThrottle>
BackForwardCacheThrottle::MaybeCreateThrottleFor(
NavigationRequest* navigation_request) {
if (navigation_request->IsServedFromBackForwardCache()) {
return base::WrapUnique(new BackForwardCacheThrottle(navigation_request));
}
return nullptr;
}
BackForwardCacheThrottle::BackForwardCacheThrottle(
NavigationRequest* navigation_request)
: NavigationThrottle(navigation_request) {
DCHECK(navigation_request->IsServedFromBackForwardCache());
}
BackForwardCacheThrottle::~BackForwardCacheThrottle() {
RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(main_rfh_id_);
// RFH could have been deleted. E.g. eviction timer fired
if (rfh && rfh->IsInBackForwardCache()) {
// rfh is still in the cache so the navigation must have failed. But we have
// already disabled eviction so the safest thing to do here to recover is to
// evict.
rfh->EvictFromBackForwardCacheWithReason(
BackForwardCacheMetrics::NotRestoredReason::
kNavigationCancelledWhileRestoring);
}
}
NavigationThrottle::ThrottleCheckResult
BackForwardCacheThrottle::WillStartRequest() {
NavigationRequest* navigation_request =
NavigationRequest::From(navigation_handle());
BackForwardCacheImpl::Entry* bfcache_entry =
navigation_request->frame_tree_node()
->navigator()
.controller()
.GetBackForwardCache()
.GetEntry(navigation_request->nav_entry_id());
if (!bfcache_entry) {
// Go on for now. NavigationRequest will later restart the navigation
// without bfcache.
return PROCEED;
}
main_rfh_id_ = bfcache_entry->render_frame_host->GetGlobalFrameRoutingId();
auto cb = base::BarrierClosure(
bfcache_entry->render_view_hosts.size(),
base::BindOnce(&BackForwardCacheThrottle::OnAckReceived,
weak_factory_.GetWeakPtr(), base::TimeTicks::Now()));
for (auto* rvh : bfcache_entry->render_view_hosts) {
rvh->PrepareToLeaveBackForwardCache(cb);
}
return DEFER;
}
const char* BackForwardCacheThrottle::GetNameForLogging() {
return "BackForwardCacheThrottle";
}
void BackForwardCacheThrottle::OnAckReceived(base::TimeTicks ipc_start_time) {
base::UmaHistogramTimes("BackForwardCache.Restore.DisableEvictionDelay",
base::TimeTicks::Now() - ipc_start_time);
Resume();
}
} // namespace content