// 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 #include #include #include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "content/public/common/resource_type.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 Value; } namespace content { class RenderProcessHost; } namespace extensions { class Extension; } namespace net { class BoundNetLog; class URLRequest; } namespace extension_web_request_api_helpers { typedef std::pair ResponseHeader; typedef std::vector ResponseHeaders; // Data container for RequestCookies as defined in the declarative WebRequest // API definition. struct RequestCookie { RequestCookie(); ~RequestCookie(); scoped_ptr name; scoped_ptr 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(); scoped_ptr name; scoped_ptr value; scoped_ptr expires; scoped_ptr max_age; scoped_ptr domain; scoped_ptr path; scoped_ptr secure; scoped_ptr 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(); scoped_ptr age_lower_bound; scoped_ptr age_upper_bound; scoped_ptr 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. scoped_ptr filter; // Used for ADD and EDIT. NULL for REMOVE. scoped_ptr 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. scoped_ptr filter; // Used for ADD and EDIT. scoped_ptr modification; private: DISALLOW_COPY_AND_ASSIGN(ResponseCookieModification); }; bool NullableEquals(const ResponseCookieModification* a, const ResponseCookieModification* b); typedef std::vector > RequestCookieModifications; typedef std::vector > 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 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. scoped_ptr 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 messages_to_extension; EventResponseDelta(const std::string& extension_id, const base::Time& extension_install_time); ~EventResponseDelta(); DISALLOW_COPY_AND_ASSIGN(EventResponseDelta); }; typedef std::list > 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& a, const linked_ptr& 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, scoped_ptr* 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::BoundNetLog* 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::BoundNetLog* 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::BoundNetLog* 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::BoundNetLog* 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::BoundNetLog* 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* override_response_headers, extensions::WarningSet* conflicting_extensions, const net::BoundNetLog* 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* override_response_headers, GURL* allowed_unsafe_redirect_url, extensions::WarningSet* conflicting_extensions, const net::BoundNetLog* 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::BoundNetLog* net_log); // Triggers clearing each renderer's in-memory cache the next time it navigates. void ClearCacheOnNavigation(); // Tells renderer processes that the web request or declarative web request // API has been used by the extension with the given |extension_id| in the // given |browser_context_id| to collect UMA statistics on Page Load Times. // Needs to be called on the UI thread. void NotifyWebRequestAPIUsed(void* browser_context_id, const std::string& extension_id); // Send updates to |host| with information about what webRequest-related // extensions are installed. void SendExtensionWebRequestStatusToHost(content::RenderProcessHost* host); // Converts the |name|, |value| pair of a http header to a HttpHeaders // dictionary. Ownership is passed to the caller. base::DictionaryValue* CreateHeaderDictionary( const std::string& name, const std::string& value); // Returns whether |type| is a ResourceType that is handled by the web request // API. bool IsRelevantResourceType(content::ResourceType type); // Returns a string representation of |type| or |other| if |type| is not handled // by the web request API. const char* ResourceTypeToString(content::ResourceType type); // Stores a |content::ResourceType| representation in |type| if |type_str| is // a resource type handled by the web request API. Returns true in case of // success. bool ParseResourceType(const std::string& type_str, content::ResourceType* type); } // namespace extension_web_request_api_helpers #endif // EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_