chromium/ios/chrome/browser/infobars/model/overlays/browser_agent/infobar_overlay_browser_agent.h

// Copyright 2020 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_INFOBARS_MODEL_OVERLAYS_BROWSER_AGENT_INFOBAR_OVERLAY_BROWSER_AGENT_H_
#define IOS_CHROME_BROWSER_INFOBARS_MODEL_OVERLAYS_BROWSER_AGENT_INFOBAR_OVERLAY_BROWSER_AGENT_H_

#import <map>
#import <memory>

#import "base/memory/raw_ptr.h"
#import "base/scoped_multi_source_observation.h"
#import "ios/chrome/browser/infobars/model/infobar_type.h"
#import "ios/chrome/browser/overlays/model/public/overlay_browser_agent_base.h"
#import "ios/chrome/browser/overlays/model/public/overlay_presenter.h"
#import "ios/chrome/browser/overlays/model/public/overlay_presenter_observer.h"
#import "ios/chrome/browser/shared/model/browser/browser_user_data.h"

class InfobarInteractionHandler;

// Browser agent class that handles the model-layer updates for infobars.
class InfobarOverlayBrowserAgent
    : public OverlayBrowserAgentBase,
      public BrowserUserData<InfobarOverlayBrowserAgent> {
 public:
  ~InfobarOverlayBrowserAgent() override;

  // Adds an InfobarInteractionHandler to make model-layer updates for
  // interactions with infobars.  An OverlayCallbackInstaller will be created
  // from each added handler for each InfobarOverlayType.  `interaction_handler`
  // must not be null.  Only one interaction handler for a given InfobarType
  // can be added.
  void AddInfobarInteractionHandler(
      std::unique_ptr<InfobarInteractionHandler> interaction_handler);

  // Adds an InfobarInteractionHandler that corresponds to the given
  // `infobar_type`to make model-layer updates for interactions with infobars.
  // This method calls `AddInfobarInteractionHandler:` to create the
  // InfobarInteractionHandler.
  void AddDefaultInfobarInteractionHandlerForInfobarType(
      InfobarType infobar_type);

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

  // Constructor used by CreateForBrowser().
  explicit InfobarOverlayBrowserAgent(Browser* browser);

  // Returns the interaction handler for the InfobarType of the infobar used to
  // configure `request`, or nullptr if `request` is not supported.
  InfobarInteractionHandler* GetInteractionHandler(OverlayRequest* request);

  // Helper object that notifies interaction handler of changes in infobar UI
  // visibility.
  class OverlayVisibilityObserver : public OverlayPresenterObserver {
   public:
    OverlayVisibilityObserver(Browser* browser,
                              InfobarOverlayBrowserAgent* browser_agent);
    ~OverlayVisibilityObserver() override;

   private:
    // Notifies the BrowserAgent's interaction handler that the visibility of
    // `request`'s UI has changed.
    void OverlayVisibilityChanged(OverlayRequest* request, bool visible);

    // OverlayPresenterObserver:
    const OverlayRequestSupport* GetRequestSupport(
        OverlayPresenter* presenter) const override;
    void DidShowOverlay(OverlayPresenter* presenter,
                        OverlayRequest* request) override;
    void DidHideOverlay(OverlayPresenter* presenter,
                        OverlayRequest* request) override;
    void OverlayPresenterDestroyed(OverlayPresenter* presenter) override;

    raw_ptr<InfobarOverlayBrowserAgent> browser_agent_ = nullptr;
    base::ScopedMultiSourceObservation<OverlayPresenter,
                                       OverlayPresenterObserver>
        scoped_observations_{this};
  };

  // The interaction handlers for each InfobarType.
  std::map<InfobarType, std::unique_ptr<InfobarInteractionHandler>>
      interaction_handlers_;
  // The observer for infobar banner presentations and dismissals.
  OverlayVisibilityObserver overlay_visibility_observer_;
};

#endif  // IOS_CHROME_BROWSER_INFOBARS_MODEL_OVERLAYS_BROWSER_AGENT_INFOBAR_OVERLAY_BROWSER_AGENT_H_