Browse Source

Add webgl site setting

Carmelo Messina 3 years ago
parent
commit
c36f7d63f3

+ 492 - 0
build/patches/Add-webgl-site-setting.patch

@@ -0,0 +1,492 @@
+From: uazo <uazo@users.noreply.github.com>
+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<BromiteCustomContentSetting>();
++        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 <https://www.gnu.org/licenses/>.
++*/
++
++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 @@
+   <release seq="1">
+     <messages fallback_to_english="true">
+       <part file="site_settings.grdp" />
++      <part file="webgl.grdp" />
+ 
+       <message name="IDS_GOT_IT" desc="Button for the user to accept a disclosure/message">
+         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 @@
++<?xml version="1.0" encoding="utf-8"?>
++<grit-part>
++  <message name="IDS_SITE_SETTINGS_TYPE_WEBGL" desc="The label used for webgl site settings controls.">
++    Webgl
++  </message>
++  <message name="IDS_SITE_SETTINGS_TYPE_WEBGL_MID_SENTENCE" desc="The label used for webgl site settings controls when used mid-sentence.">
++    webgl
++  </message>
++  <message name="IDS_WEBGL_PERMISSION_TITLE" desc="Title of the permission to use webgl [CHAR-LIMIT=32]">
++    Webgl
++  </message>
++  <message name="IDS_WEBSITE_SETTINGS_CATEGORY_WEBGL_ENABLED" desc="Summary text explaining that webgl is full enabled.">
++    Enabled
++  </message>
++  <message name="IDS_WEBSITE_SETTINGS_CATEGORY_WEBGL_DISABLED" desc="Summary text explaining that webgl is full disabled.">
++    Disabled
++  </message>
++</grit-part>
+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 @@
+       <part file="version_ui_strings.grdp" />
+       <part file="webapps_strings.grdp" />
+       <part file="user_scripts/strings/userscripts_strings.grdp" />
++      <part file="browser_ui/strings/android/webgl.grdp" />
+ 
+       <if expr="not is_ios">
+         <part file="management_strings.grdp" />
+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<ContentSettingPatternSource> auto_dark_content_rules;
+   array<ContentSettingPatternSource> timezone_override_rules;
+   string timezone_override_value;
++  array<ContentSettingPatternSource> 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 StructTraits<content_settings::mojom::RendererContentSettingRulesDataView,
+          data.ReadMixedContentRules(&out->mixed_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<ContentSettingPatternSource>& 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<blink::LocalDOMWindow>(context)) {
++    auto* frame = window->GetFrame();
++    if (frame)
++      settings = frame->GetContentSettingsClient();
++  } else if (context->IsWorkerGlobalScope()) {
++    settings =
++        blink::To<blink::WorkerGlobalScope>(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

+ 1266 - 0
build/patches/Content-settings-infrastructure.patch

@@ -0,0 +1,1266 @@
+From: uazo <uazo@users.noreply.github.com>
+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 <https://www.gnu.org/licenses/>.
++*/
++
++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 <https://www.gnu.org/licenses/>.
++*/
++
++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<BromiteCustomContentSetting> mItemList;
++
++    static {
++        mItemList = new ArrayList<BromiteCustomContentSetting>();
++    }
++
++    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<Integer> getSettingsOrder() {
++        int[] settingOrder = SiteSettingsUtil.SETTINGS_ORDER;
++        List<Integer> order = new ArrayList<Integer>();
++        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<BromiteCustomContentSetting>();
++        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/`
++
++```
++<?xml version="1.0" encoding="utf-8"?>
++<grit-part>
++  <message name="IDS_NEW_CONTENT_SETTING" desc="The label used for your content type site settings controls.">
++    your content type
++  </message>
++  <message name="IDS_NEW_CONTENT_SETTING_MID_SENTENCE" desc="The label used for your content type site settings controls when used mid-sentence.">
++    your content type
++  </message>
++  <message name="IDS_NEW_CONTENT_SETTING_PERMISSION_TITLE" desc="Title of the permission to use your content type [CHAR-LIMIT=32]">
++    your content type
++  </message>
++  <message name="IDS_NEW_CONTENT_SETTING_ENABLED" desc="Summary text explaining that your content type is enabled with fingerprinting protection.">
++    your content type is enabled
++  </message>
++  <message name="IDS_NEW_CONTENT_SETTING_ASK" desc="Summary text explaining that your content type is full enabled.">
++    ask before activate your content type
++  </message>
++  <message name="IDS_NEW_CONTENT_SETTING_DISABLED" desc="Summary text explaining that your content type is full disabled.">
++    your content type is disabled
++  </message>
++</grit-part>
++```
++
++* Reference it in `components/components_strings.grd` to have strings in native
++
++```
++<part file="browser_ui/strings/android/new_content_setting_file.grdp" />
++```
++
++* Reference it in `components/browser_ui/strings/android/browser_ui_strings.grd` to have the strings in java
++
++```
++<part file="new_content_setting_file.grdp" />
++```
+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<Integer> 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<WebsiteSettingsRegistry> 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<ContentSettingsType, ContentSetting>
+       user_specified_settings_to_display;
+   std::map<ContentSettingsType, bool>
+@@ -238,6 +247,15 @@ absl::optional<ContentSetting> 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<ContentSettingsType> 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