Chromium Code Reviews| Index: extensions/browser/api/web_request/web_request_api.h |
| diff --git a/extensions/browser/api/web_request/web_request_api.h b/extensions/browser/api/web_request/web_request_api.h |
| index 796d75fe914c714f50405204f8ff54a4af462949..75c772402cbcec990fd975ae68be3cb6f0b4ec0a 100644 |
| --- a/extensions/browser/api/web_request/web_request_api.h |
| +++ b/extensions/browser/api/web_request/web_request_api.h |
| @@ -14,6 +14,7 @@ |
| #include <utility> |
| #include <vector> |
| +#include "base/gtest_prod_util.h" |
| #include "base/macros.h" |
| #include "base/memory/singleton.h" |
| #include "base/memory/weak_ptr.h" |
| @@ -293,14 +294,6 @@ class ExtensionWebRequestEventRouter |
| int web_view_instance_id, |
| base::WeakPtr<IPC::Sender> ipc_sender); |
| - // Removes the listener for the given sub-event. |
| - void RemoveEventListener( |
| - void* browser_context, |
| - const std::string& extension_id, |
| - const std::string& sub_event_name, |
| - int embedder_process_id, |
| - int web_view_instance_id); |
| - |
| // Removes the listeners for a given <webview>. |
| void RemoveWebViewEventListeners( |
| void* browser_context, |
| @@ -318,12 +311,87 @@ class ExtensionWebRequestEventRouter |
| void AddCallbackForPageLoad(const base::Closure& callback); |
| private: |
| + friend class WebRequestAPI; |
| + FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTest, |
| + BlockingEventPrecedenceRedirect); |
| + FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTest, |
| + BlockingEventPrecedenceCancel); |
| + FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTest, |
| + SimulateChancelWhileBlocked); |
| + FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTest, AccessRequestBodyData); |
| + FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTest, |
| + MinimalAccessRequestBodyData); |
| + FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTest, NoAccessRequestBodyData); |
| + FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTest, AddAndRemoveListeners); |
| + FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTest, BlockedRequestsAreRemoved); |
| + FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestHeaderModificationTest, |
| + TestModifications); |
| + |
| + struct EventListener { |
| + // An EventListener is uniquely defined by five properties. |
|
Devlin
2016/09/07 19:18:00
This isn't strictly true, right? We potentially h
erikchen
2016/09/07 22:07:43
Two responses:
1) This comment was based on my int
Devlin
2016/09/08 17:33:12
Yep, that and others are why I was scared. :)
erikchen
2016/09/08 18:34:41
I added a long TODO & comment. We still need to us
|
| + struct Identifier { |
| + Identifier(void* browser_context, |
| + const std::string& extension_id, |
| + const std::string& sub_event_name, |
| + int embedder_process_id, |
| + int web_view_instance_id) |
| + : browser_context(browser_context), |
|
Devlin
2016/09/07 19:18:00
nit: these methods should probably be defined in t
erikchen
2016/09/07 22:07:43
Done.
|
| + extension_id(extension_id), |
| + sub_event_name(sub_event_name), |
| + embedder_process_id(embedder_process_id), |
| + web_view_instance_id(web_view_instance_id) {} |
| + |
| + // If web_view_instance_id is 0, then ignore embedder_process_id. |
| + bool LooselyMatches(const Identifier& that) const { |
|
Devlin
2016/09/07 19:18:00
Is there a time we don't want to do this? i.e., w
erikchen
2016/09/07 22:07:43
We can't use operator== everywhere because we aren
Devlin
2016/09/08 17:33:12
Ah, I see. This is annoying. Can we add another
erikchen
2016/09/08 18:34:42
Added a TODO.
|
| + if (web_view_instance_id == 0 && that.web_view_instance_id == 0) { |
| + // Since EventListeners are segmented by browser_context, check that |
| + // last, as it is exceedingly unlikely to be different. |
| + return extension_id == that.extension_id && |
| + sub_event_name == that.sub_event_name && |
| + browser_context == that.browser_context; |
| + } |
| + |
| + return *this == that; |
| + } |
| + |
| + bool operator==(const Identifier& that) const { |
| + // Since EventListeners are segmented by browser_context, check that |
| + // last, as it is exceedingly unlikely to be different. |
| + return extension_id == that.extension_id && |
| + sub_event_name == that.sub_event_name && |
| + web_view_instance_id == that.web_view_instance_id && |
| + embedder_process_id == that.embedder_process_id && |
| + browser_context == that.browser_context; |
| + } |
| + |
| + void* browser_context; |
| + std::string extension_id; |
| + std::string sub_event_name; |
| + int embedder_process_id; |
| + int web_view_instance_id; |
| + }; |
| + |
| + EventListener(Identifier id); |
| + ~EventListener(); |
| + |
| + const Identifier id; |
| + std::string extension_name; |
| + events::HistogramValue histogram_value = events::UNKNOWN; |
| + RequestFilter filter; |
| + int extra_info_spec = 0; |
| + base::WeakPtr<IPC::Sender> ipc_sender; |
| + std::unordered_set<uint64_t> blocked_requests; |
| + |
| + private: |
| + friend class WebRequestAPI; |
|
Devlin
2016/09/07 19:18:00
Why does the WebRequestAPI need to be able to copy
erikchen
2016/09/07 22:07:43
Removed.
|
| + DISALLOW_COPY_AND_ASSIGN(EventListener); |
| + }; |
| + |
| friend struct base::DefaultSingletonTraits<ExtensionWebRequestEventRouter>; |
| - struct EventListener; |
| - using EventListeners = std::vector<const EventListener*>; |
| - using ListenerMapForBrowserContext = |
| - std::map<std::string, std::set<EventListener>>; |
| + using ListenerIdentifiers = std::vector<EventListener::Identifier>; |
| + using Listeners = std::vector<std::unique_ptr<EventListener>>; |
| + using ListenerMapForBrowserContext = std::map<std::string, Listeners>; |
| using ListenerMap = std::map<void*, ListenerMapForBrowserContext>; |
| using BlockedRequestMap = std::map<uint64_t, BlockedRequest>; |
| // Map of request_id -> bit vector of EventTypes already signaled |
| @@ -337,24 +405,32 @@ class ExtensionWebRequestEventRouter |
| ExtensionWebRequestEventRouter(); |
| ~ExtensionWebRequestEventRouter(); |
| + // Returns the EventListener with the given |id|, or nullptr. Must be called |
| + // from the IO thread. |
| + EventListener* FindEventListener(const EventListener::Identifier& id); |
| + |
| + // Removes the listener for the given sub-event. Must be called from the IO |
| + // thread. |
| + void RemoveEventListener(const EventListener::Identifier& id); |
| + |
| // Ensures that future callbacks for |request| are ignored so that it can be |
| // destroyed safely. |
| void ClearPendingCallbacks(const net::URLRequest* request); |
| bool DispatchEvent(void* browser_context, |
| net::URLRequest* request, |
| - const std::vector<const EventListener*>& listeners, |
| + const ListenerIdentifiers& listener_ids, |
| std::unique_ptr<WebRequestEventDetails> event_details); |
| void DispatchEventToListeners( |
| void* browser_context, |
| - std::unique_ptr<std::vector<EventListener>> listeners, |
| + const ListenerIdentifiers& listener_ids, |
| std::unique_ptr<WebRequestEventDetails> event_details); |
| // Returns a list of event listeners that care about the given event, based |
| // on their filter parameters. |extra_info_spec| will contain the combined |
| // set of extra_info_spec flags that every matching listener asked for. |
| - std::vector<const EventListener*> GetMatchingListeners( |
| + ListenerIdentifiers GetMatchingListeners( |
| void* browser_context, |
| const extensions::InfoMap* extension_info_map, |
| const std::string& event_name, |
| @@ -365,20 +441,19 @@ class ExtensionWebRequestEventRouter |
| // browser_context of the event, the next time for the "cross" browser_context |
| // (i.e. the incognito browser_context if the event is originally for the |
| // normal browser_context, or vice versa). |
| - void GetMatchingListenersImpl( |
| - void* browser_context, |
| - const net::URLRequest* request, |
| - const extensions::InfoMap* extension_info_map, |
| - bool crosses_incognito, |
| - const std::string& event_name, |
| - const GURL& url, |
| - int render_process_host_id, |
| - int routing_id, |
| - content::ResourceType resource_type, |
| - bool is_async_request, |
| - bool is_request_from_extension, |
| - int* extra_info_spec, |
| - std::vector<const EventListener*>* matching_listeners); |
| + void GetMatchingListenersImpl(void* browser_context, |
| + const net::URLRequest* request, |
| + const extensions::InfoMap* extension_info_map, |
| + bool crosses_incognito, |
| + const std::string& event_name, |
| + const GURL& url, |
| + int render_process_host_id, |
| + int routing_id, |
| + content::ResourceType resource_type, |
| + bool is_async_request, |
| + bool is_request_from_extension, |
| + int* extra_info_spec, |
| + ListenerIdentifiers* matching_listeners); |
| // Decrements the count of event handlers blocking the given request. When the |
| // count reaches 0, we stop blocking the request and proceed it using the |
| @@ -457,6 +532,10 @@ class ExtensionWebRequestEventRouter |
| // Returns true if |request| was already signaled to some event handlers. |
| bool WasSignaled(const net::URLRequest& request) const; |
| + // Get the number of listeners - for testing only. |
| + size_t GetListenerCountForTesting(void* browser_context, |
| + const std::string& event_name); |
| + |
| // A map for each browser_context that maps an event name to a set of |
| // extensions that are listening to that event. |
| ListenerMap listeners_; |