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

#ifndef CONTENT_BROWSER_BROWSING_DATA_BROWSING_DATA_REMOVER_IMPL_H_
#define CONTENT_BROWSER_BROWSING_DATA_BROWSING_DATA_REMOVER_IMPL_H_

#include <stdint.h>

#include <map>
#include <memory>
#include <optional>
#include <set>

#include "base/cancelable_callback.h"
#include "base/containers/queue.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/supports_user_data.h"
#include "base/synchronization/waitable_event_watcher.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/storage_partition_config.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "url/origin.h"

namespace content {

class BrowserContext;
class BrowsingDataFilterBuilder;
class StoragePartition;

class CONTENT_EXPORT BrowsingDataRemoverImpl
    : public BrowsingDataRemover,
      public base::SupportsUserData::Data {
 public:
  explicit BrowsingDataRemoverImpl(BrowserContext* browser_context);

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

  ~BrowsingDataRemoverImpl() override;

  // Is the BrowsingDataRemoverImpl currently in the process of removing data?
  bool IsRemovingForTesting() { return is_removing_; }

  // Removes storage buckets of a storage key.
  // If |storage_partition_config| is null, the operation will take place
  // on the profile's default storage partition.
  void RemoveStorageBucketsAndReply(
      const std::optional<StoragePartitionConfig> storage_partition_config,
      const blink::StorageKey& storage_key,
      const std::set<std::string>& storage_buckets,
      base::OnceClosure callback);

  // BrowsingDataRemover implementation:
  void SetEmbedderDelegate(
      BrowsingDataRemoverDelegate* embedder_delegate) override;
  bool DoesOriginMatchMaskForTesting(
      uint64_t origin_type_mask,
      const url::Origin& origin,
      storage::SpecialStoragePolicy* special_storage_policy) override;
  void Remove(const base::Time& delete_begin,
              const base::Time& delete_end,
              uint64_t remove_mask,
              uint64_t origin_type_mask) override;
  void RemoveWithFilter(
      const base::Time& delete_begin,
      const base::Time& delete_end,
      uint64_t remove_mask,
      uint64_t origin_type_mask,
      std::unique_ptr<BrowsingDataFilterBuilder> filter_builder) override;
  void RemoveAndReply(const base::Time& delete_begin,
                      const base::Time& delete_end,
                      uint64_t remove_mask,
                      uint64_t origin_type_mask,
                      Observer* observer) override;
  void RemoveWithFilterAndReply(
      const base::Time& delete_begin,
      const base::Time& delete_end,
      uint64_t remove_mask,
      uint64_t origin_type_mask,
      std::unique_ptr<BrowsingDataFilterBuilder> filter_builder,
      Observer* observer) override;

  void AddObserver(Observer* observer) override;
  void RemoveObserver(Observer* observer) override;

  void SetWouldCompleteCallbackForTesting(
      const base::RepeatingCallback<
          void(base::OnceClosure continue_to_completion)>& callback) override;

  const base::Time& GetLastUsedBeginTimeForTesting() override;
  uint64_t GetLastUsedRemovalMaskForTesting() override;
  uint64_t GetLastUsedOriginTypeMaskForTesting() override;
  std::optional<StoragePartitionConfig>
  GetLastUsedStoragePartitionConfigForTesting() override;
  uint64_t GetPendingTaskCountForTesting() override;

  void ClearClientHintCacheAndReply(const url::Origin& origin,
                                    base::OnceClosure callback);

  // Used for testing.
  void OverrideStoragePartitionForTesting(
      const StoragePartitionConfig& storage_partition_config,
      StoragePartition* storage_partition);

 protected:
  // A common reduction of all public Remove[WithFilter][AndReply] methods.
  virtual void RemoveInternal(
      const base::Time& delete_begin,
      const base::Time& delete_end,
      uint64_t remove_mask,
      uint64_t origin_type_mask,
      std::unique_ptr<BrowsingDataFilterBuilder> filter_builder,
      Observer* observer);

 private:
  // Testing the private RemovalTask.
  FRIEND_TEST_ALL_PREFIXES(BrowsingDataRemoverImplTest, MultipleTasks);
  FRIEND_TEST_ALL_PREFIXES(BrowsingDataRemoverImplTest, MultipleIdenticalTasks);

  // For debugging purposes. Please add new deletion tasks at the end.
  // This enum is recorded in a histogram, so don't change or reuse ids.
  // LINT.IfChange(TracingDataType)
  enum class TracingDataType {
    kSynchronous = 1,
    kEmbedderData = 2,
    kStoragePartition = 3,
    kHttpCache = 4,
    kHttpAndMediaCaches = 5,
    kReportingCache = 6,
    kChannelIds = 7,
    kNetworkHistory = 8,
    kAuthCache = 9,
    kCodeCaches = 10,
    kNetworkErrorLogging = 11,
    kTrustTokens = 12,
    kConversions = 13,
    kDeferredCookies = 14,
    kSharedStorage = 15,
    kPreflightCache = 16,
    kSharedDictionary = 17,
    kPrefetchCache = 18,
    kPrerenderCache = 19,
    kMaxValue = kPrerenderCache,
  };
  // LINT.ThenChange(//tools/metrics/histograms/metadata/history/enums.xml:BrowsingDataRemoverTasks)

  // Returns the suffix for the History.ClearBrowsingData.Duration.Task.{Task}
  // histogram
  const char* GetHistogramSuffix(TracingDataType task);

  // Represents a single removal task. Contains all parameters needed to execute
  // it and a pointer to the observer that added it. CONTENT_EXPORTed to be
  // visible in tests.
  struct CONTENT_EXPORT RemovalTask {
    RemovalTask(const base::Time& delete_begin,
                const base::Time& delete_end,
                uint64_t remove_mask,
                uint64_t origin_type_mask,
                std::unique_ptr<BrowsingDataFilterBuilder> filter_builder,
                Observer* observer);
    RemovalTask(RemovalTask&& other) noexcept;
    ~RemovalTask();

    // Returns true if the deletion parameters are equal.
    // Does not compare |observer| and |task_started|.
    bool IsSameDeletion(const RemovalTask& other);

    base::Time delete_begin;
    base::Time delete_end;
    uint64_t remove_mask;
    uint64_t origin_type_mask;
    std::unique_ptr<BrowsingDataFilterBuilder> filter_builder;
    std::vector<raw_ptr<Observer, VectorExperimental>> observers;
    base::TimeTicks task_started;
  };

  // Setter for |is_removing_|; DCHECKs that we can only start removing if we're
  // not already removing, and vice-versa.
  void SetRemoving(bool is_removing);

  // Executes the next removal task. Called after the previous task was finished
  // or directly from Remove() if the task queue was empty.
  void RunNextTask();

  // Removes the specified items related to browsing for a specific host. If the
  // provided |remove_url| is empty, data is removed for all origins; otherwise,
  // it is restricted by the origin filter origin (where implemented yet). The
  // |origin_type_mask| parameter defines the set of origins from which data
  // should be removed (protected, unprotected, or both).
  // TODO(ttr314): Remove "(where implemented yet)" constraint above once
  // crbug.com/113621 is done.
  // TODO(crbug.com/40458377): Support all backends w/ origin filter.
  void RemoveImpl(const base::Time& delete_begin,
                  const base::Time& delete_end,
                  uint64_t remove_mask,
                  BrowsingDataFilterBuilder* filter_builder,
                  uint64_t origin_type_mask);

  void OnDelegateDone(base::OnceClosure completion_closure,
                      uint64_t failed_data_types);

  // Notifies observers and transitions to the idle state.
  void Notify();

  // Called by the closures returned by CreateTaskCompletionClosure().
  // Checks if all tasks have completed, and if so, calls Notify().
  void OnTaskComplete(TracingDataType data_type, base::TimeTicks started);

  // Called when the storage buckets data has been removed.
  void DidRemoveStorageBuckets(base::OnceClosure callback);

  // Increments the number of pending tasks by one, and returns a OnceClosure
  // that calls OnTaskComplete(). The Remover is complete once all the closures
  // created by this method have been invoked.
  base::OnceClosure CreateTaskCompletionClosure(TracingDataType data_type);

  // Same as CreateTaskCompletionClosure() but guarantees that
  // OnTaskComplete() is called if the task is dropped. That can typically
  // happen when the connection is closed while an interface call is made.
  base::OnceClosure CreateTaskCompletionClosureForMojo(
      TracingDataType data_type);

  // Records unfinished tasks from |pending_sub_tasks_| after a delay.
  void RecordUnfinishedSubTasks();

  StoragePartition* GetStoragePartition(
      std::optional<StoragePartitionConfig> storage_partition_config);

  // This does the actual clearing of the client hint cache for the provided
  // origin. It should be invoked only via ClearClientHintCacheAndReply.
  void ClearClientHintCacheAndReplyImpl(const url::Origin& origin,
                                        base::OnceClosure callback);

  // Like GetWeakPtr(), but returns a weak pointer to BrowsingDataRemoverImpl
  // for internal purposes.
  base::WeakPtr<BrowsingDataRemoverImpl> GetWeakPtr();

  // The browser context we're to remove from.
  raw_ptr<BrowserContext> browser_context_;

  // A delegate to delete the embedder-specific data. Owned by the embedder.
  raw_ptr<BrowsingDataRemoverDelegate, DanglingUntriaged> embedder_delegate_;

  // Start time to delete from.
  base::Time delete_begin_;

  // End time to delete to.
  base::Time delete_end_;

  // The removal mask for the current removal operation.
  uint64_t remove_mask_ = 0;

  // From which types of origins should we remove data?
  uint64_t origin_type_mask_ = 0;

  // The StoragePartition from which data should be removed, or the default
  // if absent.
  std::optional<StoragePartitionConfig> storage_partition_config_ =
      std::nullopt;

  std::vector<std::string> domains_for_deferred_cookie_deletion_;

  // True if Remove has been invoked.
  bool is_removing_;

  // Removal tasks to be processed.
  std::deque<RemovalTask> task_queue_;

  // If non-null, the |would_complete_callback_| is called each time an instance
  // is about to complete a browsing data removal process, and has the ability
  // to artificially delay completion. Used for testing.
  base::RepeatingCallback<void(base::OnceClosure continue_to_completion)>
      would_complete_callback_;

  // Records which tasks of a deletion are currently active.
  std::set<TracingDataType> pending_sub_tasks_;

  uint64_t failed_data_types_ = 0;

  // Fires after some time to track slow tasks. Cancelled when all tasks
  // are finished.
  base::CancelableOnceClosure slow_pending_tasks_closure_;

  // Observers of the global state and individual tasks.
  base::ObserverList<Observer, true>::Unchecked observer_list_;

  // We do not own the StoragePartitions.
  std::map<StoragePartitionConfig, raw_ptr<StoragePartition>>
      storage_partitions_for_testing_;

  base::WeakPtrFactory<BrowsingDataRemoverImpl> weak_ptr_factory_{this};
};

}  // namespace content

#endif  // CONTENT_BROWSER_BROWSING_DATA_BROWSING_DATA_REMOVER_IMPL_H_