[Extensions] Remove webRequest data when a BrowserContext is destroyed.
The ExtensionWebRequestRouter is a singleton object that can outlive a BrowserContext. This CL clears any data related to a BrowserContext when it's destroyed. Bug: 1024211 Change-Id: Idd77a089c284037c08e8737b36402fcaf4bd4646 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3445250 Reviewed-by: Devlin Cronin <rdevlin.cronin@chromium.org> Commit-Queue: David Bertoni <dbertoni@chromium.org> Cr-Commit-Position: refs/heads/main@{#969698}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
1e13a54982
commit
016d88efc2
chrome/browser/extensions/api/web_request
extensions/browser/api/web_request
@ -190,6 +190,83 @@ TEST_F(ExtensionWebRequestTest, AddAndRemoveListeners) {
|
||||
&profile_, kEventName));
|
||||
}
|
||||
|
||||
// Tests that when a browser_context shuts down, all data keyed to that
|
||||
// context is removed.
|
||||
TEST_F(ExtensionWebRequestTest, BrowserContextShutdown) {
|
||||
ExtensionWebRequestEventRouter* const event_router =
|
||||
ExtensionWebRequestEventRouter::GetInstance();
|
||||
ASSERT_TRUE(event_router);
|
||||
|
||||
std::string ext_id("abcdefghijklmnopabcdefghijklmnop");
|
||||
ExtensionWebRequestEventRouter::RequestFilter filter;
|
||||
const std::string kEventName(web_request::OnBeforeRequest::kEventName);
|
||||
const std::string kSubEventName = kEventName + "/1";
|
||||
EXPECT_EQ(0u,
|
||||
event_router->GetListenerCountForTesting(&profile_, kEventName));
|
||||
EXPECT_FALSE(event_router->HasAnyExtraHeadersListenerImpl(&profile_));
|
||||
|
||||
// Add two listeners for the main profile.
|
||||
event_router->AddEventListener(
|
||||
&profile_, ext_id, ext_id, events::FOR_TEST, kEventName, kSubEventName,
|
||||
filter, 0, 1 /* render_process_id */, 0, extensions::kMainThreadId,
|
||||
blink::mojom::kInvalidServiceWorkerVersionId);
|
||||
event_router->AddEventListener(
|
||||
&profile_, ext_id, ext_id, events::FOR_TEST, kEventName, kSubEventName,
|
||||
filter, 0, 2 /* render_process_id */, 0, extensions::kMainThreadId,
|
||||
blink::mojom::kInvalidServiceWorkerVersionId);
|
||||
event_router->IncrementExtraHeadersListenerCount(&profile_);
|
||||
EXPECT_EQ(2u,
|
||||
event_router->GetListenerCountForTesting(&profile_, kEventName));
|
||||
EXPECT_TRUE(event_router->HasAnyExtraHeadersListenerImpl(&profile_));
|
||||
|
||||
// Create an off-the-record profile.
|
||||
auto otr_profile_id = Profile::OTRProfileID::CreateUniqueForTesting();
|
||||
Profile* const otr_profile =
|
||||
profile_.GetOffTheRecordProfile(otr_profile_id,
|
||||
/*create_if_needed=*/true);
|
||||
ASSERT_TRUE(otr_profile);
|
||||
|
||||
// Because the ExtensionWebRequestEventRouter is a singleton, there are hooks
|
||||
// in the off-the-record profile for notifying it when an OTR profile is
|
||||
// created and destroyed. Unfortunately, that doesn't work with test profiles,
|
||||
// so the test needs to simulate those calls
|
||||
event_router->OnOTRBrowserContextCreated(&profile_, otr_profile);
|
||||
EXPECT_EQ(2u, event_router->cross_browser_context_map_.size());
|
||||
EXPECT_EQ(0u,
|
||||
event_router->GetListenerCountForTesting(otr_profile, kEventName));
|
||||
EXPECT_FALSE(event_router->HasAnyExtraHeadersListenerImpl(otr_profile));
|
||||
|
||||
// Add two listeners for the otr profile.
|
||||
event_router->AddEventListener(
|
||||
otr_profile, ext_id, ext_id, events::FOR_TEST, kEventName, kSubEventName,
|
||||
filter, 0, 1 /* render_process_id */, 0, extensions::kMainThreadId,
|
||||
blink::mojom::kInvalidServiceWorkerVersionId);
|
||||
event_router->AddEventListener(
|
||||
otr_profile, ext_id, ext_id, events::FOR_TEST, kEventName, kSubEventName,
|
||||
filter, 0, 2 /* render_process_id */, 0, extensions::kMainThreadId,
|
||||
blink::mojom::kInvalidServiceWorkerVersionId);
|
||||
event_router->IncrementExtraHeadersListenerCount(otr_profile);
|
||||
EXPECT_EQ(2u,
|
||||
event_router->GetListenerCountForTesting(otr_profile, kEventName));
|
||||
EXPECT_TRUE(event_router->HasAnyExtraHeadersListenerImpl(otr_profile));
|
||||
|
||||
// Simulate the OTR being destroyed.
|
||||
event_router->OnOTRBrowserContextDestroyed(&profile_, otr_profile);
|
||||
EXPECT_EQ(0u, event_router->cross_browser_context_map_.size());
|
||||
EXPECT_EQ(0u,
|
||||
event_router->GetListenerCountForTesting(otr_profile, kEventName));
|
||||
EXPECT_FALSE(event_router->HasAnyExtraHeadersListenerImpl(otr_profile));
|
||||
|
||||
// We can't just delete the profile, because the call comes through the
|
||||
// WebRequestAPI instance for that profile, and creating that requires
|
||||
// more infrastucture than it's worth. Instead, simulate it with a call
|
||||
// into the event router directly.
|
||||
event_router->OnBrowserContextShutdown(&profile_);
|
||||
EXPECT_EQ(0u,
|
||||
event_router->GetListenerCountForTesting(&profile_, kEventName));
|
||||
EXPECT_FALSE(event_router->HasAnyExtraHeadersListenerImpl(&profile_));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void TestInitFromValue(content::BrowserContext* browser_context,
|
||||
|
@ -649,6 +649,8 @@ void WebRequestAPI::Shutdown() {
|
||||
proxies_.reset();
|
||||
EventRouter::Get(browser_context_)->UnregisterObserver(this);
|
||||
extensions::ExtensionRegistry::Get(browser_context_)->RemoveObserver(this);
|
||||
ExtensionWebRequestEventRouter::GetInstance()->OnBrowserContextShutdown(
|
||||
browser_context_);
|
||||
}
|
||||
|
||||
static base::LazyInstance<
|
||||
@ -1818,6 +1820,7 @@ void ExtensionWebRequestEventRouter::OnOTRBrowserContextDestroyed(
|
||||
content::BrowserContext* otr_browser_context) {
|
||||
cross_browser_context_map_.erase(otr_browser_context);
|
||||
cross_browser_context_map_.erase(original_browser_context);
|
||||
OnBrowserContextShutdown(otr_browser_context);
|
||||
}
|
||||
|
||||
void ExtensionWebRequestEventRouter::AddCallbackForPageLoad(
|
||||
@ -1875,7 +1878,6 @@ void ExtensionWebRequestEventRouter::IncrementExtraHeadersListenerCount(
|
||||
// We only keep values greater than 0 in the map.
|
||||
DCHECK_GT(result.first->second, 0);
|
||||
result.first->second++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1891,6 +1893,12 @@ void ExtensionWebRequestEventRouter::DecrementExtraHeadersListenerCount(
|
||||
extra_headers_listener_count_.erase(it);
|
||||
}
|
||||
|
||||
void ExtensionWebRequestEventRouter::OnBrowserContextShutdown(
|
||||
content::BrowserContext* browser_context) {
|
||||
listeners_.erase(browser_context);
|
||||
extra_headers_listener_count_.erase(browser_context);
|
||||
}
|
||||
|
||||
bool ExtensionWebRequestEventRouter::HasAnyExtraHeadersListenerImpl(
|
||||
content::BrowserContext* browser_context) {
|
||||
return base::Contains(extra_headers_listener_count_, browser_context);
|
||||
|
@ -534,25 +534,14 @@ class ExtensionWebRequestEventRouter {
|
||||
void DecrementExtraHeadersListenerCount(
|
||||
content::BrowserContext* browser_context);
|
||||
|
||||
// Called when a BrowserContext is being destroyed.
|
||||
void OnBrowserContextShutdown(content::BrowserContext* browser_context);
|
||||
|
||||
private:
|
||||
friend class WebRequestAPI;
|
||||
friend class base::NoDestructor<ExtensionWebRequestEventRouter>;
|
||||
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,
|
||||
ProperFilteringInPublicSession);
|
||||
FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTest, NoAccessRequestBodyData);
|
||||
FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTest, AddAndRemoveListeners);
|
||||
FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTest, BlockedRequestsAreRemoved);
|
||||
FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestHeaderModificationTest,
|
||||
TestModifications);
|
||||
FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTest, BrowserContextShutdown);
|
||||
|
||||
struct EventListener {
|
||||
// TODO(rdevlin.cronin): There are two types of EventListeners - those
|
||||
|
Reference in New Issue
Block a user