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