diff --git a/build/patches/Add-webgl-site-setting.patch b/build/patches/Add-webgl-site-setting.patch new file mode 100644 index 00000000..5d17ba3a --- /dev/null +++ b/build/patches/Add-webgl-site-setting.patch @@ -0,0 +1,492 @@ +From: uazo +Date: Tue, 3 May 2022 14:44:11 +0000 +Subject: Add webgl site settings + +Require: Content-settings-infrastructure.patch +--- + .../browser_ui/site_settings/android/BUILD.gn | 3 + + .../BromiteCustomContentSettingImpl.java | 1 + + .../BromiteWebGLContentSetting.java | 85 +++++++++++++++++++ + .../site_settings/SiteSettingsCategory.java | 5 +- + .../strings/android/browser_ui_strings.grd | 1 + + .../browser_ui/strings/android/webgl.grdp | 18 ++++ + components/components_strings.grd | 1 + + .../core/browser/content_settings_registry.cc | 14 +++ + .../core/browser/content_settings_utils.cc | 2 + + .../core/common/content_settings.cc | 3 +- + .../core/common/content_settings.h | 1 + + .../core/common/content_settings.mojom | 1 + + .../common/content_settings_mojom_traits.cc | 3 +- + .../common/content_settings_mojom_traits.h | 5 ++ + .../core/common/content_settings_types.h | 2 + + .../renderer/content_settings_agent_impl.cc | 9 ++ + .../renderer/content_settings_agent_impl.h | 1 + + .../platform/web_content_settings_client.h | 2 + + .../execution_context/execution_context.cc | 23 +++++ + .../execution_context/execution_context.h | 5 ++ + .../webgl/webgl_rendering_context_base.cc | 32 +++---- + .../webgl/webgl_rendering_context_base.h | 2 + + 22 files changed, 196 insertions(+), 23 deletions(-) + create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteWebGLContentSetting.java + create mode 100644 components/browser_ui/strings/android/webgl.grdp + +diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/browser_ui/site_settings/android/BUILD.gn +--- a/components/browser_ui/site_settings/android/BUILD.gn ++++ b/components/browser_ui/site_settings/android/BUILD.gn +@@ -72,6 +72,9 @@ android_library("java") { + "java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java", + "java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting.java", + ] ++ sources += [ ++ "java/src/org/chromium/components/browser_ui/site_settings/BromiteWebGLContentSetting.java", ++ ] + annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] + resources_package = "org.chromium.components.browser_ui.site_settings" + deps = [ +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java +--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java +@@ -43,6 +43,7 @@ public abstract class BromiteCustomContentSettingImpl { + + static { + mItemList = new ArrayList(); ++ mItemList.add(new BromiteWebGLContentSetting()); + } + + public static SiteSettingsCategory createFromType( +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteWebGLContentSetting.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteWebGLContentSetting.java +new file mode 100644 +--- /dev/null ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteWebGLContentSetting.java +@@ -0,0 +1,85 @@ ++/* ++ This file is part of Bromite. ++ ++ Bromite is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ Bromite is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with Bromite. If not, see . ++*/ ++ ++package org.chromium.components.browser_ui.site_settings; ++ ++import org.chromium.components.browser_ui.site_settings.ContentSettingsResources; ++import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory; ++import org.chromium.components.content_settings.ContentSettingValues; ++import org.chromium.components.content_settings.ContentSettingsType; ++import org.chromium.content_public.browser.BrowserContextHandle; ++ ++import androidx.annotation.Nullable; ++import androidx.preference.Preference; ++import androidx.preference.PreferenceScreen; ++ ++import java.util.ArrayList; ++ ++public class BromiteWebGLContentSetting extends BromiteCustomContentSetting { ++ public BromiteWebGLContentSetting() { ++ super(/*contentSettingsType*/ ContentSettingsType.WEBGL, ++ /*siteSettingsCategory*/ SiteSettingsCategory.Type.WEBGL, ++ /*initialDefaultValue*/ ContentSettingValues.BLOCK, ++ /*defaultDisabledValue*/ ContentSettingValues.BLOCK, ++ /*allowException*/ true, ++ /*preferenceKey*/ "webgl", ++ /*profilePrefKey*/ "webgl"); ++ } ++ ++ @Override ++ public ContentSettingsResources.ResourceItem getResourceItem() { ++ return new ContentSettingsResources.ResourceItem( ++ /*icon*/ R.drawable.web_asset, ++ /*title*/ R.string.webgl_permission_title, ++ /*defaultEnabledValue*/ getInitialDefaultValue(), ++ /*defaultDisabledValue*/ getDefaultDisabledValue(), ++ /*enabledSummary*/ R.string.website_settings_category_webgl_enabled, ++ /*disabledSummary*/ R.string.website_settings_category_webgl_disabled); ++ } ++ ++ @Override ++ public int getCategorySummary(@Nullable @ContentSettingValues int value) { ++ switch (value) { ++ case ContentSettingValues.ALLOW: ++ return R.string.website_settings_category_webgl_enabled; ++ case ContentSettingValues.BLOCK: ++ return R.string.website_settings_category_webgl_disabled; ++ default: ++ return 0; ++ } ++ } ++ ++ @Override ++ public boolean requiresTriStateContentSetting() { ++ return false; ++ } ++ ++ @Override ++ public boolean showOnlyDescriptions() { ++ return true; ++ } ++ ++ @Override ++ public int getAddExceptionDialogMessage() { ++ return R.string.website_settings_category_webgl_enabled; ++ } ++ ++ @Override ++ public @Nullable Boolean considerException(SiteSettingsCategory category, @ContentSettingValues int value) { ++ return value != ContentSettingValues.BLOCK; ++ } ++} +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java +--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java +@@ -44,7 +44,7 @@ public class SiteSettingsCategory { + Type.PROTECTED_MEDIA, Type.SENSORS, Type.SOUND, Type.USB, Type.VIRTUAL_REALITY, + Type.USE_STORAGE, Type.AUTO_DARK_WEB_CONTENT, Type.REQUEST_DESKTOP_SITE, + Type.FEDERATED_IDENTITY_API, Type.TIMEZONE_OVERRIDE, Type.AUTOPLAY, Type.JAVASCRIPT_JIT, +- Type.IMAGES}) ++ Type.IMAGES, Type.WEBGL}) + @Retention(RetentionPolicy.SOURCE) + public @interface Type { + // All updates here must also be reflected in {@link #preferenceKey(int) +@@ -79,10 +79,11 @@ public class SiteSettingsCategory { + int AUTOPLAY = 27; + int JAVASCRIPT_JIT = 28; + int IMAGES = 29; ++ int WEBGL = 30; + /** + * Number of handled categories used for calculating array sizes. + */ +- int NUM_ENTRIES = 30; ++ int NUM_ENTRIES = 31; + } + + private final BrowserContextHandle mBrowserContextHandle; +diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/components/browser_ui/strings/android/browser_ui_strings.grd +--- a/components/browser_ui/strings/android/browser_ui_strings.grd ++++ b/components/browser_ui/strings/android/browser_ui_strings.grd +@@ -173,6 +173,7 @@ + + + ++ + + + Got it +diff --git a/components/browser_ui/strings/android/webgl.grdp b/components/browser_ui/strings/android/webgl.grdp +new file mode 100644 +--- /dev/null ++++ b/components/browser_ui/strings/android/webgl.grdp +@@ -0,0 +1,18 @@ ++ ++ ++ ++ Webgl ++ ++ ++ webgl ++ ++ ++ Webgl ++ ++ ++ Enabled ++ ++ ++ Disabled ++ ++ +diff --git a/components/components_strings.grd b/components/components_strings.grd +--- a/components/components_strings.grd ++++ b/components/components_strings.grd +@@ -334,6 +334,7 @@ + + + ++ + + + +diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc +--- a/components/content_settings/core/browser/content_settings_registry.cc ++++ b/components/content_settings/core/browser/content_settings_registry.cc +@@ -667,6 +667,20 @@ void ContentSettingsRegistry::Init() { + ContentSettingsInfo::INHERIT_IN_INCOGNITO, + ContentSettingsInfo::PERSISTENT, + ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY); ++ ++ Register(ContentSettingsType::WEBGL, "webgl", CONTENT_SETTING_BLOCK, ++ WebsiteSettingsInfo::SYNCABLE, ++ AllowlistedSchemes(), ++ ValidSettings(CONTENT_SETTING_ALLOW, ++ CONTENT_SETTING_BLOCK), ++ WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE, ++ WebsiteSettingsRegistry::PLATFORM_ANDROID, ++ ContentSettingsInfo::INHERIT_IN_INCOGNITO, ++ ContentSettingsInfo::PERSISTENT, ++ ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS, ++ /*show_into_info_page*/ true, ++ /*permission_type_ui*/ IDS_SITE_SETTINGS_TYPE_WEBGL, ++ /*permission_type_ui_mid_sentence*/ IDS_SITE_SETTINGS_TYPE_WEBGL_MID_SENTENCE); + } + + void ContentSettingsRegistry::Register( +diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc +--- a/components/content_settings/core/browser/content_settings_utils.cc ++++ b/components/content_settings/core/browser/content_settings_utils.cc +@@ -155,6 +155,8 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map, + std::string timezone; + map->GetTimezoneOverrideValue(timezone); + rules->timezone_override_value = timezone; ++ map->GetSettingsForOneType(ContentSettingsType::WEBGL, ++ &(rules->webgl_rules)); + } + + bool IsMorePermissive(ContentSetting a, ContentSetting b) { +diff --git a/components/content_settings/core/common/content_settings.cc b/components/content_settings/core/common/content_settings.cc +--- a/components/content_settings/core/common/content_settings.cc ++++ b/components/content_settings/core/common/content_settings.cc +@@ -195,7 +195,8 @@ bool RendererContentSettingRules::IsRendererContentSetting( + content_type == ContentSettingsType::POPUPS || + content_type == ContentSettingsType::MIXEDSCRIPT || + content_type == ContentSettingsType::AUTO_DARK_WEB_CONTENT || +- content_type == ContentSettingsType::TIMEZONE_OVERRIDE; ++ content_type == ContentSettingsType::TIMEZONE_OVERRIDE || ++ content_type == ContentSettingsType::WEBGL; + } + + RendererContentSettingRules::RendererContentSettingRules() {} +diff --git a/components/content_settings/core/common/content_settings.h b/components/content_settings/core/common/content_settings.h +--- a/components/content_settings/core/common/content_settings.h ++++ b/components/content_settings/core/common/content_settings.h +@@ -85,6 +85,7 @@ struct RendererContentSettingRules { + ContentSettingsForOneType auto_dark_content_rules; + ContentSettingsForOneType timezone_override_rules; + std::string timezone_override_value; ++ ContentSettingsForOneType webgl_rules; + }; + + namespace content_settings { +diff --git a/components/content_settings/core/common/content_settings.mojom b/components/content_settings/core/common/content_settings.mojom +--- a/components/content_settings/core/common/content_settings.mojom ++++ b/components/content_settings/core/common/content_settings.mojom +@@ -81,4 +81,5 @@ struct RendererContentSettingRules { + array auto_dark_content_rules; + array timezone_override_rules; + string timezone_override_value; ++ array webgl_rules; + }; +diff --git a/components/content_settings/core/common/content_settings_mojom_traits.cc b/components/content_settings/core/common/content_settings_mojom_traits.cc +--- a/components/content_settings/core/common/content_settings_mojom_traits.cc ++++ b/components/content_settings/core/common/content_settings_mojom_traits.cc +@@ -104,7 +104,8 @@ bool StructTraitsmixed_content_rules) && + data.ReadAutoDarkContentRules(&out->auto_dark_content_rules) && + data.ReadTimezoneOverrideRules(&out->timezone_override_rules) && +- data.ReadTimezoneOverrideValue(&out->timezone_override_value); ++ data.ReadTimezoneOverrideValue(&out->timezone_override_value) && ++ data.ReadWebglRules(&out->webgl_rules); + } + + } // namespace mojo +diff --git a/components/content_settings/core/common/content_settings_mojom_traits.h b/components/content_settings/core/common/content_settings_mojom_traits.h +--- a/components/content_settings/core/common/content_settings_mojom_traits.h ++++ b/components/content_settings/core/common/content_settings_mojom_traits.h +@@ -165,6 +165,11 @@ struct StructTraits< + return r.timezone_override_value; + } + ++ static const std::vector& webgl_rules( ++ const RendererContentSettingRules& r) { ++ return r.webgl_rules; ++ } ++ + static bool Read( + content_settings::mojom::RendererContentSettingRulesDataView data, + RendererContentSettingRules* out); +diff --git a/components/content_settings/core/common/content_settings_types.h b/components/content_settings/core/common/content_settings_types.h +--- a/components/content_settings/core/common/content_settings_types.h ++++ b/components/content_settings/core/common/content_settings_types.h +@@ -284,6 +284,8 @@ enum class ContentSettingsType : int32_t { + // site instead of the mobile one. + REQUEST_DESKTOP_SITE, + ++ WEBGL, ++ + // Setting to indicate whether browser should allow signing into a website via + // the browser FedCM API. + FEDERATED_IDENTITY_API, +diff --git a/components/content_settings/renderer/content_settings_agent_impl.cc b/components/content_settings/renderer/content_settings_agent_impl.cc +--- a/components/content_settings/renderer/content_settings_agent_impl.cc ++++ b/components/content_settings/renderer/content_settings_agent_impl.cc +@@ -477,6 +477,15 @@ void ContentSettingsAgentImpl::ClearBlockedContentSettings() { + cached_script_permissions_.clear(); + } + ++bool ContentSettingsAgentImpl::AllowWebgl(bool enabled_per_settings) { ++ if (!content_setting_rules_) ++ return false; ++ blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); ++ return CONTENT_SETTING_ALLOW == GetContentSettingFromRules( ++ content_setting_rules_->webgl_rules, frame, ++ url::Origin(frame->GetDocument().GetSecurityOrigin()).GetURL()); ++} ++ + bool ContentSettingsAgentImpl::IsAllowlistedForContentSettings() const { + if (should_allowlist_) + return true; +diff --git a/components/content_settings/renderer/content_settings_agent_impl.h b/components/content_settings/renderer/content_settings_agent_impl.h +--- a/components/content_settings/renderer/content_settings_agent_impl.h ++++ b/components/content_settings/renderer/content_settings_agent_impl.h +@@ -101,6 +101,7 @@ class ContentSettingsAgentImpl + bool AllowAutoplay(bool default_value) override; + bool AllowPopupsAndRedirects(bool default_value) override; + bool ShouldAutoupgradeMixedContent() override; ++ bool AllowWebgl(bool enabled_per_settings) override; + + bool allow_running_insecure_content() const { + return allow_running_insecure_content_; +diff --git a/third_party/blink/public/platform/web_content_settings_client.h b/third_party/blink/public/platform/web_content_settings_client.h +--- a/third_party/blink/public/platform/web_content_settings_client.h ++++ b/third_party/blink/public/platform/web_content_settings_client.h +@@ -99,6 +99,8 @@ class WebContentSettingsClient { + return default_value; + } + ++ virtual bool AllowWebgl(bool default_value) { return default_value; } ++ + // Reports that passive mixed content was found at the provided URL. + virtual void PassiveInsecureContentFound(const WebURL&) {} + +diff --git a/third_party/blink/renderer/core/execution_context/execution_context.cc b/third_party/blink/renderer/core/execution_context/execution_context.cc +--- a/third_party/blink/renderer/core/execution_context/execution_context.cc ++++ b/third_party/blink/renderer/core/execution_context/execution_context.cc +@@ -64,6 +64,29 @@ + + namespace blink { + ++blink::WebContentSettingsClient* GetContentSettingsClientFor( ++ ExecutionContext* context) { ++ blink::WebContentSettingsClient* settings = nullptr; ++ if (!context) ++ return settings; ++ if (auto* window = blink::DynamicTo(context)) { ++ auto* frame = window->GetFrame(); ++ if (frame) ++ settings = frame->GetContentSettingsClient(); ++ } else if (context->IsWorkerGlobalScope()) { ++ settings = ++ blink::To(context)->ContentSettingsClient(); ++ } ++ return settings; ++} ++ ++bool AllowWebgl(ExecutionContext* context) { ++ blink::WebContentSettingsClient* settings = GetContentSettingsClientFor(context); ++ if (settings) ++ return settings->AllowWebgl(false); ++ return false; ++} ++ + ExecutionContext::ExecutionContext(v8::Isolate* isolate, Agent* agent) + : isolate_(isolate), + security_context_(this), +diff --git a/third_party/blink/renderer/core/execution_context/execution_context.h b/third_party/blink/renderer/core/execution_context/execution_context.h +--- a/third_party/blink/renderer/core/execution_context/execution_context.h ++++ b/third_party/blink/renderer/core/execution_context/execution_context.h +@@ -96,6 +96,7 @@ class SecurityOrigin; + class ScriptState; + class ScriptWrappable; + class TrustedTypePolicyFactory; ++class WebContentSettingsClient; + + enum ReasonForCallingCanExecuteScripts { + kAboutToExecuteScript, +@@ -104,6 +105,10 @@ enum ReasonForCallingCanExecuteScripts { + + enum ReferrerPolicySource { kPolicySourceHttpHeader, kPolicySourceMetaTag }; + ++CORE_EXPORT bool AllowWebgl(ExecutionContext* context); ++CORE_EXPORT WebContentSettingsClient* GetContentSettingsClientFor( ++ ExecutionContext* context); ++ + // An environment in which script can execute. This class exposes the common + // properties of script execution environments on the web (i.e, common between + // script executing in a window and script executing in a worker), such as: +diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc ++++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +@@ -216,6 +216,13 @@ void WebGLRenderingContextBase::InitializeWebGLContextLimits( + } + } + ++bool WebGLRenderingContextBase::AllowWebglForHost(blink::CanvasRenderingContextHost* host) { ++ if (!host) ++ return false; ++ blink::ExecutionContext* context = host->GetTopExecutionContext(); ++ return blink::AllowWebgl(context); ++} ++ + unsigned WebGLRenderingContextBase::CurrentMaxGLContexts() { + MutexLocker locker(WebGLContextLimitMutex()); + DCHECK(webgl_context_limits_initialized_); +@@ -462,25 +469,6 @@ static String ExtractWebGLContextCreationError( + const Platform::GraphicsInfo& info) { + StringBuilder builder; + builder.Append("Could not create a WebGL context"); +- FormatWebGLStatusString( +- "VENDOR", +- info.vendor_id ? String::Format("0x%04x", info.vendor_id) : "0xffff", +- builder); +- FormatWebGLStatusString( +- "DEVICE", +- info.device_id ? String::Format("0x%04x", info.device_id) : "0xffff", +- builder); +- FormatWebGLStatusString("GL_VENDOR", info.vendor_info, builder); +- FormatWebGLStatusString("GL_RENDERER", info.renderer_info, builder); +- FormatWebGLStatusString("GL_VERSION", info.driver_version, builder); +- FormatWebGLStatusString("Sandboxed", info.sandboxed ? "yes" : "no", builder); +- FormatWebGLStatusString("Optimus", info.optimus ? "yes" : "no", builder); +- FormatWebGLStatusString("AMD switchable", info.amd_switchable ? "yes" : "no", +- builder); +- FormatWebGLStatusString( +- "Reset notification strategy", +- String::Format("0x%04x", info.reset_notification_strategy).Utf8().c_str(), +- builder); + FormatWebGLStatusString("ErrorMessage", info.error_message.Utf8().c_str(), + builder); + builder.Append('.'); +@@ -548,6 +536,12 @@ WebGLRenderingContextBase::CreateWebGraphicsContext3DProvider( + const CanvasContextCreationAttributesCore& attributes, + Platform::ContextType context_type, + Platform::GraphicsInfo* graphics_info) { ++ if (!AllowWebglForHost(host)) { ++ host->HostDispatchEvent(WebGLContextEvent::Create( ++ event_type_names::kWebglcontextcreationerror, ++ "disabled by site settings policy.")); ++ return nullptr; ++ } + if ((context_type == Platform::kWebGL1ContextType && + !host->IsWebGL1Enabled()) || + (context_type == Platform::kWebGL2ContextType && +diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h +--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h ++++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h +@@ -1826,6 +1826,8 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext, + DOMArrayBufferView* pixels, + int64_t offset); + ++ static bool AllowWebglForHost(blink::CanvasRenderingContextHost* host); ++ + // Record Canvas/OffscreenCanvas.RenderingContextDrawnTo at the first draw + // call. + void RecordUKMCanvasDrawnToAtFirstDrawCall(); +-- +2.25.1 diff --git a/build/patches/Content-settings-infrastructure.patch b/build/patches/Content-settings-infrastructure.patch new file mode 100644 index 00000000..c8706de4 --- /dev/null +++ b/build/patches/Content-settings-infrastructure.patch @@ -0,0 +1,1266 @@ +From: uazo +Date: Thu, 24 Feb 2022 07:54:36 +0000 +Subject: Content Settings Infrastructure + +Small internal framework for the simplified management of +the ui relative to the site settings for use by the other patches + +See BromiteCustomContentSetting_README.md +--- + .../browser_ui/site_settings/android/BUILD.gn | 4 + + .../BromiteCustomContentSetting.java | 125 ++++++++ + .../BromiteCustomContentSettingImpl.java | 271 ++++++++++++++++++ + .../BromiteCustomContentSetting_README.md | 151 ++++++++++ + .../ContentSettingsResources.java | 13 +- + .../site_settings/SingleCategorySettings.java | 28 +- + .../site_settings/SingleWebsiteSettings.java | 24 +- + .../site_settings/SiteSettings.java | 3 +- + .../site_settings/SiteSettingsCategory.java | 9 +- + .../TriStateSiteSettingsPreference.java | 13 +- + .../browser_ui/site_settings/Website.java | 4 + + .../WebsitePermissionsFetcher.java | 2 +- + .../WebsitePreferenceBridge.java | 2 +- + .../core/browser/content_settings_registry.cc | 11 +- + .../core/browser/content_settings_registry.h | 5 +- + .../core/browser/website_settings_info.cc | 10 +- + .../core/browser/website_settings_info.h | 12 +- + .../core/browser/website_settings_registry.cc | 8 +- + .../core/browser/website_settings_registry.h | 5 +- + .../PermissionParamsListBuilder.java | 1 + + .../android/page_info_controller_android.cc | 18 ++ + components/page_info/page_info.cc | 23 +- + components/page_info/page_info_ui.cc | 18 ++ + 23 files changed, 732 insertions(+), 28 deletions(-) + create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting.java + create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java + create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting_README.md + +diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/browser_ui/site_settings/android/BUILD.gn +--- a/components/browser_ui/site_settings/android/BUILD.gn ++++ b/components/browser_ui/site_settings/android/BUILD.gn +@@ -68,6 +68,10 @@ android_library("java") { + "java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java", + "java/src/org/chromium/components/browser_ui/site_settings/TimezoneOverrideSiteSettingsPreference.java" + ] ++ sources += [ ++ "java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java", ++ "java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting.java", ++ ] + annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] + resources_package = "org.chromium.components.browser_ui.site_settings" + deps = [ +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting.java +new file mode 100644 +--- /dev/null ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting.java +@@ -0,0 +1,125 @@ ++/* ++ This file is part of Bromite. ++ ++ Bromite is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ Bromite is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with Bromite. If not, see . ++*/ ++ ++package org.chromium.components.browser_ui.site_settings; ++ ++import org.chromium.components.browser_ui.site_settings.ContentSettingsResources; ++import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory; ++import org.chromium.components.content_settings.ContentSettingValues; ++import org.chromium.components.content_settings.ContentSettingsType; ++import org.chromium.content_public.browser.BrowserContextHandle; ++ ++import androidx.annotation.Nullable; ++import androidx.preference.Preference; ++import androidx.preference.PreferenceScreen; ++ ++import java.util.ArrayList; ++ ++public abstract class BromiteCustomContentSetting { ++ ++ private @ContentSettingsType int mContentSettingsType; ++ private @SiteSettingsCategory.Type int mSiteSettingsCategory; ++ private @ContentSettingValues Integer mInitialDefaultValue; ++ private @ContentSettingValues Integer mDefaultDisabledValue; ++ private boolean mAllowException; ++ private String mPreferenceKey; ++ private String mProfilePrefKey; ++ ++ public BromiteCustomContentSetting(@ContentSettingsType int contentSettingsType, ++ @SiteSettingsCategory.Type int siteSettingsCategory, ++ @ContentSettingValues Integer initialDefaultValue, ++ @ContentSettingValues Integer defaultDisabledValue, ++ boolean allowException, ++ String preferenceKey, ++ String profilePrefKey) { ++ mContentSettingsType = contentSettingsType; ++ mSiteSettingsCategory = siteSettingsCategory; ++ mInitialDefaultValue = initialDefaultValue; ++ mDefaultDisabledValue = defaultDisabledValue; ++ mAllowException = allowException; ++ mPreferenceKey = preferenceKey; ++ mProfilePrefKey = profilePrefKey; ++ } ++ ++ public @ContentSettingsType int getContentSetting() { ++ return mContentSettingsType; ++ } ++ ++ public @SiteSettingsCategory.Type int getSiteSettingsCategory() { ++ return mSiteSettingsCategory; ++ } ++ ++ protected @ContentSettingValues Integer getInitialDefaultValue() { ++ return mInitialDefaultValue; ++ } ++ ++ public @ContentSettingValues Integer getDefaultDisabledValue() { ++ return mDefaultDisabledValue; ++ } ++ ++ public String getPreferenceKey() { ++ return mPreferenceKey; ++ } ++ ++ public String getProfilePrefKey() { ++ return mProfilePrefKey; ++ } ++ ++ public boolean isExceptionAllowed() { ++ return mAllowException; ++ } ++ ++ public WebsitePermissionsFetcher.WebsitePermissionsType getPermissionsType() { ++ return WebsitePermissionsFetcher.WebsitePermissionsType.CONTENT_SETTING_EXCEPTION; ++ } ++ ++ public abstract ContentSettingsResources.ResourceItem getResourceItem(); ++ public abstract int getCategorySummary(@Nullable @ContentSettingValues int value); ++ public abstract int getAddExceptionDialogMessage(); ++ ++ public boolean processOnBlockList(@ContentSettingValues Integer value) { ++ return true; ++ } ++ ++ public boolean isOnBlockList(@ContentSettingValues Integer contentSetting) { ++ return mDefaultDisabledValue == contentSetting; ++ } ++ ++ public abstract @Nullable Boolean considerException(SiteSettingsCategory category, @ContentSettingValues int value); ++ ++ public ContentSettingException createCustomException(@ContentSettingsType int type, ++ @ContentSettingValues int value, ++ WebsiteAddress websiteAddress) { ++ return null; ++ } ++ ++ public boolean requiresTriStateContentSetting() { ++ return false; ++ } ++ ++ public int[] getTriStateSettingDescriptionIDs() { ++ return null; ++ } ++ ++ public boolean showOnlyDescriptions() { ++ return false; ++ } ++ ++ public boolean showIntoInfoPage() { ++ return true; ++ } ++} +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java +new file mode 100644 +--- /dev/null ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java +@@ -0,0 +1,271 @@ ++/* ++ This file is part of Bromite. ++ ++ Bromite is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ Bromite is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with Bromite. If not, see . ++*/ ++ ++package org.chromium.components.browser_ui.site_settings; ++ ++import android.app.Activity; ++import android.content.Context; ++ ++import org.chromium.components.browser_ui.site_settings.ContentSettingsResources; ++import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory; ++import org.chromium.components.content_settings.ContentSettingValues; ++import org.chromium.components.content_settings.ContentSettingsType; ++import org.chromium.content_public.browser.BrowserContextHandle; ++import org.chromium.components.browser_ui.settings.ChromeBasePreference; ++ ++import androidx.annotation.Nullable; ++import androidx.preference.Preference; ++import androidx.preference.PreferenceScreen; ++import androidx.appcompat.app.AlertDialog; ++import android.content.DialogInterface; ++ ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.List; ++ ++public abstract class BromiteCustomContentSettingImpl { ++ ++ static private final ArrayList mItemList; ++ ++ static { ++ mItemList = new ArrayList(); ++ } ++ ++ public static SiteSettingsCategory createFromType( ++ BrowserContextHandle browserContextHandle, @SiteSettingsCategory.Type int type) { ++ return null; ++ } ++ ++ public static BromiteCustomContentSetting getContentSetting(@ContentSettingsType int type) { ++ for (BromiteCustomContentSetting cs : mItemList) { ++ if (type == cs.getContentSetting()) { ++ return cs; ++ } ++ } ++ return null; ++ } ++ ++ public static @Nullable String getPreferenceKey(@SiteSettingsCategory.Type int type) { ++ for (BromiteCustomContentSetting cs : mItemList) { ++ if (type == cs.getSiteSettingsCategory()) { ++ return cs.getPreferenceKey(); ++ } ++ } ++ return null; ++ } ++ ++ public static String getProfilePrefKey(@ContentSettingsType int type) { ++ BromiteCustomContentSetting cs = getContentSetting(type); ++ if (cs != null) return cs.getProfilePrefKey(); ++ return null; ++ } ++ ++ public static @ContentSettingsType int contentSettingsType(@SiteSettingsCategory.Type int type) { ++ for (BromiteCustomContentSetting cs : mItemList) { ++ if (type == cs.getSiteSettingsCategory()) { ++ return cs.getContentSetting(); ++ } ++ } ++ return ContentSettingsType.DEFAULT; // Conversion unavailable. ++ } ++ ++ public static WebsitePermissionsFetcher.WebsitePermissionsType getPermissionsType( ++ @ContentSettingsType int type) { ++ BromiteCustomContentSetting cs = getContentSetting(type); ++ if (cs != null) return cs.getPermissionsType(); ++ return null; ++ } ++ ++ public static ContentSettingsResources.ResourceItem getResourceItem(@ContentSettingsType int type) { ++ BromiteCustomContentSetting cs = getContentSetting(type); ++ if (cs != null) return cs.getResourceItem(); ++ return null; ++ } ++ ++ public static int getCategorySummary(@ContentSettingsType int type, @Nullable @ContentSettingValues int value) { ++ BromiteCustomContentSetting cs = getContentSetting(type); ++ if (cs != null) return cs.getCategorySummary(value); ++ return 0; ++ } ++ ++ public static boolean requiresTriStateContentSetting(@ContentSettingsType int type) { ++ BromiteCustomContentSetting cs = getContentSetting(type); ++ if (cs != null) return cs.requiresTriStateContentSetting(); ++ return false; ++ } ++ ++ public static int[] getTriStateSettingDescriptionIDs(@ContentSettingsType int type) { ++ BromiteCustomContentSetting cs = getContentSetting(type); ++ if (cs != null) return cs.getTriStateSettingDescriptionIDs(); ++ return null; ++ } ++ ++ public static boolean onPreferenceChange(SiteSettingsCategory category, ++ BrowserContextHandle browserContextHandle, ++ Preference preference, Object newValue) { ++ for (BromiteCustomContentSetting cs : mItemList) { ++ if (!category.showSites(cs.getSiteSettingsCategory())) { ++ continue; ++ } ++ ++ int default_value = WebsitePreferenceBridge.getDefaultContentSetting( ++ browserContextHandle, cs.getContentSetting()); ++ if (SingleCategorySettings.BINARY_TOGGLE_KEY.equals(preference.getKey())) { ++ int setting = ((boolean) newValue) == true ? default_value : ++ cs.getDefaultDisabledValue(); ++ ++ WebsitePreferenceBridge.setDefaultContentSetting(browserContextHandle, ++ cs.getContentSetting(), setting); ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ public static boolean processOnBlockList(@ContentSettingsType int type, @ContentSettingValues Integer value) { ++ BromiteCustomContentSetting cs = getContentSetting(type); ++ if (cs != null) return cs.processOnBlockList(value); ++ return false; ++ } ++ ++ public static boolean isOnBlockList(@ContentSettingsType int type, ++ WebsitePreference website, ++ @ContentSettingValues Integer contentSetting) { ++ BromiteCustomContentSetting cs = getContentSetting(type); ++ if (cs != null) return cs.isOnBlockList(contentSetting); ++ return false; ++ } ++ ++ public static @Nullable Boolean considerException(SiteSettingsCategory category, @ContentSettingValues int value) { ++ for (BromiteCustomContentSetting cs : mItemList) { ++ if (category.showSites(cs.getSiteSettingsCategory())) { ++ return cs.considerException(category, value); ++ } ++ } ++ return null; ++ } ++ ++ public static int getAddExceptionDialogMessage(SiteSettingsCategory category) { ++ for (BromiteCustomContentSetting cs : mItemList) { ++ if (category.showSites(cs.getSiteSettingsCategory())) { ++ return cs.getAddExceptionDialogMessage(); ++ } ++ } ++ return 0; ++ } ++ ++ public static @Nullable Boolean allowSpecifyingExceptions(SiteSettingsCategory category) { ++ for (BromiteCustomContentSetting cs : mItemList) { ++ if (category.showSites(cs.getSiteSettingsCategory())) { ++ return cs.isExceptionAllowed(); ++ } ++ } ++ return null; ++ } ++ ++ public static void configurePreferences(SiteSettings settings) { ++ Activity activity = settings.getActivity(); ++ PreferenceScreen preferenceScreen = settings.getPreferenceScreen(); ++ ++ Context styledContext = settings.getPreferenceManager().getContext(); ++ for (BromiteCustomContentSetting cs : mItemList) { ++ ChromeBasePreference pref = new ChromeBasePreference(styledContext); ++ pref.setKey(cs.getPreferenceKey()); ++ pref.setFragment(SingleCategorySettings.class.getCanonicalName()); ++ preferenceScreen.addPreference(pref); ++ } ++ } ++ ++ public static List getSettingsOrder() { ++ int[] settingOrder = SiteSettingsUtil.SETTINGS_ORDER; ++ List order = new ArrayList(); ++ for (int i = 0; i < settingOrder.length && order.add(settingOrder[i]); i++); ++ ++ for (BromiteCustomContentSetting cs : mItemList) { ++ if (cs.showIntoInfoPage() && !order.contains(cs.getContentSetting())) { ++ order.add(cs.getContentSetting()); ++ } ++ } ++ return order; ++ } ++ ++ public static void onActivityCreated(SingleCategorySettings singleCategorySettings) { ++ } ++ ++ public static void configureGlobalToggles(SiteSettingsCategory category, PreferenceScreen preferences) { ++ } ++ ++ public static ContentSettingException createCustomException(@ContentSettingsType int type, ++ @ContentSettingValues int value, ++ WebsiteAddress websiteAddress) { ++ BromiteCustomContentSetting cs = getContentSetting(type); ++ if (cs != null) { ++ ContentSettingException exception = cs.createCustomException(type, value, websiteAddress); ++ if (exception == null) { ++ exception = new ContentSettingException( ++ cs.getContentSetting(), websiteAddress.getHost(), value, ""); ++ } ++ return exception; ++ } ++ return null; ++ } ++ ++ public static AlertDialog.Builder buildPreferenceDialog(Website site, @ContentSettingsType int type, ++ BrowserContextHandle browserContextHandle, ++ Context context, ++ final DialogInterface.OnClickListener listener) { ++ BromiteCustomContentSetting cs = getContentSetting(type); ++ if (cs != null && cs.requiresTriStateContentSetting()) { ++ int[] values = cs.getTriStateSettingDescriptionIDs(); ++ ++ CharSequence[] descriptions = new String[3]; ++ descriptions[0] = context.getString(values[0]); // ALLOWED ++ descriptions[1] = context.getString(values[1]); // ASK ++ descriptions[2] = context.getString(values[2]); // BLOCKED ++ ++ @ContentSettingValues ++ Integer value = site.getContentSetting(browserContextHandle, type); ++ ++ return new AlertDialog.Builder(context, R.style.Theme_Chromium_AlertDialog) ++ .setPositiveButton(R.string.cancel, null) ++ .setNegativeButton(R.string.remove, ++ (dialog, which) -> { ++ site.setContentSetting(browserContextHandle, type, ++ ContentSettingValues.DEFAULT); ++ listener.onClick(dialog, which); ++ dialog.dismiss(); ++ }) ++ .setSingleChoiceItems(descriptions, ++ value == ContentSettingValues.ALLOW ? 0 : ++ value == ContentSettingValues.ASK ? 1 : ++ 2, ++ (dialog, which) -> { ++ @ContentSettingValues ++ int permission = which == 0 ? ContentSettingValues.ALLOW : ++ which == 1 ? ContentSettingValues.ASK : ++ ContentSettingValues.BLOCK; ++ site.setContentSetting( ++ browserContextHandle, type, permission); ++ ++ listener.onClick(dialog, which); ++ dialog.dismiss(); ++ }); ++ } ++ return null; ++ } ++} +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting_README.md b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting_README.md +new file mode 100644 +--- /dev/null ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting_README.md +@@ -0,0 +1,151 @@ ++# Content Settings and Site Settings in Bromite ++ ++[TOC] ++ ++## Overview ++ ++To simplify the addition and management of content settings ui in Bromite, you can use this method: automatically the new menus in the site settings and the item in page info management will be added. ++ ++## How to use ++ ++* Add a class derived from [BromiteCustomContentSettingImpl](BromiteCustomContentSettingImpl.java) ++ ++``` ++public class NewContentSetting extends BromiteCustomContentSetting { ++ public BromiteWebGLContentSetting() { ++ super(/*contentSettingsType*/ ContentSettingsType.NEW_CONTENT_SETTING, ++ /*siteSettingsCategory*/ SiteSettingsCategory.Type.NEW_CONTENT_SETTING, ++ /*initialDefaultValue*/ ContentSettingValues.BLOCK, ++ /*defaultDisabledValue*/ ContentSettingValues.BLOCK, ++ /*allowException*/ true, ++ /*preferenceKey*/ "new_content_setting", ++ /*profilePrefKey*/ "new_content_setting"); ++ } ++ ++ @Override ++ public ContentSettingsResources.ResourceItem getResourceItem() { ++ return new ContentSettingsResources.ResourceItem( ++ /*icon*/ R.drawable.web_asset, ++ /*title*/ R.string.new_content_setting_permission_title, ++ /*defaultEnabledValue*/ getInitialDefaultValue(), ++ /*defaultDisabledValue*/ getDefaultDisabledValue(), ++ /*enabledSummary*/ R.string.new_content_setting_enabled, ++ /*disabledSummary*/ R.string.new_content_setting_disabled); ++ } ++ ++ @Override ++ public int getCategorySummary(@Nullable @ContentSettingValues int value) { ++ switch (value) { ++ case ContentSettingValues.ALLOW: ++ return R.string.new_content_setting_allow; ++ case ContentSettingValues.ASK: ++ return R.string.new_content_setting_ask; ++ case ContentSettingValues.BLOCK: ++ return R.string.new_content_setting_disabled; ++ default: ++ return 0; ++ } ++ } ++ ++ @Override ++ public boolean requiresTriStateContentSetting() { ++ return true; // or false if is a on/off content setting ++ } ++ ++ @Override ++ public int[] getTriStateSettingDescriptionIDs() { ++ // only needed if is a tristate setting ++ int[] descriptionIDs = { ++ R.string.website_settings_category_webgl_enabled_antifingerprint, // ALLOWED ++ R.string.website_settings_category_webgl_enabled, // ASK ++ R.string.website_settings_category_webgl_disabled }; // BLOCKED ++ return descriptionIDs; ++ } ++ ++ @Override ++ public boolean showOnlyDescriptions() { ++ // true will remove ALLOWED/ASK/BLOCKED from UI ++ // leaving only the descriptions ++ return true; ++ } ++ ++ @Override ++ public int getAddExceptionDialogMessage() { ++ return R.string.new_content_setting_exception_dialog_message; ++ } ++ ++ @Override ++ public @Nullable Boolean considerException(SiteSettingsCategory category, @ContentSettingValues int value) { ++ // indicate when the value should be considered an exception ++ return value != ContentSettingValues.BLOCK; ++ } ++} ++``` ++ ++* Add the new class to `BromiteCustomContentSettingImpl` `cctor` ++ ++``` ++ static { ++ mItemList = new ArrayList(); ++ mItemList.add(new NewContentSetting()); ++ } ++``` ++ ++* Register the new content setting as usual in `ContentSettingsRegistry::Init()` ++ ++``` ++ Register(ContentSettingsType::NEW_CONTENT_SETTING, "new_content_setting", CONTENT_SETTING_BLOCK, ++ WebsiteSettingsInfo::SYNCABLE, ++ AllowlistedSchemes(), ++ ValidSettings(CONTENT_SETTING_ALLOW, // allow ++ CONTENT_SETTING_ASK, // ask ++ CONTENT_SETTING_BLOCK), // block ++ WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE, ++ WebsiteSettingsRegistry::PLATFORM_ANDROID, ++ ContentSettingsInfo::INHERIT_IN_INCOGNITO, ++ ContentSettingsInfo::PERSISTENT, ++ ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS, ++ /*show_into_info_page*/ true, ++ /*permission_type_ui*/ IDS_NEW_CONTENT_SETTING, ++ /*permission_type_ui_mid_sentence*/ IDS_NEW_CONTENT_SETTING_MID_SENTENCE); ++``` ++ ++* Add your content setting in `@IntDef()` and `Type` in `SiteSettingsCategory` as usual ++ ++* Add your strings in a new file in `components/browser_ui/strings/android/` ++ ++``` ++ ++ ++ ++ your content type ++ ++ ++ your content type ++ ++ ++ your content type ++ ++ ++ your content type is enabled ++ ++ ++ ask before activate your content type ++ ++ ++ your content type is disabled ++ ++ ++``` ++ ++* Reference it in `components/components_strings.grd` to have strings in native ++ ++``` ++ ++``` ++ ++* Reference it in `components/browser_ui/strings/android/browser_ui_strings.grd` to have the strings in java ++ ++``` ++ ++``` +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java +--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java +@@ -38,7 +38,7 @@ public class ContentSettingsResources { + /** + * An inner class contains all the resources for a ContentSettingsType + */ +- private static class ResourceItem { ++ public static class ResourceItem { + private final int mIcon; + private final int mTitle; + private final @ContentSettingValues @Nullable Integer mDefaultEnabledValue; +@@ -290,6 +290,8 @@ public class ContentSettingsResources { + R.string.website_settings_category_timezone_override_custom, + R.string.website_settings_category_timezone_override_random); + } ++ ResourceItem ri = BromiteCustomContentSettingImpl.getResourceItem(contentType); ++ if (ri != null) return ri; + assert false; // NOTREACHED + return null; + } +@@ -441,7 +443,9 @@ public class ContentSettingsResources { + } + } + +- public static int getCategorySummary(int contentType, @Nullable @ContentSettingValues int value) { ++ public static int getCategorySummary(int contentType, @Nullable @ContentSettingValues int value) { // ++ int result = BromiteCustomContentSettingImpl.getCategorySummary(contentType, value); ++ if (result != 0) return result; + if (contentType == ContentSettingsType.TIMEZONE_OVERRIDE) { + switch (value) { + case ContentSettingValues.ALLOW: +@@ -454,8 +458,7 @@ public class ContentSettingsResources { + return 0; + } + } +- else +- return getCategorySummary(value); ++ return getCategorySummary(value); + } + + /** +@@ -564,6 +567,8 @@ public class ContentSettingsResources { + * Blocked states, in that order. + */ + public static int[] getTriStateSettingDescriptionIDs(int contentType) { ++ int[] value = BromiteCustomContentSettingImpl.getTriStateSettingDescriptionIDs(contentType); ++ if (value != null) return value; + if (contentType == ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER) { + // The recommended setting is different on different android versions depending on + // whether per-origin provisioning is available. See https://crbug.com/904883. +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java +--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java +@@ -227,6 +227,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment + else + return ContentSettingValues.BLOCK == contentSetting; + } ++ if (BromiteCustomContentSettingImpl.processOnBlockList(contentSetting, contentSetting)) ++ return BromiteCustomContentSettingImpl.isOnBlockList(contentSetting, website, contentSetting); + } + return false; + } +@@ -376,6 +378,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment + ? new HashSet<>(getArguments().getStringArrayList(EXTRA_SELECTED_DOMAINS)) + : null; + ++ BromiteCustomContentSettingImpl.onActivityCreated(this); + configureGlobalToggles(); + + setHasOptionsMenu(true); +@@ -475,6 +478,11 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment + BrowserContextHandle browserContextHandle = + getSiteSettingsDelegate().getBrowserContextHandle(); + PrefService prefService = UserPrefs.get(browserContextHandle); ++ if (BromiteCustomContentSettingImpl.onPreferenceChange(mCategory, ++ browserContextHandle, preference, newValue) == true) { ++ getInfoForOrigins(); ++ return true; ++ } + if (BINARY_TOGGLE_KEY.equals(preference.getKey())) { + assert !mCategory.isManaged(); + +@@ -620,6 +628,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment + } else if (mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE)) { + resource = R.string.website_settings_category_timezone_override_allowed; + } ++ if (resource == 0) ++ resource = BromiteCustomContentSettingImpl.getAddExceptionDialogMessage(mCategory); + assert resource > 0; + return getString(resource); + } +@@ -730,6 +740,9 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment + allowSpecifyingExceptions = true; + } else if (mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE)) { + allowSpecifyingExceptions = true; ++ } else { ++ Boolean allow = BromiteCustomContentSettingImpl.allowSpecifyingExceptions(mCategory); ++ if (allow != null) allowSpecifyingExceptions = (boolean)allow; + } + if (allowSpecifyingExceptions) { + getPreferenceScreen().addPreference(new AddExceptionPreference(getStyledContext(), +@@ -901,6 +914,10 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment + TriStateSiteSettingsPreference triStateToggle = + (TriStateSiteSettingsPreference) getPreferenceScreen().findPreference( + TRI_STATE_TOGGLE_KEY); ++ if (triStateToggle != null) { ++ Boolean blocked = BromiteCustomContentSettingImpl.considerException(mCategory, triStateToggle.getCheckedSetting()); ++ if (blocked != null) return (boolean)blocked; ++ } + if (triStateToggle != null) + return (triStateToggle.getCheckedSetting() == ContentSettingValues.BLOCK); + +@@ -977,6 +994,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment + if (!(mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE))) { + screen.removePreference(screen.findPreference(TIMEOVERRIDE_INFO_TEXT)); + } ++ BromiteCustomContentSettingImpl.configureGlobalToggles(mCategory, screen); + + if (permissionBlockedByOs) { + maybeShowOsWarning(screen); +@@ -1089,7 +1107,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment + getSiteSettingsDelegate().getBrowserContextHandle(), contentType); + int[] descriptionIds = + ContentSettingsResources.getTriStateSettingDescriptionIDs(contentType); +- triStateToggle.initialize(setting, descriptionIds); ++ triStateToggle.initialize(contentType, setting, descriptionIds); + } + + private void configureTimeOverrideStateToggle( +@@ -1182,6 +1200,14 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment + @ContentSettingValues + Integer value = site.getContentSetting(browserContextHandle, contentSettingsType); + ++ AlertDialog.Builder alertDialog = ++ BromiteCustomContentSettingImpl.buildPreferenceDialog(site, contentSettingsType, ++ browserContextHandle, getContext(), ++ (dialog, which) -> { getInfoForOrigins(); }); ++ if (alertDialog != null) { ++ return alertDialog; ++ } ++ + CharSequence[] descriptions = new String[2]; + descriptions[0] = + getString(ContentSettingsResources.getSiteSummary(contentSettingsType, +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java +--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java +@@ -41,6 +41,7 @@ import org.chromium.content_public.browser.BrowserContextHandle; + import java.util.Collection; + import java.util.HashMap; + import java.util.Map; ++import java.util.List; + + /** + * Shows the permissions and other settings for a particular website. +@@ -166,7 +167,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment + case ContentSettingsType.CLIPBOARD_READ_WRITE: + return "clipboard_permission_list"; + default: +- return null; ++ return BromiteCustomContentSettingImpl.getProfilePrefKey(type); + } + } + +@@ -491,7 +492,8 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment + + private void setupContentSettingsPreferences() { + mMaxPermissionOrder = findPreference(PREF_PERMISSIONS_HEADER).getOrder(); +- for (@ContentSettingsType int type : SiteSettingsUtil.SETTINGS_ORDER) { ++ List order = BromiteCustomContentSettingImpl.getSettingsOrder(); ++ for (@ContentSettingsType int type : order) { + Preference preference = new ChromeSwitchPreference(getStyledContext()); + preference.setKey(getPreferenceKey(type)); + +@@ -901,16 +903,22 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment + + private void setupContentSettingsPreference(Preference preference, + @ContentSettingValues @Nullable Integer value, boolean isEmbargoed) { +- if (value == null) return; +- setUpPreferenceCommon(preference, value); +- + int content_type = getContentSettingsTypeFromPreferenceKey(preference.getKey()); ++ BromiteCustomContentSetting cs = ++ BromiteCustomContentSettingImpl.getContentSetting(content_type); ++ if (value == null && cs == null) return; ++ if (value == null) { ++ if (cs.showIntoInfoPage() == false) return; ++ value = WebsitePreferenceBridge.getDefaultContentSetting( ++ getSiteSettingsDelegate().getBrowserContextHandle(), content_type); ++ } ++ setUpPreferenceCommon(preference, value); + + ChromeSwitchPreference switchPreference = (ChromeSwitchPreference) preference; +- switchPreference.setChecked(value == ContentSettingValues.ALLOW); ++ switchPreference.setChecked(value != ContentSettingValues.BLOCK); + switchPreference.setSummary(isEmbargoed + ? getString(R.string.automatically_blocked) +- : getString(ContentSettingsResources.getCategorySummary(content_type, value))); ++ : getString(ContentSettingsResources.getCategorySummary(content_type, value))); // + switchPreference.setOnPreferenceChangeListener(this); + @ContentSettingsType + int contentType = getContentSettingsTypeFromPreferenceKey(preference.getKey()); +@@ -1159,7 +1167,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment + } + + mSite.setContentSetting(browserContextHandle, type, permission); +- preference.setSummary(getString(ContentSettingsResources.getCategorySummary(type, permission))); ++ preference.setSummary(getString(ContentSettingsResources.getCategorySummary(type, permission))); // + preference.setIcon(getContentSettingsIcon(type, permission)); + + if (mWebsiteSettingsObserver != null) { +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java +--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java +@@ -33,6 +33,7 @@ public class SiteSettings + SettingsUtils.addPreferencesFromResource(this, R.xml.site_settings_preferences); + getActivity().setTitle(getContext().getString(R.string.prefs_site_settings)); + ++ BromiteCustomContentSettingImpl.configurePreferences(this); + configurePreferences(); + updatePreferenceStates(); + } +@@ -119,7 +120,7 @@ public class SiteSettings + } else if (requiresTriStateSetting) { + p.setSummary(ContentSettingsResources.getCategorySummary(contentType, setting)); + } else { +- p.setSummary(ContentSettingsResources.getCategorySummary(contentType, checked)); ++ p.setSummary(ContentSettingsResources.getCategorySummary(contentType, checked)); // + } + + p.setIcon(SettingsUtils.getTintedIcon( +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java +--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java +@@ -126,6 +126,9 @@ public class SiteSettingsCategory { + } else { + permission = ""; + } ++ SiteSettingsCategory category = BromiteCustomContentSettingImpl.createFromType( ++ browserContextHandle, type); ++ if (category != null) return category; + return new SiteSettingsCategory(browserContextHandle, type, permission); + } + +@@ -218,7 +221,7 @@ public class SiteSettingsCategory { + // case Type.ALL_SITES + // case Type.USE_STORAGE + default: +- return ContentSettingsType.DEFAULT; // Conversion unavailable. ++ return BromiteCustomContentSettingImpl.contentSettingsType(type); + } + } + +@@ -304,8 +307,12 @@ public class SiteSettingsCategory { + case Type.TIMEZONE_OVERRIDE: + return "timezone_override"; + default: ++ { ++ String value = BromiteCustomContentSettingImpl.getPreferenceKey(type); ++ if (value != null) return value; + assert false; + return ""; ++ } + } + } + +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/TriStateSiteSettingsPreference.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/TriStateSiteSettingsPreference.java +--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/TriStateSiteSettingsPreference.java ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/TriStateSiteSettingsPreference.java +@@ -13,6 +13,7 @@ import androidx.preference.PreferenceViewHolder; + + import org.chromium.components.browser_ui.widget.RadioButtonWithDescription; + import org.chromium.components.content_settings.ContentSettingValues; ++import org.chromium.components.content_settings.ContentSettingsType; + + /** + * A 3-state Allowed/Ask/Blocked radio group Preference used for SiteSettings. +@@ -25,6 +26,7 @@ public class TriStateSiteSettingsPreference + private RadioButtonWithDescription mAsk; + private RadioButtonWithDescription mBlocked; + private RadioGroup mRadioGroup; ++ private @ContentSettingsType int mContentType; + + public TriStateSiteSettingsPreference(Context context, AttributeSet attrs) { + super(context, attrs); +@@ -44,7 +46,9 @@ public class TriStateSiteSettingsPreference + * @param descriptionIds An array of 3 resource IDs for descriptions for + * Allowed, Ask and Blocked states, in that order. + */ +- public void initialize(@ContentSettingValues int setting, int[] descriptionIds) { ++ public void initialize(@ContentSettingsType int contentType, ++ @ContentSettingValues int setting, int[] descriptionIds) { ++ mContentType = contentType; + mSetting = setting; + mDescriptionIds = descriptionIds; + } +@@ -79,6 +83,13 @@ public class TriStateSiteSettingsPreference + mRadioGroup = (RadioGroup) holder.findViewById(R.id.radio_button_layout); + mRadioGroup.setOnCheckedChangeListener(this); + ++ BromiteCustomContentSetting cs = ++ BromiteCustomContentSettingImpl.getContentSetting(mContentType); ++ if (cs != null && cs.showOnlyDescriptions() == true) { ++ mAllowed.setPrimaryText(getContext().getText(mDescriptionIds[0])); ++ mAsk.setPrimaryText(getContext().getText(mDescriptionIds[1])); ++ mBlocked.setPrimaryText(getContext().getText(mDescriptionIds[2])); ++ } else + if (mDescriptionIds != null) { + mAllowed.setDescriptionText(getContext().getText(mDescriptionIds[0])); + mAsk.setDescriptionText(getContext().getText(mDescriptionIds[1])); +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java +--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java +@@ -259,6 +259,10 @@ public final class Website implements Serializable { + ContentSettingsType.TIMEZONE_OVERRIDE, getAddress().getHost(), value, ""); + setContentSettingException(type, exception); + } ++ } else if (exception == null) { ++ exception = BromiteCustomContentSettingImpl.createCustomException(type, value, getAddress()); ++ if (exception != null) ++ setContentSettingException(type, exception); + } + // We want to call setContentSetting even after explicitly setting + // mContentSettingException above because this will trigger the actual change +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java +--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java +@@ -89,7 +89,7 @@ public class WebsitePermissionsFetcher { + case ContentSettingsType.USB_GUARD: + return WebsitePermissionsType.CHOSEN_OBJECT_INFO; + default: +- return null; ++ return BromiteCustomContentSettingImpl.getPermissionsType(contentSettingsType); + } + } + +diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java +--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java ++++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java +@@ -226,7 +226,7 @@ public class WebsitePreferenceBridge { + case ContentSettingsType.TIMEZONE_OVERRIDE: + return true; + default: +- return false; ++ return BromiteCustomContentSettingImpl.requiresTriStateContentSetting(contentSettingsType); + } + } + +diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc +--- a/components/content_settings/core/browser/content_settings_registry.cc ++++ b/components/content_settings/core/browser/content_settings_registry.cc +@@ -15,6 +15,8 @@ + #include "components/content_settings/core/browser/website_settings_registry.h" + #include "components/content_settings/core/common/content_settings.h" + #include "components/content_settings/core/common/features.h" ++#include "components/strings/grit/components_chromium_strings.h" ++#include "components/strings/grit/components_strings.h" + + #if BUILDFLAG(IS_ANDROID) + #include "media/base/android/media_drm_bridge.h" +@@ -678,7 +680,10 @@ void ContentSettingsRegistry::Register( + Platforms platforms, + ContentSettingsInfo::IncognitoBehavior incognito_behavior, + ContentSettingsInfo::StorageBehavior storage_behavior, +- ContentSettingsInfo::OriginRestriction origin_restriction) { ++ ContentSettingsInfo::OriginRestriction origin_restriction, ++ bool show_into_info_page, ++ int permission_type_ui, ++ int permission_type_ui_mid_sentence) { + // Ensure that nothing has been registered yet for the given type. + DCHECK(!website_settings_registry_->Get(type)); + +@@ -687,7 +692,9 @@ void ContentSettingsRegistry::Register( + website_settings_registry_->Register( + type, name, std::move(default_value), sync_status, + WebsiteSettingsInfo::NOT_LOSSY, scoping_type, platforms, +- WebsiteSettingsInfo::INHERIT_IN_INCOGNITO); ++ WebsiteSettingsInfo::INHERIT_IN_INCOGNITO, ++ show_into_info_page, permission_type_ui, ++ permission_type_ui_mid_sentence); + + // WebsiteSettingsInfo::Register() will return nullptr if content setting type + // is not used on the current platform and doesn't need to be registered. +diff --git a/components/content_settings/core/browser/content_settings_registry.h b/components/content_settings/core/browser/content_settings_registry.h +--- a/components/content_settings/core/browser/content_settings_registry.h ++++ b/components/content_settings/core/browser/content_settings_registry.h +@@ -71,7 +71,10 @@ class ContentSettingsRegistry { + Platforms platforms, + ContentSettingsInfo::IncognitoBehavior incognito_behavior, + ContentSettingsInfo::StorageBehavior storage_behavior, +- ContentSettingsInfo::OriginRestriction origin_restriction); ++ ContentSettingsInfo::OriginRestriction origin_restriction, ++ bool show_into_info_page = false, ++ int permission_type_ui = 0, ++ int permission_type_ui_mid_sentence = 0); + + Map content_settings_info_; + raw_ptr website_settings_registry_; +diff --git a/components/content_settings/core/browser/website_settings_info.cc b/components/content_settings/core/browser/website_settings_info.cc +--- a/components/content_settings/core/browser/website_settings_info.cc ++++ b/components/content_settings/core/browser/website_settings_info.cc +@@ -33,7 +33,10 @@ WebsiteSettingsInfo::WebsiteSettingsInfo(ContentSettingsType type, + SyncStatus sync_status, + LossyStatus lossy_status, + ScopingType scoping_type, +- IncognitoBehavior incognito_behavior) ++ IncognitoBehavior incognito_behavior, ++ bool show_into_info_page, ++ int permission_type_ui, ++ int permission_type_ui_mid_sentence) + : type_(type), + name_(name), + pref_name_(GetPreferenceName(name, kPrefPrefix)), +@@ -42,7 +45,10 @@ WebsiteSettingsInfo::WebsiteSettingsInfo(ContentSettingsType type, + sync_status_(sync_status), + lossy_status_(lossy_status), + scoping_type_(scoping_type), +- incognito_behavior_(incognito_behavior) { ++ incognito_behavior_(incognito_behavior), ++ show_into_info_page_(show_into_info_page), ++ permission_type_ui_(permission_type_ui), ++ permission_type_ui_mid_sentence_(permission_type_ui_mid_sentence) { + // For legacy reasons the default value is currently restricted to be an int + // or none. + // TODO(raymes): We should migrate the underlying pref to be a dictionary +diff --git a/components/content_settings/core/browser/website_settings_info.h b/components/content_settings/core/browser/website_settings_info.h +--- a/components/content_settings/core/browser/website_settings_info.h ++++ b/components/content_settings/core/browser/website_settings_info.h +@@ -69,7 +69,10 @@ class WebsiteSettingsInfo { + SyncStatus sync_status, + LossyStatus lossy_status, + ScopingType scoping_type, +- IncognitoBehavior incognito_behavior); ++ IncognitoBehavior incognito_behavior, ++ bool show_into_info_page, ++ int permission_type_ui, ++ int permission_type_ui_mid_sentence); + + WebsiteSettingsInfo(const WebsiteSettingsInfo&) = delete; + WebsiteSettingsInfo& operator=(const WebsiteSettingsInfo&) = delete; +@@ -94,6 +97,10 @@ class WebsiteSettingsInfo { + ScopingType scoping_type() const { return scoping_type_; } + IncognitoBehavior incognito_behavior() const { return incognito_behavior_; } + ++ bool show_into_info_page() const { return show_into_info_page_; } ++ int permission_type_ui() const { return permission_type_ui_; } ++ int permission_type_ui_mid_sentence() const { return permission_type_ui_mid_sentence_; } ++ + private: + const ContentSettingsType type_; + const std::string name_; +@@ -105,6 +112,9 @@ class WebsiteSettingsInfo { + const LossyStatus lossy_status_; + const ScopingType scoping_type_; + const IncognitoBehavior incognito_behavior_; ++ const bool show_into_info_page_; ++ const int permission_type_ui_; ++ const int permission_type_ui_mid_sentence_; + }; + + } // namespace content_settings +diff --git a/components/content_settings/core/browser/website_settings_registry.cc b/components/content_settings/core/browser/website_settings_registry.cc +--- a/components/content_settings/core/browser/website_settings_registry.cc ++++ b/components/content_settings/core/browser/website_settings_registry.cc +@@ -62,7 +62,10 @@ const WebsiteSettingsInfo* WebsiteSettingsRegistry::Register( + WebsiteSettingsInfo::LossyStatus lossy_status, + WebsiteSettingsInfo::ScopingType scoping_type, + Platforms platform, +- WebsiteSettingsInfo::IncognitoBehavior incognito_behavior) { ++ WebsiteSettingsInfo::IncognitoBehavior incognito_behavior, ++ bool show_into_info_page, ++ int permission_type_ui, ++ int permission_type_ui_mid_sentence) { + #if BUILDFLAG(IS_WIN) + if (!(platform & PLATFORM_WINDOWS)) + return nullptr; +@@ -98,7 +101,8 @@ const WebsiteSettingsInfo* WebsiteSettingsRegistry::Register( + + WebsiteSettingsInfo* info = new WebsiteSettingsInfo( + type, name, std::move(initial_default_value), sync_status, lossy_status, +- scoping_type, incognito_behavior); ++ scoping_type, incognito_behavior, ++ show_into_info_page, permission_type_ui, permission_type_ui_mid_sentence); + website_settings_info_[info->type()] = base::WrapUnique(info); + return info; + } +diff --git a/components/content_settings/core/browser/website_settings_registry.h b/components/content_settings/core/browser/website_settings_registry.h +--- a/components/content_settings/core/browser/website_settings_registry.h ++++ b/components/content_settings/core/browser/website_settings_registry.h +@@ -76,7 +76,10 @@ class WebsiteSettingsRegistry { + WebsiteSettingsInfo::LossyStatus lossy_status, + WebsiteSettingsInfo::ScopingType scoping_type, + Platforms platforms, +- WebsiteSettingsInfo::IncognitoBehavior incognito_behavior); ++ WebsiteSettingsInfo::IncognitoBehavior incognito_behavior, ++ bool show_into_info_page = false, ++ int permission_type_ui = 0, ++ int permission_type_ui_mid_sentence = 0); + + const_iterator begin() const; + const_iterator end() const; +diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PermissionParamsListBuilder.java b/components/page_info/android/java/src/org/chromium/components/page_info/PermissionParamsListBuilder.java +--- a/components/page_info/android/java/src/org/chromium/components/page_info/PermissionParamsListBuilder.java ++++ b/components/page_info/android/java/src/org/chromium/components/page_info/PermissionParamsListBuilder.java +@@ -109,6 +109,7 @@ public class PermissionParamsListBuilder { + permissionParams.allowed = true; + break; + case ContentSettingValues.BLOCK: ++ case ContentSettingValues.ASK: + permissionParams.allowed = false; + break; + default: +diff --git a/components/page_info/android/page_info_controller_android.cc b/components/page_info/android/page_info_controller_android.cc +--- a/components/page_info/android/page_info_controller_android.cc ++++ b/components/page_info/android/page_info_controller_android.cc +@@ -11,6 +11,7 @@ + #include "base/command_line.h" + #include "base/containers/contains.h" + #include "components/content_settings/core/browser/host_content_settings_map.h" ++#include "components/content_settings/core/browser/website_settings_registry.h" + #include "components/content_settings/core/common/content_settings.h" + #include "components/content_settings/core/common/content_settings_types.h" + #include "components/page_info/android/jni_headers/PageInfoController_jni.h" +@@ -156,6 +157,14 @@ void PageInfoControllerAndroid::SetPermissionInfo( + permissions_to_display.push_back(ContentSettingsType::VR); + permissions_to_display.push_back(ContentSettingsType::AR); + ++ content_settings::WebsiteSettingsRegistry* website_settings = ++ content_settings::WebsiteSettingsRegistry::GetInstance(); ++ for (const content_settings::WebsiteSettingsInfo* info : *website_settings) { ++ if (info->show_into_info_page()) { ++ permissions_to_display.push_back(info->type()); ++ } ++ } ++ + std::map + user_specified_settings_to_display; + std::map +@@ -238,6 +247,15 @@ absl::optional PageInfoControllerAndroid::GetSettingToDisplay( + // The images content setting should show up if it is blocked globally + // to give users an easy way to create exceptions. + return permission.default_setting; ++ } else { ++ content_settings::WebsiteSettingsRegistry* website_settings = ++ content_settings::WebsiteSettingsRegistry::GetInstance(); ++ for (const content_settings::WebsiteSettingsInfo* info : *website_settings) { ++ if (info->type() == permission.type && ++ info->show_into_info_page()) { ++ return permission.default_setting; ++ } ++ } + } + + // TODO(crbug.com/1077766): Also return permissions that are non +diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc +--- a/components/page_info/page_info.cc ++++ b/components/page_info/page_info.cc +@@ -24,6 +24,7 @@ + #include "components/browser_ui/util/android/url_constants.h" + #include "components/browsing_data/content/local_storage_helper.h" + #include "components/content_settings/browser/page_specific_content_settings.h" ++#include "components/content_settings/core/browser/website_settings_registry.h" + #include "components/content_settings/core/browser/content_settings_registry.h" + #include "components/content_settings/core/browser/content_settings_utils.h" + #include "components/content_settings/core/browser/host_content_settings_map.h" +@@ -162,6 +163,15 @@ bool ShouldShowPermission(const PageInfo::PermissionInfo& info, + return true; + } + ++ content_settings::WebsiteSettingsRegistry* website_settings = ++ content_settings::WebsiteSettingsRegistry::GetInstance(); ++ for (const content_settings::WebsiteSettingsInfo* winfo : *website_settings) { ++ if (info.type == winfo->type() && ++ winfo->show_into_info_page()) { ++ return true; ++ } ++ } ++ + const bool is_incognito = web_contents->GetBrowserContext()->IsOffTheRecord(); + #if BUILDFLAG(IS_ANDROID) + // Special geolocation DSE settings apply only on Android, so make sure it +@@ -962,7 +972,18 @@ void PageInfo::PresentSitePermissions() { + PermissionInfo permission_info; + HostContentSettingsMap* content_settings = GetContentSettings(); + DCHECK(web_contents_); +- for (const ContentSettingsType type : kPermissionType) { ++ std::vector permission_list; ++ for (const ContentSettingsType type : kPermissionType) ++ permission_list.push_back(type); ++ ++ content_settings::WebsiteSettingsRegistry* website_settings = ++ content_settings::WebsiteSettingsRegistry::GetInstance(); ++ for (const content_settings::WebsiteSettingsInfo* info : *website_settings) { ++ if (info->show_into_info_page()) { ++ permission_list.push_back(info->type()); ++ } ++ } ++ for (const ContentSettingsType type : permission_list) { + permission_info.type = type; + + content_settings::SettingInfo info; +diff --git a/components/page_info/page_info_ui.cc b/components/page_info/page_info_ui.cc +--- a/components/page_info/page_info_ui.cc ++++ b/components/page_info/page_info_ui.cc +@@ -12,6 +12,7 @@ + #include "base/strings/utf_string_conversions.h" + #include "build/build_config.h" + #include "build/chromeos_buildflags.h" ++#include "components/content_settings/core/browser/website_settings_registry.h" + #include "components/omnibox/common/omnibox_features.h" + #include "components/page_info/core/features.h" + #include "components/page_info/page_info_ui_delegate.h" +@@ -559,6 +560,12 @@ std::u16string PageInfoUI::PermissionTypeToUIString(ContentSettingsType type) { + if (info.type == type) + return l10n_util::GetStringUTF16(info.string_id); + } ++ const content_settings::WebsiteSettingsInfo* settingInfo = ++ content_settings::WebsiteSettingsRegistry::GetInstance()->Get(type); ++ if (settingInfo && settingInfo->show_into_info_page() && ++ settingInfo->permission_type_ui() != 0) { ++ return l10n_util::GetStringUTF16(settingInfo->permission_type_ui()); ++ } + NOTREACHED(); + return std::u16string(); + } +@@ -570,6 +577,12 @@ std::u16string PageInfoUI::PermissionTypeToUIStringMidSentence( + if (info.type == type) + return l10n_util::GetStringUTF16(info.string_id_mid_sentence); + } ++ const content_settings::WebsiteSettingsInfo* settingInfo = ++ content_settings::WebsiteSettingsRegistry::GetInstance()->Get(type); ++ if (settingInfo && settingInfo->show_into_info_page() && ++ settingInfo->permission_type_ui_mid_sentence() != 0) { ++ return l10n_util::GetStringUTF16(settingInfo->permission_type_ui_mid_sentence()); ++ } + NOTREACHED(); + return std::u16string(); + } +@@ -970,6 +983,11 @@ bool PageInfoUI::ContentSettingsTypeInPageInfo(ContentSettingsType type) { + if (info.type == type) + return true; + } ++ const content_settings::WebsiteSettingsInfo* settingInfo = ++ content_settings::WebsiteSettingsRegistry::GetInstance()->Get(type); ++ if (settingInfo) { ++ return settingInfo->show_into_info_page(); ++ } + return false; + } + +-- +2.25.1