bromite/build/patches/Timezone-customization.patch
2022-02-04 22:09:00 +01:00

1355 lines
69 KiB
Diff

From: uazo <uazo@users.noreply.github.com>
Date: Wed, 30 Sep 2020 07:40:01 +0000
Subject: Timezone customization
Allow specifying a custom timezone, or using a random one.
See also: https://github.com/bromite/bromite/wiki/TimezoneOverride
---
.../ChromeSiteSettingsDelegate.java | 16 ++
.../browser_ui/site_settings/android/BUILD.gn | 3 +
.../res/layout/time_zone_select_dialog.xml | 36 ++++
...ezoneoverride_site_settings_preference.xml | 68 ++++++
.../res/xml/site_settings_preferences.xml | 4 +
.../java/res/xml/website_preferences.xml | 9 +
.../ContentSettingsResources.java | 35 +++-
.../site_settings/SingleCategorySettings.java | 77 ++++++-
.../site_settings/SingleWebsiteSettings.java | 8 +-
.../site_settings/SiteSettings.java | 2 +-
.../site_settings/SiteSettingsCategory.java | 10 +-
.../site_settings/SiteSettingsDelegate.java | 2 +
...imezoneOverrideSiteSettingsPreference.java | 193 ++++++++++++++++++
.../browser_ui/site_settings/Website.java | 10 +
.../WebsitePermissionsFetcher.java | 3 +
.../WebsitePreferenceBridge.java | 12 ++
.../android/website_preference_bridge.cc | 16 ++
.../strings/android/site_settings.grdp | 35 ++++
.../browser/content_settings_pref_provider.cc | 16 ++
.../browser/content_settings_pref_provider.h | 4 +
.../core/browser/content_settings_registry.cc | 12 ++
.../core/browser/content_settings_utils.cc | 7 +
.../core/browser/host_content_settings_map.cc | 8 +
.../core/browser/host_content_settings_map.h | 3 +
.../core/common/content_settings.cc | 3 +-
.../core/common/content_settings.h | 2 +
.../core/common/content_settings.mojom | 2 +
.../common/content_settings_mojom_traits.cc | 4 +-
.../common/content_settings_mojom_traits.h | 10 +
.../core/common/content_settings_types.h | 3 +
.../core/common/pref_names.cc | 3 +
.../content_settings/core/common/pref_names.h | 2 +
.../renderer/content_settings_agent_impl.cc | 89 ++++++++
.../renderer/content_settings_agent_impl.h | 4 +
.../WebLayerSiteSettingsDelegate.java | 3 +
35 files changed, 699 insertions(+), 15 deletions(-)
create mode 100755 components/browser_ui/site_settings/android/java/res/layout/time_zone_select_dialog.xml
create mode 100755 components/browser_ui/site_settings/android/java/res/layout/timezoneoverride_site_settings_preference.xml
create mode 100755 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/TimezoneOverrideSiteSettingsPreference.java
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
@@ -41,6 +41,10 @@ import org.chromium.url.GURL;
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.
*/
@@ -248,4 +252,16 @@ public class ChromeSiteSettingsDelegate implements SiteSettingsDelegate {
mPrivacySandboxController.dismissSnackbar();
}
}
+
+ // open wiki page for documentation about the timezone override feature
+ @Override
+ public void launchTimeZoneOverrideHelpAndFeedbackActivity(Activity currentActivity) {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/bromite/bromite/wiki/TimezoneOverride"));
+ // 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);
+ }
}
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
@@ -65,6 +65,7 @@ android_library("java") {
"java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java",
"java/src/org/chromium/components/browser_ui/site_settings/WebsitePreference.java",
"java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java",
+ "java/src/org/chromium/components/browser_ui/site_settings/TimezoneOverrideSiteSettingsPreference.java"
]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
resources_package = "org.chromium.components.browser_ui.site_settings"
@@ -160,6 +161,8 @@ android_resources("java_resources") {
"java/res/xml/single_website_preferences.xml",
"java/res/xml/site_settings_preferences.xml",
"java/res/xml/website_preferences.xml",
+ "java/res/layout/timezoneoverride_site_settings_preference.xml",
+ "java/res/layout/time_zone_select_dialog.xml",
]
deps = [
diff --git a/components/browser_ui/site_settings/android/java/res/layout/time_zone_select_dialog.xml b/components/browser_ui/site_settings/android/java/res/layout/time_zone_select_dialog.xml
new file mode 100755
--- /dev/null
+++ b/components/browser_ui/site_settings/android/java/res/layout/time_zone_select_dialog.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ This file is part of Bromite.
+
+ Bromite is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bromite is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bromite. If not, see <https://www.gnu.org/licenses/>.
+-->
+
+<!-- Layout used by the TimezoneOverrideSettingsPreference. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ style="@style/AlertDialogContent">
+
+ <ListView
+ android:id="@+id/listView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginTop="8dp"
+ android:choiceMode="singleChoice"
+ android:listSelector="#666666"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/components/browser_ui/site_settings/android/java/res/layout/timezoneoverride_site_settings_preference.xml b/components/browser_ui/site_settings/android/java/res/layout/timezoneoverride_site_settings_preference.xml
new file mode 100755
--- /dev/null
+++ b/components/browser_ui/site_settings/android/java/res/layout/timezoneoverride_site_settings_preference.xml
@@ -0,0 +1,68 @@
+<!--
+ This file is part of Bromite.
+
+ Bromite is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bromite is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bromite. If not, see <https://www.gnu.org/licenses/>.
+-->
+
+<!-- Layout used by the TimezoneOverrideSettingsPreference. -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:focusable="false"
+ android:orientation="vertical">
+
+ <org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout
+ android:id="@+id/radio_button_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <org.chromium.components.browser_ui.widget.RadioButtonWithDescription
+ android:id="@+id/allowed"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ app:primaryText="@string/website_settings_category_timezone_override_allowed" />
+
+ <org.chromium.components.browser_ui.widget.RadioButtonWithDescription
+ android:id="@+id/blocked"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ app:primaryText="@string/website_settings_category_timezone_override_random" />
+
+ <org.chromium.components.browser_ui.widget.RadioButtonWithEditText
+ android:id="@+id/ask"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:inputType="text"
+ android:hint="@string/website_settings_category_timezone_override_custom_hint"
+ app:descriptionText="@string/website_settings_category_timezone_override_custom" />
+
+ </org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout>
+
+ <org.chromium.ui.widget.ButtonCompat
+ android:id="@+id/select_button"
+ style="@style/TextButton"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="16dp"
+ android:paddingTop="16dp"
+ android:text="@string/website_settings_select_button"
+ app:verticalInset="0dp" />
+
+</LinearLayout>
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
@@ -41,6 +41,10 @@
<org.chromium.components.browser_ui.settings.ChromeBasePreference
android:fragment="org.chromium.components.browser_ui.site_settings.SingleCategorySettings"
android:key="javascript" />
+ <!-- Timezone Override -->
+ <org.chromium.components.browser_ui.settings.ChromeBasePreference
+ android:key="timezone_override"
+ android:fragment="org.chromium.components.browser_ui.site_settings.SingleCategorySettings" />
<!-- Popups -->
<org.chromium.components.browser_ui.settings.ChromeBasePreference
android:fragment="org.chromium.components.browser_ui.site_settings.SingleCategorySettings"
diff --git a/components/browser_ui/site_settings/android/java/res/xml/website_preferences.xml b/components/browser_ui/site_settings/android/java/res/xml/website_preferences.xml
--- a/components/browser_ui/site_settings/android/java/res/xml/website_preferences.xml
+++ b/components/browser_ui/site_settings/android/java/res/xml/website_preferences.xml
@@ -13,6 +13,12 @@
android:key="cookie_info_text"
android:summary="@string/website_settings_cookie_info"/>
+ <!-- A text message describing timeoverride settings. -->
+ <org.chromium.components.browser_ui.settings.TextMessagePreference
+ android:key="timeoverride_info_text"
+ android:summary="@string/website_settings_timeoverride_info"/>
+
+
<!-- A common binary toggle, only shown for specific categories that allow
turning default values for that category on/off.-->
<org.chromium.components.browser_ui.settings.ChromeSwitchPreference
@@ -26,6 +32,9 @@
<!-- A four state toggle for cookie preferences, only shown for the Cookies category. -->
<org.chromium.components.browser_ui.site_settings.FourStateCookieSettingsPreference
android:key="four_state_cookie_toggle" />
+ <!-- A specific state toggle for time override preferences, only shown for the TimeOverride category. -->
+ <org.chromium.components.browser_ui.site_settings.TimezoneOverrideSiteSettingsPreference
+ android:key="timeoverride_state_toggle" />
<!-- A checkbox for enabling a quiet ui for notification prompts. Only shown in the Notifications category. -->
<org.chromium.components.browser_ui.settings.ChromeBaseCheckBoxPreference
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
@@ -276,6 +276,12 @@ public class ContentSettingsResources {
ContentSettingValues.ASK, ContentSettingValues.BLOCK,
R.string.website_settings_category_vr_ask,
R.string.website_settings_category_vr_blocked);
+
+ case ContentSettingsType.TIMEZONE_OVERRIDE:
+ return new ResourceItem(R.drawable.web_asset, 0, R.string.timezone_override_permission_title,
+ ContentSettingValues.ALLOW, ContentSettingValues.BLOCK,
+ R.string.website_settings_category_timezone_override_custom,
+ R.string.website_settings_category_timezone_override_random);
}
assert false; // NOTREACHED
return null;
@@ -441,6 +447,23 @@ public class ContentSettingsResources {
}
}
+ public static int getCategorySummary(int contentType, @Nullable @ContentSettingValues int value) {
+ if (contentType == ContentSettingsType.TIMEZONE_OVERRIDE) {
+ switch (value) {
+ case ContentSettingValues.ALLOW:
+ return R.string.website_settings_category_timezone_override_allowed;
+ case ContentSettingValues.ASK:
+ return R.string.website_settings_category_timezone_override_custom;
+ case ContentSettingValues.BLOCK:
+ return R.string.website_settings_category_timezone_override_random;
+ default:
+ return 0;
+ }
+ }
+ else
+ return getCategorySummary(value);
+ }
+
/**
* Returns the string resource id for a content type to show with a permission category.
* @param enabled Whether the content type is enabled.
@@ -455,7 +478,10 @@ public class ContentSettingsResources {
* with a particular website.
* @param value The ContentSetting for which we want the resource.
*/
- public static int getSiteSummary(@ContentSettingValues @Nullable Integer value) {
+ public static int getSiteSummary(int contentType, @ContentSettingValues @Nullable Integer value) {
+ if (contentType == ContentSettingsType.TIMEZONE_OVERRIDE)
+ return getCategorySummary(contentType, value);
+
switch (value) {
case ContentSettingValues.ALLOW:
return R.string.website_settings_permissions_allow;
@@ -561,6 +587,13 @@ public class ContentSettingsResources {
return descriptionIDs;
}
}
+ else if (contentType == ContentSettingsType.TIMEZONE_OVERRIDE) {
+ int[] descriptionIDs = {
+ R.string.website_settings_category_timezone_override_allowed, // ALLOWED
+ R.string.website_settings_category_timezone_override_custom, // ASK
+ R.string.website_settings_category_timezone_override_random}; // BLOCKED
+ return descriptionIDs;
+ }
assert false;
return null;
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
@@ -58,6 +58,10 @@ import org.chromium.ui.widget.Toast;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import android.app.Activity;
+import android.content.Intent;
+import org.chromium.components.browser_ui.site_settings.TimezoneOverrideSiteSettingsPreference;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -163,6 +167,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
public static final String BINARY_TOGGLE_KEY = "binary_toggle";
public static final String TRI_STATE_TOGGLE_KEY = "tri_state_toggle";
public static final String FOUR_STATE_COOKIE_TOGGLE_KEY = "four_state_cookie_toggle";
+ public static final String TIMEOVERRIDE_STATE_TOGGLE_KEY = "timeoverride_state_toggle";
// Keys for category-specific preferences (toggle, link, button etc.), dynamically shown.
public static final String NOTIFICATIONS_VIBRATE_TOGGLE_KEY = "notifications_vibrate";
@@ -170,6 +175,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
public static final String EXPLAIN_PROTECTED_MEDIA_KEY = "protected_content_learn_more";
private static final String ADD_EXCEPTION_KEY = "add_exception";
public static final String COOKIE_INFO_TEXT_KEY = "cookie_info_text";
+ public static final String TIMEOVERRIDE_INFO_TEXT = "timeoverride_info_text";
// Keys for Allowed/Blocked preference groups/headers.
private static final String ALLOWED_GROUP = "allowed_group";
@@ -247,7 +253,10 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
Integer contentSetting = website.site().getContentSetting(
browserContextHandle, SiteSettingsCategory.contentSettingsType(i));
if (contentSetting != null) {
- return ContentSettingValues.BLOCK == contentSetting;
+ if (i == SiteSettingsCategory.Type.TIMEZONE_OVERRIDE)
+ return ContentSettingValues.ALLOW != contentSetting;
+ else
+ return ContentSettingValues.BLOCK == contentSetting;
}
}
return false;
@@ -407,7 +416,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
if (queryHasChanged) getInfoForOrigins();
});
- if (getSiteSettingsDelegate().isHelpAndFeedbackEnabled()) {
+ if (getSiteSettingsDelegate().isHelpAndFeedbackEnabled() ||
+ mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE) ) {
MenuItem help = menu.add(
Menu.NONE, R.id.menu_id_site_settings_help, Menu.NONE, R.string.menu_help);
help.setIcon(VectorDrawableCompat.create(
@@ -418,7 +428,10 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.menu_id_site_settings_help) {
- if (mCategory.showSites(SiteSettingsCategory.Type.PROTECTED_MEDIA)) {
+ if (mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE)) {
+ getSiteSettingsDelegate()
+ .launchTimeZoneOverrideHelpAndFeedbackActivity(getActivity());
+ } else if (mCategory.showSites(SiteSettingsCategory.Type.PROTECTED_MEDIA)) {
getSiteSettingsDelegate().launchProtectedContentHelpAndFeedbackActivity(
getActivity());
} else {
@@ -497,6 +510,12 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
WebsitePreferenceBridge.setDefaultContentSetting(
browserContextHandle, mCategory.getContentSettingsType(), setting);
getInfoForOrigins();
+ } else if (TIMEOVERRIDE_STATE_TOGGLE_KEY.equals(preference.getKey())) {
+ @ContentSettingValues
+ int setting = (int) newValue;
+ WebsitePreferenceBridge.setDefaultContentSetting(
+ browserContextHandle, ContentSettingsType.TIMEZONE_OVERRIDE, setting);
+ getInfoForOrigins();
} else if (FOUR_STATE_COOKIE_TOGGLE_KEY.equals(preference.getKey())) {
setCookieSettingsPreference((CookieSettingsState) newValue);
getInfoForOrigins();
@@ -594,6 +613,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
assert WebsitePreferenceBridge.isCategoryEnabled(
browserContextHandle, ContentSettingsType.AUTO_DARK_WEB_CONTENT);
resource = R.string.website_settings_add_site_description_auto_dark_block;
+ } else if (mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE)) {
+ resource = R.string.website_settings_category_timezone_override_allowed;
}
assert resource > 0;
return getString(resource);
@@ -634,6 +655,13 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
if (mCategory.showSites(SiteSettingsCategory.Type.COOKIES) && mRequiresFourStateSetting) {
setting = cookieSettingsExceptionShouldBlock() ? ContentSettingValues.BLOCK
: ContentSettingValues.ALLOW;
+ } else if (mRequiresTriStateSetting) {
+ setting = WebsitePreferenceBridge.getDefaultContentSetting(browserContextHandle, mCategory.getContentSettingsType());
+ if (setting == ContentSettingValues.ALLOW) {
+ setting = ContentSettingValues.BLOCK;
+ } else {
+ setting = ContentSettingValues.ALLOW;
+ }
} else {
setting = (WebsitePreferenceBridge.isCategoryEnabled(
browserContextHandle, mCategory.getContentSettingsType()))
@@ -696,6 +724,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
&& WebsitePreferenceBridge.isCategoryEnabled(
browserContextHandle, ContentSettingsType.AUTO_DARK_WEB_CONTENT)) {
exception = true;
+ } else if (mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE)) {
+ exception = true;
}
if (exception) {
getPreferenceScreen().addPreference(new AddExceptionPreference(getStyledContext(),
@@ -867,7 +897,14 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
TriStateSiteSettingsPreference triStateToggle =
(TriStateSiteSettingsPreference) getPreferenceScreen().findPreference(
TRI_STATE_TOGGLE_KEY);
- return (triStateToggle.getCheckedSetting() == ContentSettingValues.BLOCK);
+ if (triStateToggle != null)
+ return (triStateToggle.getCheckedSetting() == ContentSettingValues.BLOCK);
+
+ TimezoneOverrideSiteSettingsPreference timeOverrideStatePreference =
+ (TimezoneOverrideSiteSettingsPreference) getPreferenceScreen().findPreference(
+ TIMEOVERRIDE_STATE_TOGGLE_KEY);
+ if (timeOverrideStatePreference != null)
+ return (timeOverrideStatePreference.getCheckedSetting() != ContentSettingValues.ALLOW);
} else if (mRequiresFourStateSetting) {
FourStateCookieSettingsPreference fourStateCookieToggle =
(FourStateCookieSettingsPreference) getPreferenceScreen().findPreference(
@@ -896,6 +933,9 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
(FourStateCookieSettingsPreference) screen.findPreference(
FOUR_STATE_COOKIE_TOGGLE_KEY);
// TODO(crbug.com/1104836): Remove the old third-party cookie blocking UI
+ TimezoneOverrideSiteSettingsPreference timeOverrideStatePreference =
+ (TimezoneOverrideSiteSettingsPreference) screen.findPreference(
+ TIMEOVERRIDE_STATE_TOGGLE_KEY);
Preference notificationsVibrate = screen.findPreference(NOTIFICATIONS_VIBRATE_TOGGLE_KEY);
Preference notificationsQuietUi = screen.findPreference(NOTIFICATIONS_QUIET_UI_TOGGLE_KEY);
Preference explainProtectedMediaKey = screen.findPreference(EXPLAIN_PROTECTED_MEDIA_KEY);
@@ -907,20 +947,32 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
if (mRequiresTriStateSetting) {
screen.removePreference(binaryToggle);
screen.removePreference(fourStateCookieToggle);
- configureTriStateToggle(triStateToggle, contentType);
+ if (mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE)) {
+ screen.removePreference(triStateToggle);
+ configureTimeOverrideStateToggle(timeOverrideStatePreference);
+ }
+ else {
+ screen.removePreference(timeOverrideStatePreference);
+ configureTriStateToggle(triStateToggle, contentType);
+ }
} else if (mRequiresFourStateSetting) {
screen.removePreference(binaryToggle);
screen.removePreference(triStateToggle);
+ screen.removePreference(timeOverrideStatePreference);
configureFourStateCookieToggle(fourStateCookieToggle);
} else {
screen.removePreference(triStateToggle);
screen.removePreference(fourStateCookieToggle);
+ screen.removePreference(timeOverrideStatePreference);
configureBinaryToggle(binaryToggle, contentType);
}
if (!mCategory.showSites(SiteSettingsCategory.Type.COOKIES)) {
screen.removePreference(screen.findPreference(COOKIE_INFO_TEXT_KEY));
}
+ if (!(mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE))) {
+ screen.removePreference(screen.findPreference(TIMEOVERRIDE_INFO_TEXT));
+ }
if (permissionBlockedByOs) {
maybeShowOsWarning(screen);
@@ -1035,6 +1087,15 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
triStateToggle.initialize(setting, descriptionIds);
}
+ private void configureTimeOverrideStateToggle(
+ TimezoneOverrideSiteSettingsPreference timeOverrideStateToggle) {
+ timeOverrideStateToggle.setOnPreferenceChangeListener(this);
+ @ContentSettingValues
+ int setting = WebsitePreferenceBridge.getDefaultContentSetting(
+ getSiteSettingsDelegate().getBrowserContextHandle(), ContentSettingsType.TIMEZONE_OVERRIDE);
+ timeOverrideStateToggle.initialize(setting, getSiteSettingsDelegate().getBrowserContextHandle());
+ }
+
private void configureBinaryToggle(ChromeSwitchPreference binaryToggle, int contentType) {
binaryToggle.setOnPreferenceChangeListener(this);
binaryToggle.setTitle(ContentSettingsResources.getTitle(contentType));
@@ -1118,9 +1179,11 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
CharSequence[] descriptions = new String[2];
descriptions[0] =
- getString(ContentSettingsResources.getSiteSummary(ContentSettingValues.ALLOW));
+ getString(ContentSettingsResources.getSiteSummary(contentSettingsType,
+ ContentSettingValues.ALLOW));
descriptions[1] =
- getString(ContentSettingsResources.getSiteSummary(ContentSettingValues.BLOCK));
+ getString(ContentSettingsResources.getSiteSummary(contentSettingsType,
+ ContentSettingValues.BLOCK));
return new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog)
.setPositiveButton(R.string.cancel, null)
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
@@ -127,6 +127,8 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
return "popup_permission_list";
case ContentSettingsType.SOUND:
return "sound_permission_list";
+ case ContentSettingsType.TIMEZONE_OVERRIDE:
+ return "timezone_override_permission_list";
case ContentSettingsType.AR:
return "ar_permission_list";
case ContentSettingsType.MEDIASTREAM_CAMERA:
@@ -886,11 +888,13 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
if (value == null) return;
setUpPreferenceCommon(preference, value);
+ int content_type = getContentSettingsTypeFromPreferenceKey(preference.getKey());
+
ChromeSwitchPreference switchPreference = (ChromeSwitchPreference) preference;
switchPreference.setChecked(value == ContentSettingValues.ALLOW);
switchPreference.setSummary(isEmbargoed
? getString(R.string.automatically_blocked)
- : getString(ContentSettingsResources.getCategorySummary(value)));
+ : getString(ContentSettingsResources.getCategorySummary(content_type, value)));
switchPreference.setOnPreferenceChangeListener(this);
@ContentSettingsType
int contentType = getContentSettingsTypeFromPreferenceKey(preference.getKey());
@@ -1109,7 +1113,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
preference.setSummary(getDSECategorySummary(permission));
} else {
preference.setSummary(
- getString(ContentSettingsResources.getCategorySummary(permission)));
+ getString(ContentSettingsResources.getCategorySummary(type, permission)));
}
preference.setIcon(getContentSettingsIcon(type, permission));
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
@@ -117,7 +117,7 @@ public class SiteSettings
} else if (Type.AUTO_DARK_WEB_CONTENT == prefCategory) {
p.setSummary(ContentSettingsResources.getAutoDarkWebContentListSummary(checked));
} else if (requiresTriStateSetting) {
- p.setSummary(ContentSettingsResources.getCategorySummary(setting));
+ p.setSummary(ContentSettingsResources.getCategorySummary(contentType, setting));
} else {
p.setSummary(ContentSettingsResources.getCategorySummary(contentType, checked));
}
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
@@ -42,7 +42,8 @@ public class SiteSettingsCategory {
Type.CLIPBOARD, Type.COOKIES, Type.IDLE_DETECTION, Type.DEVICE_LOCATION,
Type.JAVASCRIPT, Type.MICROPHONE, Type.NFC, Type.NOTIFICATIONS, Type.POPUPS,
Type.PROTECTED_MEDIA, Type.SENSORS, Type.SOUND, Type.USB, Type.VIRTUAL_REALITY,
- Type.USE_STORAGE, Type.AUTO_DARK_WEB_CONTENT, Type.REQUEST_DESKTOP_SITE})
+ Type.USE_STORAGE, Type.AUTO_DARK_WEB_CONTENT, Type.REQUEST_DESKTOP_SITE,
+ Type.TIMEZONE_OVERRIDE})
@Retention(RetentionPolicy.SOURCE)
public @interface Type {
// All updates here must also be reflected in {@link #preferenceKey(int)
@@ -72,10 +73,11 @@ public class SiteSettingsCategory {
int USE_STORAGE = 22;
int AUTO_DARK_WEB_CONTENT = 23;
int REQUEST_DESKTOP_SITE = 24;
+ int TIMEZONE_OVERRIDE = 25;
/**
* Number of handled categories used for calculating array sizes.
*/
- int NUM_ENTRIES = 25;
+ int NUM_ENTRIES = 26;
}
private final BrowserContextHandle mBrowserContextHandle;
@@ -198,6 +200,8 @@ public class SiteSettingsCategory {
return ContentSettingsType.USB_GUARD;
case Type.VIRTUAL_REALITY:
return ContentSettingsType.VR;
+ case Type.TIMEZONE_OVERRIDE:
+ return ContentSettingsType.TIMEZONE_OVERRIDE;
// case Type.ALL_SITES
// case Type.USE_STORAGE
default:
@@ -276,6 +280,8 @@ public class SiteSettingsCategory {
return "use_storage";
case Type.VIRTUAL_REALITY:
return "virtual_reality";
+ case Type.TIMEZONE_OVERRIDE:
+ return "timezone_override";
default:
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
@@ -119,4 +119,6 @@ public interface SiteSettingsDelegate {
* Dismisses the Privacy Sandbox snackbar, if active.
*/
void dismissPrivacySandboxSnackbar();
+
+ void launchTimeZoneOverrideHelpAndFeedbackActivity(Activity currentActivity);
}
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/TimezoneOverrideSiteSettingsPreference.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/TimezoneOverrideSiteSettingsPreference.java
new file mode 100755
--- /dev/null
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/TimezoneOverrideSiteSettingsPreference.java
@@ -0,0 +1,193 @@
+/*
+ This file is part of Bromite.
+
+ Bromite is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bromite is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bromite. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+package org.chromium.components.browser_ui.site_settings;
+
+import org.chromium.base.Log;
+import android.content.Context;
+import android.content.Intent;
+import android.content.DialogInterface;
+import android.view.View;
+import android.widget.RadioGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.util.AttributeSet;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.view.LayoutInflater;
+import android.widget.AdapterView;
+import android.graphics.Color;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+import androidx.appcompat.app.AlertDialog;
+
+import org.chromium.content_public.browser.BrowserContextHandle;
+import org.chromium.components.content_settings.ContentSettingValues;
+import org.chromium.components.browser_ui.site_settings.WebsitePreferenceBridge;
+import org.chromium.components.browser_ui.widget.RadioButtonWithDescription;
+import org.chromium.components.browser_ui.widget.RadioButtonWithEditText;
+import org.chromium.components.browser_ui.widget.TintedDrawable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.TimeZone;
+
+/**
+ * TimezoneOverride Preference for SiteSettings.
+ */
+public class TimezoneOverrideSiteSettingsPreference
+ extends Preference implements RadioGroup.OnCheckedChangeListener,
+ RadioButtonWithEditText.OnTextChangeListener {
+ private @ContentSettingValues int mSetting = ContentSettingValues.DEFAULT;
+ private RadioButtonWithDescription mAllowed;
+ private RadioButtonWithEditText mAsk;
+ private RadioButtonWithDescription mBlocked;
+ private RadioGroup mRadioGroup;
+ private TextView mSelectButton;
+
+ private String currentSelected;
+
+ private BrowserContextHandle mBrowserContextHandle;
+
+ public TimezoneOverrideSiteSettingsPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ setLayoutResource(R.layout.timezoneoverride_site_settings_preference);
+ setSelectable(false);
+ }
+
+ public void initialize(@ContentSettingValues int setting, BrowserContextHandle browserContextHandle) {
+ mSetting = setting;
+ mBrowserContextHandle = browserContextHandle;
+ }
+
+ public @ContentSettingValues int getCheckedSetting() {
+ return mSetting;
+ }
+
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ if (mAllowed.isChecked()) {
+ mSetting = ContentSettingValues.ALLOW;
+ } else if (mAsk.isChecked()) {
+ mSetting = ContentSettingValues.ASK;
+ } else if (mBlocked.isChecked()) {
+ mSetting = ContentSettingValues.BLOCK;
+ }
+
+ callChangeListener(mSetting);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ mAllowed = (RadioButtonWithDescription) holder.findViewById(R.id.allowed);
+ mAsk = (RadioButtonWithEditText) holder.findViewById(R.id.ask);
+ mBlocked = (RadioButtonWithDescription) holder.findViewById(R.id.blocked);
+ mRadioGroup = (RadioGroup) holder.findViewById(R.id.radio_button_layout);
+ mRadioGroup.setOnCheckedChangeListener(this);
+
+ mAsk.setPrimaryText(WebsitePreferenceBridge.getCustomTimezone(mBrowserContextHandle));
+ mAsk.addTextChangeListener(this);
+
+ ListView listView = (ListView)holder.findViewById(R.id.listView);
+
+ mSelectButton = (TextView) holder.findViewById(R.id.select_button);
+ mSelectButton.setOnClickListener(view -> {
+ showSelectTimeZoneDialog();
+ });
+
+ RadioButtonWithDescription radioButton = findRadioButton(mSetting);
+ if (radioButton != null) radioButton.setChecked(true);
+ }
+
+ private RadioButtonWithDescription findRadioButton(@ContentSettingValues int setting) {
+ if (setting == ContentSettingValues.ALLOW) {
+ return mAllowed;
+ } else if (setting == ContentSettingValues.ASK) {
+ return mAsk;
+ } else if (setting == ContentSettingValues.BLOCK) {
+ return mBlocked;
+ } else {
+ return null;
+ }
+ }
+
+ public void onTextChanged(CharSequence newText) {
+ WebsitePreferenceBridge.setCustomTimezone(mBrowserContextHandle, newText.toString());
+ }
+
+ private void showSelectTimeZoneDialog() {
+ LayoutInflater inflater =
+ (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ View view = inflater.inflate(R.layout.time_zone_select_dialog, null);
+
+ ListView listView = view.findViewById(R.id.listView);
+ ArrayList<String> timezones = new ArrayList<>(Arrays.asList(TimeZone.getAvailableIDs()));
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1, android.R.id.text1, timezones);
+ listView.setAdapter(adapter);
+
+ currentSelected = String.valueOf(mAsk.getPrimaryText());
+ listView.post(new Runnable()
+ {
+ public void run()
+ {
+ for (int j = 0; j < timezones.size(); j++) {
+ if (currentSelected.equals(timezones.get(j))) {
+ listView.requestFocusFromTouch();
+ listView.setSelection(j);
+ adapter.notifyDataSetChanged();
+ break;
+ }
+ }
+ }
+ });
+
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
+ currentSelected = timezones.get(i);
+ listView.setSelected(true);
+ }
+ });
+
+ DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int button) {
+ if (button == AlertDialog.BUTTON_POSITIVE) {
+ mAsk.setPrimaryText(currentSelected);
+ } else {
+ dialog.dismiss();
+ }
+ }
+ };
+
+ AlertDialog.Builder alert =
+ new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog);
+ AlertDialog alertDialog =
+ alert.setTitle(R.string.website_settings_select_dialog_title)
+ .setView(view)
+ .setPositiveButton(
+ R.string.website_settings_select_dialog_button, onClickListener)
+ .setNegativeButton(R.string.cancel, onClickListener)
+ .create();
+ alertDialog.getDelegate().setHandleNativeActionModesEnabled(false);
+ alertDialog.show();
+ }
+}
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
@@ -229,6 +229,16 @@ public final class Website implements Serializable {
} else {
RecordUserAction.record("SoundContentSetting.UnmuteBy.SiteSettings");
}
+ } else if (type == ContentSettingsType.TIMEZONE_OVERRIDE) {
+ // It is possible to set the permission without having an existing exception,
+ // because we can show the ALLOW state even when this permission is set to the
+ // default. In that case, just set an exception now to ALLOW to enable changing the
+ // permission.
+ if (exception == null) {
+ exception = new ContentSettingException(
+ ContentSettingsType.TIMEZONE_OVERRIDE, getAddress().getHost(), value, "");
+ setContentSettingException(type, exception);
+ }
}
// We want to call setContentSetting even after explicitly setting
// mContentSettingException above because this will trigger the actual change
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java
@@ -67,6 +67,7 @@ public class WebsitePermissionsFetcher {
case ContentSettingsType.JAVASCRIPT_JIT:
case ContentSettingsType.POPUPS:
case ContentSettingsType.SOUND:
+ case ContentSettingsType.TIMEZONE_OVERRIDE:
return WebsitePermissionsType.CONTENT_SETTING_EXCEPTION;
case ContentSettingsType.AR:
case ContentSettingsType.CLIPBOARD_READ_WRITE:
@@ -147,6 +148,8 @@ public class WebsitePermissionsFetcher {
for (@ContentSettingsType int type = 0; type < ContentSettingsType.NUM_TYPES; type++) {
addFetcherForContentSettingsType(queue, type);
}
+ queue.add(new ExceptionInfoFetcher(ContentSettingsType.TIMEZONE_OVERRIDE));
+
queue.add(new PermissionsAvailableCallbackRunner(callback));
queue.next();
}
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
@@ -231,6 +231,8 @@ public class WebsitePreferenceBridge {
switch (contentSettingsType) {
case ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER:
return true;
+ case ContentSettingsType.TIMEZONE_OVERRIDE:
+ return true;
default:
return false;
}
@@ -361,6 +363,14 @@ public class WebsitePreferenceBridge {
contentSettingType, primaryPattern, secondaryPattern, setting);
}
+ public static String getCustomTimezone(BrowserContextHandle browserContextHandle) {
+ return WebsitePreferenceBridgeJni.get().getCustomTimezone(browserContextHandle);
+ }
+
+ public static void setCustomTimezone(BrowserContextHandle browserContextHandle, String timezone) {
+ WebsitePreferenceBridgeJni.get().setCustomTimezone(browserContextHandle, timezone);
+ }
+
@NativeMethods
public interface Natives {
boolean isNotificationEmbargoedForOrigin(
@@ -424,5 +434,7 @@ public class WebsitePreferenceBridge {
boolean isContentSettingManagedByCustodian(
BrowserContextHandle browserContextHandle, int contentSettingType);
boolean getLocationAllowedByPolicy(BrowserContextHandle browserContextHandle);
+ String getCustomTimezone(BrowserContextHandle browserContextHandle);
+ void setCustomTimezone(BrowserContextHandle browserContextHandle, String timezone);
}
}
diff --git a/components/browser_ui/site_settings/android/website_preference_bridge.cc b/components/browser_ui/site_settings/android/website_preference_bridge.cc
--- a/components/browser_ui/site_settings/android/website_preference_bridge.cc
+++ b/components/browser_ui/site_settings/android/website_preference_bridge.cc
@@ -947,3 +947,19 @@ static jboolean JNI_WebsitePreferenceBridge_GetLocationAllowedByPolicy(
->GetDefaultContentSetting(ContentSettingsType::GEOLOCATION,
nullptr) == CONTENT_SETTING_ALLOW;
}
+
+static void JNI_WebsitePreferenceBridge_SetCustomTimezone(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& jbrowser_context_handle,
+ const JavaParamRef<jstring>& timezone) {
+ std::string new_timezone = ConvertJavaStringToUTF8(env, timezone);
+ GetHostContentSettingsMap(jbrowser_context_handle)->SetTimezoneOverrideValue(new_timezone);
+}
+
+static base::android::ScopedJavaLocalRef<jstring> JNI_WebsitePreferenceBridge_GetCustomTimezone(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& jbrowser_context_handle) {
+ std::string timezone;
+ GetHostContentSettingsMap(jbrowser_context_handle)->GetTimezoneOverrideValue(timezone);
+ return ConvertUTF8ToJavaString(env, timezone);
+}
diff --git a/components/browser_ui/strings/android/site_settings.grdp b/components/browser_ui/strings/android/site_settings.grdp
--- a/components/browser_ui/strings/android/site_settings.grdp
+++ b/components/browser_ui/strings/android/site_settings.grdp
@@ -72,6 +72,9 @@
<message name="IDS_AUTO_DARK_WEB_CONTENT_TITLE" desc="Title of the permission auto darken web content [CHAR_LIMIT=32]">
Dark theme for sites
</message>
+ <message name="IDS_TIMEZONE_OVERRIDE_PERMISSION_TITLE" desc="Title of the permission to use TimeZone Override [CHAR-LIMIT=32]">
+ Timezone override
+ </message>
<message name="IDS_DESKTOP_SITE_TITLE" desc="Title of the permission to request the desktop view of a site by default [CHAR_LIMIT=32]">
Desktop site
</message>
@@ -480,6 +483,38 @@
Block sites from playing protected content
</message>
+ <!-- Timezone override -->
+ <message name="IDS_WEBSITE_SETTINGS_TIMEOVERRIDE_INFO" desc="Primary text explaining the timezone override feature.">
+ Override timezone with a custom or random one, or use the system timezone
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_ALLOWED_TEXT" desc="Primary text explaining that sites are allowed to access the system timezone.">
+ None (use system timezone)
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_RANDOM_TEXT" desc="Primary text for random timezone override.">
+ Random
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_ALLOWED" desc="Summary text explaining that sites are allowed to access the system timezone.">
+ System timezone
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_CUSTOM" desc="Summary text explaining that sites use custom timezone.">
+ Custom timezone
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_CUSTOM_HINT" desc="Hint text for edit custom timezone.">
+ Specify a custom timezone (default UTC)
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_RANDOM" desc="Summary text for random timezone override.">
+ Random (for each page)
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_SELECT_BUTTON" desc="Primary button text for choosing a timezone from a list.">
+ Choose Timezone...
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_SELECT_DIALOG_TITLE" desc="Text of the dialog to choose a timezone.">
+ Choose Timezone
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_SELECT_DIALOG_BUTTON" desc="Primary button text in the dialog used to choose the custom timezone.">
+ Select
+ </message>
+
<!-- Sound -->
<message name="IDS_WEBSITE_SETTINGS_CATEGORY_SOUND_ALLOWED" desc="Summary text explaining that sites are allowed to play sound and that it is the recommended setting.">
diff --git a/components/content_settings/core/browser/content_settings_pref_provider.cc b/components/content_settings/core/browser/content_settings_pref_provider.cc
--- a/components/content_settings/core/browser/content_settings_pref_provider.cc
+++ b/components/content_settings/core/browser/content_settings_pref_provider.cc
@@ -78,6 +78,8 @@ void PrefProvider::RegisterProfilePrefs(
info->GetPrefRegistrationFlags());
}
+ registry->RegisterStringPref(prefs::kContentSettingsCustomTimezone, std::string());
+
// Obsolete prefs ----------------------------------------------------------
// These prefs have been removed, but need to be registered so they can
@@ -157,6 +159,10 @@ PrefProvider::PrefProvider(PrefService* prefs,
event_args->set_number_of_exceptions(
num_exceptions); // PrefProvider::PrefProvider.
});
+
+ custom_timezone_ =
+ prefs_->GetString(
+ prefs::kContentSettingsCustomTimezone);
}
PrefProvider::~PrefProvider() {
@@ -284,4 +290,14 @@ void PrefProvider::SetClockForTesting(base::Clock* clock) {
clock_ = clock;
}
+void PrefProvider::GetPrefTimezoneOverrideValue(std::string& timezone) const {
+ timezone = custom_timezone_;
+}
+
+void PrefProvider::SetPrefTimezoneOverrideValue(const std::string& timezone) {
+ prefs_->SetString(
+ prefs::kContentSettingsCustomTimezone, timezone);
+ custom_timezone_ = timezone;
+}
+
} // namespace content_settings
diff --git a/components/content_settings/core/browser/content_settings_pref_provider.h b/components/content_settings/core/browser/content_settings_pref_provider.h
--- a/components/content_settings/core/browser/content_settings_pref_provider.h
+++ b/components/content_settings/core/browser/content_settings_pref_provider.h
@@ -66,6 +66,9 @@ class PrefProvider : public UserModifiableProvider {
ContentSettingsPref* GetPref(ContentSettingsType type) const;
+ void GetPrefTimezoneOverrideValue(std::string& timezone) const;
+ void SetPrefTimezoneOverrideValue(const std::string& timezone);
+
private:
friend class DeadlockCheckerObserver; // For testing.
@@ -97,6 +100,7 @@ class PrefProvider : public UserModifiableProvider {
base::ThreadChecker thread_checker_;
base::Clock* clock_;
+ std::string custom_timezone_;
};
} // namespace content_settings
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
@@ -638,6 +638,18 @@ void ContentSettingsRegistry::Init() {
ContentSettingsInfo::INHERIT_IN_INCOGNITO,
ContentSettingsInfo::PERSISTENT,
ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS);
+
+ Register(ContentSettingsType::TIMEZONE_OVERRIDE, "timezone-override", CONTENT_SETTING_ALLOW,
+ WebsiteSettingsInfo::SYNCABLE,
+ AllowlistedSchemes(kChromeUIScheme, kChromeDevToolsScheme),
+ ValidSettings(CONTENT_SETTING_ALLOW, // use system time
+ CONTENT_SETTING_ASK, // custom timezone, default UTC
+ CONTENT_SETTING_BLOCK), // random
+ WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
+ WebsiteSettingsRegistry::PLATFORM_ANDROID,
+ ContentSettingsInfo::INHERIT_IN_INCOGNITO,
+ ContentSettingsInfo::PERSISTENT,
+ ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS);
}
void ContentSettingsRegistry::Register(
diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc
--- a/components/content_settings/core/browser/content_settings_utils.cc
+++ b/components/content_settings/core/browser/content_settings_utils.cc
@@ -154,6 +154,13 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map,
&(rules->script_rules));
map->GetSettingsForOneType(ContentSettingsType::POPUPS,
&(rules->popup_redirect_rules));
+
+ // pass custom timezone rules and value to the render process
+ map->GetSettingsForOneType(ContentSettingsType::TIMEZONE_OVERRIDE,
+ &(rules->timezone_override_rules));
+ std::string timezone;
+ map->GetTimezoneOverrideValue(timezone);
+ rules->timezone_override_value = timezone;
}
bool IsMorePermissive(ContentSetting a, ContentSetting b) {
diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc
--- a/components/content_settings/core/browser/host_content_settings_map.cc
+++ b/components/content_settings/core/browser/host_content_settings_map.cc
@@ -588,6 +588,14 @@ void HostContentSettingsMap::SetClockForTesting(base::Clock* clock) {
provider->SetClockForTesting(clock);
}
+void HostContentSettingsMap::GetTimezoneOverrideValue(std::string& timezone) const {
+ GetPrefProvider()->GetPrefTimezoneOverrideValue(timezone);
+}
+
+void HostContentSettingsMap::SetTimezoneOverrideValue(const std::string& timezone) {
+ GetPrefProvider()->SetPrefTimezoneOverrideValue(timezone);
+}
+
void HostContentSettingsMap::RecordExceptionMetrics() {
auto* content_setting_registry =
content_settings::ContentSettingsRegistry::GetInstance();
diff --git a/components/content_settings/core/browser/host_content_settings_map.h b/components/content_settings/core/browser/host_content_settings_map.h
--- a/components/content_settings/core/browser/host_content_settings_map.h
+++ b/components/content_settings/core/browser/host_content_settings_map.h
@@ -332,6 +332,9 @@ class HostContentSettingsMap : public content_settings::Observer,
allow_invalid_secondary_pattern_for_testing_ = allow;
}
+ void GetTimezoneOverrideValue(std::string& timezone) const;
+ void SetTimezoneOverrideValue(const std::string& timezone);
+
private:
friend class base::RefCountedThreadSafe<HostContentSettingsMap>;
friend class content_settings::TestUtils;
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
@@ -190,7 +190,8 @@ bool RendererContentSettingRules::IsRendererContentSetting(
content_type == ContentSettingsType::CLIENT_HINTS ||
content_type == ContentSettingsType::POPUPS ||
content_type == ContentSettingsType::MIXEDSCRIPT ||
- content_type == ContentSettingsType::AUTO_DARK_WEB_CONTENT;
+ content_type == ContentSettingsType::AUTO_DARK_WEB_CONTENT ||
+ content_type == ContentSettingsType::TIMEZONE_OVERRIDE;
}
RendererContentSettingRules::RendererContentSettingRules() {}
diff --git a/components/content_settings/core/common/content_settings.h b/components/content_settings/core/common/content_settings.h
--- a/components/content_settings/core/common/content_settings.h
+++ b/components/content_settings/core/common/content_settings.h
@@ -80,6 +80,8 @@ struct RendererContentSettingRules {
ContentSettingsForOneType popup_redirect_rules;
ContentSettingsForOneType mixed_content_rules;
ContentSettingsForOneType auto_dark_content_rules;
+ ContentSettingsForOneType timezone_override_rules;
+ std::string timezone_override_value;
};
namespace content_settings {
diff --git a/components/content_settings/core/common/content_settings.mojom b/components/content_settings/core/common/content_settings.mojom
--- a/components/content_settings/core/common/content_settings.mojom
+++ b/components/content_settings/core/common/content_settings.mojom
@@ -78,4 +78,6 @@ struct RendererContentSettingRules {
array<ContentSettingPatternSource> popup_redirect_rules;
array<ContentSettingPatternSource> mixed_content_rules;
array<ContentSettingPatternSource> auto_dark_content_rules;
+ array<ContentSettingPatternSource> timezone_override_rules;
+ string timezone_override_value;
};
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
@@ -101,7 +101,9 @@ bool StructTraits<content_settings::mojom::RendererContentSettingRulesDataView,
data.ReadScriptRules(&out->script_rules) &&
data.ReadPopupRedirectRules(&out->popup_redirect_rules) &&
data.ReadMixedContentRules(&out->mixed_content_rules) &&
- data.ReadAutoDarkContentRules(&out->auto_dark_content_rules);
+ data.ReadAutoDarkContentRules(&out->auto_dark_content_rules) &&
+ data.ReadTimezoneOverrideRules(&out->timezone_override_rules) &&
+ data.ReadTimezoneOverrideValue(&out->timezone_override_value);
}
} // 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
@@ -150,6 +150,16 @@ struct StructTraits<
return r.auto_dark_content_rules;
}
+ static const std::vector<ContentSettingPatternSource>& timezone_override_rules(
+ const RendererContentSettingRules& r) {
+ return r.timezone_override_rules;
+ }
+
+ static const std::string& timezone_override_value(
+ const RendererContentSettingRules& r) {
+ return r.timezone_override_value;
+ }
+
static bool Read(
content_settings::mojom::RendererContentSettingRulesDataView data,
RendererContentSettingRules* out);
diff --git a/components/content_settings/core/common/content_settings_types.h b/components/content_settings/core/common/content_settings_types.h
--- a/components/content_settings/core/common/content_settings_types.h
+++ b/components/content_settings/core/common/content_settings_types.h
@@ -230,6 +230,9 @@ enum class ContentSettingsType : int32_t {
// by the File System Access API.
FILE_SYSTEM_LAST_PICKED_DIRECTORY,
+ // Content setting for timezone customization functionality.
+ TIMEZONE_OVERRIDE,
+
// Controls access to the getDisplayMedia API when {preferCurrentTab: true}
// is specified.
// TODO(crbug.com/1150788): Also apply this when getDisplayMedia() is called
diff --git a/components/content_settings/core/common/pref_names.cc b/components/content_settings/core/common/pref_names.cc
--- a/components/content_settings/core/common/pref_names.cc
+++ b/components/content_settings/core/common/pref_names.cc
@@ -144,4 +144,7 @@ const char kQuietNotificationPermissionUiDisabledTime[] =
const char kNotificationsVibrateEnabled[] = "notifications.vibrate_enabled";
#endif
+const char kContentSettingsCustomTimezone[] =
+ "profile.content_settings.custom_timezone";
+
} // namespace prefs
diff --git a/components/content_settings/core/common/pref_names.h b/components/content_settings/core/common/pref_names.h
--- a/components/content_settings/core/common/pref_names.h
+++ b/components/content_settings/core/common/pref_names.h
@@ -77,6 +77,8 @@ extern const char kQuietNotificationPermissionUiDisabledTime[];
extern const char kNotificationsVibrateEnabled[];
#endif
+extern const char kContentSettingsCustomTimezone[];
+
} // namespace prefs
#endif // COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_PREF_NAMES_H_
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
@@ -8,8 +8,10 @@
#include "base/bind.h"
#include "base/feature_list.h"
+#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
+#include "base/rand_util.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings.mojom.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
@@ -31,6 +33,10 @@
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_view.h"
+#include "third_party/blink/renderer/core/inspector/locale_controller.h"
+#include "third_party/blink/renderer/core/timezone/timezone_controller.h"
+#include "third_party/icu/source/common/unicode/strenum.h"
+#include "third_party/icu/source/i18n/unicode/timezone.h"
#include "url/gurl.h"
#include "url/origin.h"
#include "url/url_constants.h"
@@ -44,6 +50,8 @@ using blink::WebURL;
using blink::WebView;
using content::DocumentState;
+std::unique_ptr<blink::TimeZoneController::TimeZoneOverride> timezone_override_;
+
namespace content_settings {
namespace {
@@ -363,6 +371,10 @@ bool ContentSettingsAgentImpl::AllowScript(bool enabled_per_settings) {
allow = allow || IsAllowlistedForContentSettings();
cached_script_permissions_[frame] = allow;
+
+ if (allow)
+ UpdateOverrides();
+
return allow;
}
@@ -498,4 +510,81 @@ bool ContentSettingsAgentImpl::IsAllowlistedForContentSettings() const {
return false;
}
+bool ContentSettingsAgentImpl::UpdateOverrides() {
+ // Evaluate the content setting rules
+ ContentSetting setting = CONTENT_SETTING_ALLOW;
+
+ if (content_setting_rules_) {
+ blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
+
+ setting = GetContentSettingFromRules(
+ content_setting_rules_->timezone_override_rules, frame,
+ url::Origin(frame->GetDocument().GetSecurityOrigin()).GetURL());
+ }
+ return UpdateTimeZoneOverride(
+ setting, content_setting_rules_->timezone_override_value);
+ //&& UpdateLocaleOverride(setting);
+}
+
+bool ContentSettingsAgentImpl::UpdateTimeZoneOverride(
+ ContentSetting setting,
+ const std::string& timezone_override_value) {
+ // base/i18n/icu_util.cc # 329
+
+ /* timezone_id: third_party/icu/source/i18n/timezone.cpp
+ We first try to lookup the zone ID in our system list. If this
+ * fails, we try to parse it as a custom string GMT[+-]hh:mm. If
+ * all else fails, we return GMT, which is probably not what the
+ * user wants, but at least is a functioning TimeZone object.
+ */
+ String timezone_id;
+
+ if (setting == CONTENT_SETTING_ALLOW) {
+ // system time
+ if (timezone_override_) {
+ timezone_override_.reset();
+ }
+ return true;
+ } else if (setting == CONTENT_SETTING_BLOCK) {
+ // timezone random
+ UErrorCode ec = U_ZERO_ERROR;
+ int32_t rawOffset = base::RandInt(-12, 11) * 3600 * 1000;
+ icu::StringEnumeration* timezones = icu::TimeZone::createEnumeration(
+ rawOffset); // Obtain timezones by GMT timezone offset
+ if (timezones) {
+ const char* tzID;
+ int32_t length;
+ if ((tzID = timezones->next(&length, ec)) != NULL) {
+ timezone_id = String(tzID);
+ }
+ delete timezones;
+ }
+ } else if (setting == CONTENT_SETTING_ASK) {
+ if (timezone_override_value.empty())
+ timezone_id = "Europe/London";
+ else
+ timezone_id = String(timezone_override_value.c_str());
+ }
+
+ if (blink::TimeZoneController::HasTimeZoneOverride() == false) {
+ timezone_override_.reset();
+ timezone_override_ =
+ blink::TimeZoneController::SetTimeZoneOverride(timezone_id);
+ if (!timezone_override_) {
+ LOG(WARNING) << "UpdateTimeZoneOverride - Invalid timezone id '"
+ << timezone_id << "'";
+ return false;
+ } else {
+ LOG(INFO)
+ << "UpdateTimeZoneOverride - setting to '"
+ << timezone_id << "'";
+ return true;
+ }
+ } else {
+ LOG(INFO)
+ << "UpdateTimeZoneOverride: already set";
+ return false;
+ }
+}
+
} // namespace content_settings
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
@@ -185,6 +185,10 @@ class ContentSettingsAgentImpl
std::unique_ptr<Delegate> delegate_;
mojo::AssociatedReceiverSet<mojom::ContentSettingsAgent> receivers_;
+
+ bool UpdateOverrides();
+ bool UpdateTimeZoneOverride(ContentSetting setting, const std::string& timezone_override_value);
+ bool UpdateLocaleOverride(ContentSetting setting);
};
} // namespace content_settings
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java b/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java
--- a/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java
@@ -143,4 +143,7 @@ public class WebLayerSiteSettingsDelegate
@Override
public void dismissPrivacySandboxSnackbar() {}
+
+ @Override
+ public void launchTimeZoneOverrideHelpAndFeedbackActivity(Activity currentActivity) {}
}