blob: bbb835c9f35013fc74aefd564ffd3b871952918b [file] [log] [blame]
// Copyright 2018 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.
#ifndef CHROME_BROWSER_UI_BLOATED_RENDERER_BLOATED_RENDERER_TAB_HELPER_H_
#define CHROME_BROWSER_UI_BLOATED_RENDERER_BLOATED_RENDERER_TAB_HELPER_H_
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "chrome/browser/resource_coordinator/page_signal_receiver.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
class InfoBarService;
// This tab helper observes the OnRendererIsBloated event for its
// WebContents. Upon receiving the event it reloads the bloated tab if
// possible and activates the logic to show an infobar on the
// subsequent DidFinishNavigation event.
//
// Note that we need to show the infobar after NavigationEntryCommitted
// because the infobar service removes existing infobars there.
class BloatedRendererTabHelper
: public content::WebContentsObserver,
public content::WebContentsUserData<BloatedRendererTabHelper>,
public resource_coordinator::PageSignalObserver {
public:
~BloatedRendererTabHelper() override = default;
// content::WebContentsObserver:
void DidStartNavigation(
content::NavigationHandle* navigation_handle) override;
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
void WebContentsDestroyed() override;
// resource_coordinator::PageSignalObserver:
void OnRendererIsBloated(content::WebContents* web_contents,
const resource_coordinator::PageNavigationIdentity&
page_navigation_id) override;
static void ShowInfoBar(InfoBarService* infobar_service);
private:
friend class content::WebContentsUserData<BloatedRendererTabHelper>;
FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest, DetectReload);
FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest,
IgnoreUnrelatedNavigation);
FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest, CanReloadBloatedTab);
FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest,
CannotReloadBloatedTabCrashed);
FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest,
CannotReloadBloatedTabInvalidURL);
FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest,
CannotReloadBloatedTabPendingUserInteraction);
FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest,
CannotReloadBloatedTabWithPostData);
enum class State { kInactive, kRequestingReload, kStartedNavigation };
explicit BloatedRendererTabHelper(content::WebContents* contents);
bool CanReloadBloatedTab();
// The state transitions as follows:
// - kInactive is the initial state.
//
// - any state => kRequestingReload transition happens in
// OnRendererIsBloated before invoking NavigationController::Reload.
//
// - kRequestingReload => kStartedNavigation transition happens in
// NavigationController::Reload when it invokes DidStartNavigation.
//
// - kStartedNavigation => kInactive transitions happens in
// DidFinishNavigation.
State state_ = State::kInactive;
// The navigation id is saved on DidStartNavigation event when the state is
// kRequestingReload. The infobar is shown on the subsequent
// DidFinishNavigation only if its navigation id matches the saved id. This
// ensures that the infobar is shown only for the reload that was requested
// in OnRendererIsBloated event.
int64_t saved_navigation_id_ = 0;
DISALLOW_COPY_AND_ASSIGN(BloatedRendererTabHelper);
};
#endif // CHROME_BROWSER_UI_BLOATED_RENDERER_BLOATED_RENDERER_TAB_HELPER_H_