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::Identifier 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)); | |
378 } | 367 } |
379 | 368 |
380 // Represents a single unique listener to an event, along with whatever filter | 369 // 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 | 370 // parameters and extra_info_spec were specified at the time the listener was |
382 // added. | 371 // added. |
383 // NOTE(benjhayden) New APIs should not use this sub_event_name trick! It does | 372 // 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 | 373 // not play well with event pages. See downloads.onDeterminingFilename and |
385 // ExtensionDownloadsEventRouter for an alternative approach. | 374 // ExtensionDownloadsEventRouter for an alternative approach. |
386 struct ExtensionWebRequestEventRouter::EventListener { | 375 ExtensionWebRequestEventRouter::EventListener::EventListener(Identifier id) |
387 std::string extension_id; | 376 : id(id) {} |
388 std::string extension_name; | 377 ExtensionWebRequestEventRouter::EventListener::~EventListener() {} |
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 ListenerIdentifiers 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 ListenerIdentifiers 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 ListenerIdentifiers 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 ListenerIdentifiers 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 ListenerIdentifiers 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 ListenerIdentifiers 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 ListenerIdentifiers 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 ListenerIdentifiers 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 ListenerIdentifiers 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 ListenerIdentifiers& 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 for (const EventListener::Identifier& id : listeners) { |
1036 new std::vector<EventListener>()); | 984 EventListener* listener = FindEventListener(id); |
Devlin
2016/09/07 19:18:00
This makes me a bit sad, because it means we have
erikchen
2016/09/07 22:07:42
yup, done.
| |
1037 listeners_to_dispatch->reserve(listeners.size()); | |
1038 for (const EventListener* listener : listeners) { | |
1039 listeners_to_dispatch->push_back(*listener); | |
1040 if (listener->extra_info_spec & | 985 if (listener->extra_info_spec & |
1041 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) { | 986 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) { |
1042 listener->blocked_requests.insert(request->identifier()); | 987 listener->blocked_requests.insert(request->identifier()); |
1043 // If this is the first delegate blocking the request, go ahead and log | 988 // If this is the first delegate blocking the request, go ahead and log |
1044 // it. | 989 // it. |
1045 if (num_handlers_blocking == 0) { | 990 if (num_handlers_blocking == 0) { |
1046 std::string delegate_info = l10n_util::GetStringFUTF8( | 991 std::string delegate_info = l10n_util::GetStringFUTF8( |
1047 IDS_LOAD_STATE_PARAMETER_EXTENSION, | 992 IDS_LOAD_STATE_PARAMETER_EXTENSION, |
1048 base::UTF8ToUTF16(listener->extension_name)); | 993 base::UTF8ToUTF16(listener->extension_name)); |
1049 // LobAndReport allows extensions that block requests to be displayed in | 994 // LobAndReport allows extensions that block requests to be displayed in |
1050 // the load status bar. | 995 // the load status bar. |
1051 request->LogAndReportBlockedBy(delegate_info.c_str()); | 996 request->LogAndReportBlockedBy(delegate_info.c_str()); |
1052 } | 997 } |
1053 ++num_handlers_blocking; | 998 ++num_handlers_blocking; |
1054 } | 999 } |
1055 } | 1000 } |
1056 | 1001 |
1057 event_details.release()->DetermineFrameDataOnIO(base::Bind( | 1002 event_details.release()->DetermineFrameDataOnIO( |
1058 &ExtensionWebRequestEventRouter::DispatchEventToListeners, AsWeakPtr(), | 1003 base::Bind(&ExtensionWebRequestEventRouter::DispatchEventToListeners, |
1059 browser_context, base::Passed(&listeners_to_dispatch))); | 1004 AsWeakPtr(), browser_context, listeners)); |
Devlin
2016/09/07 19:18:00
Optimization: Shame about the copy this causes on
erikchen
2016/09/07 22:07:42
Done.
| |
1060 | 1005 |
1061 if (num_handlers_blocking > 0) { | 1006 if (num_handlers_blocking > 0) { |
1062 BlockedRequest& blocked_request = blocked_requests_[request->identifier()]; | 1007 BlockedRequest& blocked_request = blocked_requests_[request->identifier()]; |
1063 blocked_request.request = request; | 1008 blocked_request.request = request; |
1064 blocked_request.is_incognito |= IsIncognitoBrowserContext(browser_context); | 1009 blocked_request.is_incognito |= IsIncognitoBrowserContext(browser_context); |
1065 blocked_request.num_handlers_blocking += num_handlers_blocking; | 1010 blocked_request.num_handlers_blocking += num_handlers_blocking; |
1066 blocked_request.blocking_time = base::Time::Now(); | 1011 blocked_request.blocking_time = base::Time::Now(); |
1067 return true; | 1012 return true; |
1068 } | 1013 } |
1069 | 1014 |
1070 return false; | 1015 return false; |
1071 } | 1016 } |
1072 | 1017 |
1073 void ExtensionWebRequestEventRouter::DispatchEventToListeners( | 1018 void ExtensionWebRequestEventRouter::DispatchEventToListeners( |
1074 void* browser_context, | 1019 void* browser_context, |
1075 std::unique_ptr<std::vector<EventListener>> listeners, | 1020 const ListenerIdentifiers& listener_ids, |
1076 std::unique_ptr<WebRequestEventDetails> event_details) { | 1021 std::unique_ptr<WebRequestEventDetails> event_details) { |
1077 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1022 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1078 DCHECK(listeners.get()); | 1023 DCHECK_GT(listener_ids.size(), 0UL); |
Devlin
2016/09/07 19:18:00
nit: DCHECK(!listener_ids.empty())
erikchen
2016/09/07 22:07:42
Done.
| |
1079 DCHECK_GT(listeners->size(), 0UL); | |
1080 DCHECK(event_details.get()); | 1024 DCHECK(event_details.get()); |
1081 | 1025 |
1082 std::string event_name = | 1026 std::string event_name = |
1083 EventRouter::GetBaseEventName((*listeners)[0].sub_event_name); | 1027 EventRouter::GetBaseEventName(listener_ids[0].sub_event_name); |
1084 DCHECK(IsWebRequestEvent(event_name)); | 1028 DCHECK(IsWebRequestEvent(event_name)); |
1085 | 1029 |
1086 const std::set<EventListener>& event_listeners = | 1030 const Listeners& event_listeners = listeners_[browser_context][event_name]; |
1087 listeners_[browser_context][event_name]; | |
1088 void* cross_browser_context = GetCrossBrowserContext(browser_context); | 1031 void* cross_browser_context = GetCrossBrowserContext(browser_context); |
1089 const std::set<EventListener>* cross_event_listeners = | 1032 const Listeners* cross_event_listeners = |
1090 cross_browser_context ? &listeners_[cross_browser_context][event_name] | 1033 cross_browser_context ? &listeners_[cross_browser_context][event_name] |
1091 : nullptr; | 1034 : nullptr; |
1092 | 1035 |
1093 for (const EventListener& target : *listeners) { | 1036 for (const EventListener::Identifier& id : listener_ids) { |
1094 std::set<EventListener>::const_iterator listener = | 1037 // It's possible that the listener is no longer present. Check to make sure |
1095 event_listeners.find(target); | 1038 // it's still there. |
1096 // Ignore listener if it was removed between the thread hops. | 1039 const EventListener* listener = nullptr; |
1097 if (listener == event_listeners.end()) { | 1040 for (const std::unique_ptr<EventListener>& event_listener : |
Devlin
2016/09/07 19:18:00
Worth making a FindEventListenerInSet() helper fun
erikchen
2016/09/07 22:07:42
yes, done.
| |
1098 if (!cross_event_listeners) | 1041 event_listeners) { |
1099 continue; | 1042 if (event_listener->id == id) { |
1100 listener = cross_event_listeners->find(target); | 1043 listener = event_listener.get(); |
1101 if (listener == cross_event_listeners->end()) | 1044 break; |
1102 continue; | 1045 } |
1103 } | 1046 } |
1047 if (!listener) { | |
1048 for (const std::unique_ptr<EventListener>& event_listener : | |
1049 *cross_event_listeners) { | |
1050 if (event_listener->id == id) { | |
1051 listener = event_listener.get(); | |
1052 break; | |
1053 } | |
1054 } | |
1055 } | |
1056 if (!listener) | |
1057 continue; | |
1104 | 1058 |
1105 if (!listener->ipc_sender.get()) | 1059 if (!listener->ipc_sender.get()) |
1106 continue; | 1060 continue; |
1107 | 1061 |
1108 // Filter out the optional keys that this listener didn't request. | 1062 // Filter out the optional keys that this listener didn't request. |
1109 std::unique_ptr<base::ListValue> args_filtered(new base::ListValue); | 1063 std::unique_ptr<base::ListValue> args_filtered(new base::ListValue); |
1110 args_filtered->Append( | 1064 args_filtered->Append( |
1111 event_details->GetFilteredDict(listener->extra_info_spec)); | 1065 event_details->GetFilteredDict(listener->extra_info_spec)); |
1112 | 1066 |
1113 EventRouter::DispatchEventToSender( | 1067 EventRouter::DispatchEventToSender( |
1114 listener->ipc_sender.get(), browser_context, listener->extension_id, | 1068 listener->ipc_sender.get(), browser_context, listener->id.extension_id, |
1115 listener->histogram_value, listener->sub_event_name, | 1069 listener->histogram_value, listener->id.sub_event_name, |
1116 std::move(args_filtered), EventRouter::USER_GESTURE_UNKNOWN, | 1070 std::move(args_filtered), EventRouter::USER_GESTURE_UNKNOWN, |
1117 EventFilteringInfo()); | 1071 EventFilteringInfo()); |
1118 } | 1072 } |
1119 } | 1073 } |
1120 | 1074 |
1121 void ExtensionWebRequestEventRouter::OnEventHandled( | 1075 void ExtensionWebRequestEventRouter::OnEventHandled( |
1122 void* browser_context, | 1076 void* browser_context, |
1123 const std::string& extension_id, | 1077 const std::string& extension_id, |
1124 const std::string& event_name, | 1078 const std::string& event_name, |
1125 const std::string& sub_event_name, | 1079 const std::string& sub_event_name, |
1126 uint64_t request_id, | 1080 uint64_t request_id, |
1127 EventResponse* response) { | 1081 EventResponse* response) { |
1128 // TODO(robwu): Does this also work with webviews? operator< (used by find) | 1082 // TODO(robwu): This ignores WebViews. |
1129 // takes the webview ID into account, which is not set on |listener|. | 1083 Listeners& listeners = listeners_[browser_context][event_name]; |
1130 EventListener listener; | 1084 EventListener::Identifier id(browser_context, extension_id, sub_event_name, 0, |
1131 listener.extension_id = extension_id; | 1085 0); |
1132 listener.sub_event_name = sub_event_name; | 1086 for (auto it = listeners.begin(); it != listeners.end(); ++it) { |
1133 | 1087 if ((*it)->id.LooselyMatches(id)) { |
1134 // The listener may have been removed (e.g. due to the process going away) | 1088 (*it)->blocked_requests.erase(request_id); |
1135 // before we got here. | 1089 } |
1136 std::set<EventListener>::iterator found = | 1090 } |
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 | 1091 |
1141 DecrementBlockCount( | 1092 DecrementBlockCount( |
1142 browser_context, extension_id, event_name, request_id, response); | 1093 browser_context, extension_id, event_name, request_id, response); |
1143 } | 1094 } |
1144 | 1095 |
1145 bool ExtensionWebRequestEventRouter::AddEventListener( | 1096 bool ExtensionWebRequestEventRouter::AddEventListener( |
1146 void* browser_context, | 1097 void* browser_context, |
1147 const std::string& extension_id, | 1098 const std::string& extension_id, |
1148 const std::string& extension_name, | 1099 const std::string& extension_name, |
1149 events::HistogramValue histogram_value, | 1100 events::HistogramValue histogram_value, |
1150 const std::string& event_name, | 1101 const std::string& event_name, |
1151 const std::string& sub_event_name, | 1102 const std::string& sub_event_name, |
1152 const RequestFilter& filter, | 1103 const RequestFilter& filter, |
1153 int extra_info_spec, | 1104 int extra_info_spec, |
1154 int embedder_process_id, | 1105 int embedder_process_id, |
1155 int web_view_instance_id, | 1106 int web_view_instance_id, |
1156 base::WeakPtr<IPC::Sender> ipc_sender) { | 1107 base::WeakPtr<IPC::Sender> ipc_sender) { |
1157 if (!IsWebRequestEvent(event_name)) | 1108 if (!IsWebRequestEvent(event_name)) |
1158 return false; | 1109 return false; |
1159 | 1110 |
1160 EventListener listener; | 1111 if (event_name != EventRouter::GetBaseEventName(sub_event_name)) |
1161 listener.extension_id = extension_id; | 1112 return false; |
1162 listener.extension_name = extension_name; | 1113 |
1163 listener.histogram_value = histogram_value; | 1114 EventListener::Identifier id(browser_context, extension_id, sub_event_name, |
1164 listener.sub_event_name = sub_event_name; | 1115 embedder_process_id, web_view_instance_id); |
1165 listener.filter = filter; | 1116 std::unique_ptr<EventListener> listener(new EventListener(id)); |
1166 listener.extra_info_spec = extra_info_spec; | 1117 listener->extension_name = extension_name; |
1167 listener.ipc_sender = ipc_sender; | 1118 listener->histogram_value = histogram_value; |
1168 listener.embedder_process_id = embedder_process_id; | 1119 listener->filter = filter; |
1169 listener.web_view_instance_id = web_view_instance_id; | 1120 listener->extra_info_spec = extra_info_spec; |
1170 if (listener.web_view_instance_id) { | 1121 listener->ipc_sender = ipc_sender; |
1122 if (listener->id.web_view_instance_id) { | |
1171 content::RecordAction( | 1123 content::RecordAction( |
1172 base::UserMetricsAction("WebView.WebRequest.AddListener")); | 1124 base::UserMetricsAction("WebView.WebRequest.AddListener")); |
1173 } | 1125 } |
1174 | 1126 |
1175 if (base::ContainsKey(listeners_[browser_context][event_name], listener)) { | 1127 if (FindEventListener(id) != nullptr) { |
1176 // This is likely an abuse of the API by a malicious extension. | 1128 // This is likely an abuse of the API by a malicious extension. |
1177 return false; | 1129 return false; |
1178 } | 1130 } |
1179 listeners_[browser_context][event_name].insert(listener); | 1131 listeners_[browser_context][event_name].push_back(std::move(listener)); |
1180 return true; | 1132 return true; |
1181 } | 1133 } |
1182 | 1134 |
1135 size_t ExtensionWebRequestEventRouter::GetListenerCountForTesting( | |
1136 void* browser_context, | |
1137 const std::string& event_name) { | |
1138 return listeners_[browser_context][event_name].size(); | |
1139 } | |
1140 | |
1141 ExtensionWebRequestEventRouter::EventListener* | |
1142 ExtensionWebRequestEventRouter::FindEventListener( | |
1143 const EventListener::Identifier& id) { | |
1144 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
1145 std::string event_name = EventRouter::GetBaseEventName(id.sub_event_name); | |
1146 Listeners& listeners = listeners_[id.browser_context][event_name]; | |
1147 for (auto it = listeners.begin(); it != listeners.end(); ++it) { | |
1148 if ((*it)->id == id) { | |
1149 return it->get(); | |
1150 } | |
1151 } | |
1152 return nullptr; | |
1153 } | |
1154 | |
1183 void ExtensionWebRequestEventRouter::RemoveEventListener( | 1155 void ExtensionWebRequestEventRouter::RemoveEventListener( |
1184 void* browser_context, | 1156 const EventListener::Identifier& id) { |
1185 const std::string& extension_id, | 1157 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1186 const std::string& sub_event_name, | |
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 | 1158 |
1192 EventListener listener; | 1159 std::string event_name = EventRouter::GetBaseEventName(id.sub_event_name); |
1193 listener.extension_id = extension_id; | 1160 Listeners& listeners = listeners_[id.browser_context][event_name]; |
1194 listener.sub_event_name = sub_event_name; | 1161 for (auto it = listeners.begin(); it != listeners.end(); ++it) { |
1195 listener.embedder_process_id = embedder_process_id; | 1162 std::unique_ptr<EventListener>& listener = *it; |
1196 listener.web_view_instance_id = web_view_instance_id; | 1163 if (listener->id.LooselyMatches(id)) { |
1164 // Unblock any request that this event listener may have been blocking. | |
1165 for (uint64_t blocked_request_id : listener->blocked_requests) | |
1166 DecrementBlockCount(listener->id.browser_context, | |
1167 listener->id.extension_id, event_name, | |
1168 blocked_request_id, NULL); | |
1197 | 1169 |
1198 std::set<EventListener>& event_listeners = | 1170 listeners.erase(it); |
1199 listeners_[browser_context][event_name]; | 1171 helpers::ClearCacheOnNavigation(); |
1200 // It's possible for AddEventListener to fail asynchronously. In that case, | 1172 return; |
1201 // the renderer believes the listener exists, while the browser does not. | 1173 } |
1202 // Ignore a RemoveEventListener in that case. | 1174 } |
1203 std::set<EventListener>::const_iterator it = event_listeners.find(listener); | |
1204 if (it == event_listeners.end()) | |
1205 return; | |
1206 | |
1207 #if defined(OS_WIN) | |
1208 // Debugging https://crbug.com/589735 | |
1209 // Please post crash reports at the following lines to the above issue. | |
1210 unsigned event_listener_count = event_listeners.count(listener); | |
1211 CHECK_GE(event_listener_count, 0u); | |
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 } | 1175 } |
1228 | 1176 |
1229 void ExtensionWebRequestEventRouter::RemoveWebViewEventListeners( | 1177 void ExtensionWebRequestEventRouter::RemoveWebViewEventListeners( |
1230 void* browser_context, | 1178 void* browser_context, |
1231 int embedder_process_id, | 1179 int embedder_process_id, |
1232 int web_view_instance_id) { | 1180 int web_view_instance_id) { |
1233 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1181 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1234 | 1182 |
1235 // Iterate over all listeners of all WebRequest events to delete | 1183 // Iterate over all listeners of all WebRequest events to delete |
1236 // any listeners that belong to the provided <webview>. | 1184 // any listeners that belong to the provided <webview>. |
1237 ListenerMapForBrowserContext& map_for_browser_context = | 1185 ListenerMapForBrowserContext& map_for_browser_context = |
1238 listeners_[browser_context]; | 1186 listeners_[browser_context]; |
1239 for (const auto& event_iter : map_for_browser_context) { | 1187 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 | 1188 // Construct a listeners_to_delete vector so that we don't modify the set of |
1241 // listeners as we iterate through it. | 1189 // listeners as we iterate through it. |
1242 std::vector<EventListener> listeners_to_delete; | 1190 std::vector<EventListener::Identifier> listeners_to_delete; |
1243 const std::set<EventListener>& listeners = event_iter.second; | 1191 const Listeners& listeners = event_iter.second; |
1244 for (const auto& listener : listeners) { | 1192 for (const auto& listener : listeners) { |
1245 if (listener.embedder_process_id == embedder_process_id && | 1193 if (listener->id.embedder_process_id == embedder_process_id && |
1246 listener.web_view_instance_id == web_view_instance_id) { | 1194 listener->id.web_view_instance_id == web_view_instance_id) { |
1247 listeners_to_delete.push_back(listener); | 1195 listeners_to_delete.push_back(listener->id); |
1248 } | 1196 } |
1249 } | 1197 } |
1250 // Remove the listeners selected for deletion. | 1198 // Remove the listeners selected for deletion. |
1251 for (const auto& listener : listeners_to_delete) { | 1199 for (const auto& listener_id : listeners_to_delete) |
1252 RemoveEventListenerOnIOThread( | 1200 RemoveEventListener(listener_id); |
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 } | 1201 } |
1260 } | 1202 } |
1261 | 1203 |
1262 void ExtensionWebRequestEventRouter::OnOTRBrowserContextCreated( | 1204 void ExtensionWebRequestEventRouter::OnOTRBrowserContextCreated( |
1263 void* original_browser_context, void* otr_browser_context) { | 1205 void* original_browser_context, void* otr_browser_context) { |
1264 cross_browser_context_map_[original_browser_context] = | 1206 cross_browser_context_map_[original_browser_context] = |
1265 std::make_pair(false, otr_browser_context); | 1207 std::make_pair(false, otr_browser_context); |
1266 cross_browser_context_map_[otr_browser_context] = | 1208 cross_browser_context_map_[otr_browser_context] = |
1267 std::make_pair(true, original_browser_context); | 1209 std::make_pair(true, original_browser_context); |
1268 } | 1210 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1324 const InfoMap* extension_info_map, | 1266 const InfoMap* extension_info_map, |
1325 bool crosses_incognito, | 1267 bool crosses_incognito, |
1326 const std::string& event_name, | 1268 const std::string& event_name, |
1327 const GURL& url, | 1269 const GURL& url, |
1328 int render_process_host_id, | 1270 int render_process_host_id, |
1329 int routing_id, | 1271 int routing_id, |
1330 content::ResourceType resource_type, | 1272 content::ResourceType resource_type, |
1331 bool is_async_request, | 1273 bool is_async_request, |
1332 bool is_request_from_extension, | 1274 bool is_request_from_extension, |
1333 int* extra_info_spec, | 1275 int* extra_info_spec, |
1334 EventListeners* matching_listeners) { | 1276 ListenerIdentifiers* matching_listeners) { |
1335 std::string web_request_event_name(event_name); | 1277 std::string web_request_event_name(event_name); |
1336 WebViewRendererState::WebViewInfo web_view_info; | 1278 WebViewRendererState::WebViewInfo web_view_info; |
1337 bool is_web_view_guest = WebViewRendererState::GetInstance()->GetInfo( | 1279 bool is_web_view_guest = WebViewRendererState::GetInstance()->GetInfo( |
1338 render_process_host_id, routing_id, &web_view_info); | 1280 render_process_host_id, routing_id, &web_view_info); |
1339 if (is_web_view_guest) { | 1281 if (is_web_view_guest) { |
1340 web_request_event_name.replace( | 1282 web_request_event_name.replace( |
1341 0, sizeof(kWebRequestEventPrefix) - 1, webview::kWebViewEventPrefix); | 1283 0, sizeof(kWebRequestEventPrefix) - 1, webview::kWebViewEventPrefix); |
1342 } | 1284 } |
1343 | 1285 |
1344 std::set<EventListener>& listeners = | 1286 Listeners& listeners = listeners_[browser_context][web_request_event_name]; |
1345 listeners_[browser_context][web_request_event_name]; | 1287 for (const std::unique_ptr<EventListener>& listener : listeners) { |
1346 for (const EventListener& listener : listeners) { | 1288 if (!listener->ipc_sender.get()) { |
1347 if (!listener.ipc_sender.get()) { | |
1348 // The IPC sender has been deleted. This listener will be removed soon | 1289 // The IPC sender has been deleted. This listener will be removed soon |
1349 // via a call to RemoveEventListener. For now, just skip it. | 1290 // via a call to RemoveEventListener. For now, just skip it. |
1350 continue; | 1291 continue; |
1351 } | 1292 } |
1352 | 1293 |
1353 if (is_web_view_guest && | 1294 if (is_web_view_guest && |
1354 (listener.embedder_process_id != web_view_info.embedder_process_id || | 1295 (listener->id.embedder_process_id != |
1355 listener.web_view_instance_id != web_view_info.instance_id)) { | 1296 web_view_info.embedder_process_id || |
1297 listener->id.web_view_instance_id != web_view_info.instance_id)) { | |
1356 continue; | 1298 continue; |
1357 } | 1299 } |
1358 | 1300 |
1359 // Filter requests from other extensions / apps. This does not work for | 1301 // Filter requests from other extensions / apps. This does not work for |
1360 // content scripts, or extension pages in non-extension processes. | 1302 // content scripts, or extension pages in non-extension processes. |
1361 if (is_request_from_extension && | 1303 if (is_request_from_extension && |
1362 listener.embedder_process_id != render_process_host_id) { | 1304 listener->id.embedder_process_id != render_process_host_id) { |
1363 continue; | 1305 continue; |
1364 } | 1306 } |
1365 | 1307 |
1366 if (!listener.filter.urls.is_empty() && | 1308 if (!listener->filter.urls.is_empty() && |
1367 !listener.filter.urls.MatchesURL(url)) { | 1309 !listener->filter.urls.MatchesURL(url)) { |
1368 continue; | 1310 continue; |
1369 } | 1311 } |
1370 | 1312 |
1371 int render_process_id = -1; | 1313 int render_process_id = -1; |
1372 int render_frame_id = -1; | 1314 int render_frame_id = -1; |
1373 // TODO(devlin): Figure out when one/both of these can fail, and if we | 1315 // TODO(devlin): Figure out when one/both of these can fail, and if we |
1374 // need to address it. | 1316 // need to address it. |
1375 bool found_render_frame = | 1317 bool found_render_frame = |
1376 content::ResourceRequestInfo::GetRenderFrameForRequest( | 1318 content::ResourceRequestInfo::GetRenderFrameForRequest( |
1377 request, &render_process_id, &render_frame_id); | 1319 request, &render_process_id, &render_frame_id); |
1378 UMA_HISTOGRAM_BOOLEAN("Extensions.WebRequestEventFoundFrame", | 1320 UMA_HISTOGRAM_BOOLEAN("Extensions.WebRequestEventFoundFrame", |
1379 found_render_frame); | 1321 found_render_frame); |
1380 ExtensionApiFrameIdMap::FrameData frame_data; | 1322 ExtensionApiFrameIdMap::FrameData frame_data; |
1381 if (found_render_frame) { | 1323 if (found_render_frame) { |
1382 ExtensionApiFrameIdMap::Get()->GetCachedFrameDataOnIO( | 1324 ExtensionApiFrameIdMap::Get()->GetCachedFrameDataOnIO( |
1383 render_process_id, render_frame_id, &frame_data); | 1325 render_process_id, render_frame_id, &frame_data); |
1384 } | 1326 } |
1385 // Check if the tab id and window id match, if they were set in the | 1327 // Check if the tab id and window id match, if they were set in the |
1386 // listener params. | 1328 // listener params. |
1387 if ((listener.filter.tab_id != -1 && | 1329 if ((listener->filter.tab_id != -1 && |
1388 frame_data.tab_id != listener.filter.tab_id) || | 1330 frame_data.tab_id != listener->filter.tab_id) || |
1389 (listener.filter.window_id != -1 && | 1331 (listener->filter.window_id != -1 && |
1390 frame_data.window_id != listener.filter.window_id)) { | 1332 frame_data.window_id != listener->filter.window_id)) { |
1391 continue; | 1333 continue; |
1392 } | 1334 } |
1393 | 1335 |
1394 const std::vector<content::ResourceType>& types = listener.filter.types; | 1336 const std::vector<content::ResourceType>& types = listener->filter.types; |
1395 if (!types.empty() && | 1337 if (!types.empty() && |
1396 std::find(types.begin(), types.end(), resource_type) == types.end()) { | 1338 std::find(types.begin(), types.end(), resource_type) == types.end()) { |
1397 continue; | 1339 continue; |
1398 } | 1340 } |
1399 | 1341 |
1400 if (!is_web_view_guest) { | 1342 if (!is_web_view_guest) { |
1401 PermissionsData::AccessType access = | 1343 PermissionsData::AccessType access = |
1402 WebRequestPermissions::CanExtensionAccessURL( | 1344 WebRequestPermissions::CanExtensionAccessURL( |
1403 extension_info_map, listener.extension_id, url, frame_data.tab_id, | 1345 extension_info_map, listener->id.extension_id, url, |
1404 crosses_incognito, | 1346 frame_data.tab_id, crosses_incognito, |
1405 WebRequestPermissions::REQUIRE_HOST_PERMISSION); | 1347 WebRequestPermissions::REQUIRE_HOST_PERMISSION); |
1406 if (access != PermissionsData::ACCESS_ALLOWED) { | 1348 if (access != PermissionsData::ACCESS_ALLOWED) { |
1407 if (access == PermissionsData::ACCESS_WITHHELD && | 1349 if (access == PermissionsData::ACCESS_WITHHELD && |
1408 web_request_event_router_delegate_) { | 1350 web_request_event_router_delegate_) { |
1409 web_request_event_router_delegate_->NotifyWebRequestWithheld( | 1351 web_request_event_router_delegate_->NotifyWebRequestWithheld( |
1410 render_process_id, render_frame_id, listener.extension_id); | 1352 render_process_id, render_frame_id, listener->id.extension_id); |
1411 } | 1353 } |
1412 continue; | 1354 continue; |
1413 } | 1355 } |
1414 } | 1356 } |
1415 | 1357 |
1416 bool blocking_listener = | 1358 bool blocking_listener = |
1417 (listener.extra_info_spec & | 1359 (listener->extra_info_spec & |
1418 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0; | 1360 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0; |
1419 | 1361 |
1420 // We do not want to notify extensions about XHR requests that are | 1362 // We do not want to notify extensions about XHR requests that are |
1421 // triggered by themselves. This is a workaround to prevent deadlocks | 1363 // triggered by themselves. This is a workaround to prevent deadlocks |
1422 // in case of synchronous XHR requests that block the extension renderer | 1364 // in case of synchronous XHR requests that block the extension renderer |
1423 // and therefore prevent the extension from processing the request | 1365 // and therefore prevent the extension from processing the request |
1424 // handler. This is only a problem for blocking listeners. | 1366 // handler. This is only a problem for blocking listeners. |
1425 // http://crbug.com/105656 | 1367 // http://crbug.com/105656 |
1426 bool synchronous_xhr_from_extension = | 1368 bool synchronous_xhr_from_extension = |
1427 !is_async_request && is_request_from_extension && | 1369 !is_async_request && is_request_from_extension && |
1428 resource_type == content::RESOURCE_TYPE_XHR; | 1370 resource_type == content::RESOURCE_TYPE_XHR; |
1429 | 1371 |
1430 // Only send webRequest events for URLs the extension has access to. | 1372 // Only send webRequest events for URLs the extension has access to. |
1431 if (blocking_listener && synchronous_xhr_from_extension) | 1373 if (blocking_listener && synchronous_xhr_from_extension) |
1432 continue; | 1374 continue; |
1433 | 1375 |
1434 matching_listeners->push_back(&listener); | 1376 matching_listeners->push_back(listener->id); |
1435 *extra_info_spec |= listener.extra_info_spec; | 1377 *extra_info_spec |= listener->extra_info_spec; |
1436 } | 1378 } |
1437 } | 1379 } |
1438 | 1380 |
1439 ExtensionWebRequestEventRouter::EventListeners | 1381 ExtensionWebRequestEventRouter::ListenerIdentifiers |
1440 ExtensionWebRequestEventRouter::GetMatchingListeners( | 1382 ExtensionWebRequestEventRouter::GetMatchingListeners( |
1441 void* browser_context, | 1383 void* browser_context, |
1442 const InfoMap* extension_info_map, | 1384 const InfoMap* extension_info_map, |
1443 const std::string& event_name, | 1385 const std::string& event_name, |
1444 const net::URLRequest* request, | 1386 const net::URLRequest* request, |
1445 int* extra_info_spec) { | 1387 int* extra_info_spec) { |
1446 // TODO(mpcomplete): handle browser_context == NULL (should collect all | 1388 // TODO(mpcomplete): handle browser_context == NULL (should collect all |
1447 // listeners). | 1389 // listeners). |
1448 *extra_info_spec = 0; | 1390 *extra_info_spec = 0; |
1449 | 1391 |
1450 const GURL& url = request->url(); | 1392 const GURL& url = request->url(); |
1451 int render_process_host_id = content::ChildProcessHost::kInvalidUniqueID; | 1393 int render_process_host_id = content::ChildProcessHost::kInvalidUniqueID; |
1452 int routing_id = MSG_ROUTING_NONE; | 1394 int routing_id = MSG_ROUTING_NONE; |
1453 content::ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE; | 1395 content::ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE; |
1454 // We are conservative here and assume requests are asynchronous in case | 1396 // 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. | 1397 // we don't have an info object. We don't want to risk a deadlock. |
1456 bool is_async_request = false; | 1398 bool is_async_request = false; |
1457 bool is_request_from_extension = | 1399 bool is_request_from_extension = |
1458 IsRequestFromExtension(request, extension_info_map); | 1400 IsRequestFromExtension(request, extension_info_map); |
1459 | 1401 |
1460 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); | 1402 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); |
1461 if (info) { | 1403 if (info) { |
1462 is_async_request = info->IsAsync(); | 1404 is_async_request = info->IsAsync(); |
1463 if (helpers::IsRelevantResourceType(info->GetResourceType())) | 1405 if (helpers::IsRelevantResourceType(info->GetResourceType())) |
1464 resource_type = info->GetResourceType(); | 1406 resource_type = info->GetResourceType(); |
1465 render_process_host_id = info->GetChildID(); | 1407 render_process_host_id = info->GetChildID(); |
1466 routing_id = info->GetRouteID(); | 1408 routing_id = info->GetRouteID(); |
1467 } | 1409 } |
1468 | 1410 |
1469 EventListeners matching_listeners; | 1411 ListenerIdentifiers matching_listeners; |
1470 GetMatchingListenersImpl( | 1412 GetMatchingListenersImpl( |
1471 browser_context, request, extension_info_map, false, event_name, | 1413 browser_context, request, extension_info_map, false, event_name, |
1472 url, render_process_host_id, routing_id, resource_type, | 1414 url, render_process_host_id, routing_id, resource_type, |
1473 is_async_request, is_request_from_extension, extra_info_spec, | 1415 is_async_request, is_request_from_extension, extra_info_spec, |
1474 &matching_listeners); | 1416 &matching_listeners); |
1475 void* cross_browser_context = GetCrossBrowserContext(browser_context); | 1417 void* cross_browser_context = GetCrossBrowserContext(browser_context); |
1476 if (cross_browser_context) { | 1418 if (cross_browser_context) { |
1477 GetMatchingListenersImpl( | 1419 GetMatchingListenersImpl( |
1478 cross_browser_context, request, extension_info_map, true, event_name, | 1420 cross_browser_context, request, extension_info_map, true, event_name, |
1479 url, render_process_host_id, routing_id, resource_type, | 1421 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. | 1620 // declarative rules to be read from disk. |
1679 UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayStartup", block_time); | 1621 UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayStartup", block_time); |
1680 } | 1622 } |
1681 | 1623 |
1682 if (num_handlers_blocking == 0) { | 1624 if (num_handlers_blocking == 0) { |
1683 blocked_request.request->LogUnblocked(); | 1625 blocked_request.request->LogUnblocked(); |
1684 ExecuteDeltas(browser_context, request_id, true); | 1626 ExecuteDeltas(browser_context, request_id, true); |
1685 } else { | 1627 } else { |
1686 // Update the URLRequest to make sure it's tagged with an extension that's | 1628 // 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. | 1629 // still blocking it. This may end up being the same extension as before. |
1688 std::set<EventListener>& listeners = | 1630 Listeners& listeners = listeners_[browser_context][event_name]; |
1689 listeners_[browser_context][event_name]; | |
1690 | 1631 |
1691 for (const auto& listener : listeners) { | 1632 for (const auto& listener : listeners) { |
1692 if (!base::ContainsKey(listener.blocked_requests, request_id)) | 1633 if (!base::ContainsKey(listener->blocked_requests, request_id)) |
1693 continue; | 1634 continue; |
1694 std::string delegate_info = | 1635 std::string delegate_info = l10n_util::GetStringFUTF8( |
1695 l10n_util::GetStringFUTF8(IDS_LOAD_STATE_PARAMETER_EXTENSION, | 1636 IDS_LOAD_STATE_PARAMETER_EXTENSION, |
1696 base::UTF8ToUTF16(listener.extension_name)); | 1637 base::UTF8ToUTF16(listener->extension_name)); |
1697 blocked_request.request->LogAndReportBlockedBy(delegate_info.c_str()); | 1638 blocked_request.request->LogAndReportBlockedBy(delegate_info.c_str()); |
1698 break; | 1639 break; |
1699 } | 1640 } |
1700 } | 1641 } |
1701 } | 1642 } |
1702 | 1643 |
1703 void ExtensionWebRequestEventRouter::SendMessages( | 1644 void ExtensionWebRequestEventRouter::SendMessages( |
1704 void* browser_context, | 1645 void* browser_context, |
1705 const BlockedRequest& blocked_request) { | 1646 const BlockedRequest& blocked_request) { |
1706 const helpers::EventResponseDeltas& deltas = blocked_request.response_deltas; | 1647 const helpers::EventResponseDeltas& deltas = blocked_request.response_deltas; |
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2285 RunWithValidation()->Execute(); | 2226 RunWithValidation()->Execute(); |
2286 } | 2227 } |
2287 | 2228 |
2288 ExtensionFunction::ResponseAction | 2229 ExtensionFunction::ResponseAction |
2289 WebRequestHandlerBehaviorChangedFunction::Run() { | 2230 WebRequestHandlerBehaviorChangedFunction::Run() { |
2290 helpers::ClearCacheOnNavigation(); | 2231 helpers::ClearCacheOnNavigation(); |
2291 return RespondNow(NoArguments()); | 2232 return RespondNow(NoArguments()); |
2292 } | 2233 } |
2293 | 2234 |
2294 } // namespace extensions | 2235 } // namespace extensions |
OLD | NEW |