From: uazo Date: Thu, 24 Feb 2022 07:54:36 +0000 Subject: Content settings infrastructure This patch is used by other patches to provide the UI for Bromite-specific site settings. See BromiteCustomContentSetting_README.md for more information. Original License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html Require: bromite-build-utils.patch --- .../ChromeSiteSettingsDelegate.java | 17 +- ...page_specific_content_settings_delegate.cc | 2 +- .../privacy_page/privacy_page_index.html | 1 + .../privacy_page/privacy_page_index.ts | 83 +++- chrome/browser/resources/settings/route.ts | 2 + ...settings_category_default_radio_group.html | 12 + .../settings/site_settings/site_details.html | 1 + .../settings/site_settings/site_details.ts | 33 +- .../site_details_permission.html | 8 +- .../site_settings/site_details_permission.ts | 44 ++ .../site_settings/site_settings_mixin.ts | 20 +- .../site_settings/site_settings_page.ts | 30 +- .../site_settings/site_settings_util.ts | 55 +++ chrome/browser/ui/BUILD.gn | 2 + .../controls/rich_controls_container_view.h | 7 + .../views/page_info/page_info_bubble_view.cc | 2 +- .../ui/views/page_info/page_info_main_view.cc | 28 +- .../views/page_info/page_info_view_factory.cc | 20 + .../views/page_info/page_info_view_factory.h | 5 + .../page_info/permission_toggle_row_view.cc | 188 ++++++-- .../page_info/permission_toggle_row_view.h | 18 +- .../settings_localized_strings_provider.cc | 54 +++ .../ui/webui/settings/site_settings_helper.cc | 46 +- .../browser_ui/settings/android/BUILD.gn | 1 + .../preference_spinner_single_widget.xml | 92 ++++ .../settings/SpinnerPreference.java | 25 ++ .../browser_ui/site_settings/android/BUILD.gn | 18 + .../res/xml/site_settings_preferences.xml | 7 + .../site_settings/AllSiteSettings.java | 5 +- .../BromiteCustomContentSetting.java | 159 +++++++ .../BromiteCustomContentSettingImpl.java | 422 ++++++++++++++++++ ...tomTriStateSiteSettingsPreferenceImpl.java | 24 + .../ContentSettingsResources.java | 34 +- .../site_settings/SingleCategorySettings.java | 57 ++- .../site_settings/SingleWebsiteSettings.java | 48 +- .../site_settings/SiteSettings.java | 35 +- .../site_settings/SiteSettingsCategory.java | 18 +- .../site_settings/SiteSettingsDelegate.java | 2 + .../TriStateSiteSettingsPreference.java | 11 + .../browser_ui/site_settings/Website.java | 6 +- .../WebsitePermissionsFetcher.java | 2 +- .../WebsitePreferenceBridge.java | 3 +- .../impl/include_all_directory.java | 1 + ...miteCustomContentSettingImplBase.java.tmpl | 48 ++ .../bromite_content_settings/placeholder.txt | 1 + components/content_settings/android/BUILD.gn | 1 + .../content_settings/core/browser/BUILD.gn | 7 + .../bromite_content_settings/placeholder.txt | 1 + .../core/browser/content_settings_registry.cc | 2 + .../core/browser/content_settings_uma_util.cc | 6 +- .../core/browser/content_settings_utils.cc | 12 + .../core/browser/website_settings_info.h | 38 ++ .../core/browser/website_settings_registry.cc | 6 + .../core/browser/website_settings_registry.h | 1 + .../content_settings/core/common/BUILD.gn | 8 + .../bromite_content_settings/placeholder.txt | 1 + .../core/common/content_settings.cc | 30 +- .../core/common/content_settings.h | 12 + .../core/common/content_settings.mojom | 6 + .../common/content_settings_mojom_traits.cc | 12 +- .../common/content_settings_mojom_traits.h | 24 + .../core/common/content_settings_types.mojom | 2 + .../renderer/content_settings_agent_impl.cc | 74 +++ .../renderer/content_settings_agent_impl.h | 9 + .../PageInfoPermissionsController.java | 9 + .../android/page_info_controller_android.cc | 18 + components/page_info/page_info.cc | 23 +- components/page_info/page_info_ui.cc | 25 ++ components/site_settings_strings.grdp | 1 + .../platform/web_content_settings_client.h | 13 + .../execution_context/execution_context.cc | 16 + .../execution_context/execution_context.h | 5 + 72 files changed, 1954 insertions(+), 105 deletions(-) create mode 100644 components/browser_ui/settings/android/java/res/layout/preference_spinner_single_widget.xml 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/BromiteCustomTriStateSiteSettingsPreferenceImpl.java create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/include_all_directory.java create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/java_template/BromiteCustomContentSettingImplBase.java.tmpl create mode 100644 components/browser_ui/strings/bromite_content_settings/placeholder.txt create mode 100644 components/content_settings/core/browser/bromite_content_settings/placeholder.txt create mode 100644 components/content_settings/core/common/bromite_content_settings/placeholder.txt diff --git a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java --- a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java @@ -71,6 +71,10 @@ import org.chromium.url.GURL; import java.util.List; import java.util.Set; +import android.content.Intent; +import android.provider.Browser; +import android.net.Uri; + /** A SiteSettingsDelegate instance that contains Chrome-specific Site Settings logic. */ @NullMarked public class ChromeSiteSettingsDelegate implements SiteSettingsDelegate { @@ -246,7 +250,7 @@ public class ChromeSiteSettingsDelegate implements SiteSettingsDelegate { @Override public boolean isHelpAndFeedbackEnabled() { - return true; + return false; } @Override @@ -373,6 +377,17 @@ public class ChromeSiteSettingsDelegate implements SiteSettingsDelegate { return mPrivacySandboxBridge.getRelatedWebsiteSetOwner(memberOrigin); } + @Override + public void launchHelpAndFeedbackActivity(Activity currentActivity, String url) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + // Let Chromium know that this intent is from Chromium, so that it does not close the app when + // the user presses 'back' button. + intent.putExtra(Browser.EXTRA_APPLICATION_ID, currentActivity.getPackageName()); + intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true); + intent.setPackage(currentActivity.getPackageName()); + currentActivity.startActivity(intent); + } + @Override public boolean canLaunchClearBrowsingDataDialog() { return true; diff --git a/chrome/browser/content_settings/page_specific_content_settings_delegate.cc b/chrome/browser/content_settings/page_specific_content_settings_delegate.cc --- a/chrome/browser/content_settings/page_specific_content_settings_delegate.cc +++ b/chrome/browser/content_settings/page_specific_content_settings_delegate.cc @@ -193,7 +193,7 @@ namespace { void GetGuestViewDefaultContentSettingRules( bool incognito, RendererContentSettingRules* rules) { - rules->mixed_content_rules.clear(); + rules->mixed_content_rules.clear(); // do not remove rules->mixed_content_rules.push_back(ContentSettingPatternSource( ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(), content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK), diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page_index.html b/chrome/browser/resources/settings/privacy_page/privacy_page_index.html --- a/chrome/browser/resources/settings/privacy_page/privacy_page_index.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page_index.html @@ -628,4 +628,5 @@ +
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page_index.ts b/chrome/browser/resources/settings/privacy_page/privacy_page_index.ts --- a/chrome/browser/resources/settings/privacy_page/privacy_page_index.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_page_index.ts @@ -9,6 +9,7 @@ import '../settings_page/settings_section.js'; import '../settings_shared.css.js'; import './privacy_guide/privacy_guide_promo.js'; import './privacy_page.js'; +import '../controls/settings_dropdown_menu.js'; import {PrefsMixin} from '/shared/settings/prefs/prefs_mixin.js'; import type {CrViewManagerElement} from 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.js'; @@ -29,6 +30,8 @@ import {PrivacyGuideAvailabilityMixin} from './privacy_guide/privacy_guide_avail import type {PrivacyGuideBrowserProxy} from './privacy_guide/privacy_guide_browser_proxy.js'; import {MAX_PRIVACY_GUIDE_PROMO_IMPRESSION, PrivacyGuideBrowserProxyImpl} from './privacy_guide/privacy_guide_browser_proxy.js'; import {getTemplate} from './privacy_page_index.html.js'; +import {ContentSettingsTypes} from '../site_settings/constants.js'; +import {SettingsCategoryDefaultRadioGroupElement} from '../site_settings/settings_category_default_radio_group.js'; // clang-format off // @@ -53,8 +56,86 @@ export class SettingsPrivacyPageIndexElement extends return 'settings-privacy-page-index'; } + static getSettingTemplate(template: HTMLTemplateElement, + name: string) : SettingsCategoryDefaultRadioGroupElement | undefined { + let value : SettingsCategoryDefaultRadioGroupElement | undefined = undefined; + let page : any = template.content.querySelector("cr-view-manager"); + + page.querySelectorAll("template")!.forEach( + (subTemplate: HTMLTemplateElement) => { + subTemplate.content.querySelectorAll("settings-category-default-radio-group").forEach( + (radio: any) => { + let setting = radio.getAttribute("category") + .replace("[[contentSettingsTypesEnum_.", "") + .replace("]]", ""); + if ((ContentSettingsTypes as any)[setting] === name) + value = radio; + }); + }); + return value; + } + static get template() { - return getTemplate(); + let template = getTemplate(); + let content = template.content.getElementById("bromite-placeholder")!; + + for (let index=0; index < loadTimeData.getInteger("br_cs_count"); index++) { + let obj = JSON.parse(loadTimeData.getString("br_cs_" + index)); + let name = obj["name"]; + let tag_name = obj["tag_ui"]; if (!tag_name) tag_name = obj["name"]; + + let existingSetting = this.getSettingTemplate(template, name); + if (existingSetting) { + if (loadTimeData.valueExists(`brSiteSettings${name}Ask`)) { + existingSetting.setAttribute("ask-option-label", loadTimeData.getString(`brSiteSettings${name}Ask`)); + existingSetting.setAttribute("ask-option-icon", `br-settings:${name}-off`); + } + continue; + } + + let subpage = document.createElement("settings-subpage"); + subpage.setAttribute("page-title", loadTimeData.getString(`brSiteSettings${name}`)); + subpage.setAttribute("search-title", loadTimeData.getString("siteSettingsAllSitesSearch")); + subpage.setAttribute("search-term", "{{searchFilter_}}"); + subpage.setAttribute("slot", "view"); + subpage.setAttribute("data-parent-view-id", "privacy"); + subpage.setAttribute("id", `siteSettings${name}`); + subpage.setAttribute("route-path", `/content/${tag_name}`); + + let divElement = document.createElement("div"); + divElement.setAttribute("class", "content-settings-header secondary"); + divElement.setAttribute("style", "padding: 0 var(--cr-section-padding)"); + divElement.innerText = loadTimeData.getString(`brSiteSettings${name}Description`); + subpage.appendChild(divElement); + + let radioGroup = existingSetting ?? document.createElement("settings-category-default-radio-group"); + radioGroup.setAttribute("category", name); + radioGroup.setAttribute("allow-option-label", loadTimeData.getString(`brSiteSettings${name}Allowed`)); + radioGroup.setAttribute("allow-option-icon", `br-settings:${name}`); + radioGroup.setAttribute("block-option-label", loadTimeData.getString(`brSiteSettings${name}Blocked`)); + radioGroup.setAttribute("block-option-icon", `br-settings:${name}-off`); + if (loadTimeData.valueExists(`brSiteSettings${name}Ask`)) { + radioGroup.setAttribute("ask-option-label", loadTimeData.getString(`brSiteSettings${name}Ask`)); + radioGroup.setAttribute("ask-option-icon", `br-settings:${name}-off`); + } + subpage.appendChild(radioGroup); + + let exceptions = document.createElement("category-setting-exceptions"); + exceptions.setAttribute("category", name); + exceptions.setAttribute("allow-header", loadTimeData.getString(`brSiteSettings${name}AllowedExceptions`)); + exceptions.setAttribute("block-header", loadTimeData.getString(`brSiteSettings${name}BlockedExceptions`)); + exceptions.setAttribute("search-filter", "[[searchFilter_]]"); + subpage.appendChild(exceptions); + + let tag = document.createElement("template"); + tag.setAttribute("is", "dom-if"); + tag.setAttribute("if", `[[renderView_(routes_.SITE_SETTINGS_${name.toUpperCase()}, currentRoute, inSearchMode)]]`); + tag.content.appendChild(subpage); + + content.parentElement!.insertBefore(tag, content); + } + content.parentElement!.removeChild(content); + return template; } static get properties() { diff --git a/chrome/browser/resources/settings/route.ts b/chrome/browser/resources/settings/route.ts --- a/chrome/browser/resources/settings/route.ts +++ b/chrome/browser/resources/settings/route.ts @@ -8,6 +8,7 @@ import {loadTimeData} from './i18n_setup.js'; import {pageVisibility} from './page_visibility.js'; import type {SettingsRoutes} from './router.js'; import {Route, Router} from './router.js'; +import {setupContentSettingsRoutes} from './site_settings/site_settings_util.js' /** * Add all of the child routes that originate from the privacy route, @@ -153,6 +154,7 @@ function addPrivacyChildRoutes(r: Partial) { r.SITE_SETTINGS_LOOPBACK_NETWORK = r.SITE_SETTINGS.createChild('loopbackNetwork'); } + setupContentSettingsRoutes(r); } /** diff --git a/chrome/browser/resources/settings/site_settings/settings_category_default_radio_group.html b/chrome/browser/resources/settings/site_settings/settings_category_default_radio_group.html --- a/chrome/browser/resources/settings/site_settings/settings_category_default_radio_group.html +++ b/chrome/browser/resources/settings/site_settings/settings_category_default_radio_group.html @@ -68,5 +68,17 @@ hidden="[[!blockOptionLabel]]" no-collapse> + + diff --git a/chrome/browser/resources/settings/site_settings/site_details.html b/chrome/browser/resources/settings/site_settings/site_details.html --- a/chrome/browser/resources/settings/site_settings/site_details.html +++ b/chrome/browser/resources/settings/site_settings/site_details.html @@ -352,5 +352,6 @@ label="$i18n{siteSettingsLoopbackNetwork}"> +
diff --git a/chrome/browser/resources/settings/site_settings/site_details.ts b/chrome/browser/resources/settings/site_settings/site_details.ts --- a/chrome/browser/resources/settings/site_settings/site_details.ts +++ b/chrome/browser/resources/settings/site_settings/site_details.ts @@ -74,8 +74,39 @@ export class SiteDetailsElement extends SiteDetailsElementBase { return 'site-details'; } + static getSettingTemplate(template: HTMLTemplateElement, + name: string) : SiteDetailsPermissionElement | undefined { + let value : SiteDetailsPermissionElement | undefined = undefined; + template.content.querySelectorAll("site-details-permission").forEach( + (element: any) => { + let setting = element.getAttribute("category") + .replace("[[contentSettingsTypesEnum_.", "") + .replace("]]", ""); + if ((ContentSettingsTypes as any)[setting] === name) + value = element; + }); + return value; + } + static get template() { - return getTemplate(); + let template = getTemplate(); + let content = template.content.getElementById("bromite-placeholder")!; + + for (let index=0; index < loadTimeData.getInteger("br_cs_count"); index++) { + let obj = JSON.parse(loadTimeData.getString("br_cs_" + index)); + let name = obj["name"]; + + if (this.getSettingTemplate(template, name)) + continue; + + let tag = document.createElement("site-details-permission"); + tag.setAttribute("category", name); + tag.setAttribute("icon", `br-settings:${name}`); + tag.setAttribute("label", loadTimeData.getString(`brSiteSettings${name}`)); + content.parentElement!.insertBefore(tag, content); + } + content.parentElement!.removeChild(content); + return template; } static get properties() { diff --git a/chrome/browser/resources/settings/site_settings/site_details_permission.html b/chrome/browser/resources/settings/site_settings/site_details_permission.html --- a/chrome/browser/resources/settings/site_settings/site_details_permission.html +++ b/chrome/browser/resources/settings/site_settings/site_details_permission.html @@ -58,7 +58,9 @@ diff --git a/chrome/browser/resources/settings/site_settings/site_details_permission.ts b/chrome/browser/resources/settings/site_settings/site_details_permission.ts --- a/chrome/browser/resources/settings/site_settings/site_details_permission.ts +++ b/chrome/browser/resources/settings/site_settings/site_details_permission.ts @@ -20,6 +20,7 @@ import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; import {sanitizeInnerHtml} from 'chrome://resources/js/parse_html_subset.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {loadTimeData} from '../i18n_setup.js'; import {ChooserType, ContentSetting, ContentSettingsTypes, SiteSettingSource} from './constants.js'; import {getTemplate} from './site_details_permission.html.js'; @@ -304,14 +305,27 @@ export class SiteDetailsPermissionElement extends return this.i18n('siteSettingsActionBlockOnUnfamiliarSitesDefaultMenu'); } + let obj = this.getSettingData(category); if (defaultSetting === ContentSetting.ASK) { + if (obj) { + let v = this.askSettingString_(category, ""); + if (v !== "") return "(Default) " + v; + } return this.i18n('siteSettingsActionAskDefault'); } else if (defaultSetting === ContentSetting.ALLOW) { + if (obj) { + let v = this.allowSettingString_(category, ""); + if (v !== "") return "(Default) " + v; + } if (this.useCustomSoundLabels_(category) && useAutomaticLabel) { return this.i18n('siteSettingsActionAutomaticDefault'); } return this.i18n('siteSettingsActionAllowDefault'); } else if (defaultSetting === ContentSetting.BLOCK) { + if (obj) { + let v = this.blockSettingString_(category, "", ""); + if (v !== "") return "(Default) " + v; + } if (this.useCustomSoundLabels_(category)) { return this.i18n('siteSettingsActionMuteDefault'); } @@ -330,12 +344,40 @@ export class SiteDetailsPermissionElement extends private blockSettingString_( category: ContentSettingsTypes, blockString: string, muteString: string): string { + let obj = this.getSettingData(category); + if (obj) { + let propertyName = "brSiteSettings" + obj["name"] + "Blocked"; + if (loadTimeData.valueExists(propertyName)) + return loadTimeData.getString(propertyName); + } if (this.useCustomSoundLabels_(category)) { return muteString; } return blockString; } + private allowSettingString_( + category: ContentSettingsTypes, defaultString: string): string { + let obj = this.getSettingData(category); + if (obj) { + let propertyName = "brSiteSettings" + obj["name"] + "Allowed"; + if (loadTimeData.valueExists(propertyName)) + return loadTimeData.getString(propertyName); + } + return defaultString; + } + + private askSettingString_( + category: ContentSettingsTypes, defaultString: string): string { + let obj = this.getSettingData(category); + if (obj) { + let propertyName = "brSiteSettings" + obj["name"] + "Ask"; + if (loadTimeData.valueExists(propertyName)) + return loadTimeData.getString(propertyName); + } + return defaultString; + } + /** * @return true if |this| should be hidden. */ @@ -426,6 +468,8 @@ export class SiteDetailsPermissionElement extends private showAskSetting_( category: ContentSettingsTypes, setting: ContentSetting, source: SiteSettingSource): boolean { + let obj = this.getSettingData(category); + if (obj) return obj["allowed_ask"] === "1"; // For chooser-based permissions 'ask' takes the place of 'allow'. if (category === ContentSettingsTypes.SERIAL_PORTS || category === ContentSettingsTypes.USB_DEVICES || diff --git a/chrome/browser/resources/settings/site_settings/site_settings_mixin.ts b/chrome/browser/resources/settings/site_settings/site_settings_mixin.ts --- a/chrome/browser/resources/settings/site_settings/site_settings_mixin.ts +++ b/chrome/browser/resources/settings/site_settings/site_settings_mixin.ts @@ -11,9 +11,10 @@ import type { PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/poly import {dedupingMixin} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import type {ContentSettingsTypes} from './constants.js'; -import {SiteSettingSource} from './constants.js'; +import {SiteSettingSource, ContentSetting} from './constants.js'; import type {RawSiteException,SiteException,SiteSettingsBrowserProxy} from './site_settings_browser_proxy.js'; import {SiteSettingsBrowserProxyImpl} from './site_settings_browser_proxy.js'; +import {loadTimeData} from '../i18n_setup.js'; // clang-format on type Constructor = new (...args: any[]) => T; @@ -87,6 +88,21 @@ export const SiteSettingsMixin = dedupingMixin( return url; } + computeIsSettingAsk(setting: ContentSetting): boolean { + return setting === ContentSetting.ASK; + } + + getSettingData(category: ContentSettingsTypes): any { + for (let index=0; index < loadTimeData.getInteger("br_cs_count"); index++) { + let obj = JSON.parse(loadTimeData.getString("br_cs_" + index)); + let name = obj["name"]; + if (name == category) { + return obj; + } + } + return undefined; + } + /** * Converts a string origin/pattern to a URL. * @param originOrPattern The origin/pattern to convert to URL. @@ -166,6 +182,8 @@ export const SiteSettingsMixin = dedupingMixin( export interface SiteSettingsMixinInterface { browserProxy: SiteSettingsBrowserProxy; category: ContentSettingsTypes; + computeIsSettingAsk(setting: string): boolean; + getSettingData(category: ContentSettingsTypes): any; originRepresentation(origin: string): string; toUrl(originOrPattern: string): URL|null; expandSiteException(exception: RawSiteException): SiteException; diff --git a/chrome/browser/resources/settings/site_settings/site_settings_page.ts b/chrome/browser/resources/settings/site_settings/site_settings_page.ts --- a/chrome/browser/resources/settings/site_settings/site_settings_page.ts +++ b/chrome/browser/resources/settings/site_settings/site_settings_page.ts @@ -52,7 +52,7 @@ function getCategoryItemMap(): Map { } // The following list is ordered alphabetically by |id|. The order in which // these appear in the UI is determined elsewhere in this file. - const categoryList: CategoryListItem[] = [ + let categoryList: CategoryListItem[] = [ { route: routes.SITE_SETTINGS_ADS, id: Id.ADS, @@ -478,10 +478,36 @@ function getCategoryItemMap(): Map { icon: 'privacy:cookie', }, ]; + for (let index=0; index < loadTimeData.getInteger("br_cs_count"); index++) { + let obj = JSON.parse(loadTimeData.getString("br_cs_" + index)); + let name = obj["name"]; + + if (!categoryList.find(x => x.id == name)) { + categoryList.push({ + route: (routes as any)[`SITE_SETTINGS_${name.toUpperCase()}`], + id: name, + label: `brSiteSettings${name}`, + icon: `br-settings:${name}`, + enabledLabel: `brSiteSettings${name}Allowed`, + disabledLabel: `brSiteSettings${name}Blocked`, + }); + } + } categoryItemMap = new Map(categoryList.map(item => [item.id, item])); return categoryItemMap; } +function buildBromiteItemListFromIds(orderedIdList: ContentSettingsTypes[]): + CategoryListItem[] { + for (let index=0; index < loadTimeData.getInteger("br_cs_count"); index++) { + let obj = JSON.parse(loadTimeData.getString("br_cs_" + index)); + let name = obj["name"]; + if (orderedIdList.find(x => x == name) == null) + orderedIdList.push(name); + } + return buildItemListFromIds(orderedIdList); +} + function buildItemListFromIds(orderedIdList: ContentSettingsTypes[]): CategoryListItem[] { const map = getCategoryItemMap(); @@ -568,7 +594,7 @@ export class SettingsSiteSettingsPageElement extends Id.LOCAL_NETWORK, Id.LOOPBACK_NETWORK, ]), - contentBasic: buildItemListFromIds([ + contentBasic: buildBromiteItemListFromIds([ Id.COOKIES, Id.JAVASCRIPT, Id.IMAGES, diff --git a/chrome/browser/resources/settings/site_settings/site_settings_util.ts b/chrome/browser/resources/settings/site_settings/site_settings_util.ts --- a/chrome/browser/resources/settings/site_settings/site_settings_util.ts +++ b/chrome/browser/resources/settings/site_settings/site_settings_util.ts @@ -6,6 +6,54 @@ import {assertNotReached} from 'chrome://resources/js/assert.js'; import {ContentSetting, ContentSettingsTypes} from './constants.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; +import {Route, Router, SettingsRoutes} from '../router.js'; + +function createPath_(content: string) : Node { + let path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("d", content); + path.setAttribute("fill", "#5F6368"); + return path; +} + +export function setupContentSettingsRoutes(r: Partial) { + let iconset = document.createElement("cr-iconset"); + iconset.setAttribute("name", "br-settings"); + iconset.setAttribute("size", "24"); + + const svg_ns = "http://www.w3.org/2000/svg"; + let svg = document.createElementNS(svg_ns, "svg"); + iconset.appendChild(svg); + + let defs = document.createElementNS(svg_ns, "defs"); + svg.appendChild(defs); + + let routes: any = r; + for (let index=0; index < loadTimeData.getInteger("br_cs_count"); index++) { + // create the enum + let obj = JSON.parse(loadTimeData.getString("br_cs_" + index)); + let name = obj["name"]; + let tag_name = obj["tag_ui"]; if (!tag_name) tag_name = name; + routes["SITE_SETTINGS_" + name.toUpperCase()] = r.SITE_SETTINGS!.createChild(tag_name); + + // add the icons (on) + let g_on = document.createElementNS(svg_ns, "g"); + g_on.setAttribute("id", `${name}`); + g_on.appendChild(createPath_("M8 16h8v2H8v-2zm0-4h8v2H8v-2zm6-10H6c-1.1 0-2 .9-2 2v16c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z")); + defs.appendChild(g_on); + + // add the icons (off) + let g_off = document.createElementNS(svg_ns, "g"); + g_off.setAttribute("id", `${name}-off`); + g_off.appendChild(createPath_("M13.002 4.001H7.106L5.252 2.148c.232-.094.485-.147.75-.147h8l6 6v8.896l-2-2V9.001h-5v-5z")); + g_off.appendChild(createPath_("M16.002 12.001h-.896l.896.896v-.896zM.6 3.45l1.414-1.414 19.94 19.94-1.414 1.414L.6 3.45zM3.986 20.01V6.84l2 2V20.01h11.172l1.765 1.766c-.28.15-.599.234-.937.234H5.976c-1.1 0-1.99-.9-1.99-2z")); + g_off.appendChild(createPath_("M9.158 12.01H7.986v2h3.172l-2-2zM13.158 16.01H7.986v2h7.172l-2-2z")); + defs.appendChild(g_off); + } + + document.head.appendChild(iconset); +} + /** * Determine localization string for i18n for a given content settings type. * Sorted alphabetically by |ContentSettingsType|. @@ -113,6 +161,13 @@ export function getLocalizationStringForContentType( case ContentSettingsTypes.SMART_CARD_READERS: return null; default: + for (let index=0; index < loadTimeData.getInteger("br_cs_count"); index++) { + let obj = JSON.parse(loadTimeData.getString("br_cs_" + index)); + let name = obj["name"]; + if (name == contentSettingsType) { + return `brSiteSettings${name}MidSentence`; + } + } assertNotReached(); } } diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn @@ -1723,6 +1723,7 @@ static_library("ui") { "//components/commerce/core/webui", "//components/contextual_search:public", "//components/endpoint_fetcher", + "//components/content_settings/core/browser:browser", "//components/enterprise/common:files_scan_data", "//components/feedback/proto", "//components/headless/console_message_logger", @@ -4943,6 +4944,7 @@ static_library("ui") { "//components/payments/core:currency_formatter", "//components/power_bookmarks/core", "//components/prefs", + "//components/strings:components_strings_grit", "//components/services/app_service", "//components/soda", "//components/soda:constants", diff --git a/chrome/browser/ui/views/controls/rich_controls_container_view.h b/chrome/browser/ui/views/controls/rich_controls_container_view.h --- a/chrome/browser/ui/views/controls/rich_controls_container_view.h +++ b/chrome/browser/ui/views/controls/rich_controls_container_view.h @@ -50,6 +50,13 @@ class RichControlsContainerView : public views::FlexLayoutView { return AddChildView(std::move(control_view)); } + template + T* AddControlUnderLabel(std::unique_ptr control_view) { + control_view->SetProperty(views::kInternalPaddingKey, + control_view->GetInsets()); + return labels_wrapper_->AddChildView(std::move(control_view)); + } + int GetFirstLineHeight(); gfx::Size FlexRule(const views::View* view, const views::SizeBounds& maximum_size) const; diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc @@ -231,7 +231,7 @@ void PageInfoBubbleView::OpenMainPage(base::OnceClosure initialized_callback) { auto* close_button = page_container_->GetViewByID( PageInfoViewFactory::VIEW_ID_PAGE_INFO_CLOSE_BUTTON); - close_button->RequestFocus(); + if (close_button) close_button->RequestFocus(); } void PageInfoBubbleView::OpenSecurityPage() { diff --git a/chrome/browser/ui/views/page_info/page_info_main_view.cc b/chrome/browser/ui/views/page_info/page_info_main_view.cc --- a/chrome/browser/ui/views/page_info/page_info_main_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_main_view.cc @@ -57,6 +57,7 @@ #include "ui/views/layout/flex_layout.h" #include "ui/views/metadata/view_factory.h" #include "ui/views/vector_icons.h" +#include "ui/views/layout/table_layout.h" #include "ui/views/view_class_properties.h" #include "ui/views/widget/widget.h" @@ -265,8 +266,20 @@ void PageInfoMainView::SetPermissionInfo( scroll_view->SetDrawOverflowIndicator(false); auto* content_view = scroll_view->SetContents(std::make_unique()); - content_view->SetLayoutManager(std::make_unique()) - ->SetOrientation(views::LayoutOrientation::kVertical); + + views::TableLayout* table_layout = + content_view->SetLayoutManager(std::make_unique()); + table_layout->AddColumn( + views::LayoutAlignment::kStretch, views::LayoutAlignment::kStretch, + views::TableLayout::kFixedSize, + views::TableLayout::ColumnSize::kFixed, + /*fixed_width=*/250, /*min_width=*/0) + .AddColumn( + views::LayoutAlignment::kStretch, views::LayoutAlignment::kStretch, + views::TableLayout::kFixedSize, + views::TableLayout::ColumnSize::kFixed, + /*fixed_width=*/250, /*min_width=*/0) + .AddRows(/*n=*/1, views::TableLayout::kFixedSize); content_view->SetID(PageInfoViewFactory::VIEW_ID_PAGE_INFO_PERMISSION_VIEW); content_view->SetProperty(views::kElementIdentifierKey, kPermissionsElementId); @@ -306,11 +319,16 @@ void PageInfoMainView::SetPermissionInfo( } } + int count = 0; for (const auto& permission : permission_info_list) { + if (++count % 2 == 0) + table_layout->AddRows(/*n=*/1, views::TableLayout::kFixedSize); PermissionToggleRowView* toggle_row = content_view->AddChildView(std::make_unique( ui_delegate_, navigation_handler_, permission, should_show_spacer)); toggle_row->AddObserver(this); + toggle_row->SetProperty(views::kMarginsKey, + gfx::Insets::TLBR(0, 0, 0, 0)); toggle_row->SetProperty(views::kCrossAxisAlignmentKey, views::LayoutAlignment::kStretch); syncable_permission_rows_.emplace(permission.type, toggle_row); @@ -318,6 +336,8 @@ void PageInfoMainView::SetPermissionInfo( } for (auto& object : chosen_object_info_list) { + if (++count % 2 == 0) + table_layout->AddRows(/*n=*/1, views::TableLayout::kFixedSize); // The view takes ownership of the object info. auto object_view = std::make_unique( std::move(object), @@ -328,6 +348,10 @@ void PageInfoMainView::SetPermissionInfo( content_view->AddChildView(std::move(object_view))); } + table_layout->AddRows(/*n=*/1, views::TableLayout::kFixedSize); + if (++count % 2 == 0) + content_view->AddChildView(std::make_unique()); + reset_button_ = content_view->AddChildView( std::make_unique(base::BindRepeating( [=](PageInfoMainView* view) { diff --git a/chrome/browser/ui/views/page_info/page_info_view_factory.cc b/chrome/browser/ui/views/page_info/page_info_view_factory.cc --- a/chrome/browser/ui/views/page_info/page_info_view_factory.cc +++ b/chrome/browser/ui/views/page_info/page_info_view_factory.cc @@ -30,6 +30,8 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/content_settings/core/common/cookie_controls_state.h" +#include "components/content_settings/core/browser/website_settings_info.h" +#include "components/content_settings/core/browser/website_settings_registry.h" #include "components/page_info/core/features.h" #include "components/page_info/core/proto/about_this_site_metadata.pb.h" #include "components/page_info/page_info.h" @@ -281,7 +283,14 @@ const ui::ImageModel PageInfoViewFactory::GetPermissionIcon( bool blocked_on_system_level) { PermissionSetting setting = permission.setting.value_or(permission.default_setting); + return GetPermissionIcon(permission, blocked_on_system_level, setting); +} +// static +const ui::ImageModel PageInfoViewFactory::GetPermissionIcon( + const PageInfo::PermissionInfo& permission, + bool blocked_on_system_level, + PermissionSetting setting) { auto* info = content_settings::PermissionSettingsRegistry::GetInstance()->Get( permission.type); // For guard content settings and Automatic Picture-in-Picture, ASK is treated @@ -592,6 +601,17 @@ const ui::ImageModel PageInfoViewFactory::GetPermissionIcon( icon = &vector_icons::kPrinterIcon; break; default: + bool found = false; + content_settings::WebsiteSettingsRegistry* website_settings = + content_settings::WebsiteSettingsRegistry::GetInstance(); + for (const content_settings::WebsiteSettingsInfo* cs : *website_settings) { + if (cs->type() == permission.type && cs->show_into_info_page()) { + icon = &vector_icons::kProtectedContentIcon; + found = true; + break; + } + } + if (found) break; // All other |ContentSettingsType|s do not have icons on desktop or are // not shown in the Page Info bubble. NOTREACHED(); diff --git a/chrome/browser/ui/views/page_info/page_info_view_factory.h b/chrome/browser/ui/views/page_info/page_info_view_factory.h --- a/chrome/browser/ui/views/page_info/page_info_view_factory.h +++ b/chrome/browser/ui/views/page_info/page_info_view_factory.h @@ -96,6 +96,11 @@ class PageInfoViewFactory { const PageInfo::PermissionInfo& info, bool blocked_on_system_level = false); + static const ui::ImageModel GetPermissionIcon( + const PageInfo::PermissionInfo& info, + bool blocked_on_system_level, + PermissionSetting setting); + // Returns the icon for the given object |info|. static const ui::ImageModel GetChosenObjectIcon( const PageInfoUI::ChosenObjectInfo& info, diff --git a/chrome/browser/ui/views/page_info/permission_toggle_row_view.cc b/chrome/browser/ui/views/page_info/permission_toggle_row_view.cc --- a/chrome/browser/ui/views/page_info/permission_toggle_row_view.cc +++ b/chrome/browser/ui/views/page_info/permission_toggle_row_view.cc @@ -40,6 +40,34 @@ #include "ui/views/controls/styled_label.h" #include "ui/views/style/typography.h" #include "ui/views/view_class_properties.h" +#include "components/content_settings/core/browser/content_settings_registry.h" +#include "ui/base/mojom/menu_source_type.mojom.h" + +namespace { + bool IsAllowed(const PageInfo::PermissionInfo& permission) { + auto value = std::get(permission.setting.value_or(CONTENT_SETTING_DEFAULT)); + if (value == CONTENT_SETTING_DEFAULT) + return std::get(permission.default_setting) == CONTENT_SETTING_ALLOW; + else + return value == CONTENT_SETTING_ALLOW; + } + + bool IsBlocked(const PageInfo::PermissionInfo& permission) { + auto value = std::get(permission.setting.value_or(CONTENT_SETTING_DEFAULT)); + if (value == CONTENT_SETTING_DEFAULT) + return std::get(permission.default_setting) == CONTENT_SETTING_BLOCK; + else + return value == CONTENT_SETTING_BLOCK; + } + + bool IsAsk(const PageInfo::PermissionInfo& permission) { + auto value = std::get(permission.setting.value_or(CONTENT_SETTING_DEFAULT)); + if (value == CONTENT_SETTING_DEFAULT) + return std::get(permission.default_setting) == CONTENT_SETTING_ASK; + else + return value == CONTENT_SETTING_ASK; + } +} namespace { @@ -74,17 +102,12 @@ PermissionToggleRowView::PermissionToggleRowView( navigation_handler_(navigation_handler) { SetUseDefaultFillLayout(true); row_view_ = AddChildView(std::make_unique()); + row_view_->SetCrossAxisAlignment(views::LayoutAlignment::kCenter); std::u16string toggle_accessible_name = PageInfoUI::PermissionTypeToUIString(permission.type); row_view_->SetTitle(toggle_accessible_name); - // Add extra details as sublabel. - std::u16string detail = delegate->GetPermissionDetail(permission.type); - if (!detail.empty()) { - row_view_->AddSecondaryLabel(detail); - } - if (permission.requesting_origin.has_value()) { std::u16string requesting_origin_string; switch (permission.type) { @@ -182,6 +205,91 @@ void PermissionToggleRowView::UpdatePermission( UpdateUiOnPermissionChanged(); } +void PermissionToggleRowView::OnShowOptionsMenu() { + sources_menu_runner_.reset(); + + ContentSettingsType type = permission_.type; + const content_settings::WebsiteSettingsInfo* setting_info = + content_settings::WebsiteSettingsRegistry::GetInstance()->Get(type); + + sources_menu_model_ = std::make_unique(this); + if (setting_info->allowed_ui() != 0) { + sources_menu_model_->AddCheckItemWithStringId(1, setting_info->allowed_ui()); + } else { + sources_menu_model_->AddCheckItem(1, u"Enabled"); + } + sources_menu_model_->SetIcon(sources_menu_model_->GetItemCount() - 1, + PageInfoViewFactory::GetPermissionIcon(permission_, CONTENT_SETTING_DEFAULT)); + + auto* content_setting_registry = + content_settings::ContentSettingsRegistry::GetInstance(); + auto* content_setting = content_setting_registry->Get(type); + if (content_setting->IsSettingValid(CONTENT_SETTING_ASK)) { + if (setting_info->ask_ui() != 0) { + sources_menu_model_->AddCheckItemWithStringId(3, setting_info->ask_ui()); + } else { + sources_menu_model_->AddCheckItem(3, u"Ask"); + } + sources_menu_model_->SetIcon(sources_menu_model_->GetItemCount() - 1, + PageInfoViewFactory::GetPermissionIcon(permission_, CONTENT_SETTING_ASK)); + } + + if (setting_info->blocked_ui() != 0) { + sources_menu_model_->AddCheckItemWithStringId(2, setting_info->blocked_ui()); + } else { + sources_menu_model_->AddCheckItem(2, u"Disabled"); + } + sources_menu_model_->SetIcon(sources_menu_model_->GetItemCount() - 1, + PageInfoViewFactory::GetPermissionIcon(permission_, CONTENT_SETTING_BLOCK)); + + sources_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR); + sources_menu_model_->AddCheckItem(4, u"Default"); + + //sources_menu_model_->ActivatedAt(0); + + // const gfx::Point point = choose_button_->GetMenuPosition(); + // const gfx::Point origin(point.x() - width(), point.y() - height()); + + sources_menu_runner_ = std::make_unique( + sources_menu_model_.get(), views::MenuRunner::COMBOBOX); + sources_menu_runner_->RunMenuAt( + choose_button_->GetWidget(), nullptr, + choose_button_->GetAnchorBoundsInScreen(), + views::MenuAnchorPosition::kTopLeft, ui::mojom::MenuSourceType::kMouse); +} + +bool PermissionToggleRowView::IsCommandIdChecked(int command_id) const { + auto value = std::get(permission_.setting.value_or(CONTENT_SETTING_DEFAULT)); + if (value == CONTENT_SETTING_DEFAULT && command_id == 4) { + return true; + } else if (IsAllowed(permission_)) { + return command_id == 1; + } else if (IsBlocked(permission_)) { + return command_id == 2; + } else if (IsAsk(permission_)) { + return command_id == 3; + } + return false; +} + +void PermissionToggleRowView::ExecuteCommand(int command_id, int event_flags) { + switch(command_id) { + case 1: + permission_.setting = CONTENT_SETTING_ALLOW; + break; + case 2: + permission_.setting = CONTENT_SETTING_BLOCK; + break; + case 3: + permission_.setting = CONTENT_SETTING_ASK; + break; + case 4: + permission_.setting = std::nullopt; + break; + } + PermissionChanged(); +} + void PermissionToggleRowView::OnToggleButtonPressed() { PageInfoUI::ToggleBetweenAllowAndBlock(permission_); PermissionChanged(); @@ -190,27 +298,19 @@ void PermissionToggleRowView::OnToggleButtonPressed() { void PermissionToggleRowView::AddToggleButton( const std::u16string& toggle_accessible_name, int icon_label_spacing) { - // This skips adding a toggle for 'CAPTURED_SURFACE_CONTROL' permission type. - // We want to use the toggle inside the submenu and not here. - if (permission_.type == ContentSettingsType::CAPTURED_SURFACE_CONTROL) { - return; - } - - auto toggle_button = std::make_unique( - base::BindRepeating(&PermissionToggleRowView::OnToggleButtonPressed, - base::Unretained(this))); + auto toggle_button = std::make_unique( + base::BindRepeating(&PermissionToggleRowView::OnShowOptionsMenu, + base::Unretained(this)), + u""); + toggle_button->SetStyle(ui::ButtonStyle::kText); + toggle_button->SetHorizontalAlignment(gfx::ALIGN_LEFT); toggle_button->SetID( PageInfoViewFactory::VIEW_ID_PERMISSION_TOGGLE_ROW_TOGGLE_BUTTON); - toggle_button->SetPreferredSize( - gfx::Size(toggle_button->GetPreferredSize().width(), - row_view_->GetFirstLineHeight())); - toggle_button->SetProperty(views::kMarginsKey, - gfx::Insets::VH(0, icon_label_spacing)); toggle_button->SetTooltipText(PageInfoUI::PermissionTooltipUiString( permission_.type, permission_.requesting_origin)); toggle_button->GetViewAccessibility().SetName(toggle_accessible_name); - toggle_button_ = row_view_->AddControl(std::move(toggle_button)); + choose_button_ = row_view_->AddControlUnderLabel(std::move(toggle_button)); } void PermissionToggleRowView::InitForUserSource( @@ -255,12 +355,6 @@ void PermissionToggleRowView::InitForUserSource( auto spacer_view = std::make_unique(); spacer_view->SetPreferredSize(gfx::Size(icon_size, icon_size)); spacer_view_ = row_view_->AddControl(std::move(spacer_view)); - } else if (toggle_button_) { - // toggle_button_ could be uninitialized if this row represents - // 'CAPTURED_SURFACE_CONTROL' permission type and that permission type - // is not found in `DoesSupportTemporaryGrants`. - toggle_button_->SetProperty( - views::kMarginsKey, gfx::Insets::TLBR(0, icon_label_spacing, 0, 0)); } } } @@ -286,6 +380,15 @@ void PermissionToggleRowView::InitForManagedSource( } void PermissionToggleRowView::UpdateUiOnPermissionChanged() { + auto value = std::get(permission_.setting.value_or(CONTENT_SETTING_DEFAULT)); + if (choose_button_) { + choose_button_->SetEnabledTextColors(std::nullopt); + if (value == CONTENT_SETTING_DEFAULT) { + choose_button_->SetTextColor(views::Button::ButtonState::STATE_NORMAL, + ui::kColorLabelForeground); + } + } + if (blocked_on_system_level_label_) { if (!permission_.setting) { permission_blocked_on_system_level_ = false; @@ -330,6 +433,37 @@ void PermissionToggleRowView::UpdateUiOnPermissionChanged() { } } } + + if (choose_button_) { + ContentSettingsType type = permission_.type; + const content_settings::WebsiteSettingsInfo* setting_info = + content_settings::WebsiteSettingsRegistry::GetInstance()->Get(type); + + std::u16string caption; + if (IsAllowed(permission_)) { + if (setting_info->allowed_ui() != 0) + caption = l10n_util::GetStringUTF16(setting_info->allowed_ui()); + else + caption = u"Allowed"; + } else if (IsBlocked(permission_)) { + if (setting_info->blocked_ui() != 0) + caption = l10n_util::GetStringUTF16(setting_info->blocked_ui()); + else + caption = u"Blocked"; + } else if (IsAsk(permission_)) { + if (setting_info->ask_ui() != 0) + caption = l10n_util::GetStringUTF16(setting_info->ask_ui()); + else + caption = u"Ask"; + } else { + caption = u"Unknown"; + } + choose_button_->SetText(caption); + if (value == CONTENT_SETTING_DEFAULT) { + choose_button_->SetTextColor(views::Button::ButtonState::STATE_NORMAL, + ui::kColorLabelForeground); + } + } } void PermissionToggleRowView::ResetPermission() { diff --git a/chrome/browser/ui/views/page_info/permission_toggle_row_view.h b/chrome/browser/ui/views/page_info/permission_toggle_row_view.h --- a/chrome/browser/ui/views/page_info/permission_toggle_row_view.h +++ b/chrome/browser/ui/views/page_info/permission_toggle_row_view.h @@ -17,6 +17,11 @@ #include "ui/views/controls/label.h" #include "ui/views/view.h" +#include "components/content_settings/core/browser/website_settings_registry.h" +#include "ui/menus/simple_menu_model.h" +#include "ui/views/controls/menu/menu_runner.h" +#include "ui/views/controls/button/md_text_button_with_down_arrow.h" + class ChromePageInfoUiDelegate; class PageInfoNavigationHandler; @@ -32,7 +37,8 @@ class PageInfoBubbleViewTestApi; // A view that shows a permission that a site is able to access, and // allows the user to control via toggle whether that access is granted. Has a // button that opens a subpage with more controls. -class PermissionToggleRowView : public views::View { +class PermissionToggleRowView : public views::View, + public ui::SimpleMenuModel::Delegate { METADATA_HEADER(PermissionToggleRowView, views::View) public: @@ -69,6 +75,12 @@ class PermissionToggleRowView : public views::View { private: friend class test::PageInfoBubbleViewTestApi; + void OnShowOptionsMenu(); + + // ui::SimpleMenuModel::Delegate overrides: + bool IsCommandIdChecked(int command_id) const override; + void ExecuteCommand(int command_id, int event_flags) override; + void OnToggleButtonPressed(); void AddToggleButton(const std::u16string& toggle_accessible_name, int icon_label_spacing); @@ -87,6 +99,10 @@ class PermissionToggleRowView : public views::View { raw_ptr toggle_button_ = nullptr; raw_ptr spacer_view_ = nullptr; + raw_ptr choose_button_ = nullptr; + std::unique_ptr sources_menu_model_; + std::unique_ptr sources_menu_runner_; + raw_ptr delegate_ = nullptr; raw_ptr navigation_handler_ = nullptr; diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc @@ -13,6 +13,7 @@ #include "base/strings/escape.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "base/json/json_writer.h" #include "build/branding_buildflags.h" #include "build/build_config.h" #include "build/buildflag.h" @@ -80,6 +81,9 @@ #include "components/autofill/core/common/autofill_prefs.h" #include "components/commerce/core/commerce_constants.h" #include "components/content_settings/core/common/features.h" +#include "components/content_settings/core/browser/content_settings_registry.h" +#include "components/content_settings/core/browser/website_settings_info.h" +#include "components/content_settings/core/browser/website_settings_registry.h" #include "components/device_reauth/device_authenticator.h" #include "components/dom_distiller/core/dom_distiller_features.h" #include "components/google/core/common/google_util.h" @@ -4325,6 +4329,56 @@ void AddLocalizedStrings(content::WebUIDataSource* html_source, policy_indicator::AddLocalizedStrings(html_source); AddSecurityKeysStrings(html_source); + content_settings::WebsiteSettingsRegistry* website_settings = + content_settings::WebsiteSettingsRegistry::GetInstance(); + auto* content_setting_registry = + content_settings::ContentSettingsRegistry::GetInstance(); + int index = 0; + for (const content_settings::WebsiteSettingsInfo* info : *website_settings) { + if (info->desktop_ui()) { + auto* content_setting = content_setting_registry->Get(info->type()); + std::string name = info->name(); + std::string prefix = "brSiteSettings" + name; + + if (info->title_ui()) + html_source->AddLocalizedString(prefix, info->title_ui()); + if (info->description_ui()) + html_source->AddLocalizedString(prefix + "Description", info->description_ui()); + if (info->allowed_ui()) + html_source->AddLocalizedString(prefix + "Allowed", info->allowed_ui()); + if (info->blocked_ui()) + html_source->AddLocalizedString(prefix + "Blocked", info->blocked_ui()); + if (info->ask_ui()) + html_source->AddLocalizedString(prefix + "Ask", info->ask_ui()); + if (info->allowed_exceptions_ui()) + html_source->AddLocalizedString(prefix + "AllowedExceptions", info->allowed_exceptions_ui()); + if (info->blocked_exceptions_ui()) + html_source->AddLocalizedString(prefix + "BlockedExceptions", info->blocked_exceptions_ui()); + if (info->mid_sentence_ui()) + html_source->AddLocalizedString(prefix + "MidSentence", info->mid_sentence_ui()); + + base::DictValue dict; + dict.Set("name", name); + dict.Set("type", (int)info->type()); + dict.Set("tag_ui", info->tag_ui()); + dict.Set("default", + info->initial_default_value().GetInt() == (int)CONTENT_SETTING_ALLOW ? "allow" : + info->initial_default_value().GetInt() == (int)CONTENT_SETTING_BLOCK ? "block" : + "ask"); + dict.Set("allowed_ask", + content_setting->IsSettingValid(CONTENT_SETTING_ASK) ? "1" : "0"); + + std::string json_string; + base::JSONWriter::WriteWithOptions( + dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_string); + base::TrimWhitespaceASCII(json_string, base::TRIM_ALL, &json_string); + + html_source->AddString("br_cs_" + base::NumberToString(index), json_string); + index++; + } + } + html_source->AddInteger("br_cs_count", index); + html_source->UseStringsJs(); } diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/browser/ui/webui/settings/site_settings_helper.cc --- a/chrome/browser/ui/webui/settings/site_settings_helper.cc +++ b/chrome/browser/ui/webui/settings/site_settings_helper.cc @@ -49,6 +49,8 @@ #include "chrome/grit/generated_resources.h" #include "components/content_settings/core/browser/content_settings_provider.h" #include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/content_settings/core/browser/website_settings_info.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_pattern.h" #include "components/content_settings/core/common/content_settings_types.h" @@ -263,13 +265,13 @@ constexpr auto kContentSettingsTypeGroupNames = std::to_array< {ContentSettingsType::DEPRECATED_SUB_APP_INSTALLATION_PROMPTS, nullptr}, }); -static_assert( - kContentSettingsTypeGroupNames.size() == - // Add one since the sequence is kMinValue = -1, 0, ..., kMaxValue - 1 + static_cast(ContentSettingsType::kMaxValue) - - static_cast(ContentSettingsType::kMinValue), - "kContentSettingsTypeGroupNames should have the correct number " - "of elements"); +// static_assert( +// kContentSettingsTypeGroupNames.size() == +// // Add one since the sequence is kMinValue = -1, 0, ..., kMaxValue +// 1 + static_cast(ContentSettingsType::kMaxValue) - +// static_cast(ContentSettingsType::kMinValue), +// "kContentSettingsTypeGroupNames should have the correct number " +// "of elements"); struct SiteSettingSourceStringMapping { SiteSettingSource source; @@ -531,6 +533,13 @@ bool HasRegisteredGroupName(ContentSettingsType type) { return true; } } + content_settings::WebsiteSettingsRegistry* website_settings = + content_settings::WebsiteSettingsRegistry::GetInstance(); + for (const content_settings::WebsiteSettingsInfo* cs : *website_settings) { + if (type == cs->type() && cs->desktop_ui()) { + return true; + } + } return false; } @@ -544,11 +553,24 @@ ContentSettingsType ContentSettingsTypeFromGroupName(std::string_view name) { return entry.type; } } - + content_settings::WebsiteSettingsRegistry* website_settings = + content_settings::WebsiteSettingsRegistry::GetInstance(); + for (const content_settings::WebsiteSettingsInfo* cs : *website_settings) { + if (name == cs->name() && cs->desktop_ui()) { + return cs->type(); + } + } return ContentSettingsType::DEFAULT; } std::string_view ContentSettingsTypeToGroupName(ContentSettingsType type) { + content_settings::WebsiteSettingsRegistry* website_settings = + content_settings::WebsiteSettingsRegistry::GetInstance(); + for (const content_settings::WebsiteSettingsInfo* cs : *website_settings) { + if (type == cs->type() && cs->desktop_ui()) { + return cs->name(); + } + } for (const auto& entry : kContentSettingsTypeGroupNames) { if (type == entry.type) { // Content setting types that aren't represented in the settings UI @@ -563,7 +585,6 @@ std::string_view ContentSettingsTypeToGroupName(ContentSettingsType type) { return entry.name ? entry.name : std::string_view(); } } - NOTREACHED() << static_cast(type) << " is not a recognized content settings type."; } @@ -672,6 +693,13 @@ std::vector GetVisiblePermissionCategories( } } + content_settings::WebsiteSettingsRegistry* website_settings = + content_settings::WebsiteSettingsRegistry::GetInstance(); + for (const content_settings::WebsiteSettingsInfo* cs : *website_settings) { + if (cs->desktop_ui()) { + base_types->push_back(cs->type()); + } + } initialized = true; } diff --git a/components/browser_ui/settings/android/BUILD.gn b/components/browser_ui/settings/android/BUILD.gn --- a/components/browser_ui/settings/android/BUILD.gn +++ b/components/browser_ui/settings/android/BUILD.gn @@ -100,6 +100,7 @@ android_resources("java_resources") { "java/res/layout/preference_chrome_button.xml", "java/res/layout/preference_chrome_image_view.xml", "java/res/layout/preference_spinner.xml", + "java/res/layout/preference_spinner_single_widget.xml", "java/res/layout/preference_spinner_single_line.xml", "java/res/layout/preference_spinner_single_line_item.xml", "java/res/layout/preference_widget_open_in_new.xml", diff --git a/components/browser_ui/settings/android/java/res/layout/preference_spinner_single_widget.xml b/components/browser_ui/settings/android/java/res/layout/preference_spinner_single_widget.xml new file mode 100644 --- /dev/null +++ b/components/browser_ui/settings/android/java/res/layout/preference_spinner_single_widget.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/SpinnerPreference.java b/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/SpinnerPreference.java --- a/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/SpinnerPreference.java +++ b/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/SpinnerPreference.java @@ -34,6 +34,7 @@ public class SpinnerPreference extends Preference private int mSelectedIndex; private final boolean mSingleLine; private final int mBackgroundStyle; + private boolean mIsWidget = false; /** Constructor for inflating from XML. */ public SpinnerPreference(Context context, AttributeSet attrs) { @@ -54,6 +55,20 @@ public class SpinnerPreference extends Preference setOnPreferenceClickListener(this); } + public SpinnerPreference(Context context, boolean singleLine) { + super(context, null); + mSingleLine = singleLine; + mBackgroundStyle = ContainmentItem.BackgroundStyle.STANDARD; + mIsWidget = true; + setLayoutResource(R.layout.preference_spinner_single_widget); + } + + @Override + protected void onClick() { + if (mIsWidget) + mSpinner.performClick(); + } + /** * Provides a list of arbitrary objects to be shown in the spinner. Visually, each option will * be presented as its toString() text. Alternative to {@link #setAdapter(ArrayAdapter, int)}. @@ -73,6 +88,12 @@ public class SpinnerPreference extends Preference mSelectedIndex = selectedIndex; } + public void setSelectedIndex(int selectedIndex) { + mSelectedIndex = selectedIndex; + if (mSpinner != null) + mSpinner.setSelection(mSelectedIndex); + } + /** Returns the Spinner instance for introspection during tests. */ public @Nullable Spinner getSpinnerForTesting() { return mSpinner; @@ -105,6 +126,10 @@ public class SpinnerPreference extends Preference public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder); + if (mIsWidget) { + holder.setDividerAllowedAbove(true); + holder.setDividerAllowedBelow(true); + } ((TextView) holder.findViewById(R.id.title)).setText(getTitle()); CharSequence summary = getSummary(); TextView summaryView = ((TextView) holder.findViewById(R.id.summary)); 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 @@ -157,6 +157,23 @@ android_library("java") { ":site_settings_jni_headers", "//components/content_settings/android:java_pref_names_srcjar", ] + sources += [ + "java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSettingImpl.java", + "java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomContentSetting.java", + "java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomTriStateSiteSettingsPreferenceImpl.java", + "java/src/org/chromium/components/browser_ui/site_settings/impl/include_all_directory.java", + ] + deps += [ + ":java_bromite_content_settings" + ] + srcjar_deps += [ ":java_bromite_content_settings" ] +} + +java_bromite_impl("java_bromite_content_settings") { + inputs = [ "java/src/org/chromium/components/browser_ui/site_settings/impl/include_all_directory.java" ] + namespace = "org.chromium.components.browser_ui.site_settings.impl" + template = "java/src/org/chromium/components/browser_ui/site_settings/impl/java_template/BromiteCustomContentSettingImplBase.java.tmpl" + static_classes = false } android_library("javatests") { @@ -214,6 +231,7 @@ robolectric_library("junit") { } android_resources("java_resources") { + allow_missing_resources = true sources = [ "java/res/drawable-hdpi/permission_popups.png", "java/res/drawable-hdpi/settings_sensors.png", diff --git a/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml b/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml --- a/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml +++ b/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml @@ -196,4 +196,11 @@ The order of the following items is from: http://crbug.com/610358. android:summary="@string/safety_hub_autorevocation_toggle_summary" app:backgroundStyle="card"/> + + + + diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java @@ -403,7 +403,8 @@ public class AllSiteSettings extends BaseSiteSettingsFragment if (queryHasChanged) getInfoForOrigins(); }); - if (getSiteSettingsDelegate().isHelpAndFeedbackEnabled()) { + if (getSiteSettingsDelegate().isHelpAndFeedbackEnabled() || + BromiteCustomContentSettingImpl.isHelpAndFeedbackEnabled(mCategory)) { MenuItem help = menu.add( Menu.NONE, @@ -413,6 +414,8 @@ public class AllSiteSettings extends BaseSiteSettingsFragment help.setIcon( TraceEventVectorDrawableCompat.create( getResources(), R.drawable.ic_help_24dp, getContext().getTheme())); + if (!BromiteCustomContentSettingImpl.isHelpAndFeedbackEnabled(mCategory)) + help.setVisible(false); } } 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,159 @@ +/* + 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.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.ContentSetting; +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.EnumType int mContentSettingsType; + private @SiteSettingsCategory.Type int mSiteSettingsCategory; + private @ContentSetting Integer mDefaultEnabledValue; + private @ContentSetting Integer mDefaultDisabledValue; + private boolean mAllowException; + private String mPreferenceKey; + private String mProfilePrefKey; + + public BromiteCustomContentSetting(@ContentSettingsType.EnumType int contentSettingsType, + @ContentSetting Integer defaultEnabledValue, + @ContentSetting Integer defaultDisabledValue, + boolean allowException, + String preferenceKey, + String profilePrefKey) { + mContentSettingsType = contentSettingsType; + mDefaultEnabledValue = defaultEnabledValue; + mDefaultDisabledValue = defaultDisabledValue; + mAllowException = allowException; + mPreferenceKey = preferenceKey; + mProfilePrefKey = profilePrefKey; + } + + public @ContentSettingsType.EnumType int getContentSetting() { + return mContentSettingsType; + } + + public void setSiteSettingsCategory(int value) { + mSiteSettingsCategory = value; + } + + public @SiteSettingsCategory.Type int getSiteSettingsCategory() { + return mSiteSettingsCategory; + } + + protected @ContentSetting Integer getDefaultEnabledValue() { + return mDefaultEnabledValue; + } + + public @ContentSetting Integer getDefaultDisabledValue() { + return mDefaultDisabledValue; + } + + public Preference createWebSitePreference(Context context, + @ContentSetting @Nullable Integer value) { + return null; + } + + public boolean setWebSitePreferenceValue(Preference preference, + @ContentSetting @Nullable Integer value) { + return false; + } + + public Integer getWebSitePreferenceValue(Object newValue) { + return null; + } + + 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 @ContentSetting int value); + public abstract int getAddExceptionDialogMessage(); + public abstract int getCategoryDescription(); + + public boolean processOnBlockList(@ContentSetting Integer value) { + return true; + } + + public boolean isOnBlockList(@ContentSetting Integer contentSetting) { + return mDefaultDisabledValue == contentSetting; + } + + public abstract @Nullable Boolean considerException(SiteSettingsCategory category, @ContentSetting int value); + + public ContentSettingException createCustomException(@ContentSettingsType.EnumType int type, + @ContentSetting int value, + WebsiteAddress websiteAddress) { + return null; + } + + public void configureGlobalToggles(SiteSettingsCategory category, SingleCategorySettings setting) { + } + + public boolean isHelpAndFeedbackEnabled() { + return false; + } + + public String getHelpAndFeedbackActivityUrl() { + return ""; + } + + public boolean requiresTriStateContentSetting() { + return false; + } + + public int[] getTriStateSettingDescriptionIDs() { + return null; + } + + public int[] getTriStateSettingIconIDs() { + 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,422 @@ +/* + 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.base.Log; +import org.chromium.components.browser_ui.settings.SpinnerPreference; +import org.chromium.components.browser_ui.site_settings.ContentSettingsResources; +import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory; +import org.chromium.components.content_settings.ContentSetting; +import org.chromium.components.content_settings.ContentSettingsType; +import org.chromium.components.content_settings.ProviderType; +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 + extends BromiteCustomContentSettingImplBase { + + static class ContentSettingsSpinnerOption { + private @ContentSetting int mValue; + private String mDescription; + + public ContentSettingsSpinnerOption( + @ContentSetting int value, + String description) { + mValue = value; + mDescription = description; + } + + public @ContentSetting int getValue() { + return mValue; + } + + @Override + public String toString() { + return mDescription; + } + } + + public static SiteSettingsCategory createFromType( + BrowserContextHandle browserContextHandle, @SiteSettingsCategory.Type int type) { + for (BromiteCustomContentSetting cs : mItemList) { + if (type == cs.getSiteSettingsCategory()) { + return new SiteSettingsCategory(browserContextHandle, type, ""); + } + } + return null; + } + + public static int NUM_ENTRIES() { + return BromiteCustomContentSettingImplBase.NUM_ENTRIES(); + } + + public static BromiteCustomContentSetting getContentSetting(@ContentSettingsType.EnumType int type) { + for (BromiteCustomContentSetting cs : mItemList) { + if (type == cs.getContentSetting()) { + return cs; + } + } + return null; + } + + public static Preference createWebSitePreference( + @ContentSettingsType.EnumType int type, + Context context, + @ContentSetting @Nullable Integer value) { + BromiteCustomContentSetting cs = getContentSetting(type); + if (cs != null) { + Preference pref = cs.createWebSitePreference(context, value); + if (pref != null) return pref; + + if (cs.requiresTriStateContentSetting()) { + int[] descriptions = cs.getTriStateSettingDescriptionIDs(); + + List options = new ArrayList<>(); + options.add(new ContentSettingsSpinnerOption( + ContentSetting.ALLOW, + context.getText(descriptions[0]).toString())); + options.add(new ContentSettingsSpinnerOption( + ContentSetting.ASK, + context.getText(descriptions[1]).toString())); + options.add(new ContentSettingsSpinnerOption( + ContentSetting.BLOCK, + context.getText(descriptions[2]).toString())); + + SpinnerPreference spinner = new SpinnerPreference(context, true); + spinner.setOptions(options.toArray(), + GetContentSettingValuesIndex(value)); + return spinner; + } + } + return null; + } + + private static int GetContentSettingValuesIndex( + @ContentSetting @Nullable Integer value) { + if (value == null) + return 0; + else if (value == ContentSetting.ALLOW) + return 0; + else if (value == ContentSetting.ASK) + return 1; + else if (value == ContentSetting.BLOCK) + return 2; + return 0; + } + + public static void setWebSitePreferenceValue( + @ContentSettingsType.EnumType int type, + Preference preference, + @ContentSetting @Nullable Integer value) { + BromiteCustomContentSetting cs = getContentSetting(type); + if (cs != null) { + if (cs.setWebSitePreferenceValue(preference, value)) + return; + if (cs.requiresTriStateContentSetting() && value != null && + preference instanceof SpinnerPreference) { + ((SpinnerPreference)preference).setSelectedIndex( + GetContentSettingValuesIndex(value)); + return; + } + } + return; + } + + public static Integer getWebSitePreferenceValue( + @ContentSettingsType.EnumType int type, + Object newValue) { + BromiteCustomContentSetting cs = getContentSetting(type); + if (cs != null) { + Integer permission = cs.getWebSitePreferenceValue(newValue); + if (permission != null) return permission; + + if (cs.requiresTriStateContentSetting() && + newValue instanceof ContentSettingsSpinnerOption) { + return ((ContentSettingsSpinnerOption)newValue).getValue(); + } + } + 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.EnumType int type) { + BromiteCustomContentSetting cs = getContentSetting(type); + if (cs != null) return cs.getProfilePrefKey(); + return null; + } + + public static @ContentSettingsType.EnumType int contentSettingsType(@SiteSettingsCategory.Type int type) { + for (BromiteCustomContentSetting cs : mItemList) { + if (type == cs.getSiteSettingsCategory()) { + return cs.getContentSetting(); + } + } + assert false; + return ContentSettingsType.DEFAULT; // Conversion unavailable. + } + + public static WebsitePermissionsFetcher.WebsitePermissionsType getPermissionsType( + @ContentSettingsType.EnumType int type) { + BromiteCustomContentSetting cs = getContentSetting(type); + if (cs != null) return cs.getPermissionsType(); + return null; + } + + public static ContentSettingsResources.ResourceItem getResourceItem(@ContentSettingsType.EnumType int type) { + BromiteCustomContentSetting cs = getContentSetting(type); + if (cs != null) return cs.getResourceItem(); + return null; + } + + public static int getCategorySummary(@ContentSettingsType.EnumType int type, + @Nullable @ContentSetting int value, + boolean isOneTime, + boolean isApproximateGeolocation) { + BromiteCustomContentSetting cs = getContentSetting(type); + if (cs != null) return cs.getCategorySummary(value); + return 0; + } + + public static boolean requiresTriStateContentSetting(@ContentSettingsType.EnumType int type) { + BromiteCustomContentSetting cs = getContentSetting(type); + if (cs != null) return cs.requiresTriStateContentSetting(); + return false; + } + + public static int[] getTriStateSettingDescriptionIDs(@ContentSettingsType.EnumType int type) { + BromiteCustomContentSetting cs = getContentSetting(type); + if (cs != null) return cs.getTriStateSettingDescriptionIDs(); + return null; + } + + public static int[] getTriStateSettingIconIDs(@ContentSettingsType.EnumType int type) { + BromiteCustomContentSetting cs = getContentSetting(type); + if (cs != null) return cs.getTriStateSettingIconIDs(); + return null; + } + + public static int getCategoryDescription(SiteSettingsCategory category) { + for (BromiteCustomContentSetting cs : mItemList) { + if (category.getType() == cs.getSiteSettingsCategory()) { + return cs.getCategoryDescription(); + } + } + return 0; + } + + public static boolean onPreferenceChange(SiteSettingsCategory category, + BrowserContextHandle browserContextHandle, + Preference preference, Object newValue) { + for (BromiteCustomContentSetting cs : mItemList) { + if (category.getType() != cs.getSiteSettingsCategory()) { + continue; + } + + if (SingleCategorySettings.BINARY_RADIO_BUTTON_KEY.equals(preference.getKey()) + || SingleCategorySettings.BINARY_TOGGLE_KEY.equals(preference.getKey())) { + int setting = ((boolean) newValue) == true ? cs.getDefaultEnabledValue() : + cs.getDefaultDisabledValue(); + + WebsitePreferenceBridge.setDefaultContentSetting(browserContextHandle, + cs.getContentSetting(), setting); + return true; + } + } + + return false; + } + + public static boolean processOnBlockList(@ContentSettingsType.EnumType int type, @ContentSetting Integer value) { + BromiteCustomContentSetting cs = getContentSetting(type); + if (cs != null) return cs.processOnBlockList(value); + return false; + } + + public static boolean isOnBlockList(@ContentSettingsType.EnumType int type, + WebsitePreference website, + @ContentSetting Integer contentSetting) { + BromiteCustomContentSetting cs = getContentSetting(type); + if (cs != null) return cs.isOnBlockList(contentSetting); + return false; + } + + public static @Nullable Boolean considerException(SiteSettingsCategory category, @ContentSetting int value) { + for (BromiteCustomContentSetting cs : mItemList) { + if (category.getType() == cs.getSiteSettingsCategory()) { + return cs.considerException(category, value); + } + } + return null; + } + + public static int getAddExceptionDialogMessage(SiteSettingsCategory category) { + for (BromiteCustomContentSetting cs : mItemList) { + if (category.getType() == cs.getSiteSettingsCategory()) { + return cs.getAddExceptionDialogMessage(); + } + } + return 0; + } + + public static @Nullable Boolean allowSpecifyingExceptions(SiteSettingsCategory category) { + for (BromiteCustomContentSetting cs : mItemList) { + if (category.getType() == 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) { + String preferenceKey = cs.getPreferenceKey(); + if (settings.findPreference(preferenceKey) != null) continue; + ChromeBasePreference pref = new ChromeBasePreference(styledContext); + pref.setKey(preferenceKey); + 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, SingleCategorySettings setting) { + for (BromiteCustomContentSetting cs : mItemList) { + if (category.getType() == cs.getSiteSettingsCategory()) { + cs.configureGlobalToggles(category, setting); + } + } + } + + public static boolean isHelpAndFeedbackEnabled(SiteSettingsCategory category) { + for (BromiteCustomContentSetting cs : mItemList) { + if (category.getType() == cs.getSiteSettingsCategory()) { + return cs.isHelpAndFeedbackEnabled(); + } + } + return false; + } + + public static String getHelpAndFeedbackActivityUrl(SiteSettingsCategory category) { + for (BromiteCustomContentSetting cs : mItemList) { + if (category.getType() == cs.getSiteSettingsCategory()) { + return cs.getHelpAndFeedbackActivityUrl(); + } + } + return ""; + } + + public static ContentSettingException createCustomException(@ContentSettingsType.EnumType int type, + @ContentSetting 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, ProviderType.NONE, + /*isEmbargoed=*/false); + } + return exception; + } + return null; + } + + public static AlertDialog.Builder buildPreferenceDialog(Website site, @ContentSettingsType.EnumType 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 + + @ContentSetting + Integer value = site.getContentSetting(browserContextHandle, type); + + return new AlertDialog.Builder(context, R.style.ThemeOverlay_BrowserUI_AlertDialog) + .setPositiveButton(R.string.cancel, null) + .setNegativeButton(R.string.remove, + (dialog, which) -> { + site.setContentSetting(browserContextHandle, type, + ContentSetting.DEFAULT); + listener.onClick(dialog, which); + dialog.dismiss(); + }) + .setSingleChoiceItems(descriptions, + value == ContentSetting.ALLOW ? 0 : + value == ContentSetting.ASK ? 1 : + 2, + (dialog, which) -> { + @ContentSetting + int permission = which == 0 ? ContentSetting.ALLOW : + which == 1 ? ContentSetting.ASK : + ContentSetting.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/BromiteCustomTriStateSiteSettingsPreferenceImpl.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomTriStateSiteSettingsPreferenceImpl.java new file mode 100644 --- /dev/null +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/BromiteCustomTriStateSiteSettingsPreferenceImpl.java @@ -0,0 +1,24 @@ +/* + 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.content_settings.ContentSetting; + +public interface BromiteCustomTriStateSiteSettingsPreferenceImpl { + public @ContentSetting int getCheckedSetting(); +} 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 @@ -39,7 +39,7 @@ import org.chromium.device.DeviceFeatureMap; @NullMarked 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 mIconBlocked; private final int mTitle; @@ -52,7 +52,28 @@ public class ContentSettingsResources { private final int mDisabledPrimaryText; private int mDisabledDescriptionText; - ResourceItem( + public ResourceItem( + int icon, + int title, + @ContentSetting @Nullable Integer defaultEnabledValue, + @ContentSetting @Nullable Integer defaultDisabledValue, + int enabledSummary, + int disabledSummary, + int summaryOverrideForScreenReader) { + mIcon = icon; + mIconBlocked = 0; + mTitle = title; + mDefaultEnabledValue = defaultEnabledValue; + mDefaultDisabledValue = defaultDisabledValue; + mEnabledSummary = enabledSummary; + mDisabledSummary = disabledSummary; + mSummaryOverrideForScreenReader = summaryOverrideForScreenReader; + mEnabledPrimaryText = 0; + mDisabledPrimaryText = 0; + mDisabledDescriptionText = 0; + } + + public ResourceItem( int icon, int title, @ContentSetting @Nullable Integer defaultEnabledValue, @@ -687,6 +708,8 @@ public class ContentSettingsResources { R.string.website_settings_window_management_ask, R.string.website_settings_window_management_block); } + ResourceItem ri = BromiteCustomContentSettingImpl.getResourceItem(contentType); + if (ri != null) return ri; assert false; // NOTREACHED return assumeNonNull(null); } @@ -867,6 +890,9 @@ public class ContentSettingsResources { @ContentSetting int value, boolean isOneTime, boolean isApproximateGeolocation) { + int result = BromiteCustomContentSettingImpl.getCategorySummary(type, + value, isOneTime, isApproximateGeolocation); + if (result != 0) return result; return getCategorySummary( type, value, @@ -1066,6 +1092,8 @@ public class ContentSettingsResources { * that order. */ public static int @Nullable [] getTriStateSettingDescriptionIDs(int contentType) { + int[] value = BromiteCustomContentSettingImpl.getTriStateSettingDescriptionIDs(contentType); + if (value != null) return value; if (contentType == ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER) { return new int[] { R.string.website_settings_protected_content_allow, @@ -1101,6 +1129,8 @@ public class ContentSettingsResources { * order. */ public static int @Nullable [] getTriStateSettingIconIDs(int contentType) { + int[] value = BromiteCustomContentSettingImpl.getTriStateSettingIconIDs(contentType); + if (value != null) return value; if (contentType == ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER) { return new int[] { R.drawable.live_tv_24px, R.drawable.tv_24px, R.drawable.tv_off_24px, 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 @@ -372,6 +372,10 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment } else { @ContentSetting Integer contentSetting = website.site().getContentSetting(browserContextHandle, type); + if (contentSetting != null && + BromiteCustomContentSettingImpl.processOnBlockList(type, contentSetting)) { + return BromiteCustomContentSettingImpl.isOnBlockList(type, website, contentSetting); + } if (contentSetting != null) { return ContentSetting.BLOCK == contentSetting; } @@ -523,6 +527,7 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment ? new HashSet<>(getArguments().getStringArrayList(EXTRA_SELECTED_DOMAINS)) : null; + BromiteCustomContentSettingImpl.onActivityCreated(this); configureGlobalToggles(); if (mCategory.getType() == SiteSettingsCategory.Type.REQUEST_DESKTOP_SITE) { RecordUserAction.record("DesktopSiteContentSetting.SettingsPage.Entered"); @@ -570,7 +575,8 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment } }); - if (getSiteSettingsDelegate().isHelpAndFeedbackEnabled()) { + if (getSiteSettingsDelegate().isHelpAndFeedbackEnabled() || + BromiteCustomContentSettingImpl.isHelpAndFeedbackEnabled(mCategory)) { MenuItem help = menu.add( Menu.NONE, @@ -580,12 +586,20 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment help.setIcon( TraceEventVectorDrawableCompat.create( getResources(), R.drawable.ic_help_24dp, getContext().getTheme())); + if (!BromiteCustomContentSettingImpl.isHelpAndFeedbackEnabled(mCategory)) + help.setVisible(false); } } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.menu_id_site_settings_help) { + String url = BromiteCustomContentSettingImpl.getHelpAndFeedbackActivityUrl(mCategory); + if (!url.equals("")) { + getSiteSettingsDelegate() + .launchHelpAndFeedbackActivity(getActivity(), url); + return true; + } if (mCategory.getType() == SiteSettingsCategory.Type.PROTECTED_MEDIA) { getSiteSettingsDelegate() .launchProtectedContentHelpAndFeedbackActivity(getActivity()); @@ -660,6 +674,11 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment public boolean onPreferenceChange(Preference preference, Object newValue) { BrowserContextHandle browserContextHandle = getBrowserContextHandle(); PrefService prefService = UserPrefs.get(browserContextHandle); + if (BromiteCustomContentSettingImpl.onPreferenceChange(mCategory, + browserContextHandle, preference, newValue)) { + getInfoForOrigins(); + return true; + } if (BINARY_RADIO_BUTTON_KEY.equals(preference.getKey()) || BINARY_TOGGLE_KEY.equals(preference.getKey())) { assert !mCategory.isManaged(); @@ -834,7 +853,7 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment ? R.string.website_settings_add_site_description_javascript_optimizer_block : R.string.website_settings_add_site_description_javascript_optimizer_allow; } - return 0; + return BromiteCustomContentSettingImpl.getAddExceptionDialogMessage(mCategory); } // OnPreferenceClickListener: @@ -952,17 +971,15 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment break; } + Boolean allow = BromiteCustomContentSettingImpl.allowSpecifyingExceptions(mCategory); + if (allow != null) shouldAddExceptionButton = (boolean)allow; + int exceptionDialogMessageResourceId = getAddExceptionDialogMessageResourceId(); assert shouldAddExceptionButton == (exceptionDialogMessageResourceId != 0); if (shouldAddExceptionButton) { int blockAddingExceptionsReasonResourceId = mCategory.getBlockAddingExceptionsReasonResourceId(); - boolean enableAddExceptionButton = - (!mCategory.isManaged() - || mCategory.getType() - == SiteSettingsCategory.Type.THIRD_PARTY_COOKIES) - && blockAddingExceptionsReasonResourceId == 0; String exceptionDialogMessage = exceptionDialogMessageResourceId != 0 ? getString(exceptionDialogMessageResourceId) @@ -973,7 +990,7 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment getStyledContext(), ADD_EXCEPTION_KEY, exceptionDialogMessage, - enableAddExceptionButton, + /*enableAddExceptionButton*/ true, mCategory, this)); @@ -1149,8 +1166,16 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment private boolean isBlocked() { switch (mGlobalToggleLayout) { case GlobalToggleLayout.TRI_STATE_TOGGLE: + Preference triStateToggleImpl = + getPreferenceScreen().findPreference(TRI_STATE_TOGGLE_KEY); + if (triStateToggleImpl instanceof BromiteCustomTriStateSiteSettingsPreferenceImpl) { + Boolean blocked = BromiteCustomContentSettingImpl.considerException(mCategory, + ((BromiteCustomTriStateSiteSettingsPreferenceImpl)triStateToggleImpl).getCheckedSetting()); + if (blocked != null) return (boolean)blocked; + } TriStateSiteSettingsPreference triStateToggle = getPreferenceScreen().findPreference(TRI_STATE_TOGGLE_KEY); + if (triStateToggle == null) return true; return (triStateToggle.getCheckedSetting() == ContentSetting.BLOCK); case GlobalToggleLayout.COOKIE_TOGGLE: CookieSettingsPreference cookieToggle = @@ -1310,7 +1335,11 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment } else if (res_id != -1) { infoText.setSummary(res_id); } else { - screen.removePreference(infoText); + int infoMessage = BromiteCustomContentSettingImpl.getCategoryDescription(mCategory); + if (infoMessage == 0) + screen.removePreference(infoText); + else + infoText.setSummary(infoMessage); } // Hide the anti-abuse text preferences, as needed. @@ -1346,6 +1375,7 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment } else { screen.removePreference(mLocationTriStatePref); } + BromiteCustomContentSettingImpl.configureGlobalToggles(mCategory, this); maybeShowReasonToggleDisabled(screen); @@ -1512,6 +1542,7 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment ContentSettingsResources.getTriStateSettingDescriptionIDs(contentType); int[] iconIds = ContentSettingsResources.getTriStateSettingIconIDs(contentType); triStateToggle.initialize( + contentType, setting, descriptionIds, iconIds, @@ -1822,6 +1853,14 @@ public class SingleCategorySettings extends BaseSiteSettingsFragment setLocationAccessEnabled.accept(allowButton.isChecked()); } + AlertDialog.Builder alertDialogBuilder = + BromiteCustomContentSettingImpl.buildPreferenceDialog(site, contentSettingsType, + browserContextHandle, getContext(), + (dialog, which) -> { getInfoForOrigins(); }); + if (alertDialogBuilder != null) { + return alertDialogBuilder.create(); + } + AlertDialog alertDialog = new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_BrowserUI_AlertDialog) .setTitle( 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 @@ -59,6 +59,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.List; /** Shows the permissions and other settings for a particular website. */ @NullMarked @@ -209,7 +210,7 @@ public class SingleWebsiteSettings extends BaseSiteSettingsFragment case ContentSettingsType.WINDOW_MANAGEMENT: return "window_management_permission_list"; default: - return null; + return BromiteCustomContentSettingImpl.getProfilePrefKey(type); } } @@ -656,7 +657,8 @@ public class SingleWebsiteSettings extends BaseSiteSettingsFragment private void setupContentSettingsPreferences() { Preference permissionsHeaderPref = findPreference(PREF_PERMISSIONS_HEADER); mMaxPermissionOrder = permissionsHeaderPref.getOrder(); - for (@ContentSettingsType.EnumType int type : SiteSettingsUtil.SETTINGS_ORDER) { + List order = BromiteCustomContentSettingImpl.getSettingsOrder(); + for (@ContentSettingsType.EnumType int type : order) { Preference preference = getPermissionPreference(type); preference.setKey(getPreferenceKey(type)); @@ -688,6 +690,19 @@ public class SingleWebsiteSettings extends BaseSiteSettingsFragment } private Preference getPermissionPreference(@ContentSettingsType.EnumType int type) { + @ContentSetting @Nullable Integer value = + mSite.getContentSetting( + getSiteSettingsDelegate().getBrowserContextHandle(), type); + if (value == null) { + value = WebsitePreferenceBridge.getDefaultContentSetting( + getSiteSettingsDelegate().getBrowserContextHandle(), type); + } + Preference preference = + BromiteCustomContentSettingImpl + .createWebSitePreference(type, getStyledContext(), value); + if (preference != null) + return preference; + boolean isOneTime = isOneTime(type); if (type == ContentSettingsType.GEOLOCATION_WITH_OPTIONS && !isOneTime) { return createTwoActionLocationSwitchPreference(); @@ -1351,7 +1366,14 @@ public class SingleWebsiteSettings extends BaseSiteSettingsFragment value = ContentSetting.BLOCK; } - if (value == null) return; + BromiteCustomContentSetting cs = + BromiteCustomContentSettingImpl.getContentSetting(contentType); + if (value == null && cs == null) return; + if (value == null) { + if (cs.showIntoInfoPage() == false) return; + value = WebsitePreferenceBridge.getDefaultContentSetting( + getSiteSettingsDelegate().getBrowserContextHandle(), contentType); + } setUpPreferenceCommon(preference, value); preference.setOnPreferenceChangeListener(this); @@ -1401,10 +1423,14 @@ public class SingleWebsiteSettings extends BaseSiteSettingsFragment oneTimePreference.setBackgroundColor(mHighlightColor); } } else { - ChromeSwitchPreference switchPreference = (ChromeSwitchPreference) preference; - switchPreference.setChecked(value == getEnabledValue(contentType)); - if (contentType == mHighlightedPermission) { - switchPreference.setBackgroundColor( + Preference switchPreference = preference; + if (preference instanceof ChromeSwitchPreference) { + ((ChromeSwitchPreference)switchPreference).setChecked(value != ContentSetting.BLOCK); + } else { + BromiteCustomContentSettingImpl.setWebSitePreferenceValue(contentType, preference, value); + } + if (preference instanceof ChromeSwitchPreference && contentType == mHighlightedPermission) { + ((ChromeSwitchPreference)switchPreference).setBackgroundColor( AppCompatResources.getColorStateList(getContext(), mHighlightColor) .getDefaultColor()); } @@ -1710,7 +1736,13 @@ public class SingleWebsiteSettings extends BaseSiteSettingsFragment if (newValue instanceof Boolean) { permission = (Boolean) newValue ? getEnabledValue(type) : ContentSetting.BLOCK; } else { - permission = (Integer) newValue; + Integer newPermission = + BromiteCustomContentSettingImpl + .getWebSitePreferenceValue(type, newValue); + if (newPermission != null) + permission = newPermission; + else + permission = (Integer) newValue; } if (type == ContentSettingsType.GEOLOCATION_WITH_OPTIONS) { 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 @@ -61,6 +61,7 @@ public class SiteSettings extends BaseSiteSettingsFragment SettingsUtils.addPreferencesFromResource(this, R.xml.site_settings_preferences); mPageTitle.set(getContext().getString(R.string.prefs_site_settings)); + BromiteCustomContentSettingImpl.configurePreferences(this); configurePreferences(); updatePreferenceStates(); } @@ -90,7 +91,7 @@ public class SiteSettings extends BaseSiteSettingsFragment // Remove unsupported settings categories. for (@SiteSettingsCategory.Type int type = 0; - type < SiteSettingsCategory.Type.NUM_ENTRIES; + type < BromiteCustomContentSettingImpl.NUM_ENTRIES(); type++) { if (!getSiteSettingsDelegate().isCategoryVisible(type)) { Preference pref = findPreference(type); @@ -107,7 +108,7 @@ public class SiteSettings extends BaseSiteSettingsFragment @CookieControlsMode int cookieControlsMode = UserPrefs.get(browserContextHandle).getInteger(COOKIE_CONTROLS_MODE); - for (@Type int prefCategory = 0; prefCategory < Type.NUM_ENTRIES; prefCategory++) { + for (@Type int prefCategory = 0; prefCategory < BromiteCustomContentSettingImpl.NUM_ENTRIES(); prefCategory++) { Preference p = findPreference(prefCategory); int contentType = SiteSettingsCategory.contentSettingsType(prefCategory); // p can be null if the Preference was removed in configurePreferences. @@ -181,20 +182,22 @@ public class SiteSettings extends BaseSiteSettingsFragment } else if (Type.ZOOM == prefCategory) { // Don't want to set a summary for Zoom because we don't want any message to display // under the Zoom row on site settings. - } else if (requiresTriStateSetting) { - p.setSummary( - ContentSettingsResources.getCategorySummary( - setting, /* isOneTime= */ false)); } else { - @ContentSetting - Integer defaultForToggle = - checked - ? ContentSettingsResources.getDefaultEnabledValue(contentType) - : ContentSettingsResources.getDefaultDisabledValue(contentType); - assumeNonNull(defaultForToggle); - p.setSummary( - ContentSettingsResources.getCategorySummary( - defaultForToggle, /* isOneTime= */ false)); + int summary = ContentSettingsResources.getCategorySummary( + contentType, setting, /* isOneTime= */ false, /*isApproximateGeolocation*/ false); + if (summary != 0) { + p.setSummary(summary); + } else { + @ContentSetting + Integer defaultForToggle = + checked + ? ContentSettingsResources.getDefaultEnabledValue(contentType) + : ContentSettingsResources.getDefaultDisabledValue(contentType); + assumeNonNull(defaultForToggle); + summary = ContentSettingsResources.getCategorySummary( + contentType, defaultForToggle, /* isOneTime= */ false, /*isApproximateGeolocation*/ false); + p.setSummary(summary); + } } if (prefCategory != Type.THIRD_PARTY_COOKIES) { @@ -278,7 +281,7 @@ public class SiteSettings extends BaseSiteSettingsFragment // Always remove the divider as the search is based on containment style. indexData.removeEntry(PreferenceParser.createUniqueId(prefFragment, "divider")); - for (@Type int prefCategory = 0; prefCategory < Type.NUM_ENTRIES; prefCategory++) { + for (@Type int prefCategory = 0; prefCategory < BromiteCustomContentSettingImpl.NUM_ENTRIES(); prefCategory++) { if (SiteSettingsCategory.contentSettingsType(prefCategory) < 0) continue; String key = SiteSettingsCategory.preferenceKey(prefCategory); 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 @@ -83,7 +83,7 @@ public class SiteSettingsCategory { Type.AUTO_PICTURE_IN_PICTURE, Type.LOCAL_NETWORK, Type.LOOPBACK_NETWORK, - Type.NUM_ENTRIES + Type.NUM_ENTRIES_CHROMIUM }) @Retention(RetentionPolicy.SOURCE) public @interface Type { @@ -130,7 +130,7 @@ public class SiteSettingsCategory { int LOOPBACK_NETWORK = 38; /** Number of handled categories used for calculating array sizes. */ - int NUM_ENTRIES = 39; + int NUM_ENTRIES_CHROMIUM = 39; } private final BrowserContextHandle mBrowserContextHandle; @@ -189,6 +189,9 @@ public class SiteSettingsCategory { } else { permission = ""; } + SiteSettingsCategory category = BromiteCustomContentSettingImpl.createFromType( + browserContextHandle, type); + if (category != null) return category; return new SiteSettingsCategory(browserContextHandle, type, permission); } @@ -197,7 +200,7 @@ public class SiteSettingsCategory { @ContentSettingsType.EnumType int contentSettingsType) { assert contentSettingsType != -1; assert Type.ALL_SITES == 0; - for (@Type int i = Type.ALL_SITES; i < Type.NUM_ENTRIES; i++) { + for (@Type int i = Type.ALL_SITES; i < BromiteCustomContentSettingImpl.NUM_ENTRIES(); i++) { if (contentSettingsType(i) == contentSettingsType) { return createFromType(browserContextHandle, i); } @@ -208,7 +211,7 @@ public class SiteSettingsCategory { public static @Nullable SiteSettingsCategory createFromPreferenceKey( BrowserContextHandle browserContextHandle, String preferenceKey) { assert Type.ALL_SITES == 0; - for (@Type int i = Type.ALL_SITES; i < Type.NUM_ENTRIES; i++) { + for (@Type int i = Type.ALL_SITES; i < BromiteCustomContentSettingImpl.NUM_ENTRIES(); i++) { if (preferenceKey(i).equals(preferenceKey)) { return createFromType(browserContextHandle, i); } @@ -296,8 +299,7 @@ public class SiteSettingsCategory { case Type.ZOOM: return ContentSettingsType.DEFAULT; // Conversion unavailable. } - assert false; - return ContentSettingsType.DEFAULT; + return BromiteCustomContentSettingImpl.contentSettingsType(type); } /** @@ -400,8 +402,12 @@ public class SiteSettingsCategory { case Type.ZOOM: return "zoom"; 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/SiteSettingsDelegate.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java @@ -183,6 +183,8 @@ public interface SiteSettingsDelegate { */ String getRelatedWebsiteSetOwner(String memberOrigin); + void launchHelpAndFeedbackActivity(Activity currentActivity, String url); + /** * Returns whether the current implementation of the delegate is able to launch the Clear * Browsing Data dialog in Settings. 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 @@ -16,6 +16,7 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.components.browser_ui.widget.RadioButtonWithDescription; import org.chromium.components.content_settings.ContentSetting; +import org.chromium.components.content_settings.ContentSettingsType; /** A 3-state Allowed/Ask/Blocked radio group Preference used for SiteSettings. */ @NullMarked @@ -29,6 +30,7 @@ public class TriStateSiteSettingsPreference extends Preference private RadioButtonWithDescription mBlocked; private RadioGroup mRadioGroup; private int mIconMarginEnd; + private @ContentSettingsType.EnumType int mContentType; public TriStateSiteSettingsPreference(Context context, AttributeSet attrs) { super(context, attrs); @@ -49,10 +51,12 @@ public class TriStateSiteSettingsPreference extends Preference * Blocked states, in that order. */ public void initialize( + @ContentSettingsType.EnumType int contentType, @ContentSetting int setting, int @Nullable [] descriptionIds, int @Nullable [] iconIds, int iconMarginEnd) { + mContentType = contentType; mSetting = setting; mDescriptionIds = descriptionIds; mIconIds = iconIds; @@ -90,6 +94,13 @@ public class TriStateSiteSettingsPreference extends Preference 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.setPrimaryText(getContext().getText(mDescriptionIds[0])); mAsk.setPrimaryText(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 @@ -368,7 +368,11 @@ public final class Website implements WebsiteEntry { RecordUserAction.record("SoundContentSetting.UnmuteBy.SiteSettings"); } } - + 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 // on the PrefServiceBridge. 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 @@ -131,7 +131,7 @@ public class WebsitePermissionsFetcher { } break; default: - return null; + return BromiteCustomContentSettingImpl.getPermissionsType(contentSettingsType); } return null; } 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 @@ -328,7 +328,7 @@ public class WebsitePreferenceBridge { return DeviceFeatureMap.isEnabled( DeviceFeatureList.SENSORS_ALLOW_ASK_BLOCK_PERMISSION_MODEL); default: - return false; + return BromiteCustomContentSettingImpl.requiresTriStateContentSetting(contentSettingsType); } } @@ -344,7 +344,6 @@ public class WebsitePreferenceBridge { public static boolean isCategoryEnabled( BrowserContextHandle browserContextHandle, @ContentSettingsType.EnumType int contentSettingsType) { - assert !requiresTriStateContentSetting(contentSettingsType); return isContentSettingEnabled(browserContextHandle, contentSettingsType); } diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/include_all_directory.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/include_all_directory.java new file mode 100644 --- /dev/null +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/include_all_directory.java @@ -0,0 +1 @@ +this file is intentionally empty diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/java_template/BromiteCustomContentSettingImplBase.java.tmpl b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/java_template/BromiteCustomContentSettingImplBase.java.tmpl new file mode 100644 --- /dev/null +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/java_template/BromiteCustomContentSettingImplBase.java.tmpl @@ -0,0 +1,48 @@ +/* + 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 . + +*/ + +{DESCRIPTION} + +package org.chromium.components.browser_ui.site_settings; + +import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory; +import org.chromium.components.browser_ui.site_settings.BromiteCustomContentSetting; + +import java.util.ArrayList; + +{IMPORT_CLAUSE} + +public class BromiteCustomContentSettingImplBase {{ + + static protected final ArrayList mItemList; + + private static void add(BromiteCustomContentSetting setting) {{ + setting.setSiteSettingsCategory(NUM_ENTRIES()); + mItemList.add(setting); + }} + + protected static int NUM_ENTRIES() {{ + return SiteSettingsCategory.Type.NUM_ENTRIES_CHROMIUM + mItemList.size(); + }} + + static {{ + mItemList = new ArrayList(); +{ADD_CLAUSE} + }} + +}} diff --git a/components/browser_ui/strings/bromite_content_settings/placeholder.txt b/components/browser_ui/strings/bromite_content_settings/placeholder.txt new file mode 100644 --- /dev/null +++ b/components/browser_ui/strings/bromite_content_settings/placeholder.txt @@ -0,0 +1 @@ +this file is intentionally empty diff --git a/components/content_settings/android/BUILD.gn b/components/content_settings/android/BUILD.gn --- a/components/content_settings/android/BUILD.gn +++ b/components/content_settings/android/BUILD.gn @@ -59,6 +59,7 @@ android_library("content_settings_enums_java") { } java_cpp_enum("content_settings_enums_javagen") { + deps = [ "//components/content_settings/core/common:bromite_content_settings" ] sources = [ "../core/browser/cookie_settings.h", "../core/common/content_settings.h", diff --git a/components/content_settings/core/browser/BUILD.gn b/components/content_settings/core/browser/BUILD.gn --- a/components/content_settings/core/browser/BUILD.gn +++ b/components/content_settings/core/browser/BUILD.gn @@ -85,6 +85,8 @@ static_library("browser") { configs += [ "//build/config/compiler:wexit_time_destructors" ] + deps += [ ":bromite_content_settings" ] + # TODO(crbug.com/40145057): remove deprecated RWS and this include. # Allow access to /components/privacy_sandbox/privacy_sandbox_prefs.h # from /chrome/browser/ui/page_info/page_info_unittest.cc @@ -93,6 +95,11 @@ static_library("browser") { public_deps += [ "//components/privacy_sandbox:privacy_sandbox_prefs" ] } +cpp_bromite_include("bromite_content_settings") { + inputs = [ "bromite_content_settings/placeholder.txt" ] + output_file = "bromite_content_settings.inc" +} + source_set("cookie_settings") { sources = [ "cookie_settings.cc", diff --git a/components/content_settings/core/browser/bromite_content_settings/placeholder.txt b/components/content_settings/core/browser/bromite_content_settings/placeholder.txt new file mode 100644 --- /dev/null +++ b/components/content_settings/core/browser/bromite_content_settings/placeholder.txt @@ -0,0 +1 @@ +this file is intentionally empty 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 @@ -18,6 +18,7 @@ #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_strings.h" namespace content_settings { @@ -842,6 +843,7 @@ void ContentSettingsRegistry::Init() { WebsiteSettingsRegistry::PLATFORM_CHROMEOS, ContentSettingsInfo::INHERIT_IN_INCOGNITO, PermissionSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY); +#include "components/content_settings/core/browser/bromite_content_settings.inc" } void ContentSettingsRegistry::Register( diff --git a/components/content_settings/core/browser/content_settings_uma_util.cc b/components/content_settings/core/browser/content_settings_uma_util.cc --- a/components/content_settings/core/browser/content_settings_uma_util.cc +++ b/components/content_settings/core/browser/content_settings_uma_util.cc @@ -230,11 +230,7 @@ void RecordContentSettingsHistogram(const std::string& name, } int ContentSettingTypeToHistogramValue(ContentSettingsType content_setting) { - static_assert( - kHistogramValue.size() == - // DEFAULT is not in the histogram, so we want [0, kMaxValue] - 1 + static_cast(ContentSettingsType::kMaxValue), - "Update content settings histogram lookup"); + if ((true)) return 0; auto found = kHistogramValue.find(content_setting); if (found != kHistogramValue.end()) { 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 @@ -19,6 +19,7 @@ #include "components/content_settings/core/browser/permission_settings_info.h" #include "components/content_settings/core/browser/permission_settings_registry.h" #include "components/content_settings/core/browser/website_settings_registry.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/content_settings/core/common/content_settings_utils.h" @@ -133,6 +134,17 @@ PatternPair ParsePatternString(const std::string& pattern_str) { void GetRendererContentSettingRules(const HostContentSettingsMap* map, RendererContentSettingRules* rules) { + content_settings::WebsiteSettingsRegistry* website_settings = + content_settings::WebsiteSettingsRegistry::GetInstance(); + rules->settings_rules.clear(); + for (const content_settings::WebsiteSettingsInfo* info : *website_settings) { + if (info->is_renderer_content_setting()) { + ContentSettingRuleSource rule; + rule.type = (int32_t)info->type(); + rule.rules = map->GetSettingsForOneType(info->type()); + rules->settings_rules.push_back(rule); + } + } #if !BUILDFLAG(IS_IOS) rules->mixed_content_rules = map->GetSettingsForOneType(ContentSettingsType::MIXEDSCRIPT); 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 @@ -124,6 +124,32 @@ 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_; } + bool is_renderer_content_setting() const { return is_renderer_content_setting_; } + bool desktop_ui() const { return desktop_ui_; } + std::string tag_ui() const { return tag_ui_; } + int title_ui() const { return title_ui_; } + int description_ui() const { return description_ui_; } + int allowed_ui() const { return allowed_ui_; } + int blocked_ui() const { return blocked_ui_; } + int ask_ui() const { return ask_ui_; } + int allowed_exceptions_ui() const { return allowed_exceptions_ui_; } + int blocked_exceptions_ui() const { return blocked_exceptions_ui_; } + int mid_sentence_ui() const { return mid_sentence_ui_; } + + WebsiteSettingsInfo& set_show_into_info_page() { show_into_info_page_ = true; return *this; } + WebsiteSettingsInfo& set_is_renderer_content_setting() { is_renderer_content_setting_ = true; return *this; } + WebsiteSettingsInfo& set_desktop_ui() { desktop_ui_ = true; return *this; } + WebsiteSettingsInfo& set_tag_ui(const std::string& value) { tag_ui_ = value; return *this; } + WebsiteSettingsInfo& set_title_ui(int value) { title_ui_ = value; return *this; } + WebsiteSettingsInfo& set_description_ui(int value) { description_ui_ = value; return *this; } + WebsiteSettingsInfo& set_allowed_ui(int value) { allowed_ui_ = value; return *this; } + WebsiteSettingsInfo& set_blocked_ui(int value) { blocked_ui_ = value; return *this; } + WebsiteSettingsInfo& set_ask_ui(int value) { ask_ui_ = value; return *this; } + WebsiteSettingsInfo& set_allowed_exceptions_ui(int value) { allowed_exceptions_ui_ = value; return *this; } + WebsiteSettingsInfo& set_blocked_exceptions_ui(int value) { blocked_exceptions_ui_ = value; return *this; } + WebsiteSettingsInfo& set_mid_sentence_ui(int value) { mid_sentence_ui_ = value; return *this; } + private: const ContentSettingsType type_; const std::string name_; @@ -136,6 +162,18 @@ class WebsiteSettingsInfo { const LossyStatus lossy_status_; const ScopingType scoping_type_; const IncognitoBehavior incognito_behavior_; + bool show_into_info_page_ = false; + bool is_renderer_content_setting_ = false; + bool desktop_ui_ = false; + std::string tag_ui_; + int title_ui_ = 0; + int description_ui_ = 0; + int allowed_ui_ = 0; + int blocked_ui_ = 0; + int ask_ui_ = 0; + int allowed_exceptions_ui_ = 0; + int blocked_exceptions_ui_ = 0; + int mid_sentence_ui_ = 0; }; } // 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 @@ -45,6 +45,12 @@ const WebsiteSettingsInfo* WebsiteSettingsRegistry::Get( return nullptr; } +raw_ptr WebsiteSettingsRegistry::GetMutable( + ContentSettingsType type) { + const auto& it = website_settings_info_.find(type); + return it->second.get(); +} + const WebsiteSettingsInfo* WebsiteSettingsRegistry::GetByName( const std::string& name) const { for (const auto& entry : website_settings_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 @@ -61,6 +61,7 @@ class WebsiteSettingsRegistry { void ResetForTest(); const WebsiteSettingsInfo* Get(ContentSettingsType type) const; + raw_ptr GetMutable(ContentSettingsType type); const WebsiteSettingsInfo* GetByName(const std::string& name) const; // Register a new website setting. This maps an origin to an arbitrary diff --git a/components/content_settings/core/common/BUILD.gn b/components/content_settings/core/common/BUILD.gn --- a/components/content_settings/core/common/BUILD.gn +++ b/components/content_settings/core/common/BUILD.gn @@ -53,6 +53,13 @@ static_library("common") { "//net", "//url", ] + deps += [ ":bromite_content_settings" ] +} + +cpp_bromite_include("bromite_content_settings") { + inputs = [ "bromite_content_settings/placeholder.txt" ] + output_file = "bromite_content_settings.inc" + visibility = [ "*" ] } source_set("unit_tests") { @@ -85,6 +92,7 @@ mojom("content_settings_types") { sources = [ "content_settings_types.mojom" ] public_deps = [ "//mojo/public/mojom/base" ] + parser_deps = [ ":bromite_content_settings" ] webui_module_path = "/" generate_legacy_js_bindings = true diff --git a/components/content_settings/core/common/bromite_content_settings/placeholder.txt b/components/content_settings/core/common/bromite_content_settings/placeholder.txt new file mode 100644 --- /dev/null +++ b/components/content_settings/core/common/bromite_content_settings/placeholder.txt @@ -0,0 +1 @@ +this file is intentionally empty 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 @@ -17,11 +17,12 @@ #include "components/content_settings/core/common/content_settings_metadata.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/content_settings/core/common/content_settings_utils.h" +#include "components/content_settings/core/browser/website_settings_registry.h" #include "third_party/abseil-cpp/absl/functional/overload.h" namespace { -void FilterRulesForType(ContentSettingsForOneType& settings, +void FilterRulesForType(ContentSettingsForOneType& settings, // do not remove const GURL& primary_url) { std::erase_if(settings, [&primary_url](const ContentSettingPatternSource& source) { @@ -105,6 +106,13 @@ std::ostream& operator<<(std::ostream& os, // static bool RendererContentSettingRules::IsRendererContentSetting( ContentSettingsType content_type) { + content_settings::WebsiteSettingsRegistry* website_settings = + content_settings::WebsiteSettingsRegistry::GetInstance(); + for (const content_settings::WebsiteSettingsInfo* info : *website_settings) { + if (info->type() == content_type && info->is_renderer_content_setting()) { + return true; + } + } return content_type == ContentSettingsType::IMAGES || content_type == ContentSettingsType::JAVASCRIPT || content_type == ContentSettingsType::POPUPS || @@ -114,7 +122,10 @@ bool RendererContentSettingRules::IsRendererContentSetting( void RendererContentSettingRules::FilterRulesByOutermostMainFrameURL( const GURL& outermost_main_frame_url) { - FilterRulesForType(mixed_content_rules, outermost_main_frame_url); + for (ContentSettingRuleSource& info : settings_rules) { + FilterRulesForType(info.rules, outermost_main_frame_url); + } + FilterRulesForType(mixed_content_rules, outermost_main_frame_url); // do not remove } RendererContentSettingRules::RendererContentSettingRules() = default; @@ -134,7 +145,20 @@ RendererContentSettingRules& RendererContentSettingRules::operator=( RendererContentSettingRules&& rules) = default; bool RendererContentSettingRules::operator==( - const RendererContentSettingRules& other) const = default; + const RendererContentSettingRules& other) const { + return std::tie(settings_rules, mixed_content_rules) == + std::tie(other.settings_rules, other.mixed_content_rules); +} + +ContentSettingRuleSource::ContentSettingRuleSource() = default; + +ContentSettingRuleSource::~ContentSettingRuleSource() = default; + +ContentSettingRuleSource::ContentSettingRuleSource( + const ContentSettingRuleSource&) = default; + +bool ContentSettingRuleSource::operator==( + const ContentSettingRuleSource& other) const = default; content_settings::SettingInfo::SettingInfo() = default; content_settings::SettingInfo& content_settings::SettingInfo::operator=( 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 @@ -97,10 +97,22 @@ std::ostream& operator<<(std::ostream& os, typedef std::vector ContentSettingsForOneType; +struct ContentSettingRuleSource { + int type; + ContentSettingsForOneType rules; + + ContentSettingRuleSource(); + ~ContentSettingRuleSource(); + ContentSettingRuleSource(const ContentSettingRuleSource& source); + + bool operator==(const ContentSettingRuleSource& other) const; +}; + struct RendererContentSettingRules { // Returns true if |content_type| is a type that is contained in this class. // Any new type added below must also update this method. static bool IsRendererContentSetting(ContentSettingsType content_type); + std::vector settings_rules; // Filters all the rules by matching the primary pattern with // |outermost_main_frame_url|. Any new type added below that needs to match 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 @@ -74,6 +74,11 @@ struct RuleMetaData { mojo_base.mojom.Value rule_options; }; +struct ContentSettingRuleSource { + int32 type; + array rules; +}; + // This mirrors the C++ type in content_settings.h. struct ContentSettingPatternSource { ContentSettingsPattern primary_pattern; @@ -87,5 +92,6 @@ struct ContentSettingPatternSource { // This mirrors the C++ type in content_settings.h. // TODO(crbug.com/40282541): This should be removed. struct RendererContentSettingRules { + array settings_rules; array mixed_content_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 @@ -114,12 +114,22 @@ bool StructTraitsmetadata) && data.ReadSource(&out->source); } +// static +bool StructTraits:: + Read(content_settings::mojom::ContentSettingRuleSourceDataView data, + ContentSettingRuleSource* out) { + out->type = data.type(); + return data.ReadRules(&out->rules); +} + // static bool StructTraits:: Read(content_settings::mojom::RendererContentSettingRulesDataView data, RendererContentSettingRules* out) { - return data.ReadMixedContentRules(&out->mixed_content_rules); + return data.ReadSettingsRules(&out->settings_rules) && + data.ReadMixedContentRules(&out->mixed_content_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 @@ -186,10 +186,34 @@ struct StructTraits< ContentSettingPatternSource* out); }; +template <> +struct StructTraits< + content_settings::mojom::ContentSettingRuleSourceDataView, + ContentSettingRuleSource> { + static int type( + const ContentSettingRuleSource& r) { + return r.type; + } + + static const std::vector& rules( + const ContentSettingRuleSource& r) { + return r.rules; + } + + static bool Read( + content_settings::mojom::ContentSettingRuleSourceDataView data, + ContentSettingRuleSource* out); +}; + template <> struct StructTraits< content_settings::mojom::RendererContentSettingRulesDataView, RendererContentSettingRules> { + static const std::vector& settings_rules( + const RendererContentSettingRules& r) { + return r.settings_rules; + } + static const std::vector& mixed_content_rules( const RendererContentSettingRules& r) { return r.mixed_content_rules; diff --git a/components/content_settings/core/common/content_settings_types.mojom b/components/content_settings/core/common/content_settings_types.mojom --- a/components/content_settings/core/common/content_settings_types.mojom +++ b/components/content_settings/core/common/content_settings_types.mojom @@ -487,5 +487,7 @@ enum ContentSettingsType { // when suspicious warning is shown. If the user has selected this, the // notification permission will not be revoked based on suspicious verdict. SUSPICIOUS_NOTIFICATION_SHOW_ORIGINAL, + +#include "components/content_settings/core/common/bromite_content_settings.inc" }; // LINT.ThenChange(//components/content_settings/core/browser/content_settings_uma_util.cc:kHistogramValue) 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 @@ -195,6 +195,80 @@ void ContentSettingsAgentImpl::SendRendererContentSettingRules( std::move(renderer_settings)); } +ContentSetting ContentSettingsAgentImpl::GetContentSetting( + ContentSettingsType type, ContentSetting default_value) { + if (!content_setting_rules_) + return default_value; + + blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); + const GURL secondary_url = + url::Origin(frame->GetDocument().GetSecurityOrigin()).GetURL(); + for (ContentSettingRuleSource& info : content_setting_rules_->settings_rules) { + if (info.type == (int)type) { + return GetContentSettingFromRules(info.rules, secondary_url); + } + } + return default_value; +} + +bool ContentSettingsAgentImpl::AllowContentSetting( + ContentSettingsType type, bool default_value) { + if (!content_setting_rules_) + return default_value; + + blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); + const GURL secondary_url = + url::Origin(frame->GetDocument().GetSecurityOrigin()).GetURL(); + return AllowContentSetting(type, secondary_url, default_value); +} + +bool ContentSettingsAgentImpl::AllowContentSetting( + ContentSettingsType type, + const blink::WebURL& secondary_url, + bool default_value) { + if (!content_setting_rules_) + return default_value; + + for (ContentSettingRuleSource& info : content_setting_rules_->settings_rules) { + if (info.type == (int)type) { + return CONTENT_SETTING_ALLOW == GetContentSettingFromRules( + info.rules, secondary_url); + } + } + return default_value; +} + +bool ContentSettingsAgentImpl::IsAllowlistedForContentSettings() const { + const WebDocument& document = render_frame()->GetWebFrame()->GetDocument(); + WebSecurityOrigin origin = document.GetSecurityOrigin(); + WebURL document_url = document.Url(); + + if (document_url.GetString() == content::kUnreachableWebDataURL) + return true; + + if (origin.IsNull() || origin.IsOpaque()) + return false; // Uninitialized document? + + blink::WebString protocol = origin.Protocol(); + + if (protocol == content::kChromeUIScheme) + return true; // Browser UI elements should still work. + + if (protocol == content::kChromeDevToolsScheme) + return true; // DevTools UI elements should still work. + + if (document_url.ProtocolIs("chrome-extension")) + return true; // Extension pages should still work. + + // If the scheme is file:, an empty file name indicates a directory listing, + // which requires JavaScript to function properly. + if (protocol == url::kFileScheme && + document_url.ProtocolIs(url::kFileScheme)) { + return GURL(document_url).ExtractFileName().empty(); + } + return false; +} + void ContentSettingsAgentImpl::OnContentSettingsAgentRequest( mojo::PendingAssociatedReceiver receiver) { receivers_.Add(this, std::move(receiver)); 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 @@ -72,6 +72,13 @@ class ContentSettingsAgentImpl static mojom::ContentSettingsManager::StorageType ConvertToMojoStorageType( StorageType storage_type); + bool AllowContentSetting( + ContentSettingsType type, const blink::WebURL& secondary_url, bool default_value) override; + bool AllowContentSetting( + ContentSettingsType type, bool default_value) override; + ContentSetting GetContentSetting( + ContentSettingsType type, ContentSetting default_value); + // blink::WebContentSettingsClient: void AllowStorageAccess(StorageType storage_type, base::OnceCallback callback) override; @@ -123,6 +130,8 @@ class ContentSettingsAgentImpl // Resets the `content_blocked_` array. void ClearBlockedContentSettings(); + bool IsAllowlistedForContentSettings() const; + // A getter for `content_settings_manager_` that ensures it is bound. mojom::ContentSettingsManager& GetContentSettingsManager(); diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java @@ -244,6 +244,15 @@ public class PageInfoPermissionsController extends PageInfoPreferenceSubpageCont : perm1.nameMidSentence.toString()); } + String value = ""; + for (PermissionObject perm : permissions) { + if (perm.allowed) { + if (!value.equals("")) value += ", "; + value += perm.nameMidSentence.toString(); + } + } + if ((true)) return value; + // More than 2 permissions. if (same) { int resId = 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 @@ -15,6 +15,7 @@ #include "base/notimplemented.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/browser/permission_settings_registry.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/content_settings/core/common/content_settings_utils.h" @@ -211,6 +212,15 @@ void PageInfoControllerAndroid::SetPermissionInfo( } permissions_to_display.push_back(ContentSettingsType::SENSORS); + content_settings::WebsiteSettingsRegistry* website_settings = + content_settings::WebsiteSettingsRegistry::GetInstance(); + for (const content_settings::WebsiteSettingsInfo* info : *website_settings) { + if (info->show_into_info_page() && + !std::ranges::contains(permissions_to_display, info->type())) { + permissions_to_display.push_back(info->type()); + } + } + std::map user_specified_settings_to_display; @@ -289,6 +299,14 @@ std::optional PageInfoControllerAndroid::GetSettingToDisplay( return permission.setting; } + 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; + } + } + // Handle exceptions for permissions which need to be displayed even if they // are set to the default. if (permission.type == ContentSettingsType::ADS) { 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 @@ -23,6 +23,7 @@ #include "base/values.h" #include "build/build_config.h" #include "components/browsing_data/content/browsing_data_helper.h" +#include "components/content_settings/core/browser/website_settings_registry.h" #include "components/content_settings/browser/ui/cookie_controls_controller.h" #include "components/content_settings/core/browser/content_settings_registry.h" #include "components/content_settings/core/browser/content_settings_uma_util.h" @@ -1411,6 +1412,14 @@ bool PageInfo::ShouldShowPermission( } #endif // BUILDFLAG(IS_ANDROID) + 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; + } + } // Note |ContentSettingsType::ADS| will show up regardless of its default // value when it has been activated on the current origin. if (info.type == ContentSettingsType::ADS) { @@ -1559,7 +1568,19 @@ void PageInfo::PresentSitePermissions() { 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() && + !std::ranges::contains(permission_list, info->type())) { + permission_list.push_back(info->type()); + } + } + for (const ContentSettingsType type : permission_list) { PermissionInfo permission_info; permission_info.type = type; 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 @@ -16,6 +16,7 @@ #include "components/content_settings/core/browser/permission_settings_registry.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" +#include "components/content_settings/core/browser/website_settings_registry.h" #include "components/page_info/core/features.h" #include "components/page_info/page_info.h" #include "components/page_info/page_info_ui.h" @@ -258,6 +259,13 @@ void CreateOppositeToDefaultSiteException( std::u16string GetPermissionAskStateString(ContentSettingsType type) { int message_id = kInvalidResourceID; + const content_settings::WebsiteSettingsInfo* settingInfo = + content_settings::WebsiteSettingsRegistry::GetInstance()->Get(type); + if (settingInfo && settingInfo->show_into_info_page()) { + if (settingInfo->ask_ui() != 0) + return l10n_util::GetStringUTF16(settingInfo->ask_ui()); + } + switch (type) { case ContentSettingsType::GEOLOCATION: message_id = IDS_PAGE_INFO_STATE_TEXT_LOCATION_ASK; @@ -568,6 +576,12 @@ PageInfoUI::~PageInfoUI() = default; // static std::u16string PageInfoUI::PermissionTypeToUIString(ContentSettingsType type) { + const content_settings::WebsiteSettingsInfo* settingInfo = + content_settings::WebsiteSettingsRegistry::GetInstance()->Get(type); + if (settingInfo && settingInfo->show_into_info_page()) { + if (settingInfo->title_ui() != 0) + return l10n_util::GetStringUTF16(settingInfo->title_ui()); + } for (const PermissionUIInfo& info : GetContentSettingsUIInfo()) { if (info.type == type) return l10n_util::GetStringUTF16(info.string_id); @@ -578,6 +592,12 @@ std::u16string PageInfoUI::PermissionTypeToUIString(ContentSettingsType type) { // static std::u16string PageInfoUI::PermissionTypeToUIStringMidSentence( ContentSettingsType type) { + const content_settings::WebsiteSettingsInfo* settingInfo = + content_settings::WebsiteSettingsRegistry::GetInstance()->Get(type); + if (settingInfo && settingInfo->show_into_info_page()) { + if (settingInfo->mid_sentence_ui() != 0) + return l10n_util::GetStringUTF16(settingInfo->mid_sentence_ui()); + } for (const PermissionUIInfo& info : GetContentSettingsUIInfo()) { if (info.type == type) return l10n_util::GetStringUTF16(info.string_id_mid_sentence); @@ -971,6 +991,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; } diff --git a/components/site_settings_strings.grdp b/components/site_settings_strings.grdp --- a/components/site_settings_strings.grdp +++ b/components/site_settings_strings.grdp @@ -1,5 +1,6 @@ + Intrusive ads 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 @@ -10,6 +10,11 @@ #include "base/functional/callback.h" +#include "base/time/time.h" +#include "components/content_settings/core/common/content_settings_types.h" +#include "third_party/blink/public/common/client_hints/enabled_client_hints.h" +#include "third_party/blink/public/mojom/navigation/renderer_content_settings.mojom.h" + namespace blink { class WebURL; @@ -42,6 +47,14 @@ class WebContentSettingsClient { // Blocks until done. virtual bool AllowStorageAccessSync(StorageType storage_type) { return true; } + virtual bool AllowContentSetting(ContentSettingsType type, bool enabled_per_settings) { + return enabled_per_settings; + } + + virtual bool AllowContentSetting(ContentSettingsType type, const WebURL& secondary_url, bool enabled_per_settings) { + return enabled_per_settings; + } + // Controls whether insecure scripts are allowed to execute for this frame. virtual bool AllowRunningInsecureContent(bool enabled_per_settings, 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 @@ -70,6 +70,22 @@ 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; +} + ExecutionContext::ExecutionContext(v8::Isolate* isolate, Agent* agent, bool is_window) 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 @@ -43,6 +43,7 @@ #include "third_party/blink/public/mojom/origin_trials/origin_trial_feature.mojom-blink-forward.h" #include "third_party/blink/public/mojom/permissions_policy/policy_disposition.mojom-blink-forward.h" #include "third_party/blink/public/mojom/v8_cache_options.mojom-blink-forward.h" +#include "third_party/blink/public/platform/web_content_settings_client.h" #include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/execution_context/security_context.h" @@ -98,6 +99,10 @@ class SecurityOrigin; class ScriptState; class ScriptWrappable; class TrustedTypePolicyFactory; +class WebContentSettingsClient; + +CORE_EXPORT WebContentSettingsClient* GetContentSettingsClientFor( + ExecutionContext* context); enum ReasonForCallingCanExecuteScripts { kAboutToExecuteScript, --