chromium/extensions/browser/api/web_request/web_request_api_helpers.h

// 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.

// Helper classes and functions used for the WebRequest API.

#ifndef EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_
#define EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_

#include <list>
#include <optional>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "base/values.h"
#include "extensions/common/api/web_request.h"
#include "extensions/common/extension_id.h"
#include "net/base/auth.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "url/gurl.h"

namespace content {
class BrowserContext;
}

namespace extensions {
class Extension;
struct WebRequestInfo;

namespace declarative_net_request {
struct RequestAction;
}  // namespace declarative_net_request

}  // namespace extensions

namespace extension_web_request_api_helpers {

ResponseHeader;
ResponseHeaders;

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class RequestHeaderType {};

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class ResponseHeaderType {};

struct IgnoredAction {};

IgnoredActions;

// Internal representation of the extraInfoSpec parameter on webRequest
// events, used to specify extra information to be included with network
// events.
struct ExtraInfoSpec {};

// Data container for RequestCookies as defined in the declarative WebRequest
// API definition.
struct RequestCookie {};

// Data container for ResponseCookies as defined in the declarative WebRequest
// API definition.
struct ResponseCookie {};

// Data container for FilterResponseCookies as defined in the declarative
// WebRequest API definition.
struct FilterResponseCookie : ResponseCookie {};

enum CookieModificationType {};

struct RequestCookieModification {};

struct ResponseCookieModification {};

RequestCookieModifications;
ResponseCookieModifications;

// Contains the modification an extension wants to perform on an event.
struct EventResponseDelta {};

EventResponseDeltas;

// Comparison operator that returns true if the extension that caused
// |a| was installed after the extension that caused |b|.
bool InDecreasingExtensionInstallationTimeOrder(const EventResponseDelta& a,
                                                const EventResponseDelta& b);

// Converts a string to a list of integers, each in 0..255.
base::Value::List StringToCharList(const std::string& s);

// Converts a list of integer values between 0 and 255 into a string |*out|.
// Returns true if the conversion was successful.
bool CharListToString(const base::Value::List& list, std::string* out);

// The following functions calculate and return the modifications to requests
// commanded by extension handlers. All functions take the id of the extension
// that commanded a modification, the installation time of this extension (used
// for defining a precedence in conflicting modifications) and whether the
// extension requested to |cancel| the request. Other parameters depend on a
// the signal handler.

EventResponseDelta CalculateOnBeforeRequestDelta(
    const extensions::ExtensionId& extension_id,
    const base::Time& extension_install_time,
    bool cancel,
    const GURL& new_url);
EventResponseDelta CalculateOnBeforeSendHeadersDelta(
    content::BrowserContext* browser_context,
    const extensions::ExtensionId& extension_id,
    const base::Time& extension_install_time,
    bool cancel,
    net::HttpRequestHeaders* old_headers,
    net::HttpRequestHeaders* new_headers,
    int extra_info_spec);
EventResponseDelta CalculateOnHeadersReceivedDelta(
    const extensions::ExtensionId& extension_id,
    const base::Time& extension_install_time,
    bool cancel,
    const GURL& old_url,
    const GURL& new_url,
    const net::HttpResponseHeaders* old_response_headers,
    ResponseHeaders* new_response_headers,
    int extra_info_spec);
EventResponseDelta CalculateOnAuthRequiredDelta(
    const extensions::ExtensionId& extension_id,
    const base::Time& extension_install_time,
    bool cancel,
    std::optional<net::AuthCredentials> auth_credentials);

// These functions merge the responses (the |deltas|) of request handlers.
// The |deltas| need to be sorted in decreasing order of precedence of
// extensions. In case extensions had |deltas| that could not be honored, their
// IDs are reported in |conflicting_extensions|.

// Stores in |*canceled_by_extension| whether any extension wanted to cancel the
// request, std::nullopt if none did, the extension id otherwise.
void MergeCancelOfResponses(
    const EventResponseDeltas& deltas,
    std::optional<extensions::ExtensionId>* canceled_by_extension);
// Stores in |*new_url| the redirect request of the extension with highest
// precedence. Extensions that did not command to redirect the request are
// ignored in this logic.
void MergeRedirectUrlOfResponses(const GURL& url,
                                 const EventResponseDeltas& deltas,
                                 GURL* new_url,
                                 IgnoredActions* ignored_actions);
// Stores in |*new_url| the redirect request of the extension with highest
// precedence. Extensions that did not command to redirect the request are
// ignored in this logic.
void MergeOnBeforeRequestResponses(const GURL& url,
                                   const EventResponseDeltas& deltas,
                                   GURL* new_url,
                                   IgnoredActions* ignored_actions);
// Modifies the "Cookie" header in |request_headers| according to
// |deltas.request_cookie_modifications|. Conflicts are currently ignored
// silently.
void MergeCookiesInOnBeforeSendHeadersResponses(
    const GURL& gurl,
    const EventResponseDeltas& deltas,
    net::HttpRequestHeaders* request_headers);
// Modifies the headers in |request_headers| according to |deltas|. Conflicts
// are tried to be resolved.
// Stores in |request_headers_modified| whether the request headers were
// modified.
// Any actions within |request.dnr_actions| which result in headers being
// modified are added to |matched_dnr_actions|.
void MergeOnBeforeSendHeadersResponses(
    const extensions::WebRequestInfo& request,
    const EventResponseDeltas& deltas,
    net::HttpRequestHeaders* request_headers,
    IgnoredActions* ignored_actions,
    std::set<std::string>* removed_headers,
    std::set<std::string>* set_headers,
    bool* request_headers_modified,
    std::vector<const extensions::declarative_net_request::RequestAction*>*
        matched_dnr_actions);
// Modifies the "Set-Cookie" headers in |override_response_headers| according to
// |deltas.response_cookie_modifications|. If |override_response_headers| is
// NULL, a copy of |original_response_headers| is created. Conflicts are
// currently ignored silently.
void MergeCookiesInOnHeadersReceivedResponses(
    const GURL& url,
    const EventResponseDeltas& deltas,
    const net::HttpResponseHeaders* original_response_headers,
    scoped_refptr<net::HttpResponseHeaders>* override_response_headers);
// Stores a copy of |original_response_header| into |override_response_headers|
// that is modified according to |deltas|. If |deltas| does not instruct to
// modify the response headers, |override_response_headers| remains empty.
// Extension-initiated redirects are written to |override_response_headers|
// (to request redirection) and |*preserve_fragment_on_redirect_url| (to make
// sure that the URL provided by the extension isn't modified by having its
// fragment overwritten by that of the original URL). Stores in
// |response_headers_modified| whether the response headers were modified.
// Any actions within |request.dnr_actions| which result in headers being
// modified are added to |matched_dnr_actions|.
void MergeOnHeadersReceivedResponses(
    const extensions::WebRequestInfo& request,
    const EventResponseDeltas& deltas,
    const net::HttpResponseHeaders* original_response_headers,
    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
    GURL* preserve_fragment_on_redirect_url,
    IgnoredActions* ignored_actions,
    bool* response_headers_modified,
    std::vector<const extensions::declarative_net_request::RequestAction*>*
        matched_dnr_actions);
// Merge the responses of blocked onAuthRequired handlers. The first
// registered listener that supplies authentication credentials in a response,
// if any, will have its authentication credentials used. |request| must be
// non-NULL, and contain |deltas| that are sorted in decreasing order of
// precedence.
// Returns whether authentication credentials are set.
bool MergeOnAuthRequiredResponses(const EventResponseDeltas& deltas,
                                  net::AuthCredentials* auth_credentials,
                                  IgnoredActions* ignored_actions);

// Triggers clearing any back-forward caches and each renderer's in-memory cache
// the next time it navigates.
void ClearCacheOnNavigation();

// Converts the |name|, |value| pair of a http header to a HttpHeaders
// dictionary.
base::Value::Dict CreateHeaderDictionary(const std::string& name,
                                         const std::string& value);

// Returns whether a request header should be hidden from listeners.
bool ShouldHideRequestHeader(content::BrowserContext* browser_context,
                             int extra_info_spec,
                             const std::string& name);

// Returns whether a response header should be hidden from listeners.
bool ShouldHideResponseHeader(int extra_info_spec, const std::string& name);

// "Redirects" a request to `new_url` after the response has started by setting
// the appropriate headers in `override_response_headers`.
void RedirectRequestAfterHeadersReceived(
    const GURL& new_url,
    net::HttpResponseHeaders& override_response_headers,
    GURL* preserve_fragment_on_redirect_url);

}  // namespace extension_web_request_api_helpers

#endif  // EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_