| 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 |