OLD | NEW |
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/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
13 #include "base/values.h" | 13 #include "base/values.h" |
14 #include "chrome/browser/extensions/extension_event_router.h" | 14 #include "chrome/browser/extensions/extension_event_router.h" |
15 #include "chrome/browser/extensions/extension_info_map.h" | 15 #include "chrome/browser/extensions/extension_info_map.h" |
16 #include "chrome/browser/extensions/extension_prefs.h" | 16 #include "chrome/browser/extensions/extension_prefs.h" |
17 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
18 #include "chrome/browser/extensions/extension_tab_id_map.h" | 18 #include "chrome/browser/extensions/extension_tab_id_map.h" |
19 #include "chrome/browser/extensions/extension_webrequest_api_constants.h" | 19 #include "chrome/browser/extensions/extension_webrequest_api_constants.h" |
| 20 #include "chrome/browser/extensions/extension_webrequest_time_tracker.h" |
20 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
21 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" | 22 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" |
22 #include "chrome/common/extensions/extension.h" | 23 #include "chrome/common/extensions/extension.h" |
23 #include "chrome/common/extensions/extension_error_utils.h" | 24 #include "chrome/common/extensions/extension_error_utils.h" |
24 #include "chrome/common/extensions/url_pattern.h" | 25 #include "chrome/common/extensions/url_pattern.h" |
25 #include "chrome/common/url_constants.h" | 26 #include "chrome/common/url_constants.h" |
26 #include "content/browser/browser_message_filter.h" | 27 #include "content/browser/browser_message_filter.h" |
27 #include "content/browser/browser_thread.h" | 28 #include "content/browser/browser_thread.h" |
28 #include "content/browser/renderer_host/resource_dispatcher_host.h" | 29 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
29 #include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" | 30 #include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 // static | 425 // static |
425 void ExtensionWebRequestEventRouter::SetAllowChromeExtensionScheme() { | 426 void ExtensionWebRequestEventRouter::SetAllowChromeExtensionScheme() { |
426 allow_extension_scheme = true; | 427 allow_extension_scheme = true; |
427 } | 428 } |
428 | 429 |
429 // static | 430 // static |
430 ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() { | 431 ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() { |
431 return Singleton<ExtensionWebRequestEventRouter>::get(); | 432 return Singleton<ExtensionWebRequestEventRouter>::get(); |
432 } | 433 } |
433 | 434 |
434 ExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter() { | 435 ExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter() |
| 436 : request_time_tracker_(new ExtensionWebRequestTimeTracker) { |
435 } | 437 } |
436 | 438 |
437 ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() { | 439 ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() { |
438 } | 440 } |
439 | 441 |
440 int ExtensionWebRequestEventRouter::OnBeforeRequest( | 442 int ExtensionWebRequestEventRouter::OnBeforeRequest( |
441 void* profile, | 443 void* profile, |
442 ExtensionInfoMap* extension_info_map, | 444 ExtensionInfoMap* extension_info_map, |
443 net::URLRequest* request, | 445 net::URLRequest* request, |
444 net::CompletionCallback* callback, | 446 net::CompletionCallback* callback, |
445 GURL* new_url) { | 447 GURL* new_url) { |
446 // TODO(jochen): Figure out what to do with events from the system context. | 448 // TODO(jochen): Figure out what to do with events from the system context. |
447 if (!profile) | 449 if (!profile) |
448 return net::OK; | 450 return net::OK; |
449 | 451 |
450 if (!HasWebRequestScheme(request->url())) | 452 if (!HasWebRequestScheme(request->url())) |
451 return net::OK; | 453 return net::OK; |
452 | 454 |
| 455 request_time_tracker_->LogRequestStartTime(request->identifier(), |
| 456 base::Time::Now(), |
| 457 request->url()); |
| 458 |
453 bool is_main_frame = false; | 459 bool is_main_frame = false; |
454 int64 frame_id = -1; | 460 int64 frame_id = -1; |
455 int frame_id_for_extension = -1; | 461 int frame_id_for_extension = -1; |
456 int tab_id = -1; | 462 int tab_id = -1; |
457 int window_id = -1; | 463 int window_id = -1; |
458 ResourceType::Type resource_type = ResourceType::LAST_TYPE; | 464 ResourceType::Type resource_type = ResourceType::LAST_TYPE; |
459 ExtractRequestInfo(request, &is_main_frame, &frame_id, &tab_id, &window_id, | 465 ExtractRequestInfo(request, &is_main_frame, &frame_id, &tab_id, &window_id, |
460 &resource_type); | 466 &resource_type); |
461 frame_id_for_extension = GetFrameId(is_main_frame, frame_id); | 467 frame_id_for_extension = GetFrameId(is_main_frame, frame_id); |
462 | 468 |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 void ExtensionWebRequestEventRouter::OnCompleted( | 733 void ExtensionWebRequestEventRouter::OnCompleted( |
728 void* profile, | 734 void* profile, |
729 ExtensionInfoMap* extension_info_map, | 735 ExtensionInfoMap* extension_info_map, |
730 net::URLRequest* request) { | 736 net::URLRequest* request) { |
731 if (!profile) | 737 if (!profile) |
732 return; | 738 return; |
733 | 739 |
734 if (!HasWebRequestScheme(request->url())) | 740 if (!HasWebRequestScheme(request->url())) |
735 return; | 741 return; |
736 | 742 |
| 743 request_time_tracker_->LogRequestEndTime(request->identifier(), |
| 744 base::Time::Now()); |
| 745 |
737 DCHECK(request->status().status() == net::URLRequestStatus::SUCCESS); | 746 DCHECK(request->status().status() == net::URLRequestStatus::SUCCESS); |
738 | 747 |
739 DCHECK(!GetAndSetSignaled(request->identifier(), kOnCompleted)); | 748 DCHECK(!GetAndSetSignaled(request->identifier(), kOnCompleted)); |
740 | 749 |
741 base::Time time(base::Time::Now()); | 750 base::Time time(base::Time::Now()); |
742 | 751 |
743 int extra_info_spec = 0; | 752 int extra_info_spec = 0; |
744 std::vector<const EventListener*> listeners = | 753 std::vector<const EventListener*> listeners = |
745 GetMatchingListeners(profile, extension_info_map, | 754 GetMatchingListeners(profile, extension_info_map, |
746 keys::kOnCompleted, request, &extra_info_spec); | 755 keys::kOnCompleted, request, &extra_info_spec); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 void ExtensionWebRequestEventRouter::OnErrorOccurred( | 787 void ExtensionWebRequestEventRouter::OnErrorOccurred( |
779 void* profile, | 788 void* profile, |
780 ExtensionInfoMap* extension_info_map, | 789 ExtensionInfoMap* extension_info_map, |
781 net::URLRequest* request) { | 790 net::URLRequest* request) { |
782 if (!profile) | 791 if (!profile) |
783 return; | 792 return; |
784 | 793 |
785 if (!HasWebRequestScheme(request->url())) | 794 if (!HasWebRequestScheme(request->url())) |
786 return; | 795 return; |
787 | 796 |
| 797 request_time_tracker_->LogRequestEndTime(request->identifier(), |
| 798 base::Time::Now()); |
| 799 |
788 DCHECK(request->status().status() == net::URLRequestStatus::FAILED || | 800 DCHECK(request->status().status() == net::URLRequestStatus::FAILED || |
789 request->status().status() == net::URLRequestStatus::CANCELED); | 801 request->status().status() == net::URLRequestStatus::CANCELED); |
790 | 802 |
791 DCHECK(!GetAndSetSignaled(request->identifier(), kOnErrorOccurred)); | 803 DCHECK(!GetAndSetSignaled(request->identifier(), kOnErrorOccurred)); |
792 | 804 |
793 base::Time time(base::Time::Now()); | 805 base::Time time(base::Time::Now()); |
794 | 806 |
795 int extra_info_spec = 0; | 807 int extra_info_spec = 0; |
796 std::vector<const EventListener*> listeners = | 808 std::vector<const EventListener*> listeners = |
797 GetMatchingListeners(profile, extension_info_map, | 809 GetMatchingListeners(profile, extension_info_map, |
(...skipping 16 matching lines...) Expand all Loading... |
814 dict->SetDouble(keys::kTimeStampKey, time.ToDoubleT() * 1000); | 826 dict->SetDouble(keys::kTimeStampKey, time.ToDoubleT() * 1000); |
815 args.Append(dict); | 827 args.Append(dict); |
816 | 828 |
817 DispatchEvent(profile, request, listeners, args); | 829 DispatchEvent(profile, request, listeners, args); |
818 } | 830 } |
819 | 831 |
820 void ExtensionWebRequestEventRouter::OnURLRequestDestroyed( | 832 void ExtensionWebRequestEventRouter::OnURLRequestDestroyed( |
821 void* profile, net::URLRequest* request) { | 833 void* profile, net::URLRequest* request) { |
822 blocked_requests_.erase(request->identifier()); | 834 blocked_requests_.erase(request->identifier()); |
823 signaled_requests_.erase(request->identifier()); | 835 signaled_requests_.erase(request->identifier()); |
| 836 |
| 837 request_time_tracker_->LogRequestEndTime(request->identifier(), |
| 838 base::Time::Now()); |
824 } | 839 } |
825 | 840 |
826 bool ExtensionWebRequestEventRouter::DispatchEvent( | 841 bool ExtensionWebRequestEventRouter::DispatchEvent( |
827 void* profile, | 842 void* profile, |
828 net::URLRequest* request, | 843 net::URLRequest* request, |
829 const std::vector<const EventListener*>& listeners, | 844 const std::vector<const EventListener*>& listeners, |
830 const ListValue& args) { | 845 const ListValue& args) { |
831 std::string json_args; | 846 std::string json_args; |
832 | 847 |
833 // TODO(mpcomplete): Consider consolidating common (extension_id,json_args) | 848 // TODO(mpcomplete): Consider consolidating common (extension_id,json_args) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
886 listener.extension_id = extension_id; | 901 listener.extension_id = extension_id; |
887 listener.sub_event_name = sub_event_name; | 902 listener.sub_event_name = sub_event_name; |
888 | 903 |
889 // The listener may have been removed (e.g. due to the process going away) | 904 // The listener may have been removed (e.g. due to the process going away) |
890 // before we got here. | 905 // before we got here. |
891 std::set<EventListener>::iterator found = | 906 std::set<EventListener>::iterator found = |
892 listeners_[profile][event_name].find(listener); | 907 listeners_[profile][event_name].find(listener); |
893 if (found != listeners_[profile][event_name].end()) | 908 if (found != listeners_[profile][event_name].end()) |
894 found->blocked_requests.erase(request_id); | 909 found->blocked_requests.erase(request_id); |
895 | 910 |
896 DecrementBlockCount(profile, event_name, request_id, response); | 911 DecrementBlockCount(profile, extension_id, event_name, request_id, response); |
897 } | 912 } |
898 | 913 |
899 void ExtensionWebRequestEventRouter::AddEventListener( | 914 void ExtensionWebRequestEventRouter::AddEventListener( |
900 void* profile, | 915 void* profile, |
901 const std::string& extension_id, | 916 const std::string& extension_id, |
902 const std::string& extension_name, | 917 const std::string& extension_name, |
903 const std::string& event_name, | 918 const std::string& event_name, |
904 const std::string& sub_event_name, | 919 const std::string& sub_event_name, |
905 const RequestFilter& filter, | 920 const RequestFilter& filter, |
906 int extra_info_spec, | 921 int extra_info_spec, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 listeners_[profile][event_name].find(listener); | 957 listeners_[profile][event_name].find(listener); |
943 if (found == listeners_[profile][event_name].end()) | 958 if (found == listeners_[profile][event_name].end()) |
944 return; | 959 return; |
945 | 960 |
946 CHECK_EQ(listeners_[profile][event_name].count(listener), 1u) << | 961 CHECK_EQ(listeners_[profile][event_name].count(listener), 1u) << |
947 "extension=" << extension_id << " event=" << event_name; | 962 "extension=" << extension_id << " event=" << event_name; |
948 | 963 |
949 // Unblock any request that this event listener may have been blocking. | 964 // Unblock any request that this event listener may have been blocking. |
950 for (std::set<uint64>::iterator it = found->blocked_requests.begin(); | 965 for (std::set<uint64>::iterator it = found->blocked_requests.begin(); |
951 it != found->blocked_requests.end(); ++it) { | 966 it != found->blocked_requests.end(); ++it) { |
952 DecrementBlockCount(profile, event_name, *it, NULL); | 967 DecrementBlockCount(profile, extension_id, event_name, *it, NULL); |
953 } | 968 } |
954 | 969 |
955 listeners_[profile][event_name].erase(listener); | 970 listeners_[profile][event_name].erase(listener); |
956 } | 971 } |
957 | 972 |
958 void ExtensionWebRequestEventRouter::OnOTRProfileCreated( | 973 void ExtensionWebRequestEventRouter::OnOTRProfileCreated( |
959 void* original_profile, void* otr_profile) { | 974 void* original_profile, void* otr_profile) { |
960 cross_profile_map_[original_profile] = otr_profile; | 975 cross_profile_map_[original_profile] = otr_profile; |
961 cross_profile_map_[otr_profile] = original_profile; | 976 cross_profile_map_[otr_profile] = original_profile; |
962 } | 977 } |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1230 request->net_log->AddEvent( | 1245 request->net_log->AddEvent( |
1231 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 1246 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
1232 make_scoped_refptr( | 1247 make_scoped_refptr( |
1233 new NetLogExtensionIdParameter((*delta)->extension_id))); | 1248 new NetLogExtensionIdParameter((*delta)->extension_id))); |
1234 } | 1249 } |
1235 } | 1250 } |
1236 } | 1251 } |
1237 | 1252 |
1238 void ExtensionWebRequestEventRouter::DecrementBlockCount( | 1253 void ExtensionWebRequestEventRouter::DecrementBlockCount( |
1239 void* profile, | 1254 void* profile, |
| 1255 const std::string& extension_id, |
1240 const std::string& event_name, | 1256 const std::string& event_name, |
1241 uint64 request_id, | 1257 uint64 request_id, |
1242 EventResponse* response) { | 1258 EventResponse* response) { |
1243 scoped_ptr<EventResponse> response_scoped(response); | 1259 scoped_ptr<EventResponse> response_scoped(response); |
1244 | 1260 |
1245 // It's possible that this request was deleted, or cancelled by a previous | 1261 // It's possible that this request was deleted, or cancelled by a previous |
1246 // event handler. If so, ignore this response. | 1262 // event handler. If so, ignore this response. |
1247 if (blocked_requests_.find(request_id) == blocked_requests_.end()) | 1263 if (blocked_requests_.find(request_id) == blocked_requests_.end()) |
1248 return; | 1264 return; |
1249 | 1265 |
1250 BlockedRequest& blocked_request = blocked_requests_[request_id]; | 1266 BlockedRequest& blocked_request = blocked_requests_[request_id]; |
1251 int num_handlers_blocking = --blocked_request.num_handlers_blocking; | 1267 int num_handlers_blocking = --blocked_request.num_handlers_blocking; |
1252 CHECK_GE(num_handlers_blocking, 0); | 1268 CHECK_GE(num_handlers_blocking, 0); |
1253 | 1269 |
1254 if (response) { | 1270 if (response) { |
1255 blocked_request.response_deltas.push_back( | 1271 blocked_request.response_deltas.push_back( |
1256 CalculateDelta(&blocked_request, response)); | 1272 CalculateDelta(&blocked_request, response)); |
1257 } | 1273 } |
1258 | 1274 |
| 1275 base::TimeDelta block_time = |
| 1276 base::Time::Now() - blocked_request.blocking_time; |
| 1277 request_time_tracker_->IncrementExtensionBlockTime( |
| 1278 extension_id, request_id, block_time); |
| 1279 |
1259 if (num_handlers_blocking == 0) { | 1280 if (num_handlers_blocking == 0) { |
1260 // TODO(mpcomplete): it would be better if we accumulated the blocking times | 1281 request_time_tracker_->IncrementTotalBlockTime(request_id, block_time); |
1261 // for a given request over all events. | |
1262 HISTOGRAM_TIMES("Extensions.NetworkDelay", | |
1263 base::Time::Now() - blocked_request.blocking_time); | |
1264 | 1282 |
1265 EventResponseDeltas::iterator i; | 1283 EventResponseDeltas::iterator i; |
1266 EventResponseDeltas& deltas = blocked_request.response_deltas; | 1284 EventResponseDeltas& deltas = blocked_request.response_deltas; |
1267 | 1285 |
1268 bool canceled = false; | 1286 bool canceled = false; |
1269 for (i = deltas.begin(); i != deltas.end(); ++i) { | 1287 for (i = deltas.begin(); i != deltas.end(); ++i) { |
1270 if ((*i)->cancel) { | 1288 if ((*i)->cancel) { |
1271 canceled = true; | 1289 canceled = true; |
1272 blocked_request.net_log->AddEvent( | 1290 blocked_request.net_log->AddEvent( |
1273 net::NetLog::TYPE_CHROME_EXTENSION_ABORTED_REQUEST, | 1291 net::NetLog::TYPE_CHROME_EXTENSION_ABORTED_REQUEST, |
(...skipping 19 matching lines...) Expand all Loading... |
1293 std::list<std::string>::iterator conflict_iter; | 1311 std::list<std::string>::iterator conflict_iter; |
1294 for (conflict_iter = conflicting_extensions.begin(); | 1312 for (conflict_iter = conflicting_extensions.begin(); |
1295 conflict_iter != conflicting_extensions.end(); | 1313 conflict_iter != conflicting_extensions.end(); |
1296 ++conflict_iter) { | 1314 ++conflict_iter) { |
1297 // TODO(mpcomplete): Do some fancy notification in the UI. | 1315 // TODO(mpcomplete): Do some fancy notification in the UI. |
1298 LOG(ERROR) << "Extension " << *conflict_iter << " was ignored in " | 1316 LOG(ERROR) << "Extension " << *conflict_iter << " was ignored in " |
1299 "webRequest API because of conflicting request " | 1317 "webRequest API because of conflicting request " |
1300 "modifications."; | 1318 "modifications."; |
1301 } | 1319 } |
1302 | 1320 |
| 1321 if (canceled) { |
| 1322 request_time_tracker_->SetRequestCanceled(request_id); |
| 1323 } else if (blocked_request.new_url && |
| 1324 !blocked_request.new_url->is_empty()) { |
| 1325 request_time_tracker_->SetRequestRedirected(request_id); |
| 1326 } |
| 1327 |
1303 // This signals a failed request to subscribers of onErrorOccurred in case | 1328 // This signals a failed request to subscribers of onErrorOccurred in case |
1304 // a request is cancelled because net::ERR_EMPTY_RESPONSE cannot be | 1329 // a request is cancelled because net::ERR_EMPTY_RESPONSE cannot be |
1305 // distinguished from a regular failure. | 1330 // distinguished from a regular failure. |
1306 if (blocked_request.callback) { | 1331 if (blocked_request.callback) { |
1307 int rv = canceled ? net::ERR_EMPTY_RESPONSE : net::OK; | 1332 int rv = canceled ? net::ERR_EMPTY_RESPONSE : net::OK; |
1308 net::CompletionCallback* callback = blocked_request.callback; | 1333 net::CompletionCallback* callback = blocked_request.callback; |
1309 // Ensure that request is removed before callback because the callback | 1334 // Ensure that request is removed before callback because the callback |
1310 // might trigger the next event. | 1335 // might trigger the next event. |
1311 blocked_requests_.erase(request_id); | 1336 blocked_requests_.erase(request_id); |
1312 callback->Run(rv); | 1337 callback->Run(rv); |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1461 } | 1486 } |
1462 } | 1487 } |
1463 } | 1488 } |
1464 | 1489 |
1465 ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled( | 1490 ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled( |
1466 profile(), extension_id(), event_name, sub_event_name, request_id, | 1491 profile(), extension_id(), event_name, sub_event_name, request_id, |
1467 response.release()); | 1492 response.release()); |
1468 | 1493 |
1469 return true; | 1494 return true; |
1470 } | 1495 } |
OLD | NEW |