blob: 57a7cf6271bdd3d777936d005f1fc800de569656 [file] [log] [blame]
// Copyright (c) 2021 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/starscan_load_observer.h"
#include "base/allocator/partition_allocator/starscan/pcscan.h"
#include "base/logging.h"
#include "content/browser/renderer_host/frame_tree.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
namespace content {
namespace {
size_t g_loading_webcontents_ = 0;
}
// Start observing right away.
StarScanLoadObserver::StarScanLoadObserver(WebContents* contents)
: WebContentsObserver(contents) {}
StarScanLoadObserver::~StarScanLoadObserver() {
// WebContents can be destructed while loading is still in progress.
DidStopLoading();
}
void StarScanLoadObserver::ReadyToCommitNavigation(
NavigationHandle* navigation_handle) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// We don't disable PCScan for a prerendering page's navigation since
// it doesn't invoke DidStopLoading.
RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
navigation_handle->GetRenderFrameHost());
if (rfh->frame_tree()->type() == FrameTree::Type::kPrerender)
return;
// Protect against ReadyToCommitNavigation() being called twice in a row.
if (is_loading_)
return;
is_loading_ = true;
if (!g_loading_webcontents_) {
VLOG(3) << "Disabling *Scan due to loading";
base::internal::PCScan::Disable();
}
++g_loading_webcontents_;
// Set timer as a fallback if loading is too slow.
constexpr base::TimeDelta kReenableStarScanDelta = base::Seconds(10);
timer_.Start(FROM_HERE, kReenableStarScanDelta, this,
&StarScanLoadObserver::DidStopLoading);
}
void StarScanLoadObserver::DidStopLoading() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (is_loading_) {
DecrementCounterAndReenableStarScanIfNeeded();
is_loading_ = false;
}
}
void StarScanLoadObserver::DecrementCounterAndReenableStarScanIfNeeded() {
CHECK(g_loading_webcontents_);
--g_loading_webcontents_;
if (!g_loading_webcontents_) {
VLOG(3) << "Reenabling *Scan after finishing loading";
base::internal::PCScan::Reenable();
}
}
} // namespace content