blob: a6d4f8a358e2ddcb1bdef0aff7d6543772b59f1e [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_HISTORY_HISTORY_TAB_HELPER_H_
#define CHROME_BROWSER_HISTORY_HISTORY_TAB_HELPER_H_
#include <optional>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/history/core/browser/history_service_observer.h"
#include "components/sessions/core/serialized_navigation_entry.h"
#include "components/translate/core/browser/translate_driver.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
namespace history {
struct HistoryAddPageArgs;
class HistoryService;
} // namespace history
class HistoryTabHelper
: public content::WebContentsObserver,
public translate::TranslateDriver::LanguageDetectionObserver,
public history::HistoryServiceObserver,
public content::WebContentsUserData<HistoryTabHelper> {
public:
HistoryTabHelper(const HistoryTabHelper&) = delete;
HistoryTabHelper& operator=(const HistoryTabHelper&) = delete;
~HistoryTabHelper() override;
// Returns the history::HistoryAddPageArgs to use for adding a page to
// history.
history::HistoryAddPageArgs CreateHistoryAddPageArgs(
const GURL& virtual_url,
base::Time timestamp,
int nav_entry_id,
content::NavigationHandle* navigation_handle);
// Called by password manager code when the PasswordState in this tab was
// updated.
void OnPasswordStateUpdated(
sessions::SerializedNavigationEntry::PasswordState password_state);
// Fakes that the WebContents is a tab for testing purposes.
void SetForceEligibleTabForTesting(bool force) {
force_eligible_tab_for_testing_ = force;
}
#if BUILDFLAG(IS_ANDROID)
// Sets App ID that that goes into visit database.
void SetAppId(std::optional<std::string> app_id) { app_id_ = app_id; }
void SetClearAppIdAfterFirstCommit();
std::optional<std::string> GetAppId() { return app_id_; }
#endif
private:
explicit HistoryTabHelper(content::WebContents* web_contents);
friend class content::WebContentsUserData<HistoryTabHelper>;
FRIEND_TEST_ALL_PREFIXES(HistoryTabHelperTest,
CreateAddPageArgsHasOpenerWebContentsFirstPage);
FRIEND_TEST_ALL_PREFIXES(HistoryTabHelperTest,
CreateAddPageArgsHasLiveOriginalOpenerChain);
FRIEND_TEST_ALL_PREFIXES(HistoryTabHelperTest,
CreateAddPageArgsHasOpenerWebContentsNotFirstPage);
FRIEND_TEST_ALL_PREFIXES(HistoryFencedFrameBrowserTest,
FencedFrameDoesNotAffectLoadingState);
// Updates history with the specified navigation. This is called by
// DidFinishNavigation to update history state.
void UpdateHistoryForNavigation(
const history::HistoryAddPageArgs& add_page_args);
// content::WebContentsObserver implementation.
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
void DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) override;
void TitleWasSet(content::NavigationEntry* entry) override;
void WebContentsDestroyed() override;
void DidOpenRequestedURL(content::WebContents* new_contents,
content::RenderFrameHost* source_render_frame_host,
const GURL& url,
const content::Referrer& referrer,
WindowOpenDisposition disposition,
ui::PageTransition transition,
bool started_from_context_menu,
bool renderer_initiated) override;
// history::HistoryServiceObserver.
void OnURLVisited(history::HistoryService* history_service,
const history::URLRow& url_row,
const history::VisitRow& new_visit) override;
// TranslateDriver::LanguageDetectionObserver implementation.
void OnLanguageDetermined(
const translate::LanguageDetectionDetails& details) override;
// Helper function to return the history service. May return null.
history::HistoryService* GetHistoryService();
// Returns true if our observed web contents is an eligible tab.
bool IsEligibleTab(const history::HistoryAddPageArgs& add_page_args) const;
// Observes LanguageDetectionObserver, which notifies us when the language of
// the contents of the current page has been determined.
base::ScopedObservation<translate::TranslateDriver,
translate::TranslateDriver::LanguageDetectionObserver>
translate_observation_{this};
// True after navigation to a page is complete and the page is currently
// loading. Only applies to the main frame of the page.
bool is_loading_ = false;
// Number of title changes since the loading of the navigation started.
int num_title_changes_ = 0;
// The time that the current page finished loading. Only title changes within
// a certain time period after the page load is complete will be saved to the
// history system. Only applies to the main frame of the page.
base::TimeTicks last_load_completion_;
// Some cached state about the current navigation, used to identify it again
// once a new navigation has happened.
struct NavigationState {
int nav_entry_id;
GURL url;
};
std::optional<NavigationState> cached_navigation_state_;
// The package name of an app that opens a Custom Tab and visits a URL.
std::optional<std::string> app_id_ = std::nullopt;
// Set to true in unit tests to avoid need for a Browser instance.
bool force_eligible_tab_for_testing_ = false;
// The `WebContents` that opened the `WebContents` associated with `this` via
// "Open in New Tab", "Open in New Window", window.open(), etc.
base::WeakPtr<content::WebContents> opener_web_contents_;
bool clear_app_id_after_first_commit_;
// Set only when the history service observer event was invoked. Used to
// remove HistoryTabHelper object from the observer list in the destructor
// where |GetHistoryService()| doesn't work any longer.
raw_ptr<history::HistoryService> history_service_;
WEB_CONTENTS_USER_DATA_KEY_DECL();
};
#endif // CHROME_BROWSER_HISTORY_HISTORY_TAB_HELPER_H_