Files
cromite/build/patches/Timezone-customization.patch

1172 lines
51 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
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: Content-settings-infrastructure.patch
---
.../browser_ui/site_settings/android/BUILD.gn | 3 +
.../res/layout/time_zone_select_dialog.xml | 36 ++++
...ezoneoverride_site_settings_preference.xml | 68 ++++++
...imezoneOverrideSiteSettingsPreference.java | 196 ++++++++++++++++++
.../WebsitePreferenceBridge.java | 10 +
...BromiteTimezoneOverrideContentSetting.java | 157 ++++++++++++++
.../android/website_preference_bridge.cc | 16 ++
.../bromite_content_settings/timezone.grdp | 39 ++++
.../timezone_override.inc | 24 +++
.../browser/content_settings_pref_provider.cc | 16 ++
.../browser/content_settings_pref_provider.h | 4 +
.../core/browser/content_settings_utils.cc | 5 +
.../core/browser/host_content_settings_map.cc | 8 +
.../core/browser/host_content_settings_map.h | 3 +
.../bromite_content_settings/TIMEZONE.inc | 2 +
.../core/common/content_settings.h | 1 +
.../core/common/content_settings.mojom | 1 +
.../common/content_settings_mojom_traits.cc | 3 +-
.../common/content_settings_mojom_traits.h | 5 +
.../content_settings/core/common/pref_names.h | 3 +
.../renderer/content_settings_agent_impl.cc | 78 +++++++
.../renderer/content_settings_agent_impl.h | 10 +
.../blink/renderer/core/timezone/build.gni | 2 +
.../timezone/external_timezone_controller.cc | 40 ++++
.../timezone/external_timezone_controller.h | 34 +++
.../core/timezone/timezone_controller.cc | 11 -
.../core/timezone/timezone_controller.h | 12 +-
27 files changed, 770 insertions(+), 17 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
create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/BromiteTimezoneOverrideContentSetting.java
create mode 100644 components/browser_ui/strings/bromite_content_settings/timezone.grdp
create mode 100644 components/content_settings/core/browser/bromite_content_settings/timezone_override.inc
create mode 100644 components/content_settings/core/common/bromite_content_settings/TIMEZONE.inc
create mode 100644 third_party/blink/renderer/core/timezone/external_timezone_controller.cc
create mode 100644 third_party/blink/renderer/core/timezone/external_timezone_controller.h
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
@@ -108,6 +108,7 @@ android_library("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/WebsiteRowPreference.java",
+ "java/src/org/chromium/components/browser_ui/site_settings/TimezoneOverrideSiteSettingsPreference.java"
]
resources_package = "org.chromium.components.browser_ui.site_settings"
@@ -290,6 +291,8 @@ android_resources("java_resources") {
"java/res/xml/site_settings_preferences.xml",
"java/res/xml/storage_access_settings.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/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,196 @@
+/*
+ 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.ContentSetting;
+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 BromiteCustomTriStateSiteSettingsPreferenceImpl,
+ RadioGroup.OnCheckedChangeListener,
+ RadioButtonWithEditText.OnTextChangeListener {
+ private @ContentSetting int mSetting = ContentSetting.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(@ContentSetting int setting, BrowserContextHandle browserContextHandle) {
+ mSetting = setting;
+ mBrowserContextHandle = browserContextHandle;
+ }
+
+ @Override
+ public @ContentSetting int getCheckedSetting() {
+ return mSetting;
+ }
+
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ if (mAllowed.isChecked()) {
+ mSetting = ContentSetting.ALLOW;
+ } else if (mAsk.isChecked()) {
+ mSetting = ContentSetting.ASK;
+ } else if (mBlocked.isChecked()) {
+ mSetting = ContentSetting.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);
+
+ if (mBrowserContextHandle != null)
+ 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(@ContentSetting int setting) {
+ if (setting == ContentSetting.ALLOW) {
+ return mAllowed;
+ } else if (setting == ContentSetting.ASK) {
+ return mAsk;
+ } else if (setting == ContentSetting.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.ThemeOverlay_BrowserUI_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/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
@@ -571,6 +571,14 @@ public class WebsitePreferenceBridge {
WebsitePreferenceBridgeJni.get().resetNotificationsSettingsForTest(browserContextHandle);
}
+ public static String getCustomTimezone(BrowserContextHandle browserContextHandle) {
+ return WebsitePreferenceBridgeJni.get().getCustomTimezone(browserContextHandle);
+ }
+
+ public static void setCustomTimezone(BrowserContextHandle browserContextHandle, String custom_timezone) {
+ WebsitePreferenceBridgeJni.get().setCustomTimezone(browserContextHandle, custom_timezone);
+ }
+
@NativeMethods
public interface Natives {
boolean isNotificationEmbargoedForOrigin(
@@ -740,5 +748,7 @@ public class WebsitePreferenceBridge {
String toDomainWildcardPattern(String pattern);
String toHostOnlyPattern(String pattern);
+ String getCustomTimezone(BrowserContextHandle browserContextHandle);
+ void setCustomTimezone(BrowserContextHandle browserContextHandle, String custom_timezone);
}
}
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/BromiteTimezoneOverrideContentSetting.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/BromiteTimezoneOverrideContentSetting.java
new file mode 100644
--- /dev/null
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/BromiteTimezoneOverrideContentSetting.java
@@ -0,0 +1,157 @@
+/*
+ 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.impl;
+
+import org.chromium.components.browser_ui.site_settings.R;
+
+import org.chromium.components.browser_ui.site_settings.BromiteCustomContentSetting;
+import org.chromium.components.browser_ui.site_settings.ContentSettingsResources;
+import org.chromium.components.browser_ui.site_settings.SingleCategorySettings;
+import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory;
+import org.chromium.components.browser_ui.site_settings.TimezoneOverrideSiteSettingsPreference;
+import org.chromium.components.browser_ui.site_settings.WebsitePreferenceBridge;
+import org.chromium.components.content_settings.ContentSetting;
+import org.chromium.components.content_settings.ContentSettingsType;
+import org.chromium.content_public.browser.BrowserContextHandle;
+
+import android.view.View;
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import java.util.ArrayList;
+
+public class BromiteTimezoneOverrideContentSetting extends BromiteCustomContentSetting {
+ private static final String TIMEOVERRIDE_STATE_TOGGLE_KEY = "timeoverride_state_toggle";
+
+ public BromiteTimezoneOverrideContentSetting() {
+ super(/*contentSettingsType*/ ContentSettingsType.TIMEZONE_OVERRIDE,
+ /*defaultEnabledValue*/ ContentSetting.ALLOW,
+ /*defaultDisabledValue*/ ContentSetting.BLOCK,
+ /*allowException*/ true,
+ /*preferenceKey*/ "timezone_override",
+ /*profilePrefKey*/ "timezone_override_permission_list");
+ }
+
+ @Override
+ public ContentSettingsResources.ResourceItem getResourceItem() {
+ return new ContentSettingsResources.ResourceItem(
+ /*icon*/ R.drawable.web_asset,
+ /*title*/ R.string.timezone_override_permission_title,
+ /*defaultEnabledValue*/ getDefaultEnabledValue(),
+ /*defaultDisabledValue*/ getDefaultDisabledValue(),
+ /*enabledSummary*/ R.string.website_settings_category_timezone_override_custom,
+ /*disabledSummary*/ R.string.website_settings_category_timezone_override_random,
+ /*summaryOverrideForScreenReader*/ 0);
+ }
+
+ @Override
+ public int getCategorySummary(@Nullable @ContentSetting int value) {
+ switch (value) {
+ case ContentSetting.ALLOW:
+ return R.string.website_settings_category_timezone_override_allowed;
+ case ContentSetting.ASK:
+ return R.string.website_settings_category_timezone_override_custom;
+ case ContentSetting.BLOCK:
+ return R.string.website_settings_category_timezone_override_random;
+ default:
+ return 0;
+ }
+ }
+
+ @Override
+ public int[] getTriStateSettingDescriptionIDs() {
+ 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;
+ }
+
+ @Override
+ public int[] getTriStateSettingIconIDs() {
+ return new int[] {
+ R.drawable.web_asset,
+ R.drawable.web_asset,
+ R.drawable.sensors_off_24px
+ };
+ }
+
+ @Override
+ public int getCategoryDescription() {
+ return R.string.website_settings_timeoverride_info;
+ }
+
+ @Override
+ public boolean requiresTriStateContentSetting() {
+ return true;
+ }
+
+ @Override
+ public boolean showOnlyDescriptions() {
+ return true;
+ }
+
+ @Override
+ public int getAddExceptionDialogMessage() {
+ return R.string.website_settings_category_timezone_override_allowed;
+ }
+
+ @Override
+ public @Nullable Boolean considerException(SiteSettingsCategory category, @ContentSetting int value) {
+ return value != ContentSetting.ALLOW;
+ }
+
+ @Override
+ public boolean isOnBlockList(@ContentSetting Integer contentSetting) {
+ return ContentSetting.ALLOW != contentSetting;
+ }
+
+ @Override
+ public boolean isHelpAndFeedbackEnabled() {
+ return true;
+ }
+
+ @Override
+ public String getHelpAndFeedbackActivityUrl() {
+ return "https://github.com/bromite/bromite/wiki/TimezoneOverride";
+ }
+
+ @Override
+ public void configureGlobalToggles(SiteSettingsCategory category, SingleCategorySettings setting) {
+ BrowserContextHandle browserContext = setting.getSiteSettingsDelegate().getBrowserContextHandle();
+ PreferenceScreen screen = setting.getPreferenceScreen();
+
+ Preference triStateToggle = screen.findPreference(
+ SingleCategorySettings.TRI_STATE_TOGGLE_KEY);
+ int order = triStateToggle.getOrder();
+ screen.removePreference(triStateToggle);
+
+ TimezoneOverrideSiteSettingsPreference timeOverrideStatePreference =
+ new TimezoneOverrideSiteSettingsPreference(setting.getContext(), null);
+ timeOverrideStatePreference.setKey(SingleCategorySettings.TRI_STATE_TOGGLE_KEY);
+ screen.addPreference(timeOverrideStatePreference);
+ timeOverrideStatePreference.setOrder(order);
+
+ timeOverrideStatePreference.setOnPreferenceChangeListener(setting);
+ @ContentSetting
+ int value = WebsitePreferenceBridge.getDefaultContentSetting(
+ browserContext, ContentSettingsType.TIMEZONE_OVERRIDE);
+ timeOverrideStatePreference.initialize(value, browserContext);
+ }
+}
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
@@ -1319,5 +1319,21 @@ JNI_WebsitePreferenceBridge_ToHostOnlyPattern(JNIEnv* env,
return ConvertUTF8ToJavaString(env, host_only_pattern.ToString());
}
+static void JNI_WebsitePreferenceBridge_SetCustomTimezone(
+ JNIEnv* env,
+ const JavaRef<jobject>& jbrowser_context_handle,
+ const JavaRef<jstring>& custom_timezone) {
+ std::string new_timezone = ConvertJavaStringToUTF8(env, custom_timezone);
+ GetHostContentSettingsMap(jbrowser_context_handle)->SetTimezoneOverrideValue(new_timezone);
+}
+
+static base::android::ScopedJavaLocalRef<jstring> JNI_WebsitePreferenceBridge_GetCustomTimezone(
+ JNIEnv* env,
+ const JavaRef<jobject>& jbrowser_context_handle) {
+ std::string custom_timezone;
+ GetHostContentSettingsMap(jbrowser_context_handle)->GetTimezoneOverrideValue(custom_timezone);
+ return ConvertUTF8ToJavaString(env, custom_timezone);
+}
+
DEFINE_JNI(GeolocationSetting)
DEFINE_JNI(WebsitePreferenceBridge)
diff --git a/components/browser_ui/strings/bromite_content_settings/timezone.grdp b/components/browser_ui/strings/bromite_content_settings/timezone.grdp
new file mode 100644
--- /dev/null
+++ b/components/browser_ui/strings/bromite_content_settings/timezone.grdp
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <message name="IDS_SITE_SETTINGS_TIMEZONE_OVERRIDE_TITLE" desc="Description of the timezone override content setting page title.">
+ Timezone override
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_TIMEOVERRIDE_INFO" desc="Primary text explaining the timezone override feature." formatter_data="android_java">
+ 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." formatter_data="android_java">
+ None (use system timezone)
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_RANDOM_TEXT" desc="Primary text for random timezone override." formatter_data="android_java">
+ Random
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_ALLOWED" desc="Summary text explaining that sites are allowed to access the system timezone." formatter_data="android_java">
+ System timezone
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_CUSTOM" desc="Summary text explaining that sites use custom timezone." formatter_data="android_java">
+ Custom timezone
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_CUSTOM_HINT" desc="Hint text for edit custom timezone." formatter_data="android_java">
+ Specify a custom timezone (default UTC)
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_RANDOM" desc="Summary text for random timezone override." formatter_data="android_java">
+ Random (for each page)
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_SELECT_BUTTON" desc="Primary button text for choosing a timezone from a list." formatter_data="android_java">
+ Choose Timezone...
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_SELECT_DIALOG_TITLE" desc="Text of the dialog to choose a timezone." formatter_data="android_java">
+ Choose Timezone
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_SELECT_DIALOG_BUTTON" desc="Primary button text in the dialog used to choose the custom timezone." formatter_data="android_java">
+ Select
+ </message>
+ <message name="IDS_TIMEZONE_OVERRIDE_PERMISSION_TITLE" desc="Title of the permission to use TimeZone Override [CHAR-LIMIT=32]" formatter_data="android_java">
+ Timezone override
+ </message>
+</grit-part>
diff --git a/components/content_settings/core/browser/bromite_content_settings/timezone_override.inc b/components/content_settings/core/browser/bromite_content_settings/timezone_override.inc
new file mode 100644
--- /dev/null
+++ b/components/content_settings/core/browser/bromite_content_settings/timezone_override.inc
@@ -0,0 +1,24 @@
+ Register(ContentSettingsType::TIMEZONE_OVERRIDE, "timezone-override", CONTENT_SETTING_ALLOW,
+ WebsiteSettingsInfo::SYNCABLE,
+ /*allowlisted_schemes=*/{},
+ /*valid_settings=*/{CONTENT_SETTING_ALLOW, // use system time
+ CONTENT_SETTING_ASK, // custom timezone, default UTC
+ CONTENT_SETTING_BLOCK}, // random
+ WebsiteSettingsInfo::TOP_ORIGIN_ONLY_SCOPE,
+ WebsiteSettingsRegistry::ALL_PLATFORMS,
+ ContentSettingsInfo::INHERIT_IN_INCOGNITO,
+ PermissionSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS);
+
+ content_settings::WebsiteSettingsRegistry::GetInstance()
+ ->GetMutable(ContentSettingsType::TIMEZONE_OVERRIDE)
+ ->set_show_into_info_page()
+ .set_desktop_ui()
+ .set_is_renderer_content_setting()
+ .set_title_ui(IDS_SITE_SETTINGS_TIMEZONE_OVERRIDE_TITLE)
+ .set_description_ui(IDS_WEBSITE_SETTINGS_TIMEOVERRIDE_INFO)
+ .set_allowed_ui(IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_ALLOWED)
+ .set_blocked_ui(IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_RANDOM)
+ .set_ask_ui(IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_CUSTOM)
+ .set_allowed_exceptions_ui(IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_ALLOWED)
+ .set_blocked_exceptions_ui(IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_RANDOM)
+ .set_mid_sentence_ui(IDS_SITE_SETTINGS_TIMEZONE_OVERRIDE_TITLE);
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
@@ -108,6 +108,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
@@ -196,6 +198,10 @@ PrefProvider::PrefProvider(PrefService* prefs,
event_args->set_number_of_exceptions(
num_exceptions); // PrefProvider::PrefProvider.
});
+
+ custom_timezone_ =
+ prefs_->GetString(
+ prefs::kContentSettingsCustomTimezone);
}
PrefProvider::~PrefProvider() {
@@ -584,4 +590,14 @@ void PrefProvider::SetClockForTesting(const base::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
@@ -83,6 +83,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.
@@ -131,6 +134,7 @@ class PrefProvider : public UserModifiableProvider {
base::ThreadChecker thread_checker_;
raw_ptr<const base::Clock> clock_;
+ std::string custom_timezone_;
};
} // namespace content_settings
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
@@ -156,6 +156,11 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map,
ContentSettingToValue(CONTENT_SETTING_BLOCK), ProviderType::kNone,
map->IsOffTheRecord()));
#endif
+
+ // pass custom timezone value to the render process
+ 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
@@ -762,6 +762,14 @@ void HostContentSettingsMap::SetClockForTesting(const base::Clock* clock) {
}
}
+void HostContentSettingsMap::GetTimezoneOverrideValue(std::string& custom_timezone) const {
+ GetPrefProvider()->GetPrefTimezoneOverrideValue(custom_timezone);
+}
+
+void HostContentSettingsMap::SetTimezoneOverrideValue(const std::string& custom_timezone) {
+ GetPrefProvider()->SetPrefTimezoneOverrideValue(custom_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
@@ -424,6 +424,9 @@ class HostContentSettingsMap : public content_settings::Observer,
// Returns the current time of the `clock_`.
base::Time Now() const { return clock_->Now(); }
+ void GetTimezoneOverrideValue(std::string& custom_timezone) const;
+ void SetTimezoneOverrideValue(const std::string& custom_timezone);
+
private:
friend class base::RefCountedThreadSafe<HostContentSettingsMap>;
friend class content_settings::TestUtils;
diff --git a/components/content_settings/core/common/bromite_content_settings/TIMEZONE.inc b/components/content_settings/core/common/bromite_content_settings/TIMEZONE.inc
new file mode 100644
--- /dev/null
+++ b/components/content_settings/core/common/bromite_content_settings/TIMEZONE.inc
@@ -0,0 +1,2 @@
+ // Content setting for timezone customization functionality.
+ TIMEZONE_OVERRIDE,
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
@@ -131,6 +131,7 @@ struct RendererContentSettingRules {
bool operator==(const RendererContentSettingRules& other) const;
ContentSettingsForOneType mixed_content_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
@@ -94,4 +94,5 @@ struct ContentSettingPatternSource {
struct RendererContentSettingRules {
array<ContentSettingRuleSource> settings_rules;
array<ContentSettingPatternSource> mixed_content_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
@@ -129,7 +129,8 @@ bool StructTraits<content_settings::mojom::RendererContentSettingRulesDataView,
Read(content_settings::mojom::RendererContentSettingRulesDataView data,
RendererContentSettingRules* out) {
return data.ReadSettingsRules(&out->settings_rules) &&
- data.ReadMixedContentRules(&out->mixed_content_rules);
+ data.ReadMixedContentRules(&out->mixed_content_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
@@ -219,6 +219,11 @@ struct StructTraits<
return r.mixed_content_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/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
@@ -281,6 +281,9 @@ inline constexpr char kDesktopSiteWindowSettingEnabled[] =
"desktop_site.window_setting";
#endif
+inline constexpr char kContentSettingsCustomTimezone[] =
+ "profile.content_settings.custom_timezone";
+
} // 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/feature_list.h"
#include "base/functional/bind.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"
@@ -162,6 +164,7 @@ void ContentSettingsAgentImpl::DidCommitProvisionalLoad(
// correctly detect that a piece of content flipped from "not blocked" to
// "blocked".
ClearBlockedContentSettings(); // do not remove
+ UpdateOverrides();
blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
if (frame->Parent())
@@ -465,4 +468,79 @@ void ContentSettingsAgentImpl::ClearBlockedContentSettings() {
cached_script_permissions_.clear();
}
+bool ContentSettingsAgentImpl::UpdateOverrides() {
+ // Evaluate the content setting rules
+ ContentSetting setting = CONTENT_SETTING_ALLOW;
+
+ if (content_setting_rules_) {
+ setting = GetContentSetting(
+ ContentSettingsType::TIMEZONE_OVERRIDE, setting);
+ }
+ 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
+
+ if (setting == CONTENT_SETTING_ALLOW) {
+ // system time
+ if (timezone_override_) {
+ timezone_override_.reset();
+ }
+ return true;
+ }
+
+ // https://chromium-review.googlesource.com/c/chromium/src/+/7031664
+ if (blink::ExternalTimeZoneController::HasTimeZoneOverride()) {
+ DLOG(INFO) << "UpdateTimeZoneOverride: already set";
+ return false;
+ }
+
+ /* 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.
+ */
+ std::string timezone_id;
+ 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 = tzID;
+ }
+ delete timezones;
+ }
+ } else if (setting == CONTENT_SETTING_ASK) {
+ if (timezone_override_value.empty())
+ timezone_id = "Europe/London";
+ else
+ timezone_id = timezone_override_value;
+ }
+
+ timezone_override_.reset();
+ timezone_override_ =
+ blink::ExternalTimeZoneController::SetTimeZoneOverride(timezone_id);
+ if (!timezone_override_) {
+ DLOG(WARNING) << "UpdateTimeZoneOverride - Invalid timezone id '"
+ << timezone_id << "'";
+ return false;
+ } else {
+ DLOG(INFO)
+ << "UpdateTimeZoneOverride - setting to '"
+ << timezone_id << "'";
+ return true;
+ }
+}
+
} // 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
@@ -23,6 +23,10 @@
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "url/origin.h"
+#include "third_party/blink/renderer/core/timezone/external_timezone_controller.h"
+#include "third_party/icu/source/common/unicode/strenum.h"
+#include "third_party/icu/source/i18n/unicode/timezone.h"
+
namespace blink {
class WebFrame;
class WebURL;
@@ -160,6 +164,12 @@ class ContentSettingsAgentImpl
std::unique_ptr<Delegate> delegate_;
mojo::AssociatedReceiverSet<mojom::ContentSettingsAgent> receivers_;
+
+ std::unique_ptr<blink::ExternalTimeZoneController::TimeZoneOverride> timezone_override_;
+
+ bool UpdateOverrides();
+ bool UpdateTimeZoneOverride(ContentSetting setting, const std::string& timezone_override_value);
+ bool UpdateLocaleOverride(ContentSetting setting);
};
} // namespace content_settings
diff --git a/third_party/blink/renderer/core/timezone/build.gni b/third_party/blink/renderer/core/timezone/build.gni
--- a/third_party/blink/renderer/core/timezone/build.gni
+++ b/third_party/blink/renderer/core/timezone/build.gni
@@ -5,4 +5,6 @@
blink_core_sources_timezone = [
"timezone_controller.cc",
"timezone_controller.h",
+ "external_timezone_controller.cc",
+ "external_timezone_controller.h",
]
diff --git a/third_party/blink/renderer/core/timezone/external_timezone_controller.cc b/third_party/blink/renderer/core/timezone/external_timezone_controller.cc
new file mode 100644
--- /dev/null
+++ b/third_party/blink/renderer/core/timezone/external_timezone_controller.cc
@@ -0,0 +1,40 @@
+// Copyright 2019 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/timezone/external_timezone_controller.h"
+#include "third_party/blink/renderer/core/timezone/timezone_controller.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
+
+namespace blink {
+
+ExternalTimeZoneController::ExternalTimeZoneController() {
+ DCHECK(IsMainThread());
+}
+
+// static
+std::unique_ptr<ExternalTimeZoneController::TimeZoneOverride>
+ExternalTimeZoneController::SetTimeZoneOverride(const std::string& timezone_id) {
+ DCHECK(IsMainThread());
+ auto timezone = String(timezone_id.c_str());
+
+ auto result = TimeZoneController::SetTimeZoneOverride(timezone);
+ if (result.status != TimeZoneController::TimeZoneOverrideStatus::kSuccess)
+ return nullptr;
+
+ result.handle->clear_at_destruction_ = false;
+ return std::unique_ptr<TimeZoneOverride>(new TimeZoneOverride());
+}
+
+// static
+bool ExternalTimeZoneController::HasTimeZoneOverride() {
+ DCHECK(IsMainThread());
+ return TimeZoneController::HasTimeZoneOverride();
+}
+
+// static
+void ExternalTimeZoneController::ClearTimeZoneOverride() {
+ TimeZoneController::ClearTimeZoneOverride();
+}
+
+} // namespace blink
diff --git a/third_party/blink/renderer/core/timezone/external_timezone_controller.h b/third_party/blink/renderer/core/timezone/external_timezone_controller.h
new file mode 100644
--- /dev/null
+++ b/third_party/blink/renderer/core/timezone/external_timezone_controller.h
@@ -0,0 +1,34 @@
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMEZONE_EXTERNAL_TIMEZONE_CONTROLLER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMEZONE_EXTERNAL_TIMEZONE_CONTROLLER_H_
+
+#include <memory>
+#include <string>
+
+#include "third_party/blink/renderer/core/core_export.h"
+
+namespace blink {
+
+class CORE_EXPORT ExternalTimeZoneController final {
+ public:
+ class TimeZoneOverride {
+ friend ExternalTimeZoneController;
+ TimeZoneOverride() = default;
+
+ public:
+ ~TimeZoneOverride() { ClearTimeZoneOverride(); }
+ };
+
+ static std::unique_ptr<TimeZoneOverride> SetTimeZoneOverride(
+ const std::string& timezone_id);
+
+ static bool HasTimeZoneOverride();
+
+ private:
+ static void ClearTimeZoneOverride();
+
+ ExternalTimeZoneController();
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TIMEZONE_EXTERNAL_TIMEZONE_CONTROLLER_H_
diff --git a/third_party/blink/renderer/core/timezone/timezone_controller.cc b/third_party/blink/renderer/core/timezone/timezone_controller.cc
--- a/third_party/blink/renderer/core/timezone/timezone_controller.cc
+++ b/third_party/blink/renderer/core/timezone/timezone_controller.cc
@@ -141,8 +141,6 @@ TimeZoneController::TimeZoneOverrideResult
TimeZoneController::SetTimeZoneOverride(const String& timezone_id) {
DCHECK(!timezone_id.empty());
- base::AutoLock locker(instance().lock_);
-
if (timezone_id == instance().TimeZoneIdOverride()) {
// Do nothing.
return {TimeZoneOverrideStatus::kSuccess, nullptr};
@@ -168,20 +166,16 @@ TimeZoneController::SetTimeZoneOverride(const String& timezone_id) {
// static
bool TimeZoneController::HasTimeZoneOverride() {
- instance().lock_.AssertAcquired();
return !instance().override_timezone_id_.empty();
}
// static
const String& TimeZoneController::TimeZoneIdOverride() {
- instance().lock_.AssertAcquired();
return instance().override_timezone_id_;
}
// static
void TimeZoneController::ClearTimeZoneOverride() {
- base::AutoLock locker(instance().lock_);
-
DCHECK(HasTimeZoneOverride());
if (!CanonicalEquals(instance().GetHostTimezoneId(),
@@ -197,8 +191,6 @@ void TimeZoneController::ClearTimeZoneOverride() {
void TimeZoneController::ChangeTimeZoneOverride(const String& timezone_id) {
DCHECK(!timezone_id.empty());
- base::AutoLock locker(instance().lock_);
-
if (!HasTimeZoneOverride()) {
VLOG(1) << "Cannot change if there are no existing timezone override.";
return;
@@ -243,8 +235,6 @@ bool TimeZoneController::SetIcuTimeZoneAndNotifyV8(const String& timezone_id) {
void TimeZoneController::OnTimeZoneChange(const String& timezone_id) {
DCHECK(IsMainThread());
- base::AutoLock locker(instance().lock_);
-
// Remember requested timezone id so we can set it when timezone
// override is removed.
instance().host_timezone_id_ = timezone_id;
@@ -254,7 +244,6 @@ void TimeZoneController::OnTimeZoneChange(const String& timezone_id) {
}
const String& TimeZoneController::GetHostTimezoneId() {
- lock_.AssertAcquired();
if (host_timezone_id_.IsNull()) {
CHECK(base::FeatureList::IsEnabled(kLazyBlinkTimezoneInit));
host_timezone_id_ = GetCurrentTimezoneId();
diff --git a/third_party/blink/renderer/core/timezone/timezone_controller.h b/third_party/blink/renderer/core/timezone/timezone_controller.h
--- a/third_party/blink/renderer/core/timezone/timezone_controller.h
+++ b/third_party/blink/renderer/core/timezone/timezone_controller.h
@@ -12,6 +12,7 @@
#include "services/device/public/mojom/time_zone_monitor.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/core/timezone/external_timezone_controller.h"
namespace blink {
@@ -26,6 +27,7 @@ namespace blink {
// current host system time zone is assumed.
class CORE_EXPORT TimeZoneController final
: public device::mojom::blink::TimeZoneMonitorClient {
+ friend ExternalTimeZoneController;
public:
~TimeZoneController() override;
@@ -61,7 +63,9 @@ class CORE_EXPORT TimeZoneController final
ChangeTimeZoneOverride(timezone_id);
}
- ~TimeZoneOverride() { ClearTimeZoneOverride(); }
+ bool clear_at_destruction_ = true;
+
+ ~TimeZoneOverride() { if (clear_at_destruction_) ClearTimeZoneOverride(); }
};
struct TimeZoneOverrideResult {
@@ -96,10 +100,8 @@ class CORE_EXPORT TimeZoneController final
// by Oilpan.
mojo::Receiver<device::mojom::blink::TimeZoneMonitorClient> receiver_{this};
- base::Lock lock_;
-
- String host_timezone_id_ GUARDED_BY(lock_);
- String override_timezone_id_ GUARDED_BY(lock_);
+ String host_timezone_id_;
+ String override_timezone_id_;
};
} // namespace blink
--