text: // Copyright 2020 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_DISPLAY_QUEUE_H_
  #define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_DISPLAY_QUEUE_H_
  
  #include <memory>
  #include <set>
  #include <string>
  #include <vector>
  
  #include "base/callback.h"
  #include "base/scoped_observer.h"
  #include "chrome/browser/notifications/notification_blocker.h"
  #include "chrome/browser/notifications/notification_common.h"
  #include "chrome/browser/notifications/notification_handler.h"
  #include "ui/message_center/public/cpp/notification.h"
  
  class NotificationDisplayService;
  
  // The NotificationDisplayQueue holds on to a list of NotificationBlockers that
  // determine if we should block new notifications from being displayed. During
  // that time this class will hold on to new incoming notifications and display
  // them once all blockers stop being active.
  class NotificationDisplayQueue : public NotificationBlocker::Observer {
   public:
    using NotificationBlockers =
        std::vector<std::unique_ptr<NotificationBlocker>>;
  
    explicit NotificationDisplayQueue(
        NotificationDisplayService* notification_display_service);
    NotificationDisplayQueue(const NotificationDisplayQueue&) = delete;
    NotificationDisplayQueue& operator=(const NotificationDisplayQueue&) = delete;
    ~NotificationDisplayQueue() override;
  
    // NotificationBlocker::Observer:
    void OnBlockingStateChanged() override;
  
    // Returns if we should currently queue up |notification|. This is the case if
    // at least one NotificationBlocker is active and |notification_type| is a Web
    // Notification.
    bool ShouldEnqueueNotification(
        NotificationHandler::Type notification_type,
        const message_center::Notification& notification) const;
  
    // Enqueue the passed |notification| to be shown once no blocker is active
    // anymore. If there is already a notification with the same id queued, it
    // will be removed before adding this new one.
    void EnqueueNotification(
        NotificationHandler::Type notification_type,
        const message_center::Notification& notification,
        std::unique_ptr<NotificationCommon::Metadata> metadata);
  
    // Removes a queued notification by its |notification_id|. This is a no-op if
    // there was no notification queued with that id.
    void RemoveQueuedNotification(const std::string& notification_id);
  
    // Returns a set of the currently queued notification ids.
    std::set<std::string> GetQueuedNotificationIds() const;
  
    // Sets the list of |blockers| to be used and observes their state.
    void SetNotificationBlockers(NotificationBlockers blockers);
  
    // Adds |blocker| to the list of blockers to be used and observes its state.
    void AddNotificationBlocker(std::unique_ptr<NotificationBlocker> blocker);
  
   private:
    // Removes a queued notification by its |notification_id| and returns if there
    // was a queued notification with that id. If |notify| is true this will
    // notify all relevant blockers about the removal.
    bool DoRemoveQueuedNotification(const std::string& notification_id,
                                    bool notify);
  
    // Called when the state of a notification blocker changes. Will display and
    // free all queued notifications if no blocker is active anymore.
    void MaybeDisplayQueuedNotifications();
  
    // Checks if any notification blocker is currently active for |notification|.
    bool IsAnyNotificationBlockerActive(
        const message_center::Notification& notification) const;
  
    // Represents a queued notification.
    struct QueuedNotification {
      QueuedNotification(NotificationHandler::Type notification_type,
                         const message_center::Notification& notification,
                         std::unique_ptr<NotificationCommon::Metadata> metadata);
      QueuedNotification(QueuedNotification&&);
      QueuedNotification& operator=(QueuedNotification&&);
      ~QueuedNotification();
  
      NotificationHandler::Type notification_type;
      message_center::Notification notification;
      std::unique_ptr<NotificationCommon::Metadata> metadata;
    };
  
    // The |notification_display_service_| owns |this|.
    NotificationDisplayService* notification_display_service_;
  
    // A list of notification blockers that indicate when notifications should be
    // blocked and notify when their state changes.
    NotificationBlockers blockers_;
  
    // A list of queued notifications in order of last update. Each notification
    // has a unique id in this list as adding a duplication will remove the
    // existing one before inserting at the end.
    std::vector<QueuedNotification> queued_notifications_;
  
    // Observer for the list of |blockers_|.
    ScopedObserver<NotificationBlocker, NotificationBlocker::Observer>
        notification_blocker_observer_{this};
  };
  
  #endif  // CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_DISPLAY_QUEUE_H_
  