chromium/ios/chrome/browser/history/model/history_tab_helper.h

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef IOS_CHROME_BROWSER_HISTORY_MODEL_HISTORY_TAB_HELPER_H_
#define IOS_CHROME_BROWSER_HISTORY_MODEL_HISTORY_TAB_HELPER_H_

#include <vector>

#import "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "components/history/core/browser/history_context.h"
#include "components/history/core/browser/history_types.h"
#include "components/translate/core/browser/translate_driver.h"
#include "ios/web/public/web_state_observer.h"
#import "ios/web/public/web_state_user_data.h"

namespace history {
class HistoryService;
}  // namespace history

namespace web {
class NavigationItem;
class NavigationContext;
}  // namespace web

// HistoryTabHelper updates the history database based on navigation events from
// its parent WebState.
class HistoryTabHelper
    : public history::Context,
      public web::WebStateObserver,
      public translate::TranslateDriver::LanguageDetectionObserver,
      public web::WebStateUserData<HistoryTabHelper> {
 public:
  HistoryTabHelper(const HistoryTabHelper&) = delete;
  HistoryTabHelper& operator=(const HistoryTabHelper&) = delete;

  ~HistoryTabHelper() override;

  // Updates history with the specified navigation. This is called by
  // DidFinishNavigation to update history state.
  void UpdateHistoryForNavigation(
      const history::HistoryAddPageArgs& add_page_args);

  // Sends the page title to the history service. Public for testing.
  void UpdateHistoryPageTitle(const web::NavigationItem& item);

  // Returns the history::HistoryAddPageArgs to use for adding a page to
  // history. Public for testing.
  history::HistoryAddPageArgs CreateHistoryAddPageArgs(
      web::NavigationItem* last_committed_item,
      web::NavigationContext* navigation_context);

  // Sets whether the navigation should be send to the HistoryService or saved
  // for later (this will generally be set to true while the WebState is used
  // for pre-rendering).
  void SetDelayHistoryServiceNotification(bool delay_notification);

  // TranslateDriver::LanguageDetectionObserver implementation.
  void OnLanguageDetermined(
      const translate::LanguageDetectionDetails& details) override;

 private:
  friend class web::WebStateUserData<HistoryTabHelper>;

  // Constructs a new HistoryTabHelper.
  explicit HistoryTabHelper(web::WebState* web_state);

  // web::WebStateObserver implementation.
  void DidFinishNavigation(web::WebState* web_state,
                           web::NavigationContext* navigation_context) override;
  void PageLoaded(
      web::WebState* web_state,
      web::PageLoadCompletionStatus load_completion_status) override;
  void TitleWasSet(web::WebState* web_state) override;
  void WebStateDestroyed(web::WebState* web_state) override;

  // Helper function to return the history service. May return null.
  history::HistoryService* GetHistoryService();

  // The WebState this instance is observing. Will be null after
  // WebStateDestroyed has been called.
  raw_ptr<web::WebState> web_state_ = nullptr;

  // 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};

  // Hold navigation entries that need to be added to the history database.
  // Pre-rendered WebStates do not write navigation data to the history DB
  // immediately, instead they are cached in this vector and added when it
  // is converted to a non-pre-rendered state.
  std::vector<history::HistoryAddPageArgs> recorded_navigations_;

  // Controls whether the navigation will be sent to the HistoryService when
  // they happen or delayed. If delayed, then they will be sent when the flag
  // is set to false.
  bool delay_notification_ = false;

  // Number of title changes since the loading of the navigation started.
  int num_title_changes_;

  // 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_;

  WEB_STATE_USER_DATA_KEY_DECL();
};

#endif  // IOS_CHROME_BROWSER_HISTORY_MODEL_HISTORY_TAB_HELPER_H_