chromium/ios/chrome/browser/sessions/model/session_restoration_browser_agent.h

// Copyright 2019 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_SESSIONS_MODEL_SESSION_RESTORATION_BROWSER_AGENT_H_
#define IOS_CHROME_BROWSER_SESSIONS_MODEL_SESSION_RESTORATION_BROWSER_AGENT_H_

#import <CoreFoundation/CoreFoundation.h>

#import <memory>
#import <string>
#import <vector>

#import "base/memory/raw_ptr.h"
#import "base/observer_list.h"
#import "ios/chrome/browser/shared/model/browser/browser_observer.h"
#import "ios/chrome/browser/shared/model/browser/browser_user_data.h"
#import "ios/chrome/browser/shared/model/web_state_list/web_state_list_observer.h"
#import "ios/web/public/web_state_observer.h"

class AllWebStateObservationForwarder;
@class SessionWindowIOS;
@class SessionWindowIOSFactory;
class SessionRestorationObserver;
@class SessionServiceIOS;
class WebStateList;

// This class is responsible for handling requests of session restoration. It
// can be observed via SeassonRestorationObserver which it uses to notify
// observers of session restoration events. This class also automatically
// save sessions when the active webState changes, and when each web state
// completes a navigation.
class SessionRestorationBrowserAgent
    : public BrowserObserver,
      public BrowserUserData<SessionRestorationBrowserAgent>,
      public WebStateListObserver,
      public web::WebStateObserver {
 public:
  ~SessionRestorationBrowserAgent() override;

  SessionRestorationBrowserAgent(const SessionRestorationBrowserAgent&) =
      delete;
  SessionRestorationBrowserAgent& operator=(
      const SessionRestorationBrowserAgent&) = delete;

  // Set a session identification string that will be used to locate which
  // session to restore. Must be set before restoring/saving the session.
  void SetSessionID(NSString* session_identifier);

  // Returns the session identifier for the associated browser.
  NSString* GetSessionID() const;

  // Adds/Removes Observer to session restoration events.
  void AddObserver(SessionRestorationObserver* observer);
  void RemoveObserver(SessionRestorationObserver* observer);

  // Restores the `window`. If there is only one tab showing the NTP, then
  // this tab should be clobbered, otherwise, the tabs from the restored
  // sessions should be added at the end of the current list of tabs.
  void RestoreSessionWindow(SessionWindowIOS* window);

  // Restores the session whose ID matches the session ID set for this agent.
  // Restoration is done via RestoreSessionWindow(), above, and the return
  // value of that method is returned.
  void RestoreSession();

  // Persists the current list of tabs to disk, either immediately or deferred
  // based on the value of `immediately`.
  void SaveSession(const bool immediately);

  // Returns true if there is a session restoration in progress, otherwise it
  // returns false. Note that this method can be called from the UI Thread.
  // This method exists as a work around for crbug.com/763964.
  bool IsRestoringSession();

 private:
  friend class BrowserUserData<SessionRestorationBrowserAgent>;
  BROWSER_USER_DATA_KEY_DECL();

  SessionRestorationBrowserAgent(Browser* browser,
                                 SessionServiceIOS* session_service,
                                 bool enable_pinned_web_states,
                                 bool enable_tab_groups);

  // Returns true if the current session can be saved.
  bool CanSaveSession();

  // BrowserObserver methods
  void BrowserDestroyed(Browser* browser) override;

  // WebStateListObserver methods.
  void WebStateListWillChange(WebStateList* web_state_list,
                              const WebStateListChangeDetach& detach_change,
                              const WebStateListStatus& status) override;
  void WebStateListDidChange(WebStateList* web_state_list,
                             const WebStateListChange& change,
                             const WebStateListStatus& status) override;
  void WillBeginBatchOperation(WebStateList* web_state_list) override;
  void BatchOperationEnded(WebStateList* web_state_list) override;

  // web::WebStateObserver methods.
  void DidFinishNavigation(web::WebState* web_state,
                           web::NavigationContext* navigation_context) override;

  // The service object which handles the actual saving of sessions.
  SessionServiceIOS* session_service_ = nullptr;

  // The Browser containing the WebStates to be saved.
  raw_ptr<Browser> browser_ = nullptr;

  // List of registered observers.
  base::ObserverList<SessionRestorationObserver, true> observers_;

  // SessionWindowIOSFactory used to create session data for saving.
  SessionWindowIOSFactory* session_window_ios_factory_ = nullptr;

  // Session identifier for this agent.
  __strong NSString* session_identifier_ = nil;

  // True when session restoration is in progress.
  bool restoring_session_ = false;

  // Used to delay saves requested while a batch operation was in progress.
  // The save will be scheduled with a delay unless any of the SaveSession()
  // call was asking for no delay.
  bool save_after_batch_ = false;
  bool save_immediately_ = false;

  const bool enable_pinned_web_states_;
  const bool enable_tab_groups_;

  // Observer for the active web state in `browser_`'s web state list.
  std::unique_ptr<AllWebStateObservationForwarder> all_web_state_observer_;
};

#endif  // IOS_CHROME_BROWSER_SESSIONS_MODEL_SESSION_RESTORATION_BROWSER_AGENT_H_