Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: chrome/browser/extensions/extension_webrequest_api.cc

Issue 6698009: Add request_id to HttpRequestInfo and pass it to the NetworkDelegate for events. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: delegate callbcak Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/extension_webrequest_api.h" 5 #include "chrome/browser/extensions/extension_webrequest_api.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/string_number_conversions.h" 11 #include "base/string_number_conversions.h"
12 #include "base/values.h" 12 #include "base/values.h"
13 #include "chrome/browser/extensions/extension_event_router_forwarder.h" 13 #include "chrome/browser/extensions/extension_event_router_forwarder.h"
14 #include "chrome/browser/extensions/extension_webrequest_api_constants.h" 14 #include "chrome/browser/extensions/extension_webrequest_api_constants.h"
15 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/extensions/extension.h" 16 #include "chrome/common/extensions/extension.h"
17 #include "chrome/common/extensions/extension_extent.h" 17 #include "chrome/common/extensions/extension_extent.h"
18 #include "chrome/common/extensions/url_pattern.h" 18 #include "chrome/common/extensions/url_pattern.h"
19 #include "chrome/common/url_constants.h"
19 #include "content/browser/browser_thread.h" 20 #include "content/browser/browser_thread.h"
20 #include "net/base/net_errors.h" 21 #include "net/base/net_errors.h"
21 #include "net/url_request/url_request.h" 22 #include "net/url_request/url_request.h"
22 #include "googleurl/src/gurl.h" 23 #include "googleurl/src/gurl.h"
23 24
24 namespace keys = extension_webrequest_api_constants; 25 namespace keys = extension_webrequest_api_constants;
25 26
26 namespace { 27 namespace {
27 28
28 // List of all the webRequest events. 29 // List of all the webRequest events.
29 static const char *kWebRequestEvents[] = { 30 static const char *kWebRequestEvents[] = {
30 keys::kOnBeforeRedirect, 31 keys::kOnBeforeRedirect,
31 keys::kOnBeforeRequest, 32 keys::kOnBeforeRequest,
33 keys::kOnBeforeSendHeaders,
32 keys::kOnCompleted, 34 keys::kOnCompleted,
33 keys::kOnErrorOccurred, 35 keys::kOnErrorOccurred,
34 keys::kOnHeadersReceived, 36 keys::kOnHeadersReceived,
35 keys::kOnRequestSent 37 keys::kOnRequestSent
36 }; 38 };
37 39
38 // TODO(mpcomplete): should this be a set of flags? 40 // TODO(mpcomplete): should this be a set of flags?
39 static const char* kRequestFilterTypes[] = { 41 static const char* kRequestFilterTypes[] = {
40 "main_frame", 42 "main_frame",
41 "sub_frame", 43 "sub_frame",
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 // Internal representation of the extraInfoSpec parameter on webRequest events, 101 // Internal representation of the extraInfoSpec parameter on webRequest events,
100 // used to specify extra information to be included with network events. 102 // used to specify extra information to be included with network events.
101 struct ExtensionWebRequestEventRouter::ExtraInfoSpec { 103 struct ExtensionWebRequestEventRouter::ExtraInfoSpec {
102 enum Flags { 104 enum Flags {
103 REQUEST_LINE = 1<<0, 105 REQUEST_LINE = 1<<0,
104 REQUEST_HEADERS = 1<<1, 106 REQUEST_HEADERS = 1<<1,
105 STATUS_LINE = 1<<2, 107 STATUS_LINE = 1<<2,
106 RESPONSE_HEADERS = 1<<3, 108 RESPONSE_HEADERS = 1<<3,
107 REDIRECT_REQUEST_LINE = 1<<4, 109 REDIRECT_REQUEST_LINE = 1<<4,
108 REDIRECT_REQUEST_HEADERS = 1<<5, 110 REDIRECT_REQUEST_HEADERS = 1<<5,
109 BLOCKING = 1<<5, 111 BLOCKING = 1<<6,
110 }; 112 };
111 113
112 static bool InitFromValue(const ListValue& value, int* extra_info_spec); 114 static bool InitFromValue(const ListValue& value, int* extra_info_spec);
113 }; 115 };
114 116
115 // Represents a single unique listener to an event, along with whatever filter 117 // Represents a single unique listener to an event, along with whatever filter
116 // parameters and extra_info_spec were specified at the time the listener was 118 // parameters and extra_info_spec were specified at the time the listener was
117 // added. 119 // added.
118 struct ExtensionWebRequestEventRouter::EventListener { 120 struct ExtensionWebRequestEventRouter::EventListener {
119 std::string extension_id; 121 std::string extension_id;
(...skipping 21 matching lines...) Expand all
141 143
142 // The callback to call when we get a response from all event handlers. 144 // The callback to call when we get a response from all event handlers.
143 net::CompletionCallback* callback; 145 net::CompletionCallback* callback;
144 146
145 // Time the request was issued. Used for logging purposes. 147 // Time the request was issued. Used for logging purposes.
146 base::Time request_time; 148 base::Time request_time;
147 149
148 BlockedRequest() : num_handlers_blocking(0), callback(NULL) {} 150 BlockedRequest() : num_handlers_blocking(0), callback(NULL) {}
149 }; 151 };
150 152
153 // We use this class as UserData on any URLRequests that we are tracking. This
willchan no longer on Chromium 2011/03/22 23:05:35 Why is this simpler than adding a cancellation API
Matt Perry 2011/03/24 00:11:25 It isn't... I guess I'll do that then :).
154 // lets us know when the URLRequest is deleted, so we can remove it from our
155 // tracked list.
156 class ExtensionWebRequestEventRouter::TrackedRequest
157 : public net::URLRequest::UserData {
158 public:
159 TrackedRequest(net::URLRequest* request,
160 ExtensionWebRequestEventRouter* router)
161 : router_(router), request_(request) {
162 request->SetUserData(router_, this);
163 }
164 virtual ~TrackedRequest() {
165 if (router_)
166 router_->OnRequestDeleted(request_);
167 }
168
169 void StopTracking() {
170 ExtensionWebRequestEventRouter* key = router_;
171 router_ = NULL;
172 request_->SetUserData(key, NULL); // deletes |this|
173 }
174
175 net::URLRequest* request() const { return request_; }
176
177 private:
178 ExtensionWebRequestEventRouter* router_;
179 net::URLRequest* request_;
180 };
181
151 bool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue( 182 bool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue(
152 const DictionaryValue& value) { 183 const DictionaryValue& value) {
153 for (DictionaryValue::key_iterator key = value.begin_keys(); 184 for (DictionaryValue::key_iterator key = value.begin_keys();
154 key != value.end_keys(); ++key) { 185 key != value.end_keys(); ++key) {
155 if (*key == "urls") { 186 if (*key == "urls") {
156 ListValue* urls_value = NULL; 187 ListValue* urls_value = NULL;
157 if (!value.GetList("urls", &urls_value)) 188 if (!value.GetList("urls", &urls_value))
158 return false; 189 return false;
159 for (size_t i = 0; i < urls_value->GetSize(); ++i) { 190 for (size_t i = 0; i < urls_value->GetSize(); ++i) {
160 std::string url; 191 std::string url;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 252
222 // static 253 // static
223 ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() { 254 ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() {
224 return Singleton<ExtensionWebRequestEventRouter>::get(); 255 return Singleton<ExtensionWebRequestEventRouter>::get();
225 } 256 }
226 257
227 ExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter() { 258 ExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter() {
228 } 259 }
229 260
230 ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() { 261 ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() {
262 for (HttpRequestMap::iterator it = http_requests_.begin();
263 it != http_requests_.end(); ++it) {
264 it->second->StopTracking(); // deletes the object
265 }
231 } 266 }
232 267
233 bool ExtensionWebRequestEventRouter::OnBeforeRequest( 268 bool ExtensionWebRequestEventRouter::OnBeforeRequest(
234 ProfileId profile_id, 269 ProfileId profile_id,
235 ExtensionEventRouterForwarder* event_router, 270 ExtensionEventRouterForwarder* event_router,
236 net::URLRequest* request, 271 net::URLRequest* request,
237 net::CompletionCallback* callback) { 272 net::CompletionCallback* callback) {
238 // TODO(jochen): Figure out what to do with events from the system context. 273 // TODO(jochen): Figure out what to do with events from the system context.
239 if (profile_id == Profile::kInvalidProfileId) 274 if (profile_id == Profile::kInvalidProfileId)
240 return false; 275 return false;
241 std::vector<const EventListener*> listeners = 276 std::vector<const EventListener*> listeners =
242 GetMatchingListeners(profile_id, keys::kOnBeforeRequest, request->url()); 277 GetMatchingListeners(profile_id, keys::kOnBeforeRequest, request->url());
243 if (listeners.empty()) 278 if (listeners.empty())
244 return false; 279 return false;
245 280
281 // If this is an HTTP request, keep track of it. HTTP-specific events only
282 // have the request ID, so we'll need to look up the URLRequest from that.
283 if (request->url().SchemeIs(chrome::kHttpScheme) ||
284 request->url().SchemeIs(chrome::kHttpsScheme)) {
285 http_requests_[request->identifier()] = new TrackedRequest(request, this);
286 }
287
246 ListValue args; 288 ListValue args;
247 DictionaryValue* dict = new DictionaryValue(); 289 DictionaryValue* dict = new DictionaryValue();
248 dict->SetString(keys::kUrlKey, request->url().spec()); 290 dict->SetString(keys::kUrlKey, request->url().spec());
249 dict->SetString(keys::kMethodKey, request->method()); 291 dict->SetString(keys::kMethodKey, request->method());
250 // TODO(mpcomplete): implement 292 // TODO(mpcomplete): implement
251 dict->SetInteger(keys::kTabIdKey, 0); 293 dict->SetInteger(keys::kTabIdKey, 0);
252 dict->SetString(keys::kRequestIdKey, 294 dict->SetString(keys::kRequestIdKey,
253 base::Uint64ToString(request->identifier())); 295 base::Uint64ToString(request->identifier()));
254 dict->SetString(keys::kTypeKey, "main_frame"); 296 dict->SetString(keys::kTypeKey, "main_frame");
255 dict->SetInteger(keys::kTimeStampKey, 1); 297 dict->SetInteger(keys::kTimeStampKey, 1);
256 args.Append(dict); 298 args.Append(dict);
257 299
300 return DispatchEvent(profile_id, event_router, request, callback, listeners,
301 args);
302 }
303
304 bool ExtensionWebRequestEventRouter::OnBeforeSendHeaders(
305 ProfileId profile_id,
306 ExtensionEventRouterForwarder* event_router,
307 uint64 request_id,
308 net::HttpRequestHeaders* headers,
309 net::CompletionCallback* callback) {
310 // TODO(jochen): Figure out what to do with events from the system context.
311 if (profile_id == Profile::kInvalidProfileId)
312 return false;
313
314 HttpRequestMap::iterator iter = http_requests_.find(request_id);
315 if (iter == http_requests_.end())
316 return false;
317
318 net::URLRequest* request = iter->second->request();
319 iter->second->StopTracking();
320 http_requests_.erase(iter);
321
322 std::vector<const EventListener*> listeners =
323 GetMatchingListeners(profile_id, keys::kOnBeforeSendHeaders, request);
324 if (listeners.empty())
325 return false;
326
327 ListValue args;
328 DictionaryValue* dict = new DictionaryValue();
329 dict->SetString(keys::kRequestIdKey,
330 base::Uint64ToString(request->identifier()));
331 dict->SetString(keys::kUrlKey, request->url().spec());
332 dict->SetDouble(keys::kTimeStampKey, base::Time::Now().ToDoubleT() * 1000);
333 // TODO(mpcomplete): request headers.
334 args.Append(dict);
335
336 return DispatchEvent(profile_id, event_router, request, callback, listeners,
337 args);
338 }
339
340 bool ExtensionWebRequestEventRouter::DispatchEvent(
341 ProfileId profile_id,
342 ExtensionEventRouterForwarder* event_router,
343 net::URLRequest* request,
344 net::CompletionCallback* callback,
345 const std::vector<const EventListener*>& listeners,
346 const ListValue& args) {
258 std::string json_args; 347 std::string json_args;
259 base::JSONWriter::Write(&args, false, &json_args); 348 base::JSONWriter::Write(&args, false, &json_args);
260 349
261 // TODO(mpcomplete): Consider consolidating common (extension_id,json_args) 350 // TODO(mpcomplete): Consider consolidating common (extension_id,json_args)
262 // pairs into a single message sent to a list of sub_event_names. 351 // pairs into a single message sent to a list of sub_event_names.
263 int num_handlers_blocking = 0; 352 int num_handlers_blocking = 0;
264 for (std::vector<const EventListener*>::iterator it = listeners.begin(); 353 for (std::vector<const EventListener*>::const_iterator it = listeners.begin();
265 it != listeners.end(); ++it) { 354 it != listeners.end(); ++it) {
266 event_router->DispatchEventToExtension( 355 event_router->DispatchEventToExtension(
267 (*it)->extension_id, (*it)->sub_event_name, json_args, 356 (*it)->extension_id, (*it)->sub_event_name, json_args,
268 profile_id, true, GURL()); 357 profile_id, true, GURL());
269 if ((*it)->extra_info_spec & ExtraInfoSpec::BLOCKING) { 358 if (callback && (*it)->extra_info_spec & ExtraInfoSpec::BLOCKING) {
270 (*it)->blocked_requests.insert(request->identifier()); 359 (*it)->blocked_requests.insert(request->identifier());
271 ++num_handlers_blocking; 360 ++num_handlers_blocking;
272 } 361 }
273 } 362 }
274 363
275 if (num_handlers_blocking > 0) { 364 if (num_handlers_blocking > 0) {
276 CHECK(blocked_requests_.find(request->identifier()) == 365 CHECK(blocked_requests_.find(request->identifier()) ==
277 blocked_requests_.end()); 366 blocked_requests_.end());
278 blocked_requests_[request->identifier()].num_handlers_blocking = 367 blocked_requests_[request->identifier()].num_handlers_blocking =
279 num_handlers_blocking; 368 num_handlers_blocking;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 std::vector<const EventListener*> matching_listeners; 456 std::vector<const EventListener*> matching_listeners;
368 std::set<EventListener>& listeners = listeners_[profile_id][event_name]; 457 std::set<EventListener>& listeners = listeners_[profile_id][event_name];
369 for (std::set<EventListener>::iterator it = listeners.begin(); 458 for (std::set<EventListener>::iterator it = listeners.begin();
370 it != listeners.end(); ++it) { 459 it != listeners.end(); ++it) {
371 if (it->filter.urls.is_empty() || it->filter.urls.ContainsURL(url)) 460 if (it->filter.urls.is_empty() || it->filter.urls.ContainsURL(url))
372 matching_listeners.push_back(&(*it)); 461 matching_listeners.push_back(&(*it));
373 } 462 }
374 return matching_listeners; 463 return matching_listeners;
375 } 464 }
376 465
466 std::vector<const ExtensionWebRequestEventRouter::EventListener*>
467 ExtensionWebRequestEventRouter::GetMatchingListeners(
468 ProfileId profile_id,
469 const std::string& event_name,
470 net::URLRequest* request) {
471 int tab_id = -1;
472 int window_id = -1;
473 ResourceType::Type resource_type = ResourceType::LAST_TYPE;
474 ExtractRequestInfo(request, &tab_id, &window_id, &resource_type);
475
476 return GetMatchingListeners(
477 profile_id, event_name, request->url(), tab_id, window_id, resource_type);
478 }
479
377 void ExtensionWebRequestEventRouter::DecrementBlockCount(uint64 request_id, 480 void ExtensionWebRequestEventRouter::DecrementBlockCount(uint64 request_id,
378 bool cancel) { 481 bool cancel) {
379 // It's possible that this request was already cancelled by a previous event 482 // It's possible that this request was already cancelled by a previous event
380 // handler. If so, ignore this response. 483 // handler. If so, ignore this response.
381 if (blocked_requests_.find(request_id) == blocked_requests_.end()) 484 if (blocked_requests_.find(request_id) == blocked_requests_.end())
382 return; 485 return;
383 486
384 BlockedRequest& blocked_request = blocked_requests_[request_id]; 487 BlockedRequest& blocked_request = blocked_requests_[request_id];
385 int num_handlers_blocking = --blocked_request.num_handlers_blocking; 488 int num_handlers_blocking = --blocked_request.num_handlers_blocking;
386 CHECK_GE(num_handlers_blocking, 0); 489 CHECK_GE(num_handlers_blocking, 0);
387 490
388 HISTOGRAM_TIMES("Extensions.NetworkDelay", 491 HISTOGRAM_TIMES("Extensions.NetworkDelay",
389 base::Time::Now() - blocked_request.request_time); 492 base::Time::Now() - blocked_request.request_time);
390 493
391 if (num_handlers_blocking == 0 || cancel) { 494 if (num_handlers_blocking == 0 || cancel) {
392 CHECK(blocked_request.callback); 495 CHECK(blocked_request.callback);
393 blocked_request.callback->Run(cancel ? net::ERR_EMPTY_RESPONSE : net::OK); 496 blocked_request.callback->Run(cancel ? net::ERR_EMPTY_RESPONSE : net::OK);
394 blocked_requests_.erase(request_id); 497 blocked_requests_.erase(request_id);
395 } 498 }
396 } 499 }
397 500
501 void ExtensionWebRequestEventRouter::OnRequestDeleted(
502 net::URLRequest* request) {
503 http_requests_.erase(request->identifier());
504 }
505
398 bool WebRequestAddEventListener::RunImpl() { 506 bool WebRequestAddEventListener::RunImpl() {
399 // Argument 0 is the callback, which we don't use here. 507 // Argument 0 is the callback, which we don't use here.
400 508
401 ExtensionWebRequestEventRouter::RequestFilter filter; 509 ExtensionWebRequestEventRouter::RequestFilter filter;
402 if (HasOptionalArgument(1)) { 510 if (HasOptionalArgument(1)) {
403 DictionaryValue* value = NULL; 511 DictionaryValue* value = NULL;
404 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &value)); 512 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &value));
405 EXTENSION_FUNCTION_VALIDATE(filter.InitFromValue(*value)); 513 EXTENSION_FUNCTION_VALIDATE(filter.InitFromValue(*value));
406 } 514 }
407 515
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 562
455 BrowserThread::PostTask( 563 BrowserThread::PostTask(
456 BrowserThread::IO, FROM_HERE, 564 BrowserThread::IO, FROM_HERE,
457 NewRunnableFunction( 565 NewRunnableFunction(
458 &EventHandledOnIOThread, 566 &EventHandledOnIOThread,
459 profile()->GetRuntimeId(), extension_id(), 567 profile()->GetRuntimeId(), extension_id(),
460 event_name, sub_event_name, request_id, cancel)); 568 event_name, sub_event_name, request_id, cancel));
461 569
462 return true; 570 return true;
463 } 571 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698