| 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 if (ShouldHideEvent(browser_context, extension_info_map, request)) | 821 if (ShouldHideEvent(browser_context, extension_info_map, request)) |
| 874 return; | 822 return; |
| 875 | 823 |
| 876 // OnResponseStarted is even triggered, when the request was cancelled. | 824 // OnResponseStarted is even triggered, when the request was cancelled. |
| 877 if (request->status().status() != net::URLRequestStatus::SUCCESS) | 825 if (request->status().status() != net::URLRequestStatus::SUCCESS) |
| 878 return; | 826 return; |
| 879 | 827 |
| 880 int extra_info_spec = 0; | 828 int extra_info_spec = 0; |
| 881 EventListeners listeners = GetMatchingListeners( | 829 RawListeners listeners = GetMatchingListeners( |
| 882 browser_context, extension_info_map, keys::kOnResponseStartedEvent, | 830 browser_context, extension_info_map, keys::kOnResponseStartedEvent, |
| 883 request, &extra_info_spec); | 831 request, &extra_info_spec); |
| 884 if (listeners.empty()) | 832 if (listeners.empty()) |
| 885 return; | 833 return; |
| 886 | 834 |
| 887 std::unique_ptr<WebRequestEventDetails> event_details( | 835 std::unique_ptr<WebRequestEventDetails> event_details( |
| 888 CreateEventDetails(request, extra_info_spec)); | 836 CreateEventDetails(request, extra_info_spec)); |
| 889 event_details->SetResponseHeaders(request, request->response_headers()); | 837 event_details->SetResponseHeaders(request, request->response_headers()); |
| 890 event_details->SetResponseSource(request); | 838 event_details->SetResponseSource(request); |
| 891 | 839 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 909 request_time_tracker_->LogRequestEndTime(request->identifier(), | 857 request_time_tracker_->LogRequestEndTime(request->identifier(), |
| 910 base::Time::Now()); | 858 base::Time::Now()); |
| 911 | 859 |
| 912 DCHECK(request->status().status() == net::URLRequestStatus::SUCCESS); | 860 DCHECK(request->status().status() == net::URLRequestStatus::SUCCESS); |
| 913 | 861 |
| 914 DCHECK(!GetAndSetSignaled(request->identifier(), kOnCompleted)); | 862 DCHECK(!GetAndSetSignaled(request->identifier(), kOnCompleted)); |
| 915 | 863 |
| 916 ClearPendingCallbacks(request); | 864 ClearPendingCallbacks(request); |
| 917 | 865 |
| 918 int extra_info_spec = 0; | 866 int extra_info_spec = 0; |
| 919 EventListeners listeners = | 867 RawListeners listeners = |
| 920 GetMatchingListeners(browser_context, extension_info_map, | 868 GetMatchingListeners(browser_context, extension_info_map, |
| 921 keys::kOnCompletedEvent, request, &extra_info_spec); | 869 keys::kOnCompletedEvent, request, &extra_info_spec); |
| 922 if (listeners.empty()) | 870 if (listeners.empty()) |
| 923 return; | 871 return; |
| 924 | 872 |
| 925 std::unique_ptr<WebRequestEventDetails> event_details( | 873 std::unique_ptr<WebRequestEventDetails> event_details( |
| 926 CreateEventDetails(request, extra_info_spec)); | 874 CreateEventDetails(request, extra_info_spec)); |
| 927 event_details->SetResponseHeaders(request, request->response_headers()); | 875 event_details->SetResponseHeaders(request, request->response_headers()); |
| 928 event_details->SetResponseSource(request); | 876 event_details->SetResponseSource(request); |
| 929 | 877 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 949 base::Time::Now()); | 897 base::Time::Now()); |
| 950 | 898 |
| 951 DCHECK(request->status().status() == net::URLRequestStatus::FAILED || | 899 DCHECK(request->status().status() == net::URLRequestStatus::FAILED || |
| 952 request->status().status() == net::URLRequestStatus::CANCELED); | 900 request->status().status() == net::URLRequestStatus::CANCELED); |
| 953 | 901 |
| 954 DCHECK(!GetAndSetSignaled(request->identifier(), kOnErrorOccurred)); | 902 DCHECK(!GetAndSetSignaled(request->identifier(), kOnErrorOccurred)); |
| 955 | 903 |
| 956 ClearPendingCallbacks(request); | 904 ClearPendingCallbacks(request); |
| 957 | 905 |
| 958 int extra_info_spec = 0; | 906 int extra_info_spec = 0; |
| 959 EventListeners listeners = GetMatchingListeners( | 907 RawListeners listeners = GetMatchingListeners( |
| 960 browser_context, extension_info_map, | 908 browser_context, extension_info_map, |
| 961 web_request::OnErrorOccurred::kEventName, request, &extra_info_spec); | 909 web_request::OnErrorOccurred::kEventName, request, &extra_info_spec); |
| 962 if (listeners.empty()) | 910 if (listeners.empty()) |
| 963 return; | 911 return; |
| 964 | 912 |
| 965 std::unique_ptr<WebRequestEventDetails> event_details( | 913 std::unique_ptr<WebRequestEventDetails> event_details( |
| 966 CreateEventDetails(request, extra_info_spec)); | 914 CreateEventDetails(request, extra_info_spec)); |
| 967 if (started) | 915 if (started) |
| 968 event_details->SetResponseSource(request); | 916 event_details->SetResponseSource(request); |
| 969 else | 917 else |
| (...skipping 16 matching lines...) Expand all Loading... |
| 986 } | 934 } |
| 987 | 935 |
| 988 void ExtensionWebRequestEventRouter::ClearPendingCallbacks( | 936 void ExtensionWebRequestEventRouter::ClearPendingCallbacks( |
| 989 const net::URLRequest* request) { | 937 const net::URLRequest* request) { |
| 990 blocked_requests_.erase(request->identifier()); | 938 blocked_requests_.erase(request->identifier()); |
| 991 } | 939 } |
| 992 | 940 |
| 993 bool ExtensionWebRequestEventRouter::DispatchEvent( | 941 bool ExtensionWebRequestEventRouter::DispatchEvent( |
| 994 void* browser_context, | 942 void* browser_context, |
| 995 net::URLRequest* request, | 943 net::URLRequest* request, |
| 996 const std::vector<const EventListener*>& listeners, | 944 const RawListeners& listeners, |
| 997 std::unique_ptr<WebRequestEventDetails> event_details) { | 945 std::unique_ptr<WebRequestEventDetails> event_details) { |
| 998 // TODO(mpcomplete): Consider consolidating common (extension_id,json_args) | 946 // TODO(mpcomplete): Consider consolidating common (extension_id,json_args) |
| 999 // pairs into a single message sent to a list of sub_event_names. | 947 // pairs into a single message sent to a list of sub_event_names. |
| 1000 int num_handlers_blocking = 0; | 948 int num_handlers_blocking = 0; |
| 1001 | 949 |
| 1002 std::unique_ptr<std::vector<EventListener>> listeners_to_dispatch( | 950 std::unique_ptr<ListenerIDs> listeners_to_dispatch(new ListenerIDs); |
| 1003 new std::vector<EventListener>()); | |
| 1004 listeners_to_dispatch->reserve(listeners.size()); | 951 listeners_to_dispatch->reserve(listeners.size()); |
| 1005 for (const EventListener* listener : listeners) { | 952 for (EventListener* listener : listeners) { |
| 1006 listeners_to_dispatch->push_back(*listener); | 953 listeners_to_dispatch->push_back(listener->id); |
| 1007 if (listener->extra_info_spec & | 954 if (listener->extra_info_spec & |
| 1008 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) { | 955 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) { |
| 1009 listener->blocked_requests.insert(request->identifier()); | 956 listener->blocked_requests.insert(request->identifier()); |
| 1010 // If this is the first delegate blocking the request, go ahead and log | 957 // If this is the first delegate blocking the request, go ahead and log |
| 1011 // it. | 958 // it. |
| 1012 if (num_handlers_blocking == 0) { | 959 if (num_handlers_blocking == 0) { |
| 1013 std::string delegate_info = l10n_util::GetStringFUTF8( | 960 std::string delegate_info = l10n_util::GetStringFUTF8( |
| 1014 IDS_LOAD_STATE_PARAMETER_EXTENSION, | 961 IDS_LOAD_STATE_PARAMETER_EXTENSION, |
| 1015 base::UTF8ToUTF16(listener->extension_name)); | 962 base::UTF8ToUTF16(listener->extension_name)); |
| 1016 // LobAndReport allows extensions that block requests to be displayed in | 963 // LobAndReport allows extensions that block requests to be displayed in |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1032 blocked_request.num_handlers_blocking += num_handlers_blocking; | 979 blocked_request.num_handlers_blocking += num_handlers_blocking; |
| 1033 blocked_request.blocking_time = base::Time::Now(); | 980 blocked_request.blocking_time = base::Time::Now(); |
| 1034 return true; | 981 return true; |
| 1035 } | 982 } |
| 1036 | 983 |
| 1037 return false; | 984 return false; |
| 1038 } | 985 } |
| 1039 | 986 |
| 1040 void ExtensionWebRequestEventRouter::DispatchEventToListeners( | 987 void ExtensionWebRequestEventRouter::DispatchEventToListeners( |
| 1041 void* browser_context, | 988 void* browser_context, |
| 1042 std::unique_ptr<std::vector<EventListener>> listeners, | 989 std::unique_ptr<ListenerIDs> listener_ids, |
| 1043 std::unique_ptr<WebRequestEventDetails> event_details) { | 990 std::unique_ptr<WebRequestEventDetails> event_details) { |
| 1044 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 991 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1045 DCHECK(listeners.get()); | 992 DCHECK(!listener_ids->empty()); |
| 1046 DCHECK_GT(listeners->size(), 0UL); | |
| 1047 DCHECK(event_details.get()); | 993 DCHECK(event_details.get()); |
| 1048 | 994 |
| 1049 std::string event_name = | 995 std::string event_name = |
| 1050 EventRouter::GetBaseEventName((*listeners)[0].sub_event_name); | 996 EventRouter::GetBaseEventName((*listener_ids)[0].sub_event_name); |
| 1051 DCHECK(IsWebRequestEvent(event_name)); | 997 DCHECK(IsWebRequestEvent(event_name)); |
| 1052 | 998 |
| 1053 const std::set<EventListener>& event_listeners = | 999 Listeners& event_listeners = listeners_[browser_context][event_name]; |
| 1054 listeners_[browser_context][event_name]; | |
| 1055 void* cross_browser_context = GetCrossBrowserContext(browser_context); | 1000 void* cross_browser_context = GetCrossBrowserContext(browser_context); |
| 1056 const std::set<EventListener>* cross_event_listeners = | 1001 Listeners* cross_event_listeners = |
| 1057 cross_browser_context ? &listeners_[cross_browser_context][event_name] | 1002 cross_browser_context ? &listeners_[cross_browser_context][event_name] |
| 1058 : nullptr; | 1003 : nullptr; |
| 1059 | 1004 |
| 1060 for (const EventListener& target : *listeners) { | 1005 for (const EventListener::ID& id : *listener_ids) { |
| 1061 std::set<EventListener>::const_iterator listener = | 1006 // It's possible that the listener is no longer present. Check to make sure |
| 1062 event_listeners.find(target); | 1007 // it's still there. |
| 1063 // Ignore listener if it was removed between the thread hops. | 1008 const EventListener* listener = |
| 1064 if (listener == event_listeners.end()) { | 1009 FindEventListenerInContainer(id, event_listeners); |
| 1065 if (!cross_event_listeners) | 1010 if (!listener && cross_event_listeners) { |
| 1066 continue; | 1011 listener = FindEventListenerInContainer(id, *cross_event_listeners); |
| 1067 listener = cross_event_listeners->find(target); | |
| 1068 if (listener == cross_event_listeners->end()) | |
| 1069 continue; | |
| 1070 } | 1012 } |
| 1013 if (!listener) |
| 1014 continue; |
| 1071 | 1015 |
| 1072 if (!listener->ipc_sender.get()) | 1016 if (!listener->ipc_sender.get()) |
| 1073 continue; | 1017 continue; |
| 1074 | 1018 |
| 1075 // Filter out the optional keys that this listener didn't request. | 1019 // Filter out the optional keys that this listener didn't request. |
| 1076 std::unique_ptr<base::ListValue> args_filtered(new base::ListValue); | 1020 std::unique_ptr<base::ListValue> args_filtered(new base::ListValue); |
| 1077 args_filtered->Append( | 1021 args_filtered->Append( |
| 1078 event_details->GetFilteredDict(listener->extra_info_spec)); | 1022 event_details->GetFilteredDict(listener->extra_info_spec)); |
| 1079 | 1023 |
| 1080 EventRouter::DispatchEventToSender( | 1024 EventRouter::DispatchEventToSender( |
| 1081 listener->ipc_sender.get(), browser_context, listener->extension_id, | 1025 listener->ipc_sender.get(), browser_context, listener->id.extension_id, |
| 1082 listener->histogram_value, listener->sub_event_name, | 1026 listener->histogram_value, listener->id.sub_event_name, |
| 1083 std::move(args_filtered), EventRouter::USER_GESTURE_UNKNOWN, | 1027 std::move(args_filtered), EventRouter::USER_GESTURE_UNKNOWN, |
| 1084 EventFilteringInfo()); | 1028 EventFilteringInfo()); |
| 1085 } | 1029 } |
| 1086 } | 1030 } |
| 1087 | 1031 |
| 1088 void ExtensionWebRequestEventRouter::OnEventHandled( | 1032 void ExtensionWebRequestEventRouter::OnEventHandled( |
| 1089 void* browser_context, | 1033 void* browser_context, |
| 1090 const std::string& extension_id, | 1034 const std::string& extension_id, |
| 1091 const std::string& event_name, | 1035 const std::string& event_name, |
| 1092 const std::string& sub_event_name, | 1036 const std::string& sub_event_name, |
| 1093 uint64_t request_id, | 1037 uint64_t request_id, |
| 1094 EventResponse* response) { | 1038 EventResponse* response) { |
| 1095 // TODO(robwu): Does this also work with webviews? operator< (used by find) | 1039 // TODO(robwu): This ignores WebViews. |
| 1096 // takes the webview ID into account, which is not set on |listener|. | 1040 Listeners& listeners = listeners_[browser_context][event_name]; |
| 1097 EventListener listener; | 1041 EventListener::ID id(browser_context, extension_id, sub_event_name, 0, 0); |
| 1098 listener.extension_id = extension_id; | 1042 for (auto it = listeners.begin(); it != listeners.end(); ++it) { |
| 1099 listener.sub_event_name = sub_event_name; | 1043 if ((*it)->id.LooselyMatches(id)) { |
| 1100 | 1044 (*it)->blocked_requests.erase(request_id); |
| 1101 // The listener may have been removed (e.g. due to the process going away) | 1045 } |
| 1102 // before we got here. | 1046 } |
| 1103 std::set<EventListener>::iterator found = | |
| 1104 listeners_[browser_context][event_name].find(listener); | |
| 1105 if (found != listeners_[browser_context][event_name].end()) | |
| 1106 found->blocked_requests.erase(request_id); | |
| 1107 | 1047 |
| 1108 DecrementBlockCount( | 1048 DecrementBlockCount( |
| 1109 browser_context, extension_id, event_name, request_id, response); | 1049 browser_context, extension_id, event_name, request_id, response); |
| 1110 } | 1050 } |
| 1111 | 1051 |
| 1112 bool ExtensionWebRequestEventRouter::AddEventListener( | 1052 bool ExtensionWebRequestEventRouter::AddEventListener( |
| 1113 void* browser_context, | 1053 void* browser_context, |
| 1114 const std::string& extension_id, | 1054 const std::string& extension_id, |
| 1115 const std::string& extension_name, | 1055 const std::string& extension_name, |
| 1116 events::HistogramValue histogram_value, | 1056 events::HistogramValue histogram_value, |
| 1117 const std::string& event_name, | 1057 const std::string& event_name, |
| 1118 const std::string& sub_event_name, | 1058 const std::string& sub_event_name, |
| 1119 const RequestFilter& filter, | 1059 const RequestFilter& filter, |
| 1120 int extra_info_spec, | 1060 int extra_info_spec, |
| 1121 int embedder_process_id, | 1061 int embedder_process_id, |
| 1122 int web_view_instance_id, | 1062 int web_view_instance_id, |
| 1123 base::WeakPtr<IPC::Sender> ipc_sender) { | 1063 base::WeakPtr<IPC::Sender> ipc_sender) { |
| 1124 if (!IsWebRequestEvent(event_name)) | 1064 if (!IsWebRequestEvent(event_name)) |
| 1125 return false; | 1065 return false; |
| 1126 | 1066 |
| 1127 EventListener listener; | 1067 if (event_name != EventRouter::GetBaseEventName(sub_event_name)) |
| 1128 listener.extension_id = extension_id; | 1068 return false; |
| 1129 listener.extension_name = extension_name; | 1069 |
| 1130 listener.histogram_value = histogram_value; | 1070 EventListener::ID id(browser_context, extension_id, sub_event_name, |
| 1131 listener.sub_event_name = sub_event_name; | 1071 embedder_process_id, web_view_instance_id); |
| 1132 listener.filter = filter; | 1072 if (FindEventListener(id) != nullptr) { |
| 1133 listener.extra_info_spec = extra_info_spec; | 1073 // This is likely an abuse of the API by a malicious extension. |
| 1134 listener.ipc_sender = ipc_sender; | 1074 return false; |
| 1135 listener.embedder_process_id = embedder_process_id; | 1075 } |
| 1136 listener.web_view_instance_id = web_view_instance_id; | 1076 |
| 1137 if (listener.web_view_instance_id) { | 1077 std::unique_ptr<EventListener> listener(new EventListener(id)); |
| 1078 listener->extension_name = extension_name; |
| 1079 listener->histogram_value = histogram_value; |
| 1080 listener->filter = filter; |
| 1081 listener->extra_info_spec = extra_info_spec; |
| 1082 listener->ipc_sender = ipc_sender; |
| 1083 if (web_view_instance_id) { |
| 1138 content::RecordAction( | 1084 content::RecordAction( |
| 1139 base::UserMetricsAction("WebView.WebRequest.AddListener")); | 1085 base::UserMetricsAction("WebView.WebRequest.AddListener")); |
| 1140 } | 1086 } |
| 1141 | 1087 |
| 1142 if (base::ContainsKey(listeners_[browser_context][event_name], listener)) { | 1088 listeners_[browser_context][event_name].push_back(std::move(listener)); |
| 1143 // This is likely an abuse of the API by a malicious extension. | |
| 1144 return false; | |
| 1145 } | |
| 1146 listeners_[browser_context][event_name].insert(listener); | |
| 1147 return true; | 1089 return true; |
| 1148 } | 1090 } |
| 1149 | 1091 |
| 1092 size_t ExtensionWebRequestEventRouter::GetListenerCountForTesting( |
| 1093 void* browser_context, |
| 1094 const std::string& event_name) { |
| 1095 return listeners_[browser_context][event_name].size(); |
| 1096 } |
| 1097 |
| 1098 ExtensionWebRequestEventRouter::EventListener* |
| 1099 ExtensionWebRequestEventRouter::FindEventListener(const EventListener::ID& id) { |
| 1100 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1101 std::string event_name = EventRouter::GetBaseEventName(id.sub_event_name); |
| 1102 Listeners& listeners = listeners_[id.browser_context][event_name]; |
| 1103 return FindEventListenerInContainer(id, listeners); |
| 1104 } |
| 1105 |
| 1106 ExtensionWebRequestEventRouter::EventListener* |
| 1107 ExtensionWebRequestEventRouter::FindEventListenerInContainer( |
| 1108 const EventListener::ID& id, |
| 1109 Listeners& listeners) { |
| 1110 for (auto it = listeners.begin(); it != listeners.end(); ++it) { |
| 1111 if ((*it)->id == id) { |
| 1112 return it->get(); |
| 1113 } |
| 1114 } |
| 1115 return nullptr; |
| 1116 } |
| 1117 |
| 1150 void ExtensionWebRequestEventRouter::RemoveEventListener( | 1118 void ExtensionWebRequestEventRouter::RemoveEventListener( |
| 1151 void* browser_context, | 1119 const EventListener::ID& id, |
| 1152 const std::string& extension_id, | 1120 bool strict) { |
| 1153 const std::string& sub_event_name, | 1121 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1154 int embedder_process_id, | |
| 1155 int web_view_instance_id) { | |
| 1156 std::string event_name = EventRouter::GetBaseEventName(sub_event_name); | |
| 1157 DCHECK(IsWebRequestEvent(event_name)); | |
| 1158 | 1122 |
| 1159 EventListener listener; | 1123 std::string event_name = EventRouter::GetBaseEventName(id.sub_event_name); |
| 1160 listener.extension_id = extension_id; | 1124 Listeners& listeners = listeners_[id.browser_context][event_name]; |
| 1161 listener.sub_event_name = sub_event_name; | 1125 for (auto it = listeners.begin(); it != listeners.end(); ++it) { |
| 1162 listener.embedder_process_id = embedder_process_id; | 1126 std::unique_ptr<EventListener>& listener = *it; |
| 1163 listener.web_view_instance_id = web_view_instance_id; | |
| 1164 | 1127 |
| 1165 std::set<EventListener>& event_listeners = | 1128 // There are two places that call this method: RemoveWebViewEventListeners |
| 1166 listeners_[browser_context][event_name]; | 1129 // and OnListenerRemoved. The latter can't use operator== because it doesn't |
| 1167 // It's possible for AddEventListener to fail asynchronously. In that case, | 1130 // have the embedder_process_id. This shouldn't be a problem, because |
| 1168 // the renderer believes the listener exists, while the browser does not. | 1131 // OnListenerRemoved is only called for web_view_instance_id == 0. |
| 1169 // Ignore a RemoveEventListener in that case. | 1132 bool matches = |
| 1170 std::set<EventListener>::const_iterator it = event_listeners.find(listener); | 1133 strict ? listener->id == id : listener->id.LooselyMatches(id); |
| 1171 if (it == event_listeners.end()) | 1134 if (matches) { |
| 1172 return; | 1135 // Unblock any request that this event listener may have been blocking. |
| 1136 for (uint64_t blocked_request_id : listener->blocked_requests) |
| 1137 DecrementBlockCount(listener->id.browser_context, |
| 1138 listener->id.extension_id, event_name, |
| 1139 blocked_request_id, nullptr); |
| 1173 | 1140 |
| 1174 #if defined(OS_WIN) | 1141 listeners.erase(it); |
| 1175 // Debugging https://crbug.com/589735 | 1142 helpers::ClearCacheOnNavigation(); |
| 1176 // Please post crash reports at the following lines to the above issue. | 1143 return; |
| 1177 unsigned event_listener_count = event_listeners.count(listener); | 1144 } |
| 1178 CHECK_GE(event_listener_count, 0u); | 1145 } |
| 1179 CHECK_GE(event_listener_count, 1u); | |
| 1180 CHECK_LE(event_listener_count, 2u); | |
| 1181 CHECK_EQ(event_listener_count, 1u); | |
| 1182 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | |
| 1183 #endif // OS_WIN | |
| 1184 CHECK_EQ(event_listeners.count(listener), 1u) << | |
| 1185 "extension=" << extension_id << " event=" << event_name; | |
| 1186 | |
| 1187 // Unblock any request that this event listener may have been blocking. | |
| 1188 for (uint64_t id : it->blocked_requests) | |
| 1189 DecrementBlockCount(browser_context, extension_id, event_name, id, NULL); | |
| 1190 | |
| 1191 event_listeners.erase(listener); | |
| 1192 | |
| 1193 helpers::ClearCacheOnNavigation(); | |
| 1194 } | 1146 } |
| 1195 | 1147 |
| 1196 void ExtensionWebRequestEventRouter::RemoveWebViewEventListeners( | 1148 void ExtensionWebRequestEventRouter::RemoveWebViewEventListeners( |
| 1197 void* browser_context, | 1149 void* browser_context, |
| 1198 int embedder_process_id, | 1150 int embedder_process_id, |
| 1199 int web_view_instance_id) { | 1151 int web_view_instance_id) { |
| 1200 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1152 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1201 | 1153 |
| 1202 // Iterate over all listeners of all WebRequest events to delete | 1154 // Iterate over all listeners of all WebRequest events to delete |
| 1203 // any listeners that belong to the provided <webview>. | 1155 // any listeners that belong to the provided <webview>. |
| 1204 ListenerMapForBrowserContext& map_for_browser_context = | 1156 ListenerMapForBrowserContext& map_for_browser_context = |
| 1205 listeners_[browser_context]; | 1157 listeners_[browser_context]; |
| 1206 for (const auto& event_iter : map_for_browser_context) { | 1158 for (const auto& event_iter : map_for_browser_context) { |
| 1207 // Construct a listeners_to_delete vector so that we don't modify the set of | 1159 // Construct a listeners_to_delete vector so that we don't modify the set of |
| 1208 // listeners as we iterate through it. | 1160 // listeners as we iterate through it. |
| 1209 std::vector<EventListener> listeners_to_delete; | 1161 std::vector<EventListener::ID> listeners_to_delete; |
| 1210 const std::set<EventListener>& listeners = event_iter.second; | 1162 const Listeners& listeners = event_iter.second; |
| 1211 for (const auto& listener : listeners) { | 1163 for (const auto& listener : listeners) { |
| 1212 if (listener.embedder_process_id == embedder_process_id && | 1164 if (listener->id.embedder_process_id == embedder_process_id && |
| 1213 listener.web_view_instance_id == web_view_instance_id) { | 1165 listener->id.web_view_instance_id == web_view_instance_id) { |
| 1214 listeners_to_delete.push_back(listener); | 1166 listeners_to_delete.push_back(listener->id); |
| 1215 } | 1167 } |
| 1216 } | 1168 } |
| 1217 // Remove the listeners selected for deletion. | 1169 // Remove the listeners selected for deletion. |
| 1218 for (const auto& listener : listeners_to_delete) { | 1170 for (const auto& listener_id : listeners_to_delete) |
| 1219 RemoveEventListenerOnIOThread( | 1171 RemoveEventListener(listener_id, true /* strict */); |
| 1220 browser_context, | |
| 1221 listener.extension_id, | |
| 1222 listener.sub_event_name, | |
| 1223 listener.embedder_process_id, | |
| 1224 listener.web_view_instance_id); | |
| 1225 } | |
| 1226 } | 1172 } |
| 1227 } | 1173 } |
| 1228 | 1174 |
| 1229 void ExtensionWebRequestEventRouter::OnOTRBrowserContextCreated( | 1175 void ExtensionWebRequestEventRouter::OnOTRBrowserContextCreated( |
| 1230 void* original_browser_context, void* otr_browser_context) { | 1176 void* original_browser_context, void* otr_browser_context) { |
| 1231 cross_browser_context_map_[original_browser_context] = | 1177 cross_browser_context_map_[original_browser_context] = |
| 1232 std::make_pair(false, otr_browser_context); | 1178 std::make_pair(false, otr_browser_context); |
| 1233 cross_browser_context_map_[otr_browser_context] = | 1179 cross_browser_context_map_[otr_browser_context] = |
| 1234 std::make_pair(true, original_browser_context); | 1180 std::make_pair(true, original_browser_context); |
| 1235 } | 1181 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1291 const InfoMap* extension_info_map, | 1237 const InfoMap* extension_info_map, |
| 1292 bool crosses_incognito, | 1238 bool crosses_incognito, |
| 1293 const std::string& event_name, | 1239 const std::string& event_name, |
| 1294 const GURL& url, | 1240 const GURL& url, |
| 1295 int render_process_host_id, | 1241 int render_process_host_id, |
| 1296 int routing_id, | 1242 int routing_id, |
| 1297 content::ResourceType resource_type, | 1243 content::ResourceType resource_type, |
| 1298 bool is_async_request, | 1244 bool is_async_request, |
| 1299 bool is_request_from_extension, | 1245 bool is_request_from_extension, |
| 1300 int* extra_info_spec, | 1246 int* extra_info_spec, |
| 1301 EventListeners* matching_listeners) { | 1247 RawListeners* matching_listeners) { |
| 1302 std::string web_request_event_name(event_name); | 1248 std::string web_request_event_name(event_name); |
| 1303 WebViewRendererState::WebViewInfo web_view_info; | 1249 WebViewRendererState::WebViewInfo web_view_info; |
| 1304 bool is_web_view_guest = WebViewRendererState::GetInstance()->GetInfo( | 1250 bool is_web_view_guest = WebViewRendererState::GetInstance()->GetInfo( |
| 1305 render_process_host_id, routing_id, &web_view_info); | 1251 render_process_host_id, routing_id, &web_view_info); |
| 1306 if (is_web_view_guest) { | 1252 if (is_web_view_guest) { |
| 1307 web_request_event_name.replace( | 1253 web_request_event_name.replace( |
| 1308 0, sizeof(kWebRequestEventPrefix) - 1, webview::kWebViewEventPrefix); | 1254 0, sizeof(kWebRequestEventPrefix) - 1, webview::kWebViewEventPrefix); |
| 1309 } | 1255 } |
| 1310 | 1256 |
| 1311 std::set<EventListener>& listeners = | 1257 Listeners& listeners = listeners_[browser_context][web_request_event_name]; |
| 1312 listeners_[browser_context][web_request_event_name]; | 1258 for (std::unique_ptr<EventListener>& listener : listeners) { |
| 1313 for (const EventListener& listener : listeners) { | 1259 if (!listener->ipc_sender.get()) { |
| 1314 if (!listener.ipc_sender.get()) { | |
| 1315 // The IPC sender has been deleted. This listener will be removed soon | 1260 // The IPC sender has been deleted. This listener will be removed soon |
| 1316 // via a call to RemoveEventListener. For now, just skip it. | 1261 // via a call to RemoveEventListener. For now, just skip it. |
| 1317 continue; | 1262 continue; |
| 1318 } | 1263 } |
| 1319 | 1264 |
| 1320 if (is_web_view_guest && | 1265 if (is_web_view_guest && |
| 1321 (listener.embedder_process_id != web_view_info.embedder_process_id || | 1266 (listener->id.embedder_process_id != |
| 1322 listener.web_view_instance_id != web_view_info.instance_id)) { | 1267 web_view_info.embedder_process_id || |
| 1268 listener->id.web_view_instance_id != web_view_info.instance_id)) { |
| 1323 continue; | 1269 continue; |
| 1324 } | 1270 } |
| 1325 | 1271 |
| 1326 // Filter requests from other extensions / apps. This does not work for | 1272 // Filter requests from other extensions / apps. This does not work for |
| 1327 // content scripts, or extension pages in non-extension processes. | 1273 // content scripts, or extension pages in non-extension processes. |
| 1328 if (is_request_from_extension && | 1274 if (is_request_from_extension && |
| 1329 listener.embedder_process_id != render_process_host_id) { | 1275 listener->id.embedder_process_id != render_process_host_id) { |
| 1330 continue; | 1276 continue; |
| 1331 } | 1277 } |
| 1332 | 1278 |
| 1333 if (!listener.filter.urls.is_empty() && | 1279 if (!listener->filter.urls.is_empty() && |
| 1334 !listener.filter.urls.MatchesURL(url)) { | 1280 !listener->filter.urls.MatchesURL(url)) { |
| 1335 continue; | 1281 continue; |
| 1336 } | 1282 } |
| 1337 | 1283 |
| 1338 int render_process_id = -1; | 1284 int render_process_id = -1; |
| 1339 int render_frame_id = -1; | 1285 int render_frame_id = -1; |
| 1340 // TODO(devlin): Figure out when one/both of these can fail, and if we | 1286 // TODO(devlin): Figure out when one/both of these can fail, and if we |
| 1341 // need to address it. | 1287 // need to address it. |
| 1342 bool found_render_frame = | 1288 bool found_render_frame = |
| 1343 content::ResourceRequestInfo::GetRenderFrameForRequest( | 1289 content::ResourceRequestInfo::GetRenderFrameForRequest( |
| 1344 request, &render_process_id, &render_frame_id); | 1290 request, &render_process_id, &render_frame_id); |
| 1345 UMA_HISTOGRAM_BOOLEAN("Extensions.WebRequestEventFoundFrame", | 1291 UMA_HISTOGRAM_BOOLEAN("Extensions.WebRequestEventFoundFrame", |
| 1346 found_render_frame); | 1292 found_render_frame); |
| 1347 ExtensionApiFrameIdMap::FrameData frame_data; | 1293 ExtensionApiFrameIdMap::FrameData frame_data; |
| 1348 if (found_render_frame) { | 1294 if (found_render_frame) { |
| 1349 ExtensionApiFrameIdMap::Get()->GetCachedFrameDataOnIO( | 1295 ExtensionApiFrameIdMap::Get()->GetCachedFrameDataOnIO( |
| 1350 render_process_id, render_frame_id, &frame_data); | 1296 render_process_id, render_frame_id, &frame_data); |
| 1351 } | 1297 } |
| 1352 // Check if the tab id and window id match, if they were set in the | 1298 // Check if the tab id and window id match, if they were set in the |
| 1353 // listener params. | 1299 // listener params. |
| 1354 if ((listener.filter.tab_id != -1 && | 1300 if ((listener->filter.tab_id != -1 && |
| 1355 frame_data.tab_id != listener.filter.tab_id) || | 1301 frame_data.tab_id != listener->filter.tab_id) || |
| 1356 (listener.filter.window_id != -1 && | 1302 (listener->filter.window_id != -1 && |
| 1357 frame_data.window_id != listener.filter.window_id)) { | 1303 frame_data.window_id != listener->filter.window_id)) { |
| 1358 continue; | 1304 continue; |
| 1359 } | 1305 } |
| 1360 | 1306 |
| 1361 const std::vector<content::ResourceType>& types = listener.filter.types; | 1307 const std::vector<content::ResourceType>& types = listener->filter.types; |
| 1362 if (!types.empty() && | 1308 if (!types.empty() && |
| 1363 std::find(types.begin(), types.end(), resource_type) == types.end()) { | 1309 std::find(types.begin(), types.end(), resource_type) == types.end()) { |
| 1364 continue; | 1310 continue; |
| 1365 } | 1311 } |
| 1366 | 1312 |
| 1367 if (!is_web_view_guest) { | 1313 if (!is_web_view_guest) { |
| 1368 PermissionsData::AccessType access = | 1314 PermissionsData::AccessType access = |
| 1369 WebRequestPermissions::CanExtensionAccessURL( | 1315 WebRequestPermissions::CanExtensionAccessURL( |
| 1370 extension_info_map, listener.extension_id, url, frame_data.tab_id, | 1316 extension_info_map, listener->id.extension_id, url, |
| 1371 crosses_incognito, | 1317 frame_data.tab_id, crosses_incognito, |
| 1372 WebRequestPermissions::REQUIRE_HOST_PERMISSION); | 1318 WebRequestPermissions::REQUIRE_HOST_PERMISSION); |
| 1373 if (access != PermissionsData::ACCESS_ALLOWED) { | 1319 if (access != PermissionsData::ACCESS_ALLOWED) { |
| 1374 if (access == PermissionsData::ACCESS_WITHHELD && | 1320 if (access == PermissionsData::ACCESS_WITHHELD && |
| 1375 web_request_event_router_delegate_) { | 1321 web_request_event_router_delegate_) { |
| 1376 web_request_event_router_delegate_->NotifyWebRequestWithheld( | 1322 web_request_event_router_delegate_->NotifyWebRequestWithheld( |
| 1377 render_process_id, render_frame_id, listener.extension_id); | 1323 render_process_id, render_frame_id, listener->id.extension_id); |
| 1378 } | 1324 } |
| 1379 continue; | 1325 continue; |
| 1380 } | 1326 } |
| 1381 } | 1327 } |
| 1382 | 1328 |
| 1383 bool blocking_listener = | 1329 bool blocking_listener = |
| 1384 (listener.extra_info_spec & | 1330 (listener->extra_info_spec & |
| 1385 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0; | 1331 (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0; |
| 1386 | 1332 |
| 1387 // We do not want to notify extensions about XHR requests that are | 1333 // We do not want to notify extensions about XHR requests that are |
| 1388 // triggered by themselves. This is a workaround to prevent deadlocks | 1334 // triggered by themselves. This is a workaround to prevent deadlocks |
| 1389 // in case of synchronous XHR requests that block the extension renderer | 1335 // in case of synchronous XHR requests that block the extension renderer |
| 1390 // and therefore prevent the extension from processing the request | 1336 // and therefore prevent the extension from processing the request |
| 1391 // handler. This is only a problem for blocking listeners. | 1337 // handler. This is only a problem for blocking listeners. |
| 1392 // http://crbug.com/105656 | 1338 // http://crbug.com/105656 |
| 1393 bool synchronous_xhr_from_extension = | 1339 bool synchronous_xhr_from_extension = |
| 1394 !is_async_request && is_request_from_extension && | 1340 !is_async_request && is_request_from_extension && |
| 1395 resource_type == content::RESOURCE_TYPE_XHR; | 1341 resource_type == content::RESOURCE_TYPE_XHR; |
| 1396 | 1342 |
| 1397 // Only send webRequest events for URLs the extension has access to. | 1343 // Only send webRequest events for URLs the extension has access to. |
| 1398 if (blocking_listener && synchronous_xhr_from_extension) | 1344 if (blocking_listener && synchronous_xhr_from_extension) |
| 1399 continue; | 1345 continue; |
| 1400 | 1346 |
| 1401 matching_listeners->push_back(&listener); | 1347 matching_listeners->push_back(listener.get()); |
| 1402 *extra_info_spec |= listener.extra_info_spec; | 1348 *extra_info_spec |= listener->extra_info_spec; |
| 1403 } | 1349 } |
| 1404 } | 1350 } |
| 1405 | 1351 |
| 1406 ExtensionWebRequestEventRouter::EventListeners | 1352 ExtensionWebRequestEventRouter::RawListeners |
| 1407 ExtensionWebRequestEventRouter::GetMatchingListeners( | 1353 ExtensionWebRequestEventRouter::GetMatchingListeners( |
| 1408 void* browser_context, | 1354 void* browser_context, |
| 1409 const InfoMap* extension_info_map, | 1355 const InfoMap* extension_info_map, |
| 1410 const std::string& event_name, | 1356 const std::string& event_name, |
| 1411 const net::URLRequest* request, | 1357 const net::URLRequest* request, |
| 1412 int* extra_info_spec) { | 1358 int* extra_info_spec) { |
| 1413 // TODO(mpcomplete): handle browser_context == NULL (should collect all | 1359 // TODO(mpcomplete): handle browser_context == NULL (should collect all |
| 1414 // listeners). | 1360 // listeners). |
| 1415 *extra_info_spec = 0; | 1361 *extra_info_spec = 0; |
| 1416 | 1362 |
| 1417 const GURL& url = request->url(); | 1363 const GURL& url = request->url(); |
| 1418 int render_process_host_id = content::ChildProcessHost::kInvalidUniqueID; | 1364 int render_process_host_id = content::ChildProcessHost::kInvalidUniqueID; |
| 1419 int routing_id = MSG_ROUTING_NONE; | 1365 int routing_id = MSG_ROUTING_NONE; |
| 1420 content::ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE; | 1366 content::ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE; |
| 1421 // We are conservative here and assume requests are asynchronous in case | 1367 // We are conservative here and assume requests are asynchronous in case |
| 1422 // we don't have an info object. We don't want to risk a deadlock. | 1368 // we don't have an info object. We don't want to risk a deadlock. |
| 1423 bool is_async_request = false; | 1369 bool is_async_request = false; |
| 1424 bool is_request_from_extension = | 1370 bool is_request_from_extension = |
| 1425 IsRequestFromExtension(request, extension_info_map); | 1371 IsRequestFromExtension(request, extension_info_map); |
| 1426 | 1372 |
| 1427 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); | 1373 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); |
| 1428 if (info) { | 1374 if (info) { |
| 1429 is_async_request = info->IsAsync(); | 1375 is_async_request = info->IsAsync(); |
| 1430 if (helpers::IsRelevantResourceType(info->GetResourceType())) | 1376 if (helpers::IsRelevantResourceType(info->GetResourceType())) |
| 1431 resource_type = info->GetResourceType(); | 1377 resource_type = info->GetResourceType(); |
| 1432 render_process_host_id = info->GetChildID(); | 1378 render_process_host_id = info->GetChildID(); |
| 1433 routing_id = info->GetRouteID(); | 1379 routing_id = info->GetRouteID(); |
| 1434 } | 1380 } |
| 1435 | 1381 |
| 1436 EventListeners matching_listeners; | 1382 RawListeners matching_listeners; |
| 1437 GetMatchingListenersImpl( | 1383 GetMatchingListenersImpl( |
| 1438 browser_context, request, extension_info_map, false, event_name, | 1384 browser_context, request, extension_info_map, false, event_name, |
| 1439 url, render_process_host_id, routing_id, resource_type, | 1385 url, render_process_host_id, routing_id, resource_type, |
| 1440 is_async_request, is_request_from_extension, extra_info_spec, | 1386 is_async_request, is_request_from_extension, extra_info_spec, |
| 1441 &matching_listeners); | 1387 &matching_listeners); |
| 1442 void* cross_browser_context = GetCrossBrowserContext(browser_context); | 1388 void* cross_browser_context = GetCrossBrowserContext(browser_context); |
| 1443 if (cross_browser_context) { | 1389 if (cross_browser_context) { |
| 1444 GetMatchingListenersImpl( | 1390 GetMatchingListenersImpl( |
| 1445 cross_browser_context, request, extension_info_map, true, event_name, | 1391 cross_browser_context, request, extension_info_map, true, event_name, |
| 1446 url, render_process_host_id, routing_id, resource_type, | 1392 url, render_process_host_id, routing_id, resource_type, |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1645 // declarative rules to be read from disk. | 1591 // declarative rules to be read from disk. |
| 1646 UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayStartup", block_time); | 1592 UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayStartup", block_time); |
| 1647 } | 1593 } |
| 1648 | 1594 |
| 1649 if (num_handlers_blocking == 0) { | 1595 if (num_handlers_blocking == 0) { |
| 1650 blocked_request.request->LogUnblocked(); | 1596 blocked_request.request->LogUnblocked(); |
| 1651 ExecuteDeltas(browser_context, request_id, true); | 1597 ExecuteDeltas(browser_context, request_id, true); |
| 1652 } else { | 1598 } else { |
| 1653 // Update the URLRequest to make sure it's tagged with an extension that's | 1599 // Update the URLRequest to make sure it's tagged with an extension that's |
| 1654 // still blocking it. This may end up being the same extension as before. | 1600 // still blocking it. This may end up being the same extension as before. |
| 1655 std::set<EventListener>& listeners = | 1601 Listeners& listeners = listeners_[browser_context][event_name]; |
| 1656 listeners_[browser_context][event_name]; | |
| 1657 | 1602 |
| 1658 for (const auto& listener : listeners) { | 1603 for (const auto& listener : listeners) { |
| 1659 if (!base::ContainsKey(listener.blocked_requests, request_id)) | 1604 if (!base::ContainsKey(listener->blocked_requests, request_id)) |
| 1660 continue; | 1605 continue; |
| 1661 std::string delegate_info = | 1606 std::string delegate_info = l10n_util::GetStringFUTF8( |
| 1662 l10n_util::GetStringFUTF8(IDS_LOAD_STATE_PARAMETER_EXTENSION, | 1607 IDS_LOAD_STATE_PARAMETER_EXTENSION, |
| 1663 base::UTF8ToUTF16(listener.extension_name)); | 1608 base::UTF8ToUTF16(listener->extension_name)); |
| 1664 blocked_request.request->LogAndReportBlockedBy(delegate_info.c_str()); | 1609 blocked_request.request->LogAndReportBlockedBy(delegate_info.c_str()); |
| 1665 break; | 1610 break; |
| 1666 } | 1611 } |
| 1667 } | 1612 } |
| 1668 } | 1613 } |
| 1669 | 1614 |
| 1670 void ExtensionWebRequestEventRouter::SendMessages( | 1615 void ExtensionWebRequestEventRouter::SendMessages( |
| 1671 void* browser_context, | 1616 void* browser_context, |
| 1672 const BlockedRequest& blocked_request) { | 1617 const BlockedRequest& blocked_request) { |
| 1673 const helpers::EventResponseDeltas& deltas = blocked_request.response_deltas; | 1618 const helpers::EventResponseDeltas& deltas = blocked_request.response_deltas; |
| (...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2251 // Continue gracefully. | 2196 // Continue gracefully. |
| 2252 RunWithValidation()->Execute(); | 2197 RunWithValidation()->Execute(); |
| 2253 } | 2198 } |
| 2254 | 2199 |
| 2255 ExtensionFunction::ResponseAction | 2200 ExtensionFunction::ResponseAction |
| 2256 WebRequestHandlerBehaviorChangedFunction::Run() { | 2201 WebRequestHandlerBehaviorChangedFunction::Run() { |
| 2257 helpers::ClearCacheOnNavigation(); | 2202 helpers::ClearCacheOnNavigation(); |
| 2258 return RespondNow(NoArguments()); | 2203 return RespondNow(NoArguments()); |
| 2259 } | 2204 } |
| 2260 | 2205 |
| 2206 ExtensionWebRequestEventRouter::EventListener::ID::ID( |
| 2207 void* browser_context, |
| 2208 const std::string& extension_id, |
| 2209 const std::string& sub_event_name, |
| 2210 int embedder_process_id, |
| 2211 int web_view_instance_id) |
| 2212 : browser_context(browser_context), |
| 2213 extension_id(extension_id), |
| 2214 sub_event_name(sub_event_name), |
| 2215 embedder_process_id(embedder_process_id), |
| 2216 web_view_instance_id(web_view_instance_id) {} |
| 2217 |
| 2218 bool ExtensionWebRequestEventRouter::EventListener::ID::LooselyMatches( |
| 2219 const ID& that) const { |
| 2220 if (web_view_instance_id == 0 && that.web_view_instance_id == 0) { |
| 2221 // Since EventListeners are segmented by browser_context, check that |
| 2222 // last, as it is exceedingly unlikely to be different. |
| 2223 return extension_id == that.extension_id && |
| 2224 sub_event_name == that.sub_event_name && |
| 2225 browser_context == that.browser_context; |
| 2226 } |
| 2227 |
| 2228 return *this == that; |
| 2229 } |
| 2230 |
| 2231 bool ExtensionWebRequestEventRouter::EventListener::ID::operator==( |
| 2232 const ID& that) const { |
| 2233 // Since EventListeners are segmented by browser_context, check that |
| 2234 // last, as it is exceedingly unlikely to be different. |
| 2235 return extension_id == that.extension_id && |
| 2236 sub_event_name == that.sub_event_name && |
| 2237 web_view_instance_id == that.web_view_instance_id && |
| 2238 embedder_process_id == that.embedder_process_id && |
| 2239 browser_context == that.browser_context; |
| 2240 } |
| 2241 |
| 2261 } // namespace extensions | 2242 } // namespace extensions |
| OLD | NEW |