1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_H_
6 #define EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_H_
15 #include "base/memory/singleton.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/strings/string_util.h"
18 #include "base/time/time.h"
19 #include "content/public/common/resource_type.h"
20 #include "extensions/browser/api/declarative/rules_registry.h"
21 #include "extensions/browser/api/declarative_webrequest/request_stage.h"
22 #include "extensions/browser/api/web_request/web_request_api_helpers.h"
23 #include "extensions/browser/api/web_request/web_request_permissions.h"
24 #include "extensions/browser/browser_context_keyed_api_factory.h"
25 #include "extensions/browser/event_router.h"
26 #include "extensions/browser/extension_function.h"
27 #include "extensions/common/url_pattern_set.h"
28 #include "ipc/ipc_sender.h"
29 #include "net/base/completion_callback.h"
30 #include "net/base/network_delegate.h"
31 #include "net/http/http_request_headers.h"
33 class ExtensionWebRequestTimeTracker
;
37 class DictionaryValue
;
47 class AuthChallengeInfo
;
48 class AuthCredentials
;
49 class HttpRequestHeaders
;
50 class HttpResponseHeaders
;
54 namespace extensions
{
57 class WebRequestRulesRegistry
;
58 class WebRequestEventRouterDelegate
;
60 // Support class for the WebRequest API. Lives on the UI thread. Most of the
61 // work is done by ExtensionWebRequestEventRouter below. This class observes
62 // extensions::EventRouter to deal with event listeners. There is one instance
63 // per BrowserContext which is shared with incognito.
64 class WebRequestAPI
: public BrowserContextKeyedAPI
,
65 public EventRouter::Observer
{
67 explicit WebRequestAPI(content::BrowserContext
* context
);
68 ~WebRequestAPI() override
;
70 // BrowserContextKeyedAPI support:
71 static BrowserContextKeyedAPIFactory
<WebRequestAPI
>* GetFactoryInstance();
73 // EventRouter::Observer overrides:
74 void OnListenerRemoved(const EventListenerInfo
& details
) override
;
77 friend class BrowserContextKeyedAPIFactory
<WebRequestAPI
>;
79 // BrowserContextKeyedAPI support:
80 static const char* service_name() { return "WebRequestAPI"; }
81 static const bool kServiceRedirectedInIncognito
= true;
82 static const bool kServiceIsNULLWhileTesting
= true;
84 content::BrowserContext
* browser_context_
;
86 DISALLOW_COPY_AND_ASSIGN(WebRequestAPI
);
89 // This class observes network events and routes them to the appropriate
90 // extensions listening to those events. All methods must be called on the IO
91 // thread unless otherwise specified.
92 class ExtensionWebRequestEventRouter
93 : public base::SupportsWeakPtr
<ExtensionWebRequestEventRouter
> {
95 struct BlockedRequest
;
99 kOnBeforeRequest
= 1 << 0,
100 kOnBeforeSendHeaders
= 1 << 1,
101 kOnSendHeaders
= 1 << 2,
102 kOnHeadersReceived
= 1 << 3,
103 kOnBeforeRedirect
= 1 << 4,
104 kOnAuthRequired
= 1 << 5,
105 kOnResponseStarted
= 1 << 6,
106 kOnErrorOccurred
= 1 << 7,
107 kOnCompleted
= 1 << 8,
110 // Internal representation of the webRequest.RequestFilter type, used to
111 // filter what network events an extension cares about.
112 struct RequestFilter
{
116 // Returns false if there was an error initializing. If it is a user error,
117 // an error message is provided, otherwise the error is internal (and
119 bool InitFromValue(const base::DictionaryValue
& value
, std::string
* error
);
121 extensions::URLPatternSet urls
;
122 std::vector
<content::ResourceType
> types
;
127 // Internal representation of the extraInfoSpec parameter on webRequest
128 // events, used to specify extra information to be included with network
130 struct ExtraInfoSpec
{
132 REQUEST_HEADERS
= 1<<0,
133 RESPONSE_HEADERS
= 1<<1,
135 ASYNC_BLOCKING
= 1<<3,
139 static bool InitFromValue(const base::ListValue
& value
,
140 int* extra_info_spec
);
143 // Contains an extension's response to a blocking event.
144 struct EventResponse
{
145 EventResponse(const std::string
& extension_id
,
146 const base::Time
& extension_install_time
);
149 // ID of the extension that sent this response.
150 std::string extension_id
;
152 // The time that the extension was installed. Used for deciding order of
153 // precedence in case multiple extensions respond with conflicting
155 base::Time extension_install_time
;
157 // Response values. These are mutually exclusive.
160 scoped_ptr
<net::HttpRequestHeaders
> request_headers
;
161 scoped_ptr
<extension_web_request_api_helpers::ResponseHeaders
>
164 scoped_ptr
<net::AuthCredentials
> auth_credentials
;
167 DISALLOW_COPY_AND_ASSIGN(EventResponse
);
170 static ExtensionWebRequestEventRouter
* GetInstance();
172 // Registers a rule registry. Pass null for |rules_registry| to unregister
173 // the rule registry for |browser_context|.
174 void RegisterRulesRegistry(
175 void* browser_context
,
176 int rules_registry_id
,
177 scoped_refptr
<extensions::WebRequestRulesRegistry
> rules_registry
);
179 // Dispatches the OnBeforeRequest event to any extensions whose filters match
180 // the given request. Returns net::ERR_IO_PENDING if an extension is
181 // intercepting the request, OK otherwise.
182 int OnBeforeRequest(void* browser_context
,
183 const extensions::InfoMap
* extension_info_map
,
184 net::URLRequest
* request
,
185 const net::CompletionCallback
& callback
,
188 // Dispatches the onBeforeSendHeaders event. This is fired for HTTP(s)
189 // requests only, and allows modification of the outgoing request headers.
190 // Returns net::ERR_IO_PENDING if an extension is intercepting the request, OK
192 int OnBeforeSendHeaders(void* browser_context
,
193 const extensions::InfoMap
* extension_info_map
,
194 net::URLRequest
* request
,
195 const net::CompletionCallback
& callback
,
196 net::HttpRequestHeaders
* headers
);
198 // Dispatches the onSendHeaders event. This is fired for HTTP(s) requests
200 void OnSendHeaders(void* browser_context
,
201 const extensions::InfoMap
* extension_info_map
,
202 net::URLRequest
* request
,
203 const net::HttpRequestHeaders
& headers
);
205 // Dispatches the onHeadersReceived event. This is fired for HTTP(s)
206 // requests only, and allows modification of incoming response headers.
207 // Returns net::ERR_IO_PENDING if an extension is intercepting the request,
208 // OK otherwise. |original_response_headers| is reference counted. |callback|
209 // |override_response_headers| and |allowed_unsafe_redirect_url| are owned by
210 // a URLRequestJob. They are guaranteed to be valid until |callback| is called
211 // or OnURLRequestDestroyed is called (whatever comes first).
212 // Do not modify |original_response_headers| directly but write new ones
213 // into |override_response_headers|.
214 int OnHeadersReceived(
215 void* browser_context
,
216 const extensions::InfoMap
* extension_info_map
,
217 net::URLRequest
* request
,
218 const net::CompletionCallback
& callback
,
219 const net::HttpResponseHeaders
* original_response_headers
,
220 scoped_refptr
<net::HttpResponseHeaders
>* override_response_headers
,
221 GURL
* allowed_unsafe_redirect_url
);
223 // Dispatches the OnAuthRequired event to any extensions whose filters match
224 // the given request. If the listener is not registered as "blocking", then
225 // AUTH_REQUIRED_RESPONSE_OK is returned. Otherwise,
226 // AUTH_REQUIRED_RESPONSE_IO_PENDING is returned and |callback| will be
228 net::NetworkDelegate::AuthRequiredResponse
OnAuthRequired(
229 void* browser_context
,
230 const extensions::InfoMap
* extension_info_map
,
231 net::URLRequest
* request
,
232 const net::AuthChallengeInfo
& auth_info
,
233 const net::NetworkDelegate::AuthCallback
& callback
,
234 net::AuthCredentials
* credentials
);
236 // Dispatches the onBeforeRedirect event. This is fired for HTTP(s) requests
238 void OnBeforeRedirect(void* browser_context
,
239 const extensions::InfoMap
* extension_info_map
,
240 net::URLRequest
* request
,
241 const GURL
& new_location
);
243 // Dispatches the onResponseStarted event indicating that the first bytes of
244 // the response have arrived.
245 void OnResponseStarted(void* browser_context
,
246 const extensions::InfoMap
* extension_info_map
,
247 net::URLRequest
* request
);
249 // Dispatches the onComplete event.
250 void OnCompleted(void* browser_context
,
251 const extensions::InfoMap
* extension_info_map
,
252 net::URLRequest
* request
);
254 // Dispatches an onErrorOccurred event.
255 void OnErrorOccurred(void* browser_context
,
256 const extensions::InfoMap
* extension_info_map
,
257 net::URLRequest
* request
,
260 // Notifications when objects are going away.
261 void OnURLRequestDestroyed(void* browser_context
,
262 const net::URLRequest
* request
);
264 // Called when an event listener handles a blocking event and responds.
265 void OnEventHandled(void* browser_context
,
266 const std::string
& extension_id
,
267 const std::string
& event_name
,
268 const std::string
& sub_event_name
,
270 EventResponse
* response
);
272 // Adds a listener to the given event. |event_name| specifies the event being
273 // listened to. |sub_event_name| is an internal event uniquely generated in
274 // the extension process to correspond to the given filter and
275 // extra_info_spec. It returns true on success, false on failure.
276 bool AddEventListener(void* browser_context
,
277 const std::string
& extension_id
,
278 const std::string
& extension_name
,
279 events::HistogramValue histogram_value
,
280 const std::string
& event_name
,
281 const std::string
& sub_event_name
,
282 const RequestFilter
& filter
,
284 int embedder_process_id
,
285 int web_view_instance_id
,
286 base::WeakPtr
<IPC::Sender
> ipc_sender
);
288 // Removes the listener for the given sub-event.
289 void RemoveEventListener(
290 void* browser_context
,
291 const std::string
& extension_id
,
292 const std::string
& sub_event_name
,
293 int embedder_process_id
,
294 int web_view_instance_id
);
296 // Removes the listeners for a given <webview>.
297 void RemoveWebViewEventListeners(
298 void* browser_context
,
299 int embedder_process_id
,
300 int web_view_instance_id
);
302 // Called when an incognito browser_context is created or destroyed.
303 void OnOTRBrowserContextCreated(void* original_browser_context
,
304 void* otr_browser_context
);
305 void OnOTRBrowserContextDestroyed(void* original_browser_context
,
306 void* otr_browser_context
);
308 // Registers a |callback| that is executed when the next page load happens.
309 // The callback is then deleted.
310 void AddCallbackForPageLoad(const base::Closure
& callback
);
313 friend struct DefaultSingletonTraits
<ExtensionWebRequestEventRouter
>;
315 struct EventListener
;
316 using EventListeners
= std::vector
<const EventListener
*>;
317 using ListenerMapForBrowserContext
=
318 std::map
<std::string
, std::set
<EventListener
>>;
319 using ListenerMap
= std::map
<void*, ListenerMapForBrowserContext
>;
320 using BlockedRequestMap
= std::map
<uint64_t, BlockedRequest
>;
321 // Map of request_id -> bit vector of EventTypes already signaled
322 using SignaledRequestMap
= std::map
<uint64_t, int>;
323 // For each browser_context: a bool indicating whether it is an incognito
324 // browser_context, and a pointer to the corresponding (non-)incognito
326 using CrossBrowserContextMap
= std::map
<void*, std::pair
<bool, void*>>;
327 using CallbacksForPageLoad
= std::list
<base::Closure
>;
329 ExtensionWebRequestEventRouter();
330 ~ExtensionWebRequestEventRouter();
332 // Ensures that future callbacks for |request| are ignored so that it can be
334 void ClearPendingCallbacks(const net::URLRequest
* request
);
337 void* browser_context
,
338 net::URLRequest
* request
,
339 const std::vector
<const EventListener
*>& listeners
,
340 const base::ListValue
& args
);
342 // Returns a list of event listeners that care about the given event, based
343 // on their filter parameters. |extra_info_spec| will contain the combined
344 // set of extra_info_spec flags that every matching listener asked for.
345 std::vector
<const EventListener
*> GetMatchingListeners(
346 void* browser_context
,
347 const extensions::InfoMap
* extension_info_map
,
348 const std::string
& event_name
,
349 const net::URLRequest
* request
,
350 int* extra_info_spec
);
352 // Helper for the above functions. This is called twice: once for the
353 // browser_context of the event, the next time for the "cross" browser_context
354 // (i.e. the incognito browser_context if the event is originally for the
355 // normal browser_context, or vice versa).
356 void GetMatchingListenersImpl(
357 void* browser_context
,
358 const net::URLRequest
* request
,
359 const extensions::InfoMap
* extension_info_map
,
360 bool crosses_incognito
,
361 const std::string
& event_name
,
363 int render_process_host_id
,
365 content::ResourceType resource_type
,
366 bool is_async_request
,
367 bool is_request_from_extension
,
368 int* extra_info_spec
,
369 std::vector
<const EventListener
*>* matching_listeners
);
371 // Decrements the count of event handlers blocking the given request. When the
372 // count reaches 0, we stop blocking the request and proceed it using the
373 // method requested by the extension with the highest precedence. Precedence
374 // is decided by extension install time. If |response| is non-NULL, this
375 // method assumes ownership.
376 void DecrementBlockCount(void* browser_context
,
377 const std::string
& extension_id
,
378 const std::string
& event_name
,
380 EventResponse
* response
);
382 // Logs an extension action.
383 void LogExtensionActivity(
384 void* browser_context_id
,
386 const std::string
& extension_id
,
388 const std::string
& api_call
,
389 scoped_ptr
<base::DictionaryValue
> details
);
391 // Processes the generated deltas from blocked_requests_ on the specified
392 // request. If |call_back| is true, the callback registered in
393 // |blocked_requests_| is called.
394 // The function returns the error code for the network request. This is
395 // mostly relevant in case the caller passes |call_callback| = false
396 // and wants to return the correct network error code himself.
397 int ExecuteDeltas(void* browser_context
,
401 // Evaluates the rules of the declarative webrequest API and stores
402 // modifications to the request that result from WebRequestActions as
403 // deltas in |blocked_requests_|. |original_response_headers| should only be
404 // set for the OnHeadersReceived stage and NULL otherwise. Returns whether any
405 // deltas were generated.
406 bool ProcessDeclarativeRules(
407 void* browser_context
,
408 const extensions::InfoMap
* extension_info_map
,
409 const std::string
& event_name
,
410 net::URLRequest
* request
,
411 extensions::RequestStage request_stage
,
412 const net::HttpResponseHeaders
* original_response_headers
);
414 // If the BlockedRequest contains messages_to_extension entries in the event
415 // deltas, we send them to subscribers of
416 // chrome.declarativeWebRequest.onMessage.
418 void* browser_context
, const BlockedRequest
& blocked_request
);
420 // Called when the RulesRegistry is ready to unblock a request that was
421 // waiting for said event.
422 void OnRulesRegistryReady(void* browser_context
,
423 const std::string
& event_name
,
425 extensions::RequestStage request_stage
);
427 // Extracts from |request| information for the keys requestId, url, method,
428 // frameId, tabId, type, and timeStamp and writes these into |out| to be
429 // passed on to extensions.
430 void ExtractRequestInfo(const net::URLRequest
* request
,
431 base::DictionaryValue
* out
);
433 // Sets the flag that |event_type| has been signaled for |request_id|.
434 // Returns the value of the flag before setting it.
435 bool GetAndSetSignaled(uint64_t request_id
, EventTypes event_type
);
437 // Clears the flag that |event_type| has been signaled for |request_id|.
438 void ClearSignaled(uint64_t request_id
, EventTypes event_type
);
440 // Returns whether |request| represents a top level window navigation.
441 bool IsPageLoad(const net::URLRequest
* request
) const;
443 // Called on a page load to process all registered callbacks.
444 void NotifyPageLoad();
446 // Returns the matching cross browser_context (the regular browser_context if
447 // |browser_context| is OTR and vice versa).
448 void* GetCrossBrowserContext(void* browser_context
) const;
450 // Determines whether the specified browser_context is an incognito
451 // browser_context (based on the contents of the cross-browser_context table
452 // and without dereferencing the browser_context pointer).
453 bool IsIncognitoBrowserContext(void* browser_context
) const;
455 // Returns true if |request| was already signaled to some event handlers.
456 bool WasSignaled(const net::URLRequest
& request
) const;
458 // A map for each browser_context that maps an event name to a set of
459 // extensions that are listening to that event.
460 ListenerMap listeners_
;
462 // A map of network requests that are waiting for at least one event handler
464 BlockedRequestMap blocked_requests_
;
466 // A map of request ids to a bitvector indicating which events have been
467 // signaled and should not be sent again.
468 SignaledRequestMap signaled_requests_
;
470 // A map of original browser_context -> corresponding incognito
471 // browser_context (and vice versa).
472 CrossBrowserContextMap cross_browser_context_map_
;
474 // Keeps track of time spent waiting on extensions using the blocking
476 scoped_ptr
<ExtensionWebRequestTimeTracker
> request_time_tracker_
;
478 CallbacksForPageLoad callbacks_for_page_load_
;
480 typedef std::pair
<void*, int> RulesRegistryKey
;
481 // Maps each browser_context (and OTRBrowserContext) and a webview key to its
482 // respective rules registry.
483 std::map
<RulesRegistryKey
,
484 scoped_refptr
<extensions::WebRequestRulesRegistry
> > rules_registries_
;
486 scoped_ptr
<extensions::WebRequestEventRouterDelegate
>
487 web_request_event_router_delegate_
;
489 DISALLOW_COPY_AND_ASSIGN(ExtensionWebRequestEventRouter
);
492 class WebRequestInternalFunction
: public SyncIOThreadExtensionFunction
{
494 WebRequestInternalFunction() {}
497 ~WebRequestInternalFunction() override
{}
499 const std::string
& extension_id_safe() const {
500 return extension() ? extension_id() : base::EmptyString();
504 class WebRequestInternalAddEventListenerFunction
505 : public WebRequestInternalFunction
{
507 DECLARE_EXTENSION_FUNCTION("webRequestInternal.addEventListener",
508 WEBREQUESTINTERNAL_ADDEVENTLISTENER
)
511 ~WebRequestInternalAddEventListenerFunction() override
{}
513 // ExtensionFunction:
514 bool RunSync() override
;
517 class WebRequestInternalEventHandledFunction
518 : public WebRequestInternalFunction
{
520 DECLARE_EXTENSION_FUNCTION("webRequestInternal.eventHandled",
521 WEBREQUESTINTERNAL_EVENTHANDLED
)
524 ~WebRequestInternalEventHandledFunction() override
{}
526 // Unblocks the network request and sets |error_| such that the developer
527 // console will show the respective error message. Use this function to handle
528 // incorrect requests from the extension that cannot be detected by the schema
530 void RespondWithError(
531 const std::string
& event_name
,
532 const std::string
& sub_event_name
,
534 scoped_ptr
<ExtensionWebRequestEventRouter::EventResponse
> response
,
535 const std::string
& error
);
537 // ExtensionFunction:
538 bool RunSync() override
;
541 class WebRequestHandlerBehaviorChangedFunction
542 : public WebRequestInternalFunction
{
544 DECLARE_EXTENSION_FUNCTION("webRequest.handlerBehaviorChanged",
545 WEBREQUEST_HANDLERBEHAVIORCHANGED
)
548 ~WebRequestHandlerBehaviorChangedFunction() override
{}
550 // ExtensionFunction:
551 void GetQuotaLimitHeuristics(
552 extensions::QuotaLimitHeuristics
* heuristics
) const override
;
553 // Handle quota exceeded gracefully: Only warn the user but still execute the
555 void OnQuotaExceeded(const std::string
& error
) override
;
556 bool RunSync() override
;
559 } // namespace extensions
561 #endif // EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_H_