chromium/ios/chrome/browser/follow/model/follow_tab_helper.h

// Copyright 2022 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_FOLLOW_MODEL_FOLLOW_TAB_HELPER_H_
#define IOS_CHROME_BROWSER_FOLLOW_MODEL_FOLLOW_TAB_HELPER_H_

#import <UIKit/UIKit.h>

#import "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/time/time.h"
#include "ios/web/public/web_state_observer.h"
#include "ios/web/public/web_state_user_data.h"

namespace history {
struct DailyVisitsResult;
}

namespace web {
class WebState;
}

class GURL;
@class WebPageURLs;
@protocol FollowMenuUpdater;
@protocol HelpCommands;

// FollowTabHelper encapsulates tab behavior related to following channels.
class FollowTabHelper : public web::WebStateObserver,
                        public web::WebStateUserData<FollowTabHelper> {
 public:
  FollowTabHelper(const FollowTabHelper&) = delete;
  FollowTabHelper& operator=(const FollowTabHelper&) = delete;

  ~FollowTabHelper() override;

  // Sets the handler for showing follow in-product help (IPH). `help_handler`
  // is not retained by this tab helper.
  void set_help_handler(id<HelpCommands> help_handler);

  // Sets the value of `shoud_update_follow_item_`.
  void set_should_update_follow_item(bool shoud_update_follow_item) {
    should_update_follow_item_ = shoud_update_follow_item;
  }

  // Sets the follow menu updater. `follow_menu_updater` is not retained by this
  // tab helper.
  void SetFollowMenuUpdater(id<FollowMenuUpdater> follow_menu_updater);

  // Removes the follow menu updater.
  void RemoveFollowMenuUpdater();

  // Updates the follow menu item.
  void UpdateFollowMenuItem();

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

  explicit FollowTabHelper(web::WebState* web_state);

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

  // Invoked asynchronously after fetching the `web_page_urls` from the
  // successfully loaded page at `url`. The initial time of the page load
  // is recorded in `page_load_time` and can be used to limit the delay
  // before displaying UI.
  void OnSuccessfulPageLoad(const GURL& url,
                            base::Time page_load_time,
                            WebPageURLs* web_page_urls);

  // Invoked with daily visit from history `result`. The initial time of the
  // page load is recorded in `page_load_time` and can be used to limit the
  // delay before displaying UI. `recommended_url` is the recommended URL for
  // the website whose visit have been queried.
  void OnDailyVisitQueryResult(base::Time page_load_time,
                               NSURL* recommended_url,
                               history::DailyVisitsResult result);

  // Updates follow menu item. `web_page_urls` is the page url object used to
  // check follow status.
  void UpdateFollowMenuItemWithURL(WebPageURLs* web_page_urls);

  // Presents the Follow in-product help (IPH) for `recommended_url`.
  void PresentFollowIPH(NSURL* recommended_url);

  raw_ptr<web::WebState> web_state_ = nullptr;

  // Presenter for follow in-product help (IPH).
  __weak id<HelpCommands> help_handler_ = nil;

  // Manages this object as an observer of `web_state_`.
  base::ScopedObservation<web::WebState, web::WebStateObserver>
      web_state_observation_{this};

  // True if the follow menu item should be updated. Ex. Set to true when a new
  // navigation starts, to ensure the follow menu item would be updated when the
  // page finishes loading.
  bool should_update_follow_item_ = false;

  // Used to update the follow menu item.
  __weak id<FollowMenuUpdater> follow_menu_updater_ = nil;

  base::CancelableTaskTracker history_task_tracker_;
  base::WeakPtrFactory<FollowTabHelper> weak_ptr_factory_{this};

  WEB_STATE_USER_DATA_KEY_DECL();
};

#endif  // IOS_CHROME_BROWSER_FOLLOW_MODEL_FOLLOW_TAB_HELPER_H_