Update PageNode content settings when they change
Bug: 1370699
Change-Id: I490f589914cd03598a5c098e3d6d829e88871db4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3949359
Reviewed-by: Patrick Monette <pmonette@chromium.org>
Commit-Queue: Anthony Vallée-Dubois <anthonyvd@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1058319}
diff --git a/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper.cc b/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper.cc
index 2de52a2..b4967c779 100644
--- a/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper.cc
+++ b/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper.cc
@@ -7,8 +7,14 @@
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
+#include "components/content_settings/core/browser/content_settings_observer.h"
+#include "components/content_settings/core/browser/content_settings_type_set.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/content_settings/core/common/content_settings_pattern.h"
+#include "components/content_settings/core/common/content_settings_types.h"
#include "components/performance_manager/public/decorators/page_live_state_decorator.h"
#include "components/performance_manager/public/performance_manager.h"
+#include "components/permissions/permissions_client.h"
#include "content/public/browser/web_contents_observer.h"
#if !BUILDFLAG(IS_ANDROID)
@@ -78,7 +84,8 @@
// and updates the PageLiveStateDecorator accordingly. Destroys itself when the
// WebContents it observes is destroyed.
class PageLiveStateDecoratorHelper::WebContentsObserver
- : public content::WebContentsObserver {
+ : public content::WebContentsObserver,
+ public content_settings::Observer {
public:
explicit WebContentsObserver(content::WebContents* web_contents,
PageLiveStateDecoratorHelper* outer)
@@ -92,6 +99,10 @@
next_->prev_ = this;
}
outer_->first_web_contents_observer_ = this;
+
+ content_settings_observation_.Observe(
+ permissions::PermissionsClient::Get()->GetSettingsMap(
+ web_contents->GetBrowserContext()));
}
WebContentsObserver(const WebContentsObserver&) = delete;
@@ -101,6 +112,28 @@
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
+ // content_settings::Observer:
+ void OnContentSettingChanged(
+ const ContentSettingsPattern& primary_pattern,
+ const ContentSettingsPattern& secondary_pattern,
+ ContentSettingsTypeSet content_type_set) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ GURL url = web_contents()->GetLastCommittedURL();
+ if (content_type_set.Contains(ContentSettingsType::NOTIFICATIONS) &&
+ primary_pattern.Matches(url)) {
+ // This web contents is affected by this content settings change, get the
+ // latest value and send it over to the PageLiveStateDecorator so it can
+ // be attached to the corresponding PageNode.
+ ContentSetting setting =
+ permissions::PermissionsClient::Get()
+ ->GetSettingsMap(web_contents()->GetBrowserContext())
+ ->GetContentSetting(url, url, ContentSettingsType::NOTIFICATIONS);
+
+ PageLiveStateDecorator::SetContentSettings(
+ web_contents(), {{ContentSettingsType::NOTIFICATIONS, setting}});
+ }
+ }
+
// content::WebContentsObserver:
void OnIsConnectedToBluetoothDeviceChanged(
bool is_connected_to_bluetooth_device) override {
@@ -144,6 +177,9 @@
raw_ptr<WebContentsObserver> prev_;
raw_ptr<WebContentsObserver> next_;
+ base::ScopedObservation<HostContentSettingsMap, content_settings::Observer>
+ content_settings_observation_{this};
+
SEQUENCE_CHECKER(sequence_checker_);
};
diff --git a/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper_unittest.cc b/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper_unittest.cc
index 419bb0c..ca63b7d 100644
--- a/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper_unittest.cc
+++ b/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper_unittest.cc
@@ -6,9 +6,11 @@
#include "base/callback.h"
#include "base/callback_helpers.h"
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/performance_manager/embedder/performance_manager_registry.h"
#include "components/performance_manager/performance_manager_impl.h"
#include "components/performance_manager/public/decorators/page_live_state_decorator.h"
@@ -196,6 +198,73 @@
&PageLiveStateDecorator::Data::IsConnectedToUSBDevice, false);
}
+TEST_F(PageLiveStateDecoratorHelperTest, ContentSettingsChanged) {
+ base::WeakPtr<PageNode> node =
+ PerformanceManager::GetPrimaryPageNodeForWebContents(web_contents());
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/path"));
+
+ {
+ base::RunLoop run_loop;
+ PerformanceManager::CallOnGraph(
+ FROM_HERE, base::BindLambdaForTesting([&]() {
+ ASSERT_TRUE(node);
+ const PageLiveStateDecorator::Data* data =
+ PageLiveStateDecorator::Data::FromPageNode(node.get());
+ ASSERT_TRUE(data);
+ EXPECT_EQ(data->IsContentSettingTypeAllowed(
+ ContentSettingsType::NOTIFICATIONS),
+ false);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
+
+ HostContentSettingsMap* host_content_settings_map =
+ HostContentSettingsMapFactory::GetForProfile(
+ web_contents()->GetBrowserContext());
+ host_content_settings_map->SetContentSettingDefaultScope(
+ GURL("https://www.example.com/"), GURL(),
+ ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_ALLOW);
+
+ {
+ base::RunLoop run_loop;
+ PerformanceManager::CallOnGraph(
+ FROM_HERE, base::BindLambdaForTesting([&]() {
+ ASSERT_TRUE(node);
+ const PageLiveStateDecorator::Data* data =
+ PageLiveStateDecorator::Data::FromPageNode(node.get());
+ ASSERT_TRUE(data);
+ EXPECT_EQ(data->IsContentSettingTypeAllowed(
+ ContentSettingsType::NOTIFICATIONS),
+ true);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
+
+ // Changing content settings for a different URL doesn't affect this one.
+ host_content_settings_map->SetContentSettingDefaultScope(
+ GURL("https://other.url.com/"), GURL(),
+ ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_BLOCK);
+
+ {
+ base::RunLoop run_loop;
+ PerformanceManager::CallOnGraph(
+ FROM_HERE, base::BindLambdaForTesting([&]() {
+ ASSERT_TRUE(node);
+ const PageLiveStateDecorator::Data* data =
+ PageLiveStateDecorator::Data::FromPageNode(node.get());
+ ASSERT_TRUE(data);
+ EXPECT_EQ(data->IsContentSettingTypeAllowed(
+ ContentSettingsType::NOTIFICATIONS),
+ true);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
+}
+
// Create many WebContents to exercice the code that maintains the linked list
// of PageLiveStateDecoratorHelper::WebContentsObservers.
TEST_F(PageLiveStateDecoratorHelperTest, ManyPageNodes) {