OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #ifndef CHROME_BROWSER_EXTENSIONS_API_WEB_REQUEST_WEB_REQUEST_API_H_ | |
6 #define CHROME_BROWSER_EXTENSIONS_API_WEB_REQUEST_WEB_REQUEST_API_H_ | |
7 | |
8 #include <list> | |
9 #include <map> | |
10 #include <set> | |
11 #include <string> | |
12 #include <vector> | |
13 | |
14 #include "base/memory/singleton.h" | |
15 #include "base/memory/weak_ptr.h" | |
16 #include "base/time/time.h" | |
17 #include "content/public/common/resource_type.h" | |
18 #include "extensions/browser/api/declarative/rules_registry.h" | |
19 #include "extensions/browser/api/declarative_webrequest/request_stage.h" | |
20 #include "extensions/browser/api/web_request/web_request_api_helpers.h" | |
21 #include "extensions/browser/api/web_request/web_request_permissions.h" | |
22 #include "extensions/browser/browser_context_keyed_api_factory.h" | |
23 #include "extensions/browser/event_router.h" | |
24 #include "extensions/browser/extension_function.h" | |
25 #include "extensions/common/url_pattern_set.h" | |
26 #include "ipc/ipc_sender.h" | |
27 #include "net/base/completion_callback.h" | |
28 #include "net/base/network_delegate.h" | |
29 #include "net/http/http_request_headers.h" | |
30 | |
31 class ExtensionWebRequestTimeTracker; | |
32 class GURL; | |
33 | |
34 namespace base { | |
35 class DictionaryValue; | |
36 class ListValue; | |
37 class StringValue; | |
38 } | |
39 | |
40 namespace content { | |
41 class BrowserContext; | |
42 } | |
43 | |
44 namespace net { | |
45 class AuthCredentials; | |
46 class AuthChallengeInfo; | |
47 class HttpRequestHeaders; | |
48 class HttpResponseHeaders; | |
49 class URLRequest; | |
50 } | |
51 | |
52 namespace extensions { | |
53 | |
54 class InfoMap; | |
55 class WebRequestRulesRegistry; | |
56 class WebRequestEventRouterDelegate; | |
57 | |
58 // Support class for the WebRequest API. Lives on the UI thread. Most of the | |
59 // work is done by ExtensionWebRequestEventRouter below. This class observes | |
60 // extensions::EventRouter to deal with event listeners. There is one instance | |
61 // per BrowserContext which is shared with incognito. | |
62 class WebRequestAPI : public BrowserContextKeyedAPI, | |
63 public EventRouter::Observer { | |
64 public: | |
65 explicit WebRequestAPI(content::BrowserContext* context); | |
66 virtual ~WebRequestAPI(); | |
67 | |
68 // BrowserContextKeyedAPI support: | |
69 static BrowserContextKeyedAPIFactory<WebRequestAPI>* GetFactoryInstance(); | |
70 | |
71 // EventRouter::Observer overrides: | |
72 virtual void OnListenerRemoved(const EventListenerInfo& details) OVERRIDE; | |
73 | |
74 private: | |
75 friend class BrowserContextKeyedAPIFactory<WebRequestAPI>; | |
76 | |
77 // BrowserContextKeyedAPI support: | |
78 static const char* service_name() { return "WebRequestAPI"; } | |
79 static const bool kServiceRedirectedInIncognito = true; | |
80 static const bool kServiceIsNULLWhileTesting = true; | |
81 | |
82 content::BrowserContext* browser_context_; | |
83 | |
84 DISALLOW_COPY_AND_ASSIGN(WebRequestAPI); | |
85 }; | |
86 | |
87 } // namespace extensions | |
88 | |
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> { | |
94 public: | |
95 struct BlockedRequest; | |
96 | |
97 enum EventTypes { | |
98 kInvalidEvent = 0, | |
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, | |
108 }; | |
109 | |
110 // Internal representation of the webRequest.RequestFilter type, used to | |
111 // filter what network events an extension cares about. | |
112 struct RequestFilter { | |
113 RequestFilter(); | |
114 ~RequestFilter(); | |
115 | |
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 | |
118 // unexpected). | |
119 bool InitFromValue(const base::DictionaryValue& value, std::string* error); | |
120 | |
121 extensions::URLPatternSet urls; | |
122 std::vector<content::ResourceType> types; | |
123 int tab_id; | |
124 int window_id; | |
125 }; | |
126 | |
127 // Internal representation of the extraInfoSpec parameter on webRequest | |
128 // events, used to specify extra information to be included with network | |
129 // events. | |
130 struct ExtraInfoSpec { | |
131 enum Flags { | |
132 REQUEST_HEADERS = 1<<0, | |
133 RESPONSE_HEADERS = 1<<1, | |
134 BLOCKING = 1<<2, | |
135 ASYNC_BLOCKING = 1<<3, | |
136 REQUEST_BODY = 1<<4, | |
137 }; | |
138 | |
139 static bool InitFromValue(const base::ListValue& value, | |
140 int* extra_info_spec); | |
141 }; | |
142 | |
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); | |
147 ~EventResponse(); | |
148 | |
149 // ID of the extension that sent this response. | |
150 std::string extension_id; | |
151 | |
152 // The time that the extension was installed. Used for deciding order of | |
153 // precedence in case multiple extensions respond with conflicting | |
154 // decisions. | |
155 base::Time extension_install_time; | |
156 | |
157 // Response values. These are mutually exclusive. | |
158 bool cancel; | |
159 GURL new_url; | |
160 scoped_ptr<net::HttpRequestHeaders> request_headers; | |
161 scoped_ptr<extension_web_request_api_helpers::ResponseHeaders> | |
162 response_headers; | |
163 | |
164 scoped_ptr<net::AuthCredentials> auth_credentials; | |
165 | |
166 DISALLOW_COPY_AND_ASSIGN(EventResponse); | |
167 }; | |
168 | |
169 static ExtensionWebRequestEventRouter* GetInstance(); | |
170 | |
171 // Registers a rule registry. Pass null for |rules_registry| to unregister | |
172 // the rule registry for |browser_context|. | |
173 void RegisterRulesRegistry( | |
174 void* browser_context, | |
175 const extensions::RulesRegistry::WebViewKey& webview_key, | |
176 scoped_refptr<extensions::WebRequestRulesRegistry> rules_registry); | |
177 | |
178 // Dispatches the OnBeforeRequest event to any extensions whose filters match | |
179 // the given request. Returns net::ERR_IO_PENDING if an extension is | |
180 // intercepting the request, OK otherwise. | |
181 int OnBeforeRequest(void* browser_context, | |
182 extensions::InfoMap* extension_info_map, | |
183 net::URLRequest* request, | |
184 const net::CompletionCallback& callback, | |
185 GURL* new_url); | |
186 | |
187 // Dispatches the onBeforeSendHeaders event. This is fired for HTTP(s) | |
188 // requests only, and allows modification of the outgoing request headers. | |
189 // Returns net::ERR_IO_PENDING if an extension is intercepting the request, OK | |
190 // otherwise. | |
191 int OnBeforeSendHeaders(void* browser_context, | |
192 extensions::InfoMap* extension_info_map, | |
193 net::URLRequest* request, | |
194 const net::CompletionCallback& callback, | |
195 net::HttpRequestHeaders* headers); | |
196 | |
197 // Dispatches the onSendHeaders event. This is fired for HTTP(s) requests | |
198 // only. | |
199 void OnSendHeaders(void* browser_context, | |
200 extensions::InfoMap* extension_info_map, | |
201 net::URLRequest* request, | |
202 const net::HttpRequestHeaders& headers); | |
203 | |
204 // Dispatches the onHeadersReceived event. This is fired for HTTP(s) | |
205 // requests only, and allows modification of incoming response headers. | |
206 // Returns net::ERR_IO_PENDING if an extension is intercepting the request, | |
207 // OK otherwise. |original_response_headers| is reference counted. |callback| | |
208 // |override_response_headers| and |allowed_unsafe_redirect_url| are owned by | |
209 // a URLRequestJob. They are guaranteed to be valid until |callback| is called | |
210 // or OnURLRequestDestroyed is called (whatever comes first). | |
211 // Do not modify |original_response_headers| directly but write new ones | |
212 // into |override_response_headers|. | |
213 int OnHeadersReceived( | |
214 void* browser_context, | |
215 extensions::InfoMap* extension_info_map, | |
216 net::URLRequest* request, | |
217 const net::CompletionCallback& callback, | |
218 const net::HttpResponseHeaders* original_response_headers, | |
219 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, | |
220 GURL* allowed_unsafe_redirect_url); | |
221 | |
222 // Dispatches the OnAuthRequired event to any extensions whose filters match | |
223 // the given request. If the listener is not registered as "blocking", then | |
224 // AUTH_REQUIRED_RESPONSE_OK is returned. Otherwise, | |
225 // AUTH_REQUIRED_RESPONSE_IO_PENDING is returned and |callback| will be | |
226 // invoked later. | |
227 net::NetworkDelegate::AuthRequiredResponse OnAuthRequired( | |
228 void* browser_context, | |
229 extensions::InfoMap* extension_info_map, | |
230 net::URLRequest* request, | |
231 const net::AuthChallengeInfo& auth_info, | |
232 const net::NetworkDelegate::AuthCallback& callback, | |
233 net::AuthCredentials* credentials); | |
234 | |
235 // Dispatches the onBeforeRedirect event. This is fired for HTTP(s) requests | |
236 // only. | |
237 void OnBeforeRedirect(void* browser_context, | |
238 extensions::InfoMap* extension_info_map, | |
239 net::URLRequest* request, | |
240 const GURL& new_location); | |
241 | |
242 // Dispatches the onResponseStarted event indicating that the first bytes of | |
243 // the response have arrived. | |
244 void OnResponseStarted(void* browser_context, | |
245 extensions::InfoMap* extension_info_map, | |
246 net::URLRequest* request); | |
247 | |
248 // Dispatches the onComplete event. | |
249 void OnCompleted(void* browser_context, | |
250 extensions::InfoMap* extension_info_map, | |
251 net::URLRequest* request); | |
252 | |
253 // Dispatches an onErrorOccurred event. | |
254 void OnErrorOccurred(void* browser_context, | |
255 extensions::InfoMap* extension_info_map, | |
256 net::URLRequest* request, | |
257 bool started); | |
258 | |
259 // Notifications when objects are going away. | |
260 void OnURLRequestDestroyed(void* browser_context, net::URLRequest* request); | |
261 | |
262 // Called when an event listener handles a blocking event and responds. | |
263 void OnEventHandled( | |
264 void* browser_context, | |
265 const std::string& extension_id, | |
266 const std::string& event_name, | |
267 const std::string& sub_event_name, | |
268 uint64 request_id, | |
269 EventResponse* response); | |
270 | |
271 // Adds a listener to the given event. |event_name| specifies the event being | |
272 // listened to. |sub_event_name| is an internal event uniquely generated in | |
273 // the extension process to correspond to the given filter and | |
274 // extra_info_spec. It returns true on success, false on failure. | |
275 bool AddEventListener( | |
276 void* browser_context, | |
277 const std::string& extension_id, | |
278 const std::string& extension_name, | |
279 const std::string& event_name, | |
280 const std::string& sub_event_name, | |
281 const RequestFilter& filter, | |
282 int extra_info_spec, | |
283 int embedder_process_id, | |
284 int web_view_instance_id, | |
285 base::WeakPtr<IPC::Sender> ipc_sender); | |
286 | |
287 // Removes the listener for the given sub-event. | |
288 void RemoveEventListener( | |
289 void* browser_context, | |
290 const std::string& extension_id, | |
291 const std::string& sub_event_name); | |
292 | |
293 // Removes the listeners for a given <webview>. | |
294 void RemoveWebViewEventListeners( | |
295 void* browser_context, | |
296 const std::string& extension_id, | |
297 int embedder_process_id, | |
298 int web_view_instance_id); | |
299 | |
300 // Called when an incognito browser_context is created or destroyed. | |
301 void OnOTRBrowserContextCreated(void* original_browser_context, | |
302 void* otr_browser_context); | |
303 void OnOTRBrowserContextDestroyed(void* original_browser_context, | |
304 void* otr_browser_context); | |
305 | |
306 // Registers a |callback| that is executed when the next page load happens. | |
307 // The callback is then deleted. | |
308 void AddCallbackForPageLoad(const base::Closure& callback); | |
309 | |
310 private: | |
311 friend struct DefaultSingletonTraits<ExtensionWebRequestEventRouter>; | |
312 | |
313 struct EventListener; | |
314 typedef std::map<std::string, std::set<EventListener> > | |
315 ListenerMapForBrowserContext; | |
316 typedef std::map<void*, ListenerMapForBrowserContext> ListenerMap; | |
317 typedef std::map<uint64, BlockedRequest> BlockedRequestMap; | |
318 // Map of request_id -> bit vector of EventTypes already signaled | |
319 typedef std::map<uint64, int> SignaledRequestMap; | |
320 // For each browser_context: a bool indicating whether it is an incognito | |
321 // browser_context, and a pointer to the corresponding (non-)incognito | |
322 // browser_context. | |
323 typedef std::map<void*, std::pair<bool, void*> > CrossBrowserContextMap; | |
324 typedef std::list<base::Closure> CallbacksForPageLoad; | |
325 | |
326 ExtensionWebRequestEventRouter(); | |
327 ~ExtensionWebRequestEventRouter(); | |
328 | |
329 // Ensures that future callbacks for |request| are ignored so that it can be | |
330 // destroyed safely. | |
331 void ClearPendingCallbacks(net::URLRequest* request); | |
332 | |
333 bool DispatchEvent( | |
334 void* browser_context, | |
335 net::URLRequest* request, | |
336 const std::vector<const EventListener*>& listeners, | |
337 const base::ListValue& args); | |
338 | |
339 // Returns a list of event listeners that care about the given event, based | |
340 // on their filter parameters. |extra_info_spec| will contain the combined | |
341 // set of extra_info_spec flags that every matching listener asked for. | |
342 std::vector<const EventListener*> GetMatchingListeners( | |
343 void* browser_context, | |
344 extensions::InfoMap* extension_info_map, | |
345 const std::string& event_name, | |
346 net::URLRequest* request, | |
347 int* extra_info_spec); | |
348 | |
349 // Helper for the above functions. This is called twice: once for the | |
350 // browser_context of the event, the next time for the "cross" browser_context | |
351 // (i.e. the incognito browser_context if the event is originally for the | |
352 // normal browser_context, or vice versa). | |
353 void GetMatchingListenersImpl( | |
354 void* browser_context, | |
355 net::URLRequest* request, | |
356 extensions::InfoMap* extension_info_map, | |
357 bool crosses_incognito, | |
358 const std::string& event_name, | |
359 const GURL& url, | |
360 int render_process_host_id, | |
361 int routing_id, | |
362 content::ResourceType resource_type, | |
363 bool is_async_request, | |
364 bool is_request_from_extension, | |
365 int* extra_info_spec, | |
366 std::vector<const ExtensionWebRequestEventRouter::EventListener*>* | |
367 matching_listeners); | |
368 | |
369 // Decrements the count of event handlers blocking the given request. When the | |
370 // count reaches 0, we stop blocking the request and proceed it using the | |
371 // method requested by the extension with the highest precedence. Precedence | |
372 // is decided by extension install time. If |response| is non-NULL, this | |
373 // method assumes ownership. | |
374 void DecrementBlockCount( | |
375 void* browser_context, | |
376 const std::string& extension_id, | |
377 const std::string& event_name, | |
378 uint64 request_id, | |
379 EventResponse* response); | |
380 | |
381 // Logs an extension action. | |
382 void LogExtensionActivity( | |
383 void* browser_context_id, | |
384 bool is_incognito, | |
385 const std::string& extension_id, | |
386 const GURL& url, | |
387 const std::string& api_call, | |
388 scoped_ptr<base::DictionaryValue> details); | |
389 | |
390 // Processes the generated deltas from blocked_requests_ on the specified | |
391 // request. If |call_back| is true, the callback registered in | |
392 // |blocked_requests_| is called. | |
393 // The function returns the error code for the network request. This is | |
394 // mostly relevant in case the caller passes |call_callback| = false | |
395 // and wants to return the correct network error code himself. | |
396 int ExecuteDeltas( | |
397 void* browser_context, uint64 request_id, bool call_callback); | |
398 | |
399 // Evaluates the rules of the declarative webrequest API and stores | |
400 // modifications to the request that result from WebRequestActions as | |
401 // deltas in |blocked_requests_|. |original_response_headers| should only be | |
402 // set for the OnHeadersReceived stage and NULL otherwise. Returns whether any | |
403 // deltas were generated. | |
404 bool ProcessDeclarativeRules( | |
405 void* browser_context, | |
406 extensions::InfoMap* extension_info_map, | |
407 const std::string& event_name, | |
408 net::URLRequest* request, | |
409 extensions::RequestStage request_stage, | |
410 const net::HttpResponseHeaders* original_response_headers); | |
411 | |
412 // If the BlockedRequest contains messages_to_extension entries in the event | |
413 // deltas, we send them to subscribers of | |
414 // chrome.declarativeWebRequest.onMessage. | |
415 void SendMessages( | |
416 void* browser_context, const BlockedRequest& blocked_request); | |
417 | |
418 // Called when the RulesRegistry is ready to unblock a request that was | |
419 // waiting for said event. | |
420 void OnRulesRegistryReady( | |
421 void* browser_context, | |
422 const std::string& event_name, | |
423 uint64 request_id, | |
424 extensions::RequestStage request_stage); | |
425 | |
426 // Extracts from |request| information for the keys requestId, url, method, | |
427 // frameId, tabId, type, and timeStamp and writes these into |out| to be | |
428 // passed on to extensions. | |
429 void ExtractRequestInfo(net::URLRequest* request, base::DictionaryValue* out); | |
430 | |
431 // Sets the flag that |event_type| has been signaled for |request_id|. | |
432 // Returns the value of the flag before setting it. | |
433 bool GetAndSetSignaled(uint64 request_id, EventTypes event_type); | |
434 | |
435 // Clears the flag that |event_type| has been signaled for |request_id|. | |
436 void ClearSignaled(uint64 request_id, EventTypes event_type); | |
437 | |
438 // Returns whether |request| represents a top level window navigation. | |
439 bool IsPageLoad(net::URLRequest* request) const; | |
440 | |
441 // Called on a page load to process all registered callbacks. | |
442 void NotifyPageLoad(); | |
443 | |
444 // Returns the matching cross browser_context (the regular browser_context if | |
445 // |browser_context| is OTR and vice versa). | |
446 void* GetCrossBrowserContext(void* browser_context) const; | |
447 | |
448 // Determines whether the specified browser_context is an incognito | |
449 // browser_context (based on the contents of the cross-browser_context table | |
450 // and without dereferencing the browser_context pointer). | |
451 bool IsIncognitoBrowserContext(void* browser_context) const; | |
452 | |
453 // Returns true if |request| was already signaled to some event handlers. | |
454 bool WasSignaled(const net::URLRequest& request) const; | |
455 | |
456 // A map for each browser_context that maps an event name to a set of | |
457 // extensions that are listening to that event. | |
458 ListenerMap listeners_; | |
459 | |
460 // A map of network requests that are waiting for at least one event handler | |
461 // to respond. | |
462 BlockedRequestMap blocked_requests_; | |
463 | |
464 // A map of request ids to a bitvector indicating which events have been | |
465 // signaled and should not be sent again. | |
466 SignaledRequestMap signaled_requests_; | |
467 | |
468 // A map of original browser_context -> corresponding incognito | |
469 // browser_context (and vice versa). | |
470 CrossBrowserContextMap cross_browser_context_map_; | |
471 | |
472 // Keeps track of time spent waiting on extensions using the blocking | |
473 // webRequest API. | |
474 scoped_ptr<ExtensionWebRequestTimeTracker> request_time_tracker_; | |
475 | |
476 CallbacksForPageLoad callbacks_for_page_load_; | |
477 | |
478 typedef std::pair<void*, extensions::RulesRegistry::WebViewKey> | |
479 RulesRegistryKey; | |
480 // Maps each browser_context (and OTRBrowserContext) and a webview key to its | |
481 // respective rules registry. | |
482 std::map<RulesRegistryKey, | |
483 scoped_refptr<extensions::WebRequestRulesRegistry> > rules_registries_; | |
484 | |
485 scoped_ptr<extensions::WebRequestEventRouterDelegate> | |
486 web_request_event_router_delegate_; | |
487 | |
488 DISALLOW_COPY_AND_ASSIGN(ExtensionWebRequestEventRouter); | |
489 }; | |
490 | |
491 class WebRequestInternalAddEventListenerFunction | |
492 : public SyncIOThreadExtensionFunction { | |
493 public: | |
494 DECLARE_EXTENSION_FUNCTION("webRequestInternal.addEventListener", | |
495 WEBREQUESTINTERNAL_ADDEVENTLISTENER) | |
496 | |
497 protected: | |
498 virtual ~WebRequestInternalAddEventListenerFunction() {} | |
499 | |
500 // ExtensionFunction: | |
501 virtual bool RunSync() OVERRIDE; | |
502 }; | |
503 | |
504 class WebRequestInternalEventHandledFunction | |
505 : public SyncIOThreadExtensionFunction { | |
506 public: | |
507 DECLARE_EXTENSION_FUNCTION("webRequestInternal.eventHandled", | |
508 WEBREQUESTINTERNAL_EVENTHANDLED) | |
509 | |
510 protected: | |
511 virtual ~WebRequestInternalEventHandledFunction() {} | |
512 | |
513 // Unblocks the network request and sets |error_| such that the developer | |
514 // console will show the respective error message. Use this function to handle | |
515 // incorrect requests from the extension that cannot be detected by the schema | |
516 // validator. | |
517 void RespondWithError( | |
518 const std::string& event_name, | |
519 const std::string& sub_event_name, | |
520 uint64 request_id, | |
521 scoped_ptr<ExtensionWebRequestEventRouter::EventResponse> response, | |
522 const std::string& error); | |
523 | |
524 // ExtensionFunction: | |
525 virtual bool RunSync() OVERRIDE; | |
526 }; | |
527 | |
528 class WebRequestHandlerBehaviorChangedFunction | |
529 : public SyncIOThreadExtensionFunction { | |
530 public: | |
531 DECLARE_EXTENSION_FUNCTION("webRequest.handlerBehaviorChanged", | |
532 WEBREQUEST_HANDLERBEHAVIORCHANGED) | |
533 | |
534 protected: | |
535 virtual ~WebRequestHandlerBehaviorChangedFunction() {} | |
536 | |
537 // ExtensionFunction: | |
538 virtual void GetQuotaLimitHeuristics( | |
539 extensions::QuotaLimitHeuristics* heuristics) const OVERRIDE; | |
540 // Handle quota exceeded gracefully: Only warn the user but still execute the | |
541 // function. | |
542 virtual void OnQuotaExceeded(const std::string& error) OVERRIDE; | |
543 virtual bool RunSync() OVERRIDE; | |
544 }; | |
545 | |
546 #endif // CHROME_BROWSER_EXTENSIONS_API_WEB_REQUEST_WEB_REQUEST_API_H_ | |
OLD | NEW |