910e62b5创建于 1月15日历史提交
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_DOWNLOAD_NOTIFICATION_MULTI_PROFILE_DOWNLOAD_NOTIFIER_H_
#define CHROME_BROWSER_DOWNLOAD_NOTIFICATION_MULTI_PROFILE_DOWNLOAD_NOTIFIER_H_

#include <memory>
#include <set>
#include <string>

#include "base/containers/unique_ptr_adapters.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_multi_source_observation.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_observer.h"
#include "components/download/content/public/all_download_item_notifier.h"

// `MultiProfileDownloadNotifier` observes the `DownloadItem`s created on an
// arbitrary number of `Profile`s. No `Profile`s are observed by default; a
// client must specify `Profile`s to be observed using `AddProfile()`. Once a
// `Profile` is being observed, any off-the-record profile it has spawned or
// spawns later will also be observed unless it is filtered out by
// `ShouldObserveProfile()`.

// Example Usage:
// class DownloadsDelegate : public MultiProfileDownloadNotifier::Client {
//  public:
//   DownloadsDelegate(Profile* profile) {
//     downloads_notifier_.AddProfile(profile);
//   }
//
// void OnManagerInitialized(content::DownloadManager* manager) override { ... }
// void OnManagerGoingDown(content::DownloadManager* manager) override { ... }
// void OnDownloadCreated(content::DownloadManager* manager,
//                        download::DownloadItem* item) override { ... }
// void OnDownloadUpdated(content::DownloadManager* manager,
//                        download::DownloadItem* item) override { ... }
// void OnDownloadDestroyed(content::DownloadManager* manager,
//                          download::DownloadItem* item) override { ... }
// bool ShouldObserveProfile(Profile* profile) override { ... }
//
//  private:
//   MultiProfileDownloadNotifier downloads_notifier_{this};
// };

namespace content {
class DownloadManager;
}  // namespace content

namespace download {
class DownloadItem;
}  // namespace download

class MultiProfileDownloadNotifier
    : public ProfileObserver,
      public download::AllDownloadItemNotifier::Observer {
 public:
  class Client {
   public:
    Client() = default;
    Client(const Client&) = delete;
    Client& operator=(const Client&) = delete;
    virtual ~Client() = default;

    // Each method is called with the relevant download manager for use in a
    // client's auxiliary data structures, if applicable.
    virtual void OnManagerInitialized(content::DownloadManager* manager) {}
    virtual void OnManagerGoingDown(content::DownloadManager* manager) {}
    virtual void OnDownloadCreated(content::DownloadManager* manager,
                                   download::DownloadItem* item) {}
    virtual void OnDownloadUpdated(content::DownloadManager* manager,
                                   download::DownloadItem* item) {}
    virtual void OnDownloadDestroyed(content::DownloadManager* manager,
                                     download::DownloadItem* item) {}

    // Specifies whether the client wants to be notified for downloads created
    // on `profile`. This function is called before observing any profile,
    // regardless of whether `profile` was added automatically as the
    // off-the-record child of an observed profile or the client added it
    // explicitly using `AddProfile()`.
    virtual bool ShouldObserveProfile(Profile* profile);
  };

  // `wait_for_manager_initialization` controls whether `client` will be
  // notified about downloads belonging to `Profile`s with uninitialized
  // `DownloadManager`s.
  MultiProfileDownloadNotifier(Client* client,
                               bool wait_for_manager_initialization);
  MultiProfileDownloadNotifier(const MultiProfileDownloadNotifier&) = delete;
  MultiProfileDownloadNotifier& operator=(const MultiProfileDownloadNotifier&) =
      delete;
  ~MultiProfileDownloadNotifier() override;

  // Creates a download notifier for the download manager associated with
  // `profile` if one does not already exist.
  void AddProfile(Profile* profile);

  // Returns all downloads for all observed profiles.
  std::vector<raw_ptr<download::DownloadItem, VectorExperimental>>
  GetAllDownloads();

  // Searches all download notifiers for an observed `DownloadItem` matching
  // `guid`. Returns the item if found or nullptr if none exists. Note that this
  // function will return a matching download item even if it belongs to an
  // uninitialized manager and `wait_for_manager_initialization_` is true.
  download::DownloadItem* GetDownloadByGuid(const std::string& guid);

 private:
  // ProfileObserver:
  void OnOffTheRecordProfileCreated(Profile* off_the_record) override;
  void OnProfileWillBeDestroyed(Profile* profile) override;

  // download::AllDownloadItemNotifier::Observer:
  void OnManagerInitialized(content::DownloadManager* manager) override;
  void OnManagerGoingDown(content::DownloadManager* manager) override;
  void OnDownloadCreated(content::DownloadManager* manager,
                         download::DownloadItem* item) override;
  void OnDownloadUpdated(content::DownloadManager* manager,
                         download::DownloadItem* item) override;
  void OnDownloadDestroyed(content::DownloadManager* manager,
                           download::DownloadItem* item) override;

  // Helper function that makes sure a `DownloadManager` is initialized if
  // `client_` requires it to be.
  bool IsManagerReady(content::DownloadManager* manager);

  const raw_ptr<MultiProfileDownloadNotifier::Client> client_;

  const bool wait_for_manager_initialization_;

  std::set<std::unique_ptr<download::AllDownloadItemNotifier>,
           base::UniquePtrComparator>
      download_notifiers_;

  base::ScopedMultiSourceObservation<Profile, ProfileObserver>
      profile_observer_{this};
};

#endif  // CHROME_BROWSER_DOWNLOAD_NOTIFICATION_MULTI_PROFILE_DOWNLOAD_NOTIFIER_H_