OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "extensions/browser/api/web_request/web_request_api.h" | 5 #include "extensions/browser/api/web_request/web_request_api.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <memory> | 10 #include <memory> |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 histogram_value = events::DECLARATIVE_WEB_REQUEST_ON_MESSAGE; | 264 histogram_value = events::DECLARATIVE_WEB_REQUEST_ON_MESSAGE; |
265 event_name = declarative_keys::kOnMessage; | 265 event_name = declarative_keys::kOnMessage; |
266 } | 266 } |
267 | 267 |
268 std::unique_ptr<Event> event(new Event( | 268 std::unique_ptr<Event> event(new Event( |
269 histogram_value, event_name, std::move(event_args), browser_context, | 269 histogram_value, event_name, std::move(event_args), browser_context, |
270 GURL(), EventRouter::USER_GESTURE_UNKNOWN, event_filtering_info)); | 270 GURL(), EventRouter::USER_GESTURE_UNKNOWN, event_filtering_info)); |
271 event_router->DispatchEventToExtension(extension_id, std::move(event)); | 271 event_router->DispatchEventToExtension(extension_id, std::move(event)); |
272 } | 272 } |
273 | 273 |
274 void RemoveEventListenerOnIOThread( | |
275 void* browser_context, | |
276 const std::string& extension_id, | |
277 const std::string& sub_event_name, | |
278 int embedder_process_id, | |
279 int web_view_instance_id) { | |
280 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
281 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( | |
282 browser_context, extension_id, sub_event_name, | |
283 embedder_process_id, web_view_instance_id); | |
284 } | |
285 | |
286 events::HistogramValue GetEventHistogramValue(const std::string& event_name) { | 274 events::HistogramValue GetEventHistogramValue(const std::string& event_name) { |
287 // Event names will either be webRequest events, or guest view (probably web | 275 // Event names will either be webRequest events, or guest view (probably web |
288 // view) events that map to webRequest events. Check webRequest first. | 276 // view) events that map to webRequest events. Check webRequest first. |
289 static struct ValueAndName { | 277 static struct ValueAndName { |
290 events::HistogramValue histogram_value; | 278 events::HistogramValue histogram_value; |
291 const char* const event_name; | 279 const char* const event_name; |
292 } values_and_names[] = { | 280 } values_and_names[] = { |
293 {events::WEB_REQUEST_ON_BEFORE_REDIRECT, keys::kOnBeforeRedirectEvent}, | 281 {events::WEB_REQUEST_ON_BEFORE_REDIRECT, keys::kOnBeforeRedirectEvent}, |
294 {events::WEB_REQUEST_ON_BEFORE_REQUEST, | 282 {events::WEB_REQUEST_ON_BEFORE_REQUEST, |
295 web_request::OnBeforeRequest::kEventName}, | 283 web_request::OnBeforeRequest::kEventName}, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 } | 348 } |
361 | 349 |
362 void WebRequestAPI::OnListenerRemoved(const EventListenerInfo& details) { | 350 void WebRequestAPI::OnListenerRemoved(const EventListenerInfo& details) { |
363 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 351 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
364 // Note that details.event_name includes the sub-event details (e.g. "/123"). | 352 // Note that details.event_name includes the sub-event details (e.g. "/123"). |
365 // TODO(fsamuel): <webview> events will not be removed through this code path. | 353 // TODO(fsamuel): <webview> events will not be removed through this code path. |
366 // <webview> events will be removed in RemoveWebViewEventListeners. Ideally, | 354 // <webview> events will be removed in RemoveWebViewEventListeners. Ideally, |
367 // this code should be decoupled from extensions, we should use the host ID | 355 // this code should be decoupled from extensions, we should use the host ID |
368 // instead, and not have two different code paths. This is a huge undertaking | 356 // instead, and not have two different code paths. This is a huge undertaking |
369 // unfortunately, so we'll resort to two code paths for now. | 357 // unfortunately, so we'll resort to two code paths for now. |
370 BrowserThread::PostTask(BrowserThread::IO, | 358 // |
371 FROM_HERE, | 359 // Note that details.event_name is actually the sub_event_name! |
372 base::Bind(&RemoveEventListenerOnIOThread, | 360 ExtensionWebRequestEventRouter::EventListener::ID id( |
373 details.browser_context, | 361 details.browser_context, details.extension_id, details.event_name, 0, 0); |
374 details.extension_id, | 362 BrowserThread::PostTask( |
375 details.event_name, | 363 BrowserThread::IO, FROM_HERE, |
376 0 /* embedder_process_id (ignored) */, | 364 base::Bind( |
377 0 /* web_view_instance_id */)); | 365 &ExtensionWebRequestEventRouter::RemoveEventListener, |
| 366 base::Unretained(ExtensionWebRequestEventRouter::GetInstance()), id, |
| 367 false /* not strict */)); |
378 } | 368 } |
379 | 369 |
380 // Represents a single unique listener to an event, along with whatever filter | 370 // Represents a single unique listener to an event, along with whatever filter |
381 // parameters and extra_info_spec were specified at the time the listener was | 371 // parameters and extra_info_spec were specified at the time the listener was |
382 // added. | 372 // added. |
383 // NOTE(benjhayden) New APIs should not use this sub_event_name trick! It does | 373 // NOTE(benjhayden) New APIs should not use this sub_event_name trick! It does |
384 // not play well with event pages. See downloads.onDeterminingFilename and | 374 // not play well with event pages. See downloads.onDeterminingFilename and |
385 // ExtensionDownloadsEventRouter for an alternative approach. | 375 // ExtensionDownloadsEventRouter for an alternative approach. |
386 struct ExtensionWebRequestEventRouter::EventListener { | 376 ExtensionWebRequestEventRouter::EventListener::EventListener(ID id) : id(id) {} |
387 std::string extension_id; | 377 ExtensionWebRequestEventRouter::EventListener::~EventListener() {} |
388 std::string extension_name; | |
389 events::HistogramValue histogram_value; | |
390 std::string sub_event_name; | |
391 RequestFilter filter; | |
392 int extra_info_spec; | |
393 int embedder_process_id; | |
394 int web_view_instance_id; | |
395 base::WeakPtr<IPC::Sender> ipc_sender; | |
396 mutable std::set<uint64_t> blocked_requests; | |
397 | |
398 // Comparator to work with std::set. | |
399 bool operator<(const EventListener& that) const { | |
400 if (extension_id != that.extension_id) | |
401 return extension_id < that.extension_id; | |
402 | |
403 if (sub_event_name != that.sub_event_name) | |
404 return sub_event_name < that.sub_event_name; | |
405 | |
406 if (web_view_instance_id != that.web_view_instance_id) | |
407 return web_view_instance_id < that.web_view_instance_id; | |
408 | |
409 if (web_view_instance_id == 0) { | |
410 // Do not filter by process ID for non-webviews, because this comparator | |
411 // is also used to find and remove an event listener when an extension is | |
412 // unloaded. At this point, the event listener cannot be mapped back to | |
413 // the original process, so 0 is used instead of the actual process ID. | |
414 if (embedder_process_id == 0 || that.embedder_process_id == 0) | |
415 return false; | |
416 } | |
417 | |
418 if (embedder_process_id != that.embedder_process_id) | |
419 return embedder_process_id < that.embedder_process_id; | |
420 | |
421 return false; | |
422 } | |
423 | |
424 EventListener() | |
425 : histogram_value(events::UNKNOWN), | |
426 extra_info_spec(0), | |
427 embedder_process_id(0), | |
428 web_view_instance_id(0) {} | |
429 }; | |
430 | 378 |
431 // Contains info about requests that are blocked waiting for a response from | 379 // Contains info about requests that are blocked waiting for a response from |
432 // an extension. | 380 // an extension. |
433 struct ExtensionWebRequestEventRouter::BlockedRequest { | 381 struct ExtensionWebRequestEventRouter::BlockedRequest { |
434 // The request that is being blocked. | 382 // The request that is being blocked. |
435 net::URLRequest* request; | 383 net::URLRequest* request; |
436 | 384 |
437 // Whether the request originates from an incognito tab. | 385 // Whether the request originates from an incognito tab. |
438 bool is_incognito; | 386 bool is_incognito; |
439 | 387 |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 | 571 |
624 // Whether to initialized |blocked_requests_|. | 572 // Whether to initialized |blocked_requests_|. |
625 bool initialize_blocked_requests = false; | 573 bool initialize_blocked_requests = false; |
626 | 574 |
627 initialize_blocked_requests |= | 575 initialize_blocked_requests |= |
628 ProcessDeclarativeRules(browser_context, extension_info_map, | 576 ProcessDeclarativeRules(browser_context, extension_info_map, |
629 web_request::OnBeforeRequest::kEventName, request, | 577 web_request::OnBeforeRequest::kEventName, request, |
630 ON_BEFORE_REQUEST, NULL); | 578 ON_BEFORE_REQUEST, NULL); |
631 | 579 |
632 int extra_info_spec = 0; | 580 int extra_info_spec = 0; |
633 EventListeners listeners = GetMatchingListeners( | 581 RawListeners listeners = GetMatchingListeners( |
634 browser_context, extension_info_map, | 582 browser_context, extension_info_map, |
635 web_request::OnBeforeRequest::kEventName, request, &extra_info_spec); | 583 web_request::OnBeforeRequest::kEventName, request, &extra_info_spec); |
636 if (!listeners.empty() && | 584 if (!listeners.empty() && |
637 !GetAndSetSignaled(request->identifier(), kOnBeforeRequest)) { | 585 !GetAndSetSignaled(request->identifier(), kOnBeforeRequest)) { |
638 std::unique_ptr<WebRequestEventDetails> event_details( | 586 std::unique_ptr<WebRequestEventDetails> event_details( |
639 CreateEventDetails(request, extra_info_spec)); | 587 CreateEventDetails(request, extra_info_spec)); |
640 event_details->SetRequestBody(request); | 588 event_details->SetRequestBody(request); |
641 | 589 |
642 initialize_blocked_requests |= DispatchEvent( | 590 initialize_blocked_requests |= DispatchEvent( |
643 browser_context, request, listeners, std::move(event_details)); | 591 browser_context, request, listeners, std::move(event_details)); |
(...skipping 28 matching lines...) Expand all Loading... |
672 if (ShouldHideEvent(browser_context, extension_info_map, request)) | 620 if (ShouldHideEvent(browser_context, extension_info_map, request)) |
673 return net::OK; | 621 return net::OK; |
674 | 622 |
675 bool initialize_blocked_requests = false; | 623 bool initialize_blocked_requests = false; |
676 | 624 |
677 initialize_blocked_requests |= ProcessDeclarativeRules( | 625 initialize_blocked_requests |= ProcessDeclarativeRules( |
678 browser_context, extension_info_map, keys::kOnBeforeSendHeadersEvent, | 626 browser_context, extension_info_map, keys::kOnBeforeSendHeadersEvent, |
679 request, ON_BEFORE_SEND_HEADERS, NULL); | 627 request, ON_BEFORE_SEND_HEADERS, NULL); |
680 | 628 |
681 int extra_info_spec = 0; | 629 int extra_info_spec = 0; |
682 EventListeners listeners = GetMatchingListeners( | 630 RawListeners listeners = GetMatchingListeners( |
683 browser_context, extension_info_map, keys::kOnBeforeSendHeadersEvent, | 631 browser_context, extension_info_map, keys::kOnBeforeSendHeadersEvent, |
684 request, &extra_info_spec); | 632 request, &extra_info_spec); |
685 if (!listeners.empty() && | 633 if (!listeners.empty() && |
686 !GetAndSetSignaled(request->identifier(), kOnBeforeSendHeaders)) { | 634 !GetAndSetSignaled(request->identifier(), kOnBeforeSendHeaders)) { |
687 std::unique_ptr<WebRequestEventDetails> event_details( | 635 std::unique_ptr<WebRequestEventDetails> event_details( |
688 CreateEventDetails(request, extra_info_spec)); | 636 CreateEventDetails(request, extra_info_spec)); |
689 event_details->SetRequestHeaders(*headers); | 637 event_details->SetRequestHeaders(*headers); |
690 | 638 |
691 initialize_blocked_requests |= DispatchEvent( | 639 initialize_blocked_requests |= DispatchEvent( |
692 browser_context, request, listeners, std::move(event_details)); | 640 browser_context, request, listeners, std::move(event_details)); |
(...skipping 26 matching lines...) Expand all Loading... |
719 const net::HttpRequestHeaders& headers) { | 667 const net::HttpRequestHeaders& headers) { |
720 if (ShouldHideEvent(browser_context, extension_info_map, request)) | 668 if (ShouldHideEvent(browser_context, extension_info_map, request)) |
721 return; | 669 return; |
722 | 670 |
723 if (GetAndSetSignaled(request->identifier(), kOnSendHeaders)) | 671 if (GetAndSetSignaled(request->identifier(), kOnSendHeaders)) |
724 return; | 672 return; |
725 | 673 |
726 ClearSignaled(request->identifier(), kOnBeforeRedirect); | 674 ClearSignaled(request->identifier(), kOnBeforeRedirect); |
727 | 675 |
728 int extra_info_spec = 0; | 676 int extra_info_spec = 0; |
729 EventListeners listeners = GetMatchingListeners( | 677 RawListeners listeners = GetMatchingListeners( |
730 browser_context, extension_info_map, keys::kOnSendHeadersEvent, request, | 678 browser_context, extension_info_map, keys::kOnSendHeadersEvent, request, |
731 &extra_info_spec); | 679 &extra_info_spec); |
732 if (listeners.empty()) | 680 if (listeners.empty()) |
733 return; | 681 return; |
734 | 682 |
735 std::unique_ptr<WebRequestEventDetails> event_details( | 683 std::unique_ptr<WebRequestEventDetails> event_details( |
736 CreateEventDetails(request, extra_info_spec)); | 684 CreateEventDetails(request, extra_info_spec)); |
737 event_details->SetRequestHeaders(headers); | 685 event_details->SetRequestHeaders(headers); |
738 | 686 |
739 DispatchEvent(browser_context, request, listeners, std::move(event_details)); | 687 DispatchEvent(browser_context, request, listeners, std::move(event_details)); |
(...skipping 10 matching lines...) Expand all Loading... |
750 if (ShouldHideEvent(browser_context, extension_info_map, request)) | 698 if (ShouldHideEvent(browser_context, extension_info_map, request)) |
751 return net::OK; | 699 return net::OK; |
752 | 700 |
753 bool initialize_blocked_requests = false; | 701 bool initialize_blocked_requests = false; |
754 | 702 |
755 initialize_blocked_requests |= ProcessDeclarativeRules( | 703 initialize_blocked_requests |= ProcessDeclarativeRules( |
756 browser_context, extension_info_map, keys::kOnHeadersReceivedEvent, | 704 browser_context, extension_info_map, keys::kOnHeadersReceivedEvent, |
757 request, ON_HEADERS_RECEIVED, original_response_headers); | 705 request, ON_HEADERS_RECEIVED, original_response_headers); |
758 | 706 |
759 int extra_info_spec = 0; | 707 int extra_info_spec = 0; |
760 EventListeners listeners = GetMatchingListeners( | 708 RawListeners listeners = GetMatchingListeners( |
761 browser_context, extension_info_map, keys::kOnHeadersReceivedEvent, | 709 browser_context, extension_info_map, keys::kOnHeadersReceivedEvent, |
762 request, &extra_info_spec); | 710 request, &extra_info_spec); |
763 | 711 |
764 if (!listeners.empty() && | 712 if (!listeners.empty() && |
765 !GetAndSetSignaled(request->identifier(), kOnHeadersReceived)) { | 713 !GetAndSetSignaled(request->identifier(), kOnHeadersReceived)) { |
766 std::unique_ptr<WebRequestEventDetails> event_details( | 714 std::unique_ptr<WebRequestEventDetails> event_details( |
767 CreateEventDetails(request, extra_info_spec)); | 715 CreateEventDetails(request, extra_info_spec)); |
768 event_details->SetResponseHeaders(request, original_response_headers); | 716 event_details->SetResponseHeaders(request, original_response_headers); |
769 | 717 |
770 initialize_blocked_requests |= DispatchEvent( | 718 initialize_blocked_requests |= DispatchEvent( |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 const net::NetworkDelegate::AuthCallback& callback, | 750 const net::NetworkDelegate::AuthCallback& callback, |
803 net::AuthCredentials* credentials) { | 751 net::AuthCredentials* credentials) { |
804 // No browser_context means that this is for authentication challenges in the | 752 // No browser_context means that this is for authentication challenges in the |
805 // system context. Skip in that case. Also skip sensitive requests. | 753 // system context. Skip in that case. Also skip sensitive requests. |
806 if (!browser_context || | 754 if (!browser_context || |
807 WebRequestPermissions::HideRequest(extension_info_map, request)) { | 755 WebRequestPermissions::HideRequest(extension_info_map, request)) { |
808 return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION; | 756 return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION; |
809 } | 757 } |
810 | 758 |
811 int extra_info_spec = 0; | 759 int extra_info_spec = 0; |
812 EventListeners listeners = GetMatchingListeners( | 760 RawListeners listeners = GetMatchingListeners( |
813 browser_context, extension_info_map, keys::kOnAuthRequiredEvent, request, | 761 browser_context, extension_info_map, keys::kOnAuthRequiredEvent, request, |
814 &extra_info_spec); | 762 &extra_info_spec); |
815 if (listeners.empty()) | 763 if (listeners.empty()) |
816 return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION; | 764 return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION; |
817 | 765 |
818 std::unique_ptr<WebRequestEventDetails> event_details( | 766 std::unique_ptr<WebRequestEventDetails> event_details( |
819 CreateEventDetails(request, extra_info_spec)); | 767 CreateEventDetails(request, extra_info_spec)); |
820 event_details->SetResponseHeaders(request, request->response_headers()); | 768 event_details->SetResponseHeaders(request, request->response_headers()); |
821 event_details->SetAuthInfo(auth_info); | 769 event_details->SetAuthInfo(auth_info); |
822 | 770 |
(...skipping 21 matching lines...) Expand all Loading... |
844 | 792 |
845 if (GetAndSetSignaled(request->identifier(), kOnBeforeRedirect)) | 793 if (GetAndSetSignaled(request->identifier(), kOnBeforeRedirect)) |
846 return; | 794 return; |
847 | 795 |
848 ClearSignaled(request->identifier(), kOnBeforeRequest); | 796 ClearSignaled(request->identifier(), kOnBeforeRequest); |
849 ClearSignaled(request->identifier(), kOnBeforeSendHeaders); | 797 ClearSignaled(request->identifier(), kOnBeforeSendHeaders); |
850 ClearSignaled(request->identifier(), kOnSendHeaders); | 798 ClearSignaled(request->identifier(), kOnSendHeaders); |
851 ClearSignaled(request->identifier(), kOnHeadersReceived); | 799 ClearSignaled(request->identifier(), kOnHeadersReceived); |
852 | 800 |
853 int extra_info_spec = 0; | 801 int extra_info_spec = 0; |
854 EventListeners listeners = GetMatchingListeners( | 802 RawListeners listeners = GetMatchingListeners( |
855 browser_context, extension_info_map, keys::kOnBeforeRedirectEvent, | 803 browser_context, extension_info_map, keys::kOnBeforeRedirectEvent, |
856 request, &extra_info_spec); | 804 request, &extra_info_spec); |
857 if (listeners.empty()) | 805 if (listeners.empty()) |
858 return; | 806 return; |
859 | 807 |
860 std::unique_ptr<WebRequestEventDetails> event_details( | 808 std::unique_ptr<WebRequestEventDetails> event_details( |
861 CreateEventDetails(request, extra_info_spec)); | 809 CreateEventDetails(request, extra_info_spec)); |
862 event_details->SetResponseHeaders(request, request->response_headers()); | 810 event_details->SetResponseHeaders(request, request->response_headers()); |
863 event_details->SetResponseSource(request); | 811 event_details->SetResponseSource(request); |
864 event_details->SetString(keys::kRedirectUrlKey, new_location.spec()); | 812 event_details->SetString(keys::kRedirectUrlKey, new_location.spec()); |
865 | 813 |
866 DispatchEvent(browser_context, request, listeners, std::move(event_details)); | 814 DispatchEvent(browser_context, request, listeners, std::move(event_details)); |
867 } | 815 } |
868 | 816 |
869 void ExtensionWebRequestEventRouter::OnResponseStarted( | 817 void ExtensionWebRequestEventRouter::OnResponseStarted( |
870 void* browser_context, | 818 void* browser_context, |
871 const InfoMap* extension_info_map, | 819 const InfoMap* extension_info_map, |
872 net::URLRequest* request, | 820 net::URLRequest* request, |
873 int net_error) { | 821 int net_error) { |
874 DCHECK_NE(net::ERR_IO_PENDING, net_error); | 822 DCHECK_NE(net::ERR_IO_PENDING, net_error); |
875 | 823 |
876 if (ShouldHideEvent(browser_context, extension_info_map, request)) | 824 if (ShouldHideEvent(browser_context, extension_info_map, request)) |
877 return; | 825 return; |
878 | 826 |
879 // OnResponseStarted is even triggered, when the request was cancelled. | 827 // OnResponseStarted is even triggered, when the request was cancelled. |
880 if (net_error != net::OK) | 828 if (net_error != net::OK) |
881 return; | 829 return; |
882 | 830 |
883 int extra_info_spec = 0; | 831 int extra_info_spec = 0; |
884 EventListeners listeners = GetMatchingListeners( | 832 RawListeners listeners = GetMatchingListeners( |
885 browser_context, extension_info_map, keys::kOnResponseStartedEvent, | 833 browser_context, extension_info_map, keys::kOnResponseStartedEvent, |
886 request, &extra_info_spec); | 834 request, &extra_info_spec); |
887 if (listeners.empty()) | 835 if (listeners.empty()) |
888 return; | 836 return; |
889 | 837 |
890 std::unique_ptr<WebRequestEventDetails> event_details( | 838 std::unique_ptr<WebRequestEventDetails> event_details( |
891 CreateEventDetails(request, extra_info_spec)); | 839 CreateEventDetails(request, extra_info_spec)); |
892 event_details->SetResponseHeaders(request, request->response_headers()); | 840 event_details->SetResponseHeaders(request, request->response_headers()); |
893 event_details->SetResponseSource(request); | 841 event_details->SetResponseSource(request); |
894 | 842 |
(...skipping 28 matching lines...) Expand all Loading... |
923 request_time_tracker_->LogRequestEndTime(request->identifier(), | 871 request_time_tracker_->LogRequestEndTime(request->identifier(), |
924 base::Time::Now()); | 872 base::Time::Now()); |
925 | 873 |
926 DCHECK_EQ(net::OK, net_error); | 874 DCHECK_EQ(net::OK, net_error); |
927 | 875 |
928 DCHECK(!GetAndSetSignaled(request->identifier(), kOnCompleted)); | 876 DCHECK(!GetAndSetSignaled(request->identifier(), kOnCompleted)); |
929 | 877 |
930 ClearPendingCallbacks(request); | 878 ClearPendingCallbacks(request); |
931 | 879 |
932 int extra_info_spec = 0; | 880 int extra_info_spec = 0; |
933 EventListeners listeners = | 881 RawListeners listeners = |
934 GetMatchingListeners(browser_context, extension_info_map, | 882 GetMatchingListeners(browser_context, extension_info_map, |
935 keys::kOnCompletedEvent, request, &extra_info_spec); | 883 keys::kOnCompletedEvent, request, &extra_info_spec); |
936 if (listeners.empty()) | 884 if (listeners.empty()) |
937 return; | 885 return; |
938 | 886 |
939 std::unique_ptr<WebRequestEventDetails> event_details( | 887 std::unique_ptr<WebRequestEventDetails> event_details( |
940 CreateEventDetails(request, extra_info_spec)); | 888 CreateEventDetails(request, extra_info_spec)); |
941 event_details->SetResponseHeaders(request, request->response_headers()); | 889 event_details->SetResponseHeaders(request, request->response_headers()); |
942 event_details->SetResponseSource(request); | 890 event_details->SetResponseSource(request); |
943 | 891 |
(...skipping 30 matching lines...) Expand all Loading... |
974 base::Time::Now()); | 922 base::Time::Now()); |
975 | 923 |
976 DCHECK_NE(net::OK, net_error); | 924 DCHECK_NE(net::OK, net_error); |
977 DCHECK_NE(net::ERR_IO_PENDING, net_error); | 925 DCHECK_NE(net::ERR_IO_PENDING, net_error); |
978 | 926 |
979 DCHECK(!GetAndSetSignaled(request->identifier(), kOnErrorOccurred)); | 927 DCHECK(!GetAndSetSignaled(request->identifier(), kOnErrorOccurred)); |
980 | 928 |
981 ClearPendingCallbacks(request); | 929 ClearPendingCallbacks(request); |
982 | 930 |
983 int extra_info_spec = 0; | 931 int extra_info_spec = 0; |
984 EventListeners listeners = GetMatchingListeners( | 932 RawListeners listeners = GetMatchingListeners( |
985 browser_context, extension_info_map, | 933 browser_context, extension_info_map, |
986 web_request::OnErrorOccurred::kEventName, request, &extra_info_spec); | 934 web_request::OnErrorOccurred::kEventName, request, &extra_info_spec); |
987 if (listeners.empty()) | 935 if (listeners.empty()) |
988 return; | 936 return; |
989 | 937 |
990 std::unique_ptr<WebRequestEventDetails> event_details( | 938 std::unique_ptr<WebRequestEventDetails> event_details( |
991 CreateEventDetails(request, extra_info_spec)); | 939 CreateEventDetails(request, extra_info_spec)); |
992 if (started) | 940 if (started) |
993 event_details->SetResponseSource(request); | 941 event_details->SetResponseSource(request); |
994 else | 942 else |
(...skipping 24 matching lines...) Expand all Loading... |
1019 } | 967 } |
1020 | 968 |
1021 void ExtensionWebRequestEventRouter::ClearPendingCallbacks( | 969 void ExtensionWebRequestEventRouter::ClearPendingCallbacks( |
1022 const net::URLRequest* request) { | 970 const net::URLRequest* request) { |
1023 blocked_requests_.erase(request->identifier()); | 971 blocked_requests_.erase(request->identifier()); |
1024 } | 972 } |
1025 | 973 |
1026 bool ExtensionWebRequestEventRouter::DispatchEvent( | 974 bool ExtensionWebRequestEventRouter::DispatchEvent( |
1027 void* browser_context, | 975 void* browser_context, |
1028 net::URLRequest* request, | 976 net::URLRequest* request, |
1029 const std::vector<const EventListener*>& listeners, | 977 const RawListeners& listeners, |
1030 std::unique_ptr<WebRequestEventDetails> event_details) { | 978 std::unique_ptr<WebRequestEventDetails> event_details) { |
1031 // TODO(mpcomplete): Consider consolidating common (extension_id,json_args) | 979 // TODO(mpcomplete): Consider consolidating common (extension_id,json_args) |
1032 // pairs into a single message sent to a list of sub_event_names. | 980 // pairs into a single message sent to a list of sub_event_names. |
1033 int num_handlers_blocking = 0; | 981 int num_handlers_blocking = 0; |
1034 | 982 |
1035 std::unique_ptr<std::vector<EventListener>> listeners_to_dispatch( | 983 std::unique_ptr<ListenerIDs> listeners_to_dispatch(new ListenerIDs); |
1036 new std::vector<EventListener>()); | |
1037 listeners_to_dispatch->reserve(listeners.size()); | 984 listeners_to_dispatch->reserve(listeners.size()); |
1038 for (const EventListener* listener : listeners) { | 985 for (EventListener* listener : listeners) { |
1039 listeners_to_dispatch->push_back(*listener); | 986 listeners_to_dispatch->push_back(listener->id); |
1040 if (listener->extra_info_spec & | 987 if (listener->extra_info_spec & |
1041 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) { | 988 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) { |
1042 listener->blocked_requests.insert(request->identifier()); | 989 listener->blocked_requests.insert(request->identifier()); |
1043 // If this is the first delegate blocking the request, go ahead and log | 990 // If this is the first delegate blocking the request, go ahead and log |
1044 // it. | 991 // it. |
1045 if (num_handlers_blocking == 0) { | 992 if (num_handlers_blocking == 0) { |
1046 std::string delegate_info = l10n_util::GetStringFUTF8( | 993 std::string delegate_info = l10n_util::GetStringFUTF8( |
1047 IDS_LOAD_STATE_PARAMETER_EXTENSION, | 994 IDS_LOAD_STATE_PARAMETER_EXTENSION, |
1048 base::UTF8ToUTF16(listener->extension_name)); | 995 base::UTF8ToUTF16(listener->extension_name)); |
1049 // LobAndReport allows extensions that block requests to be displayed in | 996 // LobAndReport allows extensions that block requests to be displayed in |
(...skipping 15 matching lines...) Expand all Loading... |
1065 blocked_request.num_handlers_blocking += num_handlers_blocking; | 1012 blocked_request.num_handlers_blocking += num_handlers_blocking; |
1066 blocked_request.blocking_time = base::Time::Now(); | 1013 blocked_request.blocking_time = base::Time::Now(); |
1067 return true; | 1014 return true; |
1068 } | 1015 } |
1069 | 1016 |
1070 return false; | 1017 return false; |
1071 } | 1018 } |
1072 | 1019 |
1073 void ExtensionWebRequestEventRouter::DispatchEventToListeners( | 1020 void ExtensionWebRequestEventRouter::DispatchEventToListeners( |
1074 void* browser_context, | 1021 void* browser_context, |
1075 std::unique_ptr<std::vector<EventListener>> listeners, | 1022 std::unique_ptr<ListenerIDs> listener_ids, |
1076 std::unique_ptr<WebRequestEventDetails> event_details) { | 1023 std::unique_ptr<WebRequestEventDetails> event_details) { |
1077 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1024 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1078 DCHECK(listeners.get()); | 1025 DCHECK(!listener_ids->empty()); |
1079 DCHECK_GT(listeners->size(), 0UL); | |
1080 DCHECK(event_details.get()); | 1026 DCHECK(event_details.get()); |
1081 | 1027 |
1082 std::string event_name = | 1028 std::string event_name = |
1083 EventRouter::GetBaseEventName((*listeners)[0].sub_event_name); | 1029 EventRouter::GetBaseEventName((*listener_ids)[0].sub_event_name); |
1084 DCHECK(IsWebRequestEvent(event_name)); | 1030 DCHECK(IsWebRequestEvent(event_name)); |
1085 | 1031 |
1086 const std::set<EventListener>& event_listeners = | 1032 Listeners& event_listeners = listeners_[browser_context][event_name]; |
1087 listeners_[browser_context][event_name]; | |
1088 void* cross_browser_context = GetCrossBrowserContext(browser_context); | 1033 void* cross_browser_context = GetCrossBrowserContext(browser_context); |
1089 const std::set<EventListener>* cross_event_listeners = | 1034 Listeners* cross_event_listeners = |
1090 cross_browser_context ? &listeners_[cross_browser_context][event_name] | 1035 cross_browser_context ? &listeners_[cross_browser_context][event_name] |
1091 : nullptr; | 1036 : nullptr; |
1092 | 1037 |
1093 for (const EventListener& target : *listeners) { | 1038 for (const EventListener::ID& id : *listener_ids) { |
1094 std::set<EventListener>::const_iterator listener = | 1039 // It's possible that the listener is no longer present. Check to make sure |
1095 event_listeners.find(target); | 1040 // it's still there. |
1096 // Ignore listener if it was removed between the thread hops. | 1041 const EventListener* listener = |
1097 if (listener == event_listeners.end()) { | 1042 FindEventListenerInContainer(id, event_listeners); |
1098 if (!cross_event_listeners) | 1043 if (!listener && cross_event_listeners) { |
1099 continue; | 1044 listener = FindEventListenerInContainer(id, *cross_event_listeners); |
1100 listener = cross_event_listeners->find(target); | |
1101 if (listener == cross_event_listeners->end()) | |
1102 continue; | |
1103 } | 1045 } |
| 1046 if (!listener) |
| 1047 continue; |
1104 | 1048 |
1105 if (!listener->ipc_sender.get()) | 1049 if (!listener->ipc_sender.get()) |
1106 continue; | 1050 continue; |
1107 | 1051 |
1108 // Filter out the optional keys that this listener didn't request. | 1052 // Filter out the optional keys that this listener didn't request. |
1109 std::unique_ptr<base::ListValue> args_filtered(new base::ListValue); | 1053 std::unique_ptr<base::ListValue> args_filtered(new base::ListValue); |
1110 args_filtered->Append( | 1054 args_filtered->Append( |
1111 event_details->GetFilteredDict(listener->extra_info_spec)); | 1055 event_details->GetFilteredDict(listener->extra_info_spec)); |
1112 | 1056 |
1113 EventRouter::DispatchEventToSender( | 1057 EventRouter::DispatchEventToSender( |
1114 listener->ipc_sender.get(), browser_context, listener->extension_id, | 1058 listener->ipc_sender.get(), browser_context, listener->id.extension_id, |
1115 listener->histogram_value, listener->sub_event_name, | 1059 listener->histogram_value, listener->id.sub_event_name, |
1116 std::move(args_filtered), EventRouter::USER_GESTURE_UNKNOWN, | 1060 std::move(args_filtered), EventRouter::USER_GESTURE_UNKNOWN, |
1117 EventFilteringInfo()); | 1061 EventFilteringInfo()); |
1118 } | 1062 } |
1119 } | 1063 } |
1120 | 1064 |
1121 void ExtensionWebRequestEventRouter::OnEventHandled( | 1065 void ExtensionWebRequestEventRouter::OnEventHandled( |
1122 void* browser_context, | 1066 void* browser_context, |
1123 const std::string& extension_id, | 1067 const std::string& extension_id, |
1124 const std::string& event_name, | 1068 const std::string& event_name, |
1125 const std::string& sub_event_name, | 1069 const std::string& sub_event_name, |
1126 uint64_t request_id, | 1070 uint64_t request_id, |
1127 EventResponse* response) { | 1071 EventResponse* response) { |
1128 // TODO(robwu): Does this also work with webviews? operator< (used by find) | 1072 // TODO(robwu): This ignores WebViews. |
1129 // takes the webview ID into account, which is not set on |listener|. | 1073 Listeners& listeners = listeners_[browser_context][event_name]; |
1130 EventListener listener; | 1074 EventListener::ID id(browser_context, extension_id, sub_event_name, 0, 0); |
1131 listener.extension_id = extension_id; | 1075 for (auto it = listeners.begin(); it != listeners.end(); ++it) { |
1132 listener.sub_event_name = sub_event_name; | 1076 if ((*it)->id.LooselyMatches(id)) { |
1133 | 1077 (*it)->blocked_requests.erase(request_id); |
1134 // The listener may have been removed (e.g. due to the process going away) | 1078 } |
1135 // before we got here. | 1079 } |
1136 std::set<EventListener>::iterator found = | |
1137 listeners_[browser_context][event_name].find(listener); | |
1138 if (found != listeners_[browser_context][event_name].end()) | |
1139 found->blocked_requests.erase(request_id); | |
1140 | 1080 |
1141 DecrementBlockCount( | 1081 DecrementBlockCount( |
1142 browser_context, extension_id, event_name, request_id, response); | 1082 browser_context, extension_id, event_name, request_id, response); |
1143 } | 1083 } |
1144 | 1084 |
1145 bool ExtensionWebRequestEventRouter::AddEventListener( | 1085 bool ExtensionWebRequestEventRouter::AddEventListener( |
1146 void* browser_context, | 1086 void* browser_context, |
1147 const std::string& extension_id, | 1087 const std::string& extension_id, |
1148 const std::string& extension_name, | 1088 const std::string& extension_name, |
1149 events::HistogramValue histogram_value, | 1089 events::HistogramValue histogram_value, |
1150 const std::string& event_name, | 1090 const std::string& event_name, |
1151 const std::string& sub_event_name, | 1091 const std::string& sub_event_name, |
1152 const RequestFilter& filter, | 1092 const RequestFilter& filter, |
1153 int extra_info_spec, | 1093 int extra_info_spec, |
1154 int embedder_process_id, | 1094 int embedder_process_id, |
1155 int web_view_instance_id, | 1095 int web_view_instance_id, |
1156 base::WeakPtr<IPC::Sender> ipc_sender) { | 1096 base::WeakPtr<IPC::Sender> ipc_sender) { |
1157 if (!IsWebRequestEvent(event_name)) | 1097 if (!IsWebRequestEvent(event_name)) |
1158 return false; | 1098 return false; |
1159 | 1099 |
1160 EventListener listener; | 1100 if (event_name != EventRouter::GetBaseEventName(sub_event_name)) |
1161 listener.extension_id = extension_id; | 1101 return false; |
1162 listener.extension_name = extension_name; | 1102 |
1163 listener.histogram_value = histogram_value; | 1103 EventListener::ID id(browser_context, extension_id, sub_event_name, |
1164 listener.sub_event_name = sub_event_name; | 1104 embedder_process_id, web_view_instance_id); |
1165 listener.filter = filter; | 1105 if (FindEventListener(id) != nullptr) { |
1166 listener.extra_info_spec = extra_info_spec; | 1106 // This is likely an abuse of the API by a malicious extension. |
1167 listener.ipc_sender = ipc_sender; | 1107 return false; |
1168 listener.embedder_process_id = embedder_process_id; | 1108 } |
1169 listener.web_view_instance_id = web_view_instance_id; | 1109 |
1170 if (listener.web_view_instance_id) { | 1110 std::unique_ptr<EventListener> listener(new EventListener(id)); |
| 1111 listener->extension_name = extension_name; |
| 1112 listener->histogram_value = histogram_value; |
| 1113 listener->filter = filter; |
| 1114 listener->extra_info_spec = extra_info_spec; |
| 1115 listener->ipc_sender = ipc_sender; |
| 1116 if (web_view_instance_id) { |
1171 content::RecordAction( | 1117 content::RecordAction( |
1172 base::UserMetricsAction("WebView.WebRequest.AddListener")); | 1118 base::UserMetricsAction("WebView.WebRequest.AddListener")); |
1173 } | 1119 } |
1174 | 1120 |
1175 if (base::ContainsKey(listeners_[browser_context][event_name], listener)) { | 1121 listeners_[browser_context][event_name].push_back(std::move(listener)); |
1176 // This is likely an abuse of the API by a malicious extension. | |
1177 return false; | |
1178 } | |
1179 listeners_[browser_context][event_name].insert(listener); | |
1180 return true; | 1122 return true; |
1181 } | 1123 } |
1182 | 1124 |
| 1125 size_t ExtensionWebRequestEventRouter::GetListenerCountForTesting( |
| 1126 void* browser_context, |
| 1127 const std::string& event_name) { |
| 1128 return listeners_[browser_context][event_name].size(); |
| 1129 } |
| 1130 |
| 1131 ExtensionWebRequestEventRouter::EventListener* |
| 1132 ExtensionWebRequestEventRouter::FindEventListener(const EventListener::ID& id) { |
| 1133 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1134 std::string event_name = EventRouter::GetBaseEventName(id.sub_event_name); |
| 1135 Listeners& listeners = listeners_[id.browser_context][event_name]; |
| 1136 return FindEventListenerInContainer(id, listeners); |
| 1137 } |
| 1138 |
| 1139 ExtensionWebRequestEventRouter::EventListener* |
| 1140 ExtensionWebRequestEventRouter::FindEventListenerInContainer( |
| 1141 const EventListener::ID& id, |
| 1142 Listeners& listeners) { |
| 1143 for (auto it = listeners.begin(); it != listeners.end(); ++it) { |
| 1144 if ((*it)->id == id) { |
| 1145 return it->get(); |
| 1146 } |
| 1147 } |
| 1148 return nullptr; |
| 1149 } |
| 1150 |
1183 void ExtensionWebRequestEventRouter::RemoveEventListener( | 1151 void ExtensionWebRequestEventRouter::RemoveEventListener( |
1184 void* browser_context, | 1152 const EventListener::ID& id, |
1185 const std::string& extension_id, | 1153 bool strict) { |
1186 const std::string& sub_event_name, | 1154 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1187 int embedder_process_id, | |
1188 int web_view_instance_id) { | |
1189 std::string event_name = EventRouter::GetBaseEventName(sub_event_name); | |
1190 DCHECK(IsWebRequestEvent(event_name)); | |
1191 | 1155 |
1192 EventListener listener; | 1156 std::string event_name = EventRouter::GetBaseEventName(id.sub_event_name); |
1193 listener.extension_id = extension_id; | 1157 Listeners& listeners = listeners_[id.browser_context][event_name]; |
1194 listener.sub_event_name = sub_event_name; | 1158 for (auto it = listeners.begin(); it != listeners.end(); ++it) { |
1195 listener.embedder_process_id = embedder_process_id; | 1159 std::unique_ptr<EventListener>& listener = *it; |
1196 listener.web_view_instance_id = web_view_instance_id; | |
1197 | 1160 |
1198 std::set<EventListener>& event_listeners = | 1161 // There are two places that call this method: RemoveWebViewEventListeners |
1199 listeners_[browser_context][event_name]; | 1162 // and OnListenerRemoved. The latter can't use operator== because it doesn't |
1200 // It's possible for AddEventListener to fail asynchronously. In that case, | 1163 // have the embedder_process_id. This shouldn't be a problem, because |
1201 // the renderer believes the listener exists, while the browser does not. | 1164 // OnListenerRemoved is only called for web_view_instance_id == 0. |
1202 // Ignore a RemoveEventListener in that case. | 1165 bool matches = |
1203 std::set<EventListener>::const_iterator it = event_listeners.find(listener); | 1166 strict ? listener->id == id : listener->id.LooselyMatches(id); |
1204 if (it == event_listeners.end()) | 1167 if (matches) { |
1205 return; | 1168 // Unblock any request that this event listener may have been blocking. |
| 1169 for (uint64_t blocked_request_id : listener->blocked_requests) |
| 1170 DecrementBlockCount(listener->id.browser_context, |
| 1171 listener->id.extension_id, event_name, |
| 1172 blocked_request_id, nullptr); |
1206 | 1173 |
1207 #if defined(OS_WIN) | 1174 listeners.erase(it); |
1208 // Debugging https://crbug.com/589735 | 1175 helpers::ClearCacheOnNavigation(); |
1209 // Please post crash reports at the following lines to the above issue. | 1176 return; |
1210 unsigned event_listener_count = event_listeners.count(listener); | 1177 } |
1211 CHECK_GE(event_listener_count, 0u); | 1178 } |
1212 CHECK_GE(event_listener_count, 1u); | |
1213 CHECK_LE(event_listener_count, 2u); | |
1214 CHECK_EQ(event_listener_count, 1u); | |
1215 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | |
1216 #endif // OS_WIN | |
1217 CHECK_EQ(event_listeners.count(listener), 1u) << | |
1218 "extension=" << extension_id << " event=" << event_name; | |
1219 | |
1220 // Unblock any request that this event listener may have been blocking. | |
1221 for (uint64_t id : it->blocked_requests) | |
1222 DecrementBlockCount(browser_context, extension_id, event_name, id, NULL); | |
1223 | |
1224 event_listeners.erase(listener); | |
1225 | |
1226 helpers::ClearCacheOnNavigation(); | |
1227 } | 1179 } |
1228 | 1180 |
1229 void ExtensionWebRequestEventRouter::RemoveWebViewEventListeners( | 1181 void ExtensionWebRequestEventRouter::RemoveWebViewEventListeners( |
1230 void* browser_context, | 1182 void* browser_context, |
1231 int embedder_process_id, | 1183 int embedder_process_id, |
1232 int web_view_instance_id) { | 1184 int web_view_instance_id) { |
1233 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1185 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1234 | 1186 |
1235 // Iterate over all listeners of all WebRequest events to delete | 1187 // Iterate over all listeners of all WebRequest events to delete |
1236 // any listeners that belong to the provided <webview>. | 1188 // any listeners that belong to the provided <webview>. |
1237 ListenerMapForBrowserContext& map_for_browser_context = | 1189 ListenerMapForBrowserContext& map_for_browser_context = |
1238 listeners_[browser_context]; | 1190 listeners_[browser_context]; |
1239 for (const auto& event_iter : map_for_browser_context) { | 1191 for (const auto& event_iter : map_for_browser_context) { |
1240 // Construct a listeners_to_delete vector so that we don't modify the set of | 1192 // Construct a listeners_to_delete vector so that we don't modify the set of |
1241 // listeners as we iterate through it. | 1193 // listeners as we iterate through it. |
1242 std::vector<EventListener> listeners_to_delete; | 1194 std::vector<EventListener::ID> listeners_to_delete; |
1243 const std::set<EventListener>& listeners = event_iter.second; | 1195 const Listeners& listeners = event_iter.second; |
1244 for (const auto& listener : listeners) { | 1196 for (const auto& listener : listeners) { |
1245 if (listener.embedder_process_id == embedder_process_id && | 1197 if (listener->id.embedder_process_id == embedder_process_id && |
1246 listener.web_view_instance_id == web_view_instance_id) { | 1198 listener->id.web_view_instance_id == web_view_instance_id) { |
1247 listeners_to_delete.push_back(listener); | 1199 listeners_to_delete.push_back(listener->id); |
1248 } | 1200 } |
1249 } | 1201 } |
1250 // Remove the listeners selected for deletion. | 1202 // Remove the listeners selected for deletion. |
1251 for (const auto& listener : listeners_to_delete) { | 1203 for (const auto& listener_id : listeners_to_delete) |
1252 RemoveEventListenerOnIOThread( | 1204 RemoveEventListener(listener_id, true /* strict */); |
1253 browser_context, | |
1254 listener.extension_id, | |
1255 listener.sub_event_name, | |
1256 listener.embedder_process_id, | |
1257 listener.web_view_instance_id); | |
1258 } | |
1259 } | 1205 } |
1260 } | 1206 } |
1261 | 1207 |
1262 void ExtensionWebRequestEventRouter::OnOTRBrowserContextCreated( | 1208 void ExtensionWebRequestEventRouter::OnOTRBrowserContextCreated( |
1263 void* original_browser_context, void* otr_browser_context) { | 1209 void* original_browser_context, void* otr_browser_context) { |
1264 cross_browser_context_map_[original_browser_context] = | 1210 cross_browser_context_map_[original_browser_context] = |
1265 std::make_pair(false, otr_browser_context); | 1211 std::make_pair(false, otr_browser_context); |
1266 cross_browser_context_map_[otr_browser_context] = | 1212 cross_browser_context_map_[otr_browser_context] = |
1267 std::make_pair(true, original_browser_context); | 1213 std::make_pair(true, original_browser_context); |
1268 } | 1214 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1324 const InfoMap* extension_info_map, | 1270 const InfoMap* extension_info_map, |
1325 bool crosses_incognito, | 1271 bool crosses_incognito, |
1326 const std::string& event_name, | 1272 const std::string& event_name, |
1327 const GURL& url, | 1273 const GURL& url, |
1328 int render_process_host_id, | 1274 int render_process_host_id, |
1329 int routing_id, | 1275 int routing_id, |
1330 content::ResourceType resource_type, | 1276 content::ResourceType resource_type, |
1331 bool is_async_request, | 1277 bool is_async_request, |
1332 bool is_request_from_extension, | 1278 bool is_request_from_extension, |
1333 int* extra_info_spec, | 1279 int* extra_info_spec, |
1334 EventListeners* matching_listeners) { | 1280 RawListeners* matching_listeners) { |
1335 std::string web_request_event_name(event_name); | 1281 std::string web_request_event_name(event_name); |
1336 WebViewRendererState::WebViewInfo web_view_info; | 1282 WebViewRendererState::WebViewInfo web_view_info; |
1337 bool is_web_view_guest = WebViewRendererState::GetInstance()->GetInfo( | 1283 bool is_web_view_guest = WebViewRendererState::GetInstance()->GetInfo( |
1338 render_process_host_id, routing_id, &web_view_info); | 1284 render_process_host_id, routing_id, &web_view_info); |
1339 if (is_web_view_guest) { | 1285 if (is_web_view_guest) { |
1340 web_request_event_name.replace( | 1286 web_request_event_name.replace( |
1341 0, sizeof(kWebRequestEventPrefix) - 1, webview::kWebViewEventPrefix); | 1287 0, sizeof(kWebRequestEventPrefix) - 1, webview::kWebViewEventPrefix); |
1342 } | 1288 } |
1343 | 1289 |
1344 std::set<EventListener>& listeners = | 1290 Listeners& listeners = listeners_[browser_context][web_request_event_name]; |
1345 listeners_[browser_context][web_request_event_name]; | 1291 for (std::unique_ptr<EventListener>& listener : listeners) { |
1346 for (const EventListener& listener : listeners) { | 1292 if (!listener->ipc_sender.get()) { |
1347 if (!listener.ipc_sender.get()) { | |
1348 // The IPC sender has been deleted. This listener will be removed soon | 1293 // The IPC sender has been deleted. This listener will be removed soon |
1349 // via a call to RemoveEventListener. For now, just skip it. | 1294 // via a call to RemoveEventListener. For now, just skip it. |
1350 continue; | 1295 continue; |
1351 } | 1296 } |
1352 | 1297 |
1353 if (is_web_view_guest && | 1298 if (is_web_view_guest && |
1354 (listener.embedder_process_id != web_view_info.embedder_process_id || | 1299 (listener->id.embedder_process_id != |
1355 listener.web_view_instance_id != web_view_info.instance_id)) { | 1300 web_view_info.embedder_process_id || |
| 1301 listener->id.web_view_instance_id != web_view_info.instance_id)) { |
1356 continue; | 1302 continue; |
1357 } | 1303 } |
1358 | 1304 |
1359 // Filter requests from other extensions / apps. This does not work for | 1305 // Filter requests from other extensions / apps. This does not work for |
1360 // content scripts, or extension pages in non-extension processes. | 1306 // content scripts, or extension pages in non-extension processes. |
1361 if (is_request_from_extension && | 1307 if (is_request_from_extension && |
1362 listener.embedder_process_id != render_process_host_id) { | 1308 listener->id.embedder_process_id != render_process_host_id) { |
1363 continue; | 1309 continue; |
1364 } | 1310 } |
1365 | 1311 |
1366 if (!listener.filter.urls.is_empty() && | 1312 if (!listener->filter.urls.is_empty() && |
1367 !listener.filter.urls.MatchesURL(url)) { | 1313 !listener->filter.urls.MatchesURL(url)) { |
1368 continue; | 1314 continue; |
1369 } | 1315 } |
1370 | 1316 |
1371 int render_process_id = -1; | 1317 int render_process_id = -1; |
1372 int render_frame_id = -1; | 1318 int render_frame_id = -1; |
1373 // TODO(devlin): Figure out when one/both of these can fail, and if we | 1319 // TODO(devlin): Figure out when one/both of these can fail, and if we |
1374 // need to address it. | 1320 // need to address it. |
1375 bool found_render_frame = | 1321 bool found_render_frame = |
1376 content::ResourceRequestInfo::GetRenderFrameForRequest( | 1322 content::ResourceRequestInfo::GetRenderFrameForRequest( |
1377 request, &render_process_id, &render_frame_id); | 1323 request, &render_process_id, &render_frame_id); |
1378 UMA_HISTOGRAM_BOOLEAN("Extensions.WebRequestEventFoundFrame", | 1324 UMA_HISTOGRAM_BOOLEAN("Extensions.WebRequestEventFoundFrame", |
1379 found_render_frame); | 1325 found_render_frame); |
1380 ExtensionApiFrameIdMap::FrameData frame_data; | 1326 ExtensionApiFrameIdMap::FrameData frame_data; |
1381 if (found_render_frame) { | 1327 if (found_render_frame) { |
1382 ExtensionApiFrameIdMap::Get()->GetCachedFrameDataOnIO( | 1328 ExtensionApiFrameIdMap::Get()->GetCachedFrameDataOnIO( |
1383 render_process_id, render_frame_id, &frame_data); | 1329 render_process_id, render_frame_id, &frame_data); |
1384 } | 1330 } |
1385 // Check if the tab id and window id match, if they were set in the | 1331 // Check if the tab id and window id match, if they were set in the |
1386 // listener params. | 1332 // listener params. |
1387 if ((listener.filter.tab_id != -1 && | 1333 if ((listener->filter.tab_id != -1 && |
1388 frame_data.tab_id != listener.filter.tab_id) || | 1334 frame_data.tab_id != listener->filter.tab_id) || |
1389 (listener.filter.window_id != -1 && | 1335 (listener->filter.window_id != -1 && |
1390 frame_data.window_id != listener.filter.window_id)) { | 1336 frame_data.window_id != listener->filter.window_id)) { |
1391 continue; | 1337 continue; |
1392 } | 1338 } |
1393 | 1339 |
1394 const std::vector<content::ResourceType>& types = listener.filter.types; | 1340 const std::vector<content::ResourceType>& types = listener->filter.types; |
1395 if (!types.empty() && | 1341 if (!types.empty() && |
1396 std::find(types.begin(), types.end(), resource_type) == types.end()) { | 1342 std::find(types.begin(), types.end(), resource_type) == types.end()) { |
1397 continue; | 1343 continue; |
1398 } | 1344 } |
1399 | 1345 |
1400 if (!is_web_view_guest) { | 1346 if (!is_web_view_guest) { |
1401 PermissionsData::AccessType access = | 1347 PermissionsData::AccessType access = |
1402 WebRequestPermissions::CanExtensionAccessURL( | 1348 WebRequestPermissions::CanExtensionAccessURL( |
1403 extension_info_map, listener.extension_id, url, frame_data.tab_id, | 1349 extension_info_map, listener->id.extension_id, url, |
1404 crosses_incognito, | 1350 frame_data.tab_id, crosses_incognito, |
1405 WebRequestPermissions::REQUIRE_HOST_PERMISSION); | 1351 WebRequestPermissions::REQUIRE_HOST_PERMISSION); |
1406 if (access != PermissionsData::ACCESS_ALLOWED) { | 1352 if (access != PermissionsData::ACCESS_ALLOWED) { |
1407 if (access == PermissionsData::ACCESS_WITHHELD && | 1353 if (access == PermissionsData::ACCESS_WITHHELD && |
1408 web_request_event_router_delegate_) { | 1354 web_request_event_router_delegate_) { |
1409 web_request_event_router_delegate_->NotifyWebRequestWithheld( | 1355 web_request_event_router_delegate_->NotifyWebRequestWithheld( |
1410 render_process_id, render_frame_id, listener.extension_id); | 1356 render_process_id, render_frame_id, listener->id.extension_id); |
1411 } | 1357 } |
1412 continue; | 1358 continue; |
1413 } | 1359 } |
1414 } | 1360 } |
1415 | 1361 |
1416 bool blocking_listener = | 1362 bool blocking_listener = |
1417 (listener.extra_info_spec & | 1363 (listener->extra_info_spec & |
1418 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0; | 1364 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0; |
1419 | 1365 |
1420 // We do not want to notify extensions about XHR requests that are | 1366 // We do not want to notify extensions about XHR requests that are |
1421 // triggered by themselves. This is a workaround to prevent deadlocks | 1367 // triggered by themselves. This is a workaround to prevent deadlocks |
1422 // in case of synchronous XHR requests that block the extension renderer | 1368 // in case of synchronous XHR requests that block the extension renderer |
1423 // and therefore prevent the extension from processing the request | 1369 // and therefore prevent the extension from processing the request |
1424 // handler. This is only a problem for blocking listeners. | 1370 // handler. This is only a problem for blocking listeners. |
1425 // http://crbug.com/105656 | 1371 // http://crbug.com/105656 |
1426 bool synchronous_xhr_from_extension = | 1372 bool synchronous_xhr_from_extension = |
1427 !is_async_request && is_request_from_extension && | 1373 !is_async_request && is_request_from_extension && |
1428 resource_type == content::RESOURCE_TYPE_XHR; | 1374 resource_type == content::RESOURCE_TYPE_XHR; |
1429 | 1375 |
1430 // Only send webRequest events for URLs the extension has access to. | 1376 // Only send webRequest events for URLs the extension has access to. |
1431 if (blocking_listener && synchronous_xhr_from_extension) | 1377 if (blocking_listener && synchronous_xhr_from_extension) |
1432 continue; | 1378 continue; |
1433 | 1379 |
1434 matching_listeners->push_back(&listener); | 1380 matching_listeners->push_back(listener.get()); |
1435 *extra_info_spec |= listener.extra_info_spec; | 1381 *extra_info_spec |= listener->extra_info_spec; |
1436 } | 1382 } |
1437 } | 1383 } |
1438 | 1384 |
1439 ExtensionWebRequestEventRouter::EventListeners | 1385 ExtensionWebRequestEventRouter::RawListeners |
1440 ExtensionWebRequestEventRouter::GetMatchingListeners( | 1386 ExtensionWebRequestEventRouter::GetMatchingListeners( |
1441 void* browser_context, | 1387 void* browser_context, |
1442 const InfoMap* extension_info_map, | 1388 const InfoMap* extension_info_map, |
1443 const std::string& event_name, | 1389 const std::string& event_name, |
1444 const net::URLRequest* request, | 1390 const net::URLRequest* request, |
1445 int* extra_info_spec) { | 1391 int* extra_info_spec) { |
1446 // TODO(mpcomplete): handle browser_context == NULL (should collect all | 1392 // TODO(mpcomplete): handle browser_context == NULL (should collect all |
1447 // listeners). | 1393 // listeners). |
1448 *extra_info_spec = 0; | 1394 *extra_info_spec = 0; |
1449 | 1395 |
1450 const GURL& url = request->url(); | 1396 const GURL& url = request->url(); |
1451 int render_process_host_id = content::ChildProcessHost::kInvalidUniqueID; | 1397 int render_process_host_id = content::ChildProcessHost::kInvalidUniqueID; |
1452 int routing_id = MSG_ROUTING_NONE; | 1398 int routing_id = MSG_ROUTING_NONE; |
1453 content::ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE; | 1399 content::ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE; |
1454 // We are conservative here and assume requests are asynchronous in case | 1400 // We are conservative here and assume requests are asynchronous in case |
1455 // we don't have an info object. We don't want to risk a deadlock. | 1401 // we don't have an info object. We don't want to risk a deadlock. |
1456 bool is_async_request = false; | 1402 bool is_async_request = false; |
1457 bool is_request_from_extension = | 1403 bool is_request_from_extension = |
1458 IsRequestFromExtension(request, extension_info_map); | 1404 IsRequestFromExtension(request, extension_info_map); |
1459 | 1405 |
1460 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); | 1406 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); |
1461 if (info) { | 1407 if (info) { |
1462 is_async_request = info->IsAsync(); | 1408 is_async_request = info->IsAsync(); |
1463 if (helpers::IsRelevantResourceType(info->GetResourceType())) | 1409 if (helpers::IsRelevantResourceType(info->GetResourceType())) |
1464 resource_type = info->GetResourceType(); | 1410 resource_type = info->GetResourceType(); |
1465 render_process_host_id = info->GetChildID(); | 1411 render_process_host_id = info->GetChildID(); |
1466 routing_id = info->GetRouteID(); | 1412 routing_id = info->GetRouteID(); |
1467 } | 1413 } |
1468 | 1414 |
1469 EventListeners matching_listeners; | 1415 RawListeners matching_listeners; |
1470 GetMatchingListenersImpl( | 1416 GetMatchingListenersImpl( |
1471 browser_context, request, extension_info_map, false, event_name, | 1417 browser_context, request, extension_info_map, false, event_name, |
1472 url, render_process_host_id, routing_id, resource_type, | 1418 url, render_process_host_id, routing_id, resource_type, |
1473 is_async_request, is_request_from_extension, extra_info_spec, | 1419 is_async_request, is_request_from_extension, extra_info_spec, |
1474 &matching_listeners); | 1420 &matching_listeners); |
1475 void* cross_browser_context = GetCrossBrowserContext(browser_context); | 1421 void* cross_browser_context = GetCrossBrowserContext(browser_context); |
1476 if (cross_browser_context) { | 1422 if (cross_browser_context) { |
1477 GetMatchingListenersImpl( | 1423 GetMatchingListenersImpl( |
1478 cross_browser_context, request, extension_info_map, true, event_name, | 1424 cross_browser_context, request, extension_info_map, true, event_name, |
1479 url, render_process_host_id, routing_id, resource_type, | 1425 url, render_process_host_id, routing_id, resource_type, |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1678 // declarative rules to be read from disk. | 1624 // declarative rules to be read from disk. |
1679 UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayStartup", block_time); | 1625 UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayStartup", block_time); |
1680 } | 1626 } |
1681 | 1627 |
1682 if (num_handlers_blocking == 0) { | 1628 if (num_handlers_blocking == 0) { |
1683 blocked_request.request->LogUnblocked(); | 1629 blocked_request.request->LogUnblocked(); |
1684 ExecuteDeltas(browser_context, request_id, true); | 1630 ExecuteDeltas(browser_context, request_id, true); |
1685 } else { | 1631 } else { |
1686 // Update the URLRequest to make sure it's tagged with an extension that's | 1632 // Update the URLRequest to make sure it's tagged with an extension that's |
1687 // still blocking it. This may end up being the same extension as before. | 1633 // still blocking it. This may end up being the same extension as before. |
1688 std::set<EventListener>& listeners = | 1634 Listeners& listeners = listeners_[browser_context][event_name]; |
1689 listeners_[browser_context][event_name]; | |
1690 | 1635 |
1691 for (const auto& listener : listeners) { | 1636 for (const auto& listener : listeners) { |
1692 if (!base::ContainsKey(listener.blocked_requests, request_id)) | 1637 if (!base::ContainsKey(listener->blocked_requests, request_id)) |
1693 continue; | 1638 continue; |
1694 std::string delegate_info = | 1639 std::string delegate_info = l10n_util::GetStringFUTF8( |
1695 l10n_util::GetStringFUTF8(IDS_LOAD_STATE_PARAMETER_EXTENSION, | 1640 IDS_LOAD_STATE_PARAMETER_EXTENSION, |
1696 base::UTF8ToUTF16(listener.extension_name)); | 1641 base::UTF8ToUTF16(listener->extension_name)); |
1697 blocked_request.request->LogAndReportBlockedBy(delegate_info.c_str()); | 1642 blocked_request.request->LogAndReportBlockedBy(delegate_info.c_str()); |
1698 break; | 1643 break; |
1699 } | 1644 } |
1700 } | 1645 } |
1701 } | 1646 } |
1702 | 1647 |
1703 void ExtensionWebRequestEventRouter::SendMessages( | 1648 void ExtensionWebRequestEventRouter::SendMessages( |
1704 void* browser_context, | 1649 void* browser_context, |
1705 const BlockedRequest& blocked_request) { | 1650 const BlockedRequest& blocked_request) { |
1706 const helpers::EventResponseDeltas& deltas = blocked_request.response_deltas; | 1651 const helpers::EventResponseDeltas& deltas = blocked_request.response_deltas; |
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2284 // Continue gracefully. | 2229 // Continue gracefully. |
2285 RunWithValidation()->Execute(); | 2230 RunWithValidation()->Execute(); |
2286 } | 2231 } |
2287 | 2232 |
2288 ExtensionFunction::ResponseAction | 2233 ExtensionFunction::ResponseAction |
2289 WebRequestHandlerBehaviorChangedFunction::Run() { | 2234 WebRequestHandlerBehaviorChangedFunction::Run() { |
2290 helpers::ClearCacheOnNavigation(); | 2235 helpers::ClearCacheOnNavigation(); |
2291 return RespondNow(NoArguments()); | 2236 return RespondNow(NoArguments()); |
2292 } | 2237 } |
2293 | 2238 |
| 2239 ExtensionWebRequestEventRouter::EventListener::ID::ID( |
| 2240 void* browser_context, |
| 2241 const std::string& extension_id, |
| 2242 const std::string& sub_event_name, |
| 2243 int embedder_process_id, |
| 2244 int web_view_instance_id) |
| 2245 : browser_context(browser_context), |
| 2246 extension_id(extension_id), |
| 2247 sub_event_name(sub_event_name), |
| 2248 embedder_process_id(embedder_process_id), |
| 2249 web_view_instance_id(web_view_instance_id) {} |
| 2250 |
| 2251 bool ExtensionWebRequestEventRouter::EventListener::ID::LooselyMatches( |
| 2252 const ID& that) const { |
| 2253 if (web_view_instance_id == 0 && that.web_view_instance_id == 0) { |
| 2254 // Since EventListeners are segmented by browser_context, check that |
| 2255 // last, as it is exceedingly unlikely to be different. |
| 2256 return extension_id == that.extension_id && |
| 2257 sub_event_name == that.sub_event_name && |
| 2258 browser_context == that.browser_context; |
| 2259 } |
| 2260 |
| 2261 return *this == that; |
| 2262 } |
| 2263 |
| 2264 bool ExtensionWebRequestEventRouter::EventListener::ID::operator==( |
| 2265 const ID& that) const { |
| 2266 // Since EventListeners are segmented by browser_context, check that |
| 2267 // last, as it is exceedingly unlikely to be different. |
| 2268 return extension_id == that.extension_id && |
| 2269 sub_event_name == that.sub_event_name && |
| 2270 web_view_instance_id == that.web_view_instance_id && |
| 2271 embedder_process_id == that.embedder_process_id && |
| 2272 browser_context == that.browser_context; |
| 2273 } |
| 2274 |
2294 } // namespace extensions | 2275 } // namespace extensions |
OLD | NEW |