910e62b5创建于 1月15日历史提交
// Copyright 2018 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_CLEAR_SITE_DATA_HANDLER_H_
#define CONTENT_BROWSER_BROWSING_DATA_CLEAR_SITE_DATA_HANDLER_H_

#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/functional/callback.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/public/browser/clear_site_data_utils.h"
#include "content/public/browser/storage_partition_config.h"
#include "net/cookies/cookie_partition_key.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace content {

class WebContents;
class BrowserContext;

// This handler parses the Clear-Site-Data header and executes the clearing
// of browsing data. The resource load is delayed until the header is parsed
// and, if valid, until the browsing data are deleted. See the W3C working draft
// at https://w3c.github.io/webappsec-clear-site-data/.
class CONTENT_EXPORT ClearSiteDataHandler {
 public:
  // Stores and outputs console messages.
  class CONTENT_EXPORT ConsoleMessagesDelegate {
   public:
    struct Message {
      GURL url;
      std::string text;
      blink::mojom::ConsoleMessageLevel level;
    };

    using OutputFormattedMessageFunction =
        base::RepeatingCallback<void(WebContents*,
                                     blink::mojom::ConsoleMessageLevel,
                                     const std::string&)>;

    ConsoleMessagesDelegate();
    virtual ~ConsoleMessagesDelegate();

    // Logs a |text| message from |url| with |level|.
    virtual void AddMessage(const GURL& url,
                            const std::string& text,
                            blink::mojom::ConsoleMessageLevel level);

    // Outputs stored messages to the console of WebContents.
    virtual void OutputMessages(base::WeakPtr<WebContents> web_contents);

    const std::vector<Message>& GetMessagesForTesting() const {
      return messages_;
    }

   protected:
    void SetOutputFormattedMessageFunctionForTesting(
        const OutputFormattedMessageFunction& function);

   private:
    std::vector<Message> messages_;
    OutputFormattedMessageFunction output_formatted_message_function_;
  };

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

  // |header_value| is the string value of the 'Clear-Site-Data' header. This
  // method calls ParseHeader() to parse it, and then ExecuteClearingTask() if
  // applicable.
  static void HandleHeader(
      base::WeakPtr<BrowserContext> browser_context,
      base::WeakPtr<WebContents> web_contents,
      const StoragePartitionConfig& storage_partition_config,
      const GURL& url,
      const std::string& header_value,
      int load_flags,
      const std::optional<net::CookiePartitionKey> cookie_partition_key,
      const std::optional<blink::StorageKey> storage_key,
      bool partitioned_state_allowed_only,
      base::OnceClosure callback);

  // Exposes ParseHeader() publicly for testing.
  static bool ParseHeaderForTesting(
      const std::string& header,
      ClearSiteDataTypeSet* clear_site_data_types,
      std::set<std::string>* storage_buckets_to_remove,
      ConsoleMessagesDelegate* delegate,
      const GURL& current_url);

 protected:
  ClearSiteDataHandler(
      base::WeakPtr<BrowserContext> browser_context,
      base::WeakPtr<WebContents> web_contents,
      const StoragePartitionConfig& storage_partition_config,
      const GURL& url,
      const std::string& header_value,
      int load_flags,
      const std::optional<net::CookiePartitionKey> cookie_partition_key,
      const std::optional<blink::StorageKey> storage_key,
      bool partitioned_state_allowed_only,
      base::OnceClosure callback,
      std::unique_ptr<ConsoleMessagesDelegate> delegate);
  virtual ~ClearSiteDataHandler();

  // Calls |HandleHeaderImpl| to handle headers, and output console message if
  // not deferred. Returns |true| if the request was deferred.
  bool HandleHeaderAndOutputConsoleMessages();

  // Handles headers and maybe execute clearing task. Returns |true| if the
  // request was deferred.
  bool Run();

  // Parses the value of the 'Clear-Site-Data' header and outputs which types of
  // data to clear to `clear_site_data_types` and `storage_buckets_to_remove`.
  // The `delegate` will be filled with messages to be output in the console,
  // prepended by the `current_url`. Returns true if parsing was successful.
  static bool ParseHeader(const std::string& header,
                          ClearSiteDataTypeSet* clear_site_data_types,
                          std::set<std::string>* storage_buckets_to_remove,
                          ConsoleMessagesDelegate* delegate,
                          const GURL& current_url);

  // Executes the clearing task. Can be overridden for testing.
  virtual void ExecuteClearingTask(
      const url::Origin& origin,
      const ClearSiteDataTypeSet clear_site_data_types,
      const std::set<std::string>& storage_buckets_to_remove,
      base::OnceClosure callback);

  // Signals that a parsing and deletion task was finished.
  // |clearing_started| is the time when the last clearing operation started.
  // Used when clearing finishes to compute the duration.
  static void TaskFinished(base::TimeTicks clearing_started,
                           std::unique_ptr<ConsoleMessagesDelegate> delegate,
                           base::WeakPtr<WebContents> web_contents,
                           base::OnceClosure callback);

  // Outputs the console messages in the |delegate_|.
  void OutputConsoleMessages();

  // Run the callback to resume loading. No clearing actions were conducted.
  void RunCallbackNotDeferred();

  const StoragePartitionConfig& StoragePartitionConfigForTesting() const {
    return storage_partition_config_;
  }

  const GURL& GetURLForTesting();

  const std::optional<net::CookiePartitionKey> CookiePartitionKeyForTesting()
      const {
    return cookie_partition_key_;
  }

  const std::optional<blink::StorageKey> StorageKeyForTesting() const {
    return storage_key_;
  }

  bool PartitionedStateOnlyForTesting() const {
    return partitioned_state_allowed_only_;
  }

 private:
  // Required to clear the data.
  base::WeakPtr<BrowserContext> browser_context_;
  base::WeakPtr<WebContents> web_contents_;

  // The config for the target storage partition which stores the data.
  const StoragePartitionConfig storage_partition_config_;

  // Target URL whose data will be cleared.
  const GURL url_;

  // Raw string value of the 'Clear-Site-Data' header.
  const std::string header_value_;

  // Load flags of the current request, used to check cookie policies.
  const int load_flags_;

  // The cookie partition key for which we need to clear partitioned cookies
  // when we receive the Clear-Site-Data header.
  const std::optional<net::CookiePartitionKey> cookie_partition_key_;

  // The storage key for which we need to clear partitioned storage when we
  // receive the Clear-Site-Data header.
  const std::optional<blink::StorageKey> storage_key_;

  // If third-party cookie blocking is enabled and applies to the response that
  // sent Clear-Site-Data.
  const bool partitioned_state_allowed_only_;

  // Used to notify that the clearing has completed. Callers could resuming
  // loading after this point.
  base::OnceClosure callback_;

  // The delegate that stores and outputs console messages.
  std::unique_ptr<ConsoleMessagesDelegate> delegate_;
};

}  // namespace content

#endif  // CONTENT_BROWSER_BROWSING_DATA_CLEAR_SITE_DATA_HANDLER_H_