blob: 6e25fa5e73fac435e9bb4570a338fb1e1e1f343a [file] [log] [blame]
// Copyright (c) 2012 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.
// 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 <memory>
#include <set>
#include <string>
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "extensions/browser/warning_set.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 base {
class ListValue;
class DictionaryValue;
}
namespace extensions {
class Extension;
}
namespace net {
class NetLogWithSource;
}
namespace extension_web_request_api_helpers {
typedef std::pair<std::string, std::string> ResponseHeader;
typedef std::vector<ResponseHeader> ResponseHeaders;
// Internal representation of the extraInfoSpec parameter on webRequest
// events, used to specify extra information to be included with network
// events.
struct ExtraInfoSpec {
enum Flags {
REQUEST_HEADERS = 1 << 0,
RESPONSE_HEADERS = 1 << 1,
BLOCKING = 1 << 2,
ASYNC_BLOCKING = 1 << 3,
REQUEST_BODY = 1 << 4,
};
static bool InitFromValue(const base::ListValue& value, int* extra_info_spec);
};
// Data container for RequestCookies as defined in the declarative WebRequest
// API definition.
struct RequestCookie {
RequestCookie();
~RequestCookie();
std::unique_ptr<std::string> name;
std::unique_ptr<std::string> value;
private:
DISALLOW_COPY_AND_ASSIGN(RequestCookie);
};
bool NullableEquals(const RequestCookie* a, const RequestCookie* b);
// Data container for ResponseCookies as defined in the declarative WebRequest
// API definition.
struct ResponseCookie {
ResponseCookie();
~ResponseCookie();
std::unique_ptr<std::string> name;
std::unique_ptr<std::string> value;
std::unique_ptr<std::string> expires;
std::unique_ptr<int> max_age;
std::unique_ptr<std::string> domain;
std::unique_ptr<std::string> path;
std::unique_ptr<bool> secure;
std::unique_ptr<bool> http_only;
private:
DISALLOW_COPY_AND_ASSIGN(ResponseCookie);
};
bool NullableEquals(const ResponseCookie* a, const ResponseCookie* b);
// Data container for FilterResponseCookies as defined in the declarative
// WebRequest API definition.
struct FilterResponseCookie : ResponseCookie {
FilterResponseCookie();
~FilterResponseCookie();
std::unique_ptr<int> age_lower_bound;
std::unique_ptr<int> age_upper_bound;
std::unique_ptr<bool> session_cookie;
private:
DISALLOW_COPY_AND_ASSIGN(FilterResponseCookie);
};
bool NullableEquals(const FilterResponseCookie* a,
const FilterResponseCookie* b);
enum CookieModificationType {
ADD,
EDIT,
REMOVE,
};
struct RequestCookieModification {
RequestCookieModification();
~RequestCookieModification();
CookieModificationType type;
// Used for EDIT and REMOVE. NULL for ADD.
std::unique_ptr<RequestCookie> filter;
// Used for ADD and EDIT. NULL for REMOVE.
std::unique_ptr<RequestCookie> modification;
private:
DISALLOW_COPY_AND_ASSIGN(RequestCookieModification);
};
bool NullableEquals(const RequestCookieModification* a,
const RequestCookieModification* b);
struct ResponseCookieModification {
ResponseCookieModification();
~ResponseCookieModification();
CookieModificationType type;
// Used for EDIT and REMOVE.
std::unique_ptr<FilterResponseCookie> filter;
// Used for ADD and EDIT.
std::unique_ptr<ResponseCookie> modification;
private:
DISALLOW_COPY_AND_ASSIGN(ResponseCookieModification);
};
bool NullableEquals(const ResponseCookieModification* a,
const ResponseCookieModification* b);
typedef std::vector<linked_ptr<RequestCookieModification> >
RequestCookieModifications;
typedef std::vector<linked_ptr<ResponseCookieModification> >
ResponseCookieModifications;
// Contains the modification an extension wants to perform on an event.
struct EventResponseDelta {
// ID of the extension that sent this response.
std::string extension_id;
// The time that the extension was installed. Used for deciding order of
// precedence in case multiple extensions respond with conflicting
// decisions.
base::Time extension_install_time;
// Response values. These are mutually exclusive.
bool cancel;
GURL new_url;
// Newly introduced or overridden request headers.
net::HttpRequestHeaders modified_request_headers;
// Keys of request headers to be deleted.
std::vector<std::string> deleted_request_headers;
// Headers that were added to the response. A modification of a header
// corresponds to a deletion and subsequent addition of the new header.
ResponseHeaders added_response_headers;
// Headers that were deleted from the response.
ResponseHeaders deleted_response_headers;
// Authentication Credentials to use.
std::unique_ptr<net::AuthCredentials> auth_credentials;
// Modifications to cookies in request headers.
RequestCookieModifications request_cookie_modifications;
// Modifications to cookies in response headers.
ResponseCookieModifications response_cookie_modifications;
// Messages that shall be sent to the background/event/... pages of the
// extension.
std::set<std::string> messages_to_extension;
EventResponseDelta(const std::string& extension_id,
const base::Time& extension_install_time);
~EventResponseDelta();
DISALLOW_COPY_AND_ASSIGN(EventResponseDelta);
};
typedef std::list<linked_ptr<EventResponseDelta> > EventResponseDeltas;
// Comparison operator that returns true if the extension that caused
// |a| was installed after the extension that caused |b|.
bool InDecreasingExtensionInstallationTimeOrder(
const linked_ptr<EventResponseDelta>& a,
const linked_ptr<EventResponseDelta>& b);
// Converts a string to a list of integers, each in 0..255. Ownership
// of the created list is passed to the caller.
base::ListValue* 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::ListValue* 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. Ownership of the returned object is passed to the caller.
EventResponseDelta* CalculateOnBeforeRequestDelta(
const std::string& extension_id,
const base::Time& extension_install_time,
bool cancel,
const GURL& new_url);
EventResponseDelta* CalculateOnBeforeSendHeadersDelta(
const std::string& extension_id,
const base::Time& extension_install_time,
bool cancel,
net::HttpRequestHeaders* old_headers,
net::HttpRequestHeaders* new_headers);
EventResponseDelta* CalculateOnHeadersReceivedDelta(
const std::string& extension_id,
const base::Time& extension_install_time,
bool cancel,
const GURL& new_url,
const net::HttpResponseHeaders* old_response_headers,
ResponseHeaders* new_response_headers);
// Destructively moves the auth credentials from |auth_credentials| to the
// returned EventResponseDelta.
EventResponseDelta* CalculateOnAuthRequiredDelta(
const std::string& extension_id,
const base::Time& extension_install_time,
bool cancel,
std::unique_ptr<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|. NetLog events that shall be
// reported will be stored in |event_log_entries|.
// Stores in |canceled| whether any extension wanted to cancel the request.
void MergeCancelOfResponses(const EventResponseDeltas& deltas,
bool* canceled,
const net::NetLogWithSource* net_log);
// 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 EventResponseDeltas& deltas,
GURL* new_url,
extensions::WarningSet* conflicting_extensions,
const net::NetLogWithSource* net_log);
// 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 EventResponseDeltas& deltas,
GURL* new_url,
extensions::WarningSet* conflicting_extensions,
const net::NetLogWithSource* net_log);
// Modifies the "Cookie" header in |request_headers| according to
// |deltas.request_cookie_modifications|. Conflicts are currently ignored
// silently.
void MergeCookiesInOnBeforeSendHeadersResponses(
const EventResponseDeltas& deltas,
net::HttpRequestHeaders* request_headers,
extensions::WarningSet* conflicting_extensions,
const net::NetLogWithSource* net_log);
// Modifies the headers in |request_headers| according to |deltas|. Conflicts
// are tried to be resolved.
void MergeOnBeforeSendHeadersResponses(
const EventResponseDeltas& deltas,
net::HttpRequestHeaders* request_headers,
extensions::WarningSet* conflicting_extensions,
const net::NetLogWithSource* net_log);
// 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 EventResponseDeltas& deltas,
const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
extensions::WarningSet* conflicting_extensions,
const net::NetLogWithSource* net_log);
// 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 |*allowed_unsafe_redirect_url| (to make sure
// that the request is not cancelled with net::ERR_UNSAFE_REDIRECT).
void MergeOnHeadersReceivedResponses(
const EventResponseDeltas& deltas,
const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
GURL* allowed_unsafe_redirect_url,
extensions::WarningSet* conflicting_extensions,
const net::NetLogWithSource* net_log);
// 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,
extensions::WarningSet* conflicting_extensions,
const net::NetLogWithSource* net_log);
// Triggers clearing 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.
std::unique_ptr<base::DictionaryValue> CreateHeaderDictionary(
const std::string& name,
const std::string& value);
} // namespace extension_web_request_api_helpers
#endif // EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_