Timezone-customization.patch 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356
  1. From: uazo <uazo@users.noreply.github.com>
  2. Date: Wed, 30 Sep 2020 07:40:01 +0000
  3. Subject: Timezone customization
  4. Allow specifying a custom timezone, or using a random one.
  5. See also: https://github.com/bromite/bromite/wiki/TimezoneOverride
  6. ---
  7. .../ChromeSiteSettingsDelegate.java | 16 ++
  8. .../browser_ui/site_settings/android/BUILD.gn | 3 +
  9. .../res/layout/time_zone_select_dialog.xml | 36 ++++
  10. ...ezoneoverride_site_settings_preference.xml | 68 ++++++
  11. .../res/xml/site_settings_preferences.xml | 4 +
  12. .../java/res/xml/website_preferences.xml | 9 +
  13. .../ContentSettingsResources.java | 35 +++-
  14. .../site_settings/SingleCategorySettings.java | 77 ++++++-
  15. .../site_settings/SingleWebsiteSettings.java | 8 +-
  16. .../site_settings/SiteSettings.java | 2 +-
  17. .../site_settings/SiteSettingsCategory.java | 9 +-
  18. .../site_settings/SiteSettingsDelegate.java | 2 +
  19. ...imezoneOverrideSiteSettingsPreference.java | 193 ++++++++++++++++++
  20. .../browser_ui/site_settings/Website.java | 10 +
  21. .../WebsitePermissionsFetcher.java | 3 +
  22. .../WebsitePreferenceBridge.java | 12 ++
  23. .../android/website_preference_bridge.cc | 16 ++
  24. .../strings/android/site_settings.grdp | 35 ++++
  25. .../browser/content_settings_pref_provider.cc | 16 ++
  26. .../browser/content_settings_pref_provider.h | 4 +
  27. .../core/browser/content_settings_registry.cc | 12 ++
  28. .../core/browser/content_settings_utils.cc | 7 +
  29. .../core/browser/host_content_settings_map.cc | 8 +
  30. .../core/browser/host_content_settings_map.h | 3 +
  31. .../core/common/content_settings.cc | 3 +-
  32. .../core/common/content_settings.h | 2 +
  33. .../core/common/content_settings.mojom | 2 +
  34. .../common/content_settings_mojom_traits.cc | 4 +-
  35. .../common/content_settings_mojom_traits.h | 10 +
  36. .../core/common/content_settings_types.h | 3 +
  37. .../core/common/pref_names.cc | 3 +
  38. .../content_settings/core/common/pref_names.h | 2 +
  39. .../renderer/content_settings_agent_impl.cc | 89 ++++++++
  40. .../renderer/content_settings_agent_impl.h | 4 +
  41. .../WebLayerSiteSettingsDelegate.java | 3 +
  42. 35 files changed, 698 insertions(+), 15 deletions(-)
  43. create mode 100755 components/browser_ui/site_settings/android/java/res/layout/time_zone_select_dialog.xml
  44. create mode 100755 components/browser_ui/site_settings/android/java/res/layout/timezoneoverride_site_settings_preference.xml
  45. create mode 100755 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/TimezoneOverrideSiteSettingsPreference.java
  46. 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
  47. --- a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java
  48. +++ b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java
  49. @@ -43,6 +43,10 @@ import org.chromium.url.GURL;
  50. import java.util.Set;
  51. +import android.content.Intent;
  52. +import android.provider.Browser;
  53. +import android.net.Uri;
  54. +
  55. /**
  56. * A SiteSettingsDelegate instance that contains Chrome-specific Site Settings logic.
  57. */
  58. @@ -257,4 +261,16 @@ public class ChromeSiteSettingsDelegate implements SiteSettingsDelegate {
  59. mPrivacySandboxController.dismissSnackbar();
  60. }
  61. }
  62. +
  63. + // open wiki page for documentation about the timezone override feature
  64. + @Override
  65. + public void launchTimeZoneOverrideHelpAndFeedbackActivity(Activity currentActivity) {
  66. + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/bromite/bromite/wiki/TimezoneOverride"));
  67. + // Let Chromium know that this intent is from Chromium, so that it does not close the app when
  68. + // the user presses 'back' button.
  69. + intent.putExtra(Browser.EXTRA_APPLICATION_ID, currentActivity.getPackageName());
  70. + intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true);
  71. + intent.setPackage(currentActivity.getPackageName());
  72. + currentActivity.startActivity(intent);
  73. + }
  74. }
  75. diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/browser_ui/site_settings/android/BUILD.gn
  76. --- a/components/browser_ui/site_settings/android/BUILD.gn
  77. +++ b/components/browser_ui/site_settings/android/BUILD.gn
  78. @@ -66,6 +66,7 @@ android_library("java") {
  79. "java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java",
  80. "java/src/org/chromium/components/browser_ui/site_settings/WebsitePreference.java",
  81. "java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java",
  82. + "java/src/org/chromium/components/browser_ui/site_settings/TimezoneOverrideSiteSettingsPreference.java"
  83. ]
  84. annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
  85. resources_package = "org.chromium.components.browser_ui.site_settings"
  86. @@ -162,6 +163,8 @@ android_resources("java_resources") {
  87. "java/res/xml/single_website_preferences.xml",
  88. "java/res/xml/site_settings_preferences.xml",
  89. "java/res/xml/website_preferences.xml",
  90. + "java/res/layout/timezoneoverride_site_settings_preference.xml",
  91. + "java/res/layout/time_zone_select_dialog.xml",
  92. ]
  93. deps = [
  94. 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
  95. new file mode 100755
  96. --- /dev/null
  97. +++ b/components/browser_ui/site_settings/android/java/res/layout/time_zone_select_dialog.xml
  98. @@ -0,0 +1,36 @@
  99. +<?xml version="1.0" encoding="utf-8"?>
  100. +<!--
  101. + This file is part of Bromite.
  102. +
  103. + Bromite is free software: you can redistribute it and/or modify
  104. + it under the terms of the GNU General Public License as published by
  105. + the Free Software Foundation, either version 3 of the License, or
  106. + (at your option) any later version.
  107. +
  108. + Bromite is distributed in the hope that it will be useful,
  109. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  110. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  111. + GNU General Public License for more details.
  112. +
  113. + You should have received a copy of the GNU General Public License
  114. + along with Bromite. If not, see <https://www.gnu.org/licenses/>.
  115. +-->
  116. +
  117. +<!-- Layout used by the TimezoneOverrideSettingsPreference. -->
  118. +
  119. +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  120. + android:orientation="vertical"
  121. + style="@style/AlertDialogContent">
  122. +
  123. + <ListView
  124. + android:id="@+id/listView"
  125. + android:layout_width="match_parent"
  126. + android:layout_height="wrap_content"
  127. + android:layout_marginBottom="8dp"
  128. + android:layout_marginEnd="8dp"
  129. + android:layout_marginStart="8dp"
  130. + android:layout_marginTop="8dp"
  131. + android:choiceMode="singleChoice"
  132. + android:listSelector="#666666"/>
  133. +
  134. +</LinearLayout>
  135. \ No newline at end of file
  136. 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
  137. new file mode 100755
  138. --- /dev/null
  139. +++ b/components/browser_ui/site_settings/android/java/res/layout/timezoneoverride_site_settings_preference.xml
  140. @@ -0,0 +1,68 @@
  141. +<!--
  142. + This file is part of Bromite.
  143. +
  144. + Bromite is free software: you can redistribute it and/or modify
  145. + it under the terms of the GNU General Public License as published by
  146. + the Free Software Foundation, either version 3 of the License, or
  147. + (at your option) any later version.
  148. +
  149. + Bromite is distributed in the hope that it will be useful,
  150. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  151. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  152. + GNU General Public License for more details.
  153. +
  154. + You should have received a copy of the GNU General Public License
  155. + along with Bromite. If not, see <https://www.gnu.org/licenses/>.
  156. +-->
  157. +
  158. +<!-- Layout used by the TimezoneOverrideSettingsPreference. -->
  159. +
  160. +<LinearLayout
  161. + xmlns:android="http://schemas.android.com/apk/res/android"
  162. + xmlns:app="http://schemas.android.com/apk/res-auto"
  163. + android:layout_width="match_parent"
  164. + android:layout_height="wrap_content"
  165. + android:focusable="false"
  166. + android:orientation="vertical">
  167. +
  168. + <org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout
  169. + android:id="@+id/radio_button_layout"
  170. + android:layout_width="match_parent"
  171. + android:layout_height="match_parent">
  172. +
  173. + <org.chromium.components.browser_ui.widget.RadioButtonWithDescription
  174. + android:id="@+id/allowed"
  175. + android:layout_width="match_parent"
  176. + android:layout_height="wrap_content"
  177. + android:paddingStart="?android:attr/listPreferredItemPaddingStart"
  178. + app:primaryText="@string/website_settings_category_timezone_override_allowed" />
  179. +
  180. + <org.chromium.components.browser_ui.widget.RadioButtonWithDescription
  181. + android:id="@+id/blocked"
  182. + android:layout_width="match_parent"
  183. + android:layout_height="wrap_content"
  184. + android:paddingStart="?android:attr/listPreferredItemPaddingStart"
  185. + app:primaryText="@string/website_settings_category_timezone_override_random" />
  186. +
  187. + <org.chromium.components.browser_ui.widget.RadioButtonWithEditText
  188. + android:id="@+id/ask"
  189. + android:layout_width="match_parent"
  190. + android:layout_height="wrap_content"
  191. + android:paddingStart="?android:attr/listPreferredItemPaddingStart"
  192. + android:inputType="text"
  193. + android:hint="@string/website_settings_category_timezone_override_custom_hint"
  194. + app:descriptionText="@string/website_settings_category_timezone_override_custom" />
  195. +
  196. + </org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout>
  197. +
  198. + <org.chromium.ui.widget.ButtonCompat
  199. + android:id="@+id/select_button"
  200. + style="@style/TextButton"
  201. + android:layout_width="match_parent"
  202. + android:layout_height="wrap_content"
  203. + android:paddingBottom="16dp"
  204. + android:paddingTop="16dp"
  205. + android:text="@string/website_settings_select_button"
  206. + app:verticalInset="0dp" />
  207. +
  208. +</LinearLayout>
  209. 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
  210. --- a/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml
  211. +++ b/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml
  212. @@ -41,6 +41,10 @@
  213. <org.chromium.components.browser_ui.settings.ChromeBasePreference
  214. android:fragment="org.chromium.components.browser_ui.site_settings.SingleCategorySettings"
  215. android:key="javascript" />
  216. + <!-- Timezone Override -->
  217. + <org.chromium.components.browser_ui.settings.ChromeBasePreference
  218. + android:key="timezone_override"
  219. + android:fragment="org.chromium.components.browser_ui.site_settings.SingleCategorySettings" />
  220. <!-- Popups -->
  221. <org.chromium.components.browser_ui.settings.ChromeBasePreference
  222. android:fragment="org.chromium.components.browser_ui.site_settings.SingleCategorySettings"
  223. 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
  224. --- a/components/browser_ui/site_settings/android/java/res/xml/website_preferences.xml
  225. +++ b/components/browser_ui/site_settings/android/java/res/xml/website_preferences.xml
  226. @@ -13,6 +13,12 @@
  227. android:key="cookie_info_text"
  228. android:summary="@string/website_settings_cookie_info"/>
  229. + <!-- A text message describing timeoverride settings. -->
  230. + <org.chromium.components.browser_ui.settings.TextMessagePreference
  231. + android:key="timeoverride_info_text"
  232. + android:summary="@string/website_settings_timeoverride_info"/>
  233. +
  234. +
  235. <!-- A common binary toggle, only shown for specific categories that allow
  236. turning default values for that category on/off.-->
  237. <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
  238. @@ -26,6 +32,9 @@
  239. <!-- A four state toggle for cookie preferences, only shown for the Cookies category. -->
  240. <org.chromium.components.browser_ui.site_settings.FourStateCookieSettingsPreference
  241. android:key="four_state_cookie_toggle" />
  242. + <!-- A specific state toggle for time override preferences, only shown for the TimeOverride category. -->
  243. + <org.chromium.components.browser_ui.site_settings.TimezoneOverrideSiteSettingsPreference
  244. + android:key="timeoverride_state_toggle" />
  245. <!-- A checkbox for enabling a quiet ui for notification prompts. Only shown in the Notifications category. -->
  246. <org.chromium.components.browser_ui.settings.ChromeBaseCheckBoxPreference
  247. 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
  248. --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java
  249. +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java
  250. @@ -269,6 +269,12 @@ public class ContentSettingsResources {
  251. R.string.vr_permission_title, ContentSettingValues.ASK,
  252. ContentSettingValues.BLOCK, R.string.website_settings_category_vr_ask,
  253. R.string.website_settings_category_vr_blocked);
  254. +
  255. + case ContentSettingsType.TIMEZONE_OVERRIDE:
  256. + return new ResourceItem(R.drawable.web_asset, R.string.timezone_override_permission_title,
  257. + ContentSettingValues.ALLOW, ContentSettingValues.BLOCK,
  258. + R.string.website_settings_category_timezone_override_custom,
  259. + R.string.website_settings_category_timezone_override_random);
  260. }
  261. assert false; // NOTREACHED
  262. return null;
  263. @@ -421,6 +427,23 @@ public class ContentSettingsResources {
  264. }
  265. }
  266. + public static int getCategorySummary(int contentType, @Nullable @ContentSettingValues int value) {
  267. + if (contentType == ContentSettingsType.TIMEZONE_OVERRIDE) {
  268. + switch (value) {
  269. + case ContentSettingValues.ALLOW:
  270. + return R.string.website_settings_category_timezone_override_allowed;
  271. + case ContentSettingValues.ASK:
  272. + return R.string.website_settings_category_timezone_override_custom;
  273. + case ContentSettingValues.BLOCK:
  274. + return R.string.website_settings_category_timezone_override_random;
  275. + default:
  276. + return 0;
  277. + }
  278. + }
  279. + else
  280. + return getCategorySummary(value);
  281. + }
  282. +
  283. /**
  284. * Returns the string resource id for a content type to show with a permission category.
  285. * @param enabled Whether the content type is enabled.
  286. @@ -435,7 +458,10 @@ public class ContentSettingsResources {
  287. * with a particular website.
  288. * @param value The ContentSetting for which we want the resource.
  289. */
  290. - public static int getSiteSummary(@ContentSettingValues @Nullable Integer value) {
  291. + public static int getSiteSummary(int contentType, @ContentSettingValues @Nullable Integer value) {
  292. + if (contentType == ContentSettingsType.TIMEZONE_OVERRIDE)
  293. + return getCategorySummary(contentType, value);
  294. +
  295. switch (value) {
  296. case ContentSettingValues.ALLOW:
  297. return R.string.website_settings_permissions_allow;
  298. @@ -541,6 +567,13 @@ public class ContentSettingsResources {
  299. return descriptionIDs;
  300. }
  301. }
  302. + else if (contentType == ContentSettingsType.TIMEZONE_OVERRIDE) {
  303. + int[] descriptionIDs = {
  304. + R.string.website_settings_category_timezone_override_allowed, // ALLOWED
  305. + R.string.website_settings_category_timezone_override_custom, // ASK
  306. + R.string.website_settings_category_timezone_override_random}; // BLOCKED
  307. + return descriptionIDs;
  308. + }
  309. assert false;
  310. return null;
  311. 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
  312. --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
  313. +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
  314. @@ -62,6 +62,10 @@ import org.chromium.ui.widget.Toast;
  315. import java.lang.annotation.Retention;
  316. import java.lang.annotation.RetentionPolicy;
  317. +import android.app.Activity;
  318. +import android.content.Intent;
  319. +import org.chromium.components.browser_ui.site_settings.TimezoneOverrideSiteSettingsPreference;
  320. +
  321. import java.util.ArrayList;
  322. import java.util.Collection;
  323. import java.util.Collections;
  324. @@ -141,6 +145,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  325. public static final String BINARY_TOGGLE_KEY = "binary_toggle";
  326. public static final String TRI_STATE_TOGGLE_KEY = "tri_state_toggle";
  327. public static final String FOUR_STATE_COOKIE_TOGGLE_KEY = "four_state_cookie_toggle";
  328. + public static final String TIMEOVERRIDE_STATE_TOGGLE_KEY = "timeoverride_state_toggle";
  329. // Keys for category-specific preferences (toggle, link, button etc.), dynamically shown.
  330. public static final String NOTIFICATIONS_VIBRATE_TOGGLE_KEY = "notifications_vibrate";
  331. @@ -148,6 +153,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  332. public static final String EXPLAIN_PROTECTED_MEDIA_KEY = "protected_content_learn_more";
  333. public static final String ADD_EXCEPTION_KEY = "add_exception";
  334. public static final String COOKIE_INFO_TEXT_KEY = "cookie_info_text";
  335. + public static final String TIMEOVERRIDE_INFO_TEXT = "timeoverride_info_text";
  336. // Keys for Allowed/Blocked preference groups/headers.
  337. private static final String ALLOWED_GROUP = "allowed_group";
  338. @@ -216,7 +222,10 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  339. Integer contentSetting = website.site().getContentSetting(
  340. browserContextHandle, SiteSettingsCategory.contentSettingsType(i));
  341. if (contentSetting != null) {
  342. - return ContentSettingValues.BLOCK == contentSetting;
  343. + if (i == SiteSettingsCategory.Type.TIMEZONE_OVERRIDE)
  344. + return ContentSettingValues.ALLOW != contentSetting;
  345. + else
  346. + return ContentSettingValues.BLOCK == contentSetting;
  347. }
  348. }
  349. return false;
  350. @@ -387,7 +396,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  351. if (queryHasChanged) getInfoForOrigins();
  352. });
  353. - if (getSiteSettingsDelegate().isHelpAndFeedbackEnabled()) {
  354. + if (getSiteSettingsDelegate().isHelpAndFeedbackEnabled() ||
  355. + mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE) ) {
  356. MenuItem help = menu.add(
  357. Menu.NONE, R.id.menu_id_site_settings_help, Menu.NONE, R.string.menu_help);
  358. help.setIcon(VectorDrawableCompat.create(
  359. @@ -398,7 +408,10 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  360. @Override
  361. public boolean onOptionsItemSelected(MenuItem item) {
  362. if (item.getItemId() == R.id.menu_id_site_settings_help) {
  363. - if (mCategory.showSites(SiteSettingsCategory.Type.PROTECTED_MEDIA)) {
  364. + if (mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE)) {
  365. + getSiteSettingsDelegate()
  366. + .launchTimeZoneOverrideHelpAndFeedbackActivity(getActivity());
  367. + } else if (mCategory.showSites(SiteSettingsCategory.Type.PROTECTED_MEDIA)) {
  368. getSiteSettingsDelegate().launchProtectedContentHelpAndFeedbackActivity(
  369. getActivity());
  370. } else {
  371. @@ -492,6 +505,12 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  372. WebsitePreferenceBridge.setDefaultContentSetting(
  373. browserContextHandle, mCategory.getContentSettingsType(), setting);
  374. getInfoForOrigins();
  375. + } else if (TIMEOVERRIDE_STATE_TOGGLE_KEY.equals(preference.getKey())) {
  376. + @ContentSettingValues
  377. + int setting = (int) newValue;
  378. + WebsitePreferenceBridge.setDefaultContentSetting(
  379. + browserContextHandle, ContentSettingsType.TIMEZONE_OVERRIDE, setting);
  380. + getInfoForOrigins();
  381. } else if (FOUR_STATE_COOKIE_TOGGLE_KEY.equals(preference.getKey())) {
  382. setCookieSettingsPreference((CookieSettingsState) newValue);
  383. getInfoForOrigins();
  384. @@ -589,6 +608,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  385. assert WebsitePreferenceBridge.isCategoryEnabled(
  386. browserContextHandle, ContentSettingsType.AUTO_DARK_WEB_CONTENT);
  387. resource = R.string.website_settings_add_site_description_auto_dark_block;
  388. + } else if (mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE)) {
  389. + resource = R.string.website_settings_category_timezone_override_allowed;
  390. }
  391. assert resource > 0;
  392. return getString(resource);
  393. @@ -629,6 +650,13 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  394. if (mCategory.showSites(SiteSettingsCategory.Type.COOKIES) && mRequiresFourStateSetting) {
  395. setting = cookieSettingsExceptionShouldBlock() ? ContentSettingValues.BLOCK
  396. : ContentSettingValues.ALLOW;
  397. + } else if (mRequiresTriStateSetting) {
  398. + setting = WebsitePreferenceBridge.getDefaultContentSetting(browserContextHandle, mCategory.getContentSettingsType());
  399. + if (setting == ContentSettingValues.ALLOW) {
  400. + setting = ContentSettingValues.BLOCK;
  401. + } else {
  402. + setting = ContentSettingValues.ALLOW;
  403. + }
  404. } else {
  405. setting = (WebsitePreferenceBridge.isCategoryEnabled(
  406. browserContextHandle, mCategory.getContentSettingsType()))
  407. @@ -685,6 +713,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  408. && !WebsitePreferenceBridge.isCategoryEnabled(
  409. browserContextHandle, ContentSettingsType.AUTOMATIC_DOWNLOADS)) {
  410. allowSpecifyingExceptions = true;
  411. + } else if (mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE)) {
  412. + allowSpecifyingExceptions = true;
  413. }
  414. if (allowSpecifyingExceptions) {
  415. getPreferenceScreen().addPreference(new AddExceptionPreference(getStyledContext(),
  416. @@ -856,7 +886,14 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  417. TriStateSiteSettingsPreference triStateToggle =
  418. (TriStateSiteSettingsPreference) getPreferenceScreen().findPreference(
  419. TRI_STATE_TOGGLE_KEY);
  420. - return (triStateToggle.getCheckedSetting() == ContentSettingValues.BLOCK);
  421. + if (triStateToggle != null)
  422. + return (triStateToggle.getCheckedSetting() == ContentSettingValues.BLOCK);
  423. +
  424. + TimezoneOverrideSiteSettingsPreference timeOverrideStatePreference =
  425. + (TimezoneOverrideSiteSettingsPreference) getPreferenceScreen().findPreference(
  426. + TIMEOVERRIDE_STATE_TOGGLE_KEY);
  427. + if (timeOverrideStatePreference != null)
  428. + return (timeOverrideStatePreference.getCheckedSetting() != ContentSettingValues.ALLOW);
  429. } else if (mRequiresFourStateSetting) {
  430. FourStateCookieSettingsPreference fourStateCookieToggle =
  431. (FourStateCookieSettingsPreference) getPreferenceScreen().findPreference(
  432. @@ -885,6 +922,9 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  433. (FourStateCookieSettingsPreference) screen.findPreference(
  434. FOUR_STATE_COOKIE_TOGGLE_KEY);
  435. // TODO(crbug.com/1104836): Remove the old third-party cookie blocking UI
  436. + TimezoneOverrideSiteSettingsPreference timeOverrideStatePreference =
  437. + (TimezoneOverrideSiteSettingsPreference) screen.findPreference(
  438. + TIMEOVERRIDE_STATE_TOGGLE_KEY);
  439. Preference notificationsVibrate = screen.findPreference(NOTIFICATIONS_VIBRATE_TOGGLE_KEY);
  440. Preference notificationsQuietUi = screen.findPreference(NOTIFICATIONS_QUIET_UI_TOGGLE_KEY);
  441. Preference explainProtectedMediaKey = screen.findPreference(EXPLAIN_PROTECTED_MEDIA_KEY);
  442. @@ -896,20 +936,32 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  443. if (mRequiresTriStateSetting) {
  444. screen.removePreference(binaryToggle);
  445. screen.removePreference(fourStateCookieToggle);
  446. - configureTriStateToggle(triStateToggle, contentType);
  447. + if (mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE)) {
  448. + screen.removePreference(triStateToggle);
  449. + configureTimeOverrideStateToggle(timeOverrideStatePreference);
  450. + }
  451. + else {
  452. + screen.removePreference(timeOverrideStatePreference);
  453. + configureTriStateToggle(triStateToggle, contentType);
  454. + }
  455. } else if (mRequiresFourStateSetting) {
  456. screen.removePreference(binaryToggle);
  457. screen.removePreference(triStateToggle);
  458. + screen.removePreference(timeOverrideStatePreference);
  459. configureFourStateCookieToggle(fourStateCookieToggle);
  460. } else {
  461. screen.removePreference(triStateToggle);
  462. screen.removePreference(fourStateCookieToggle);
  463. + screen.removePreference(timeOverrideStatePreference);
  464. configureBinaryToggle(binaryToggle, contentType);
  465. }
  466. if (!mCategory.showSites(SiteSettingsCategory.Type.COOKIES)) {
  467. screen.removePreference(screen.findPreference(COOKIE_INFO_TEXT_KEY));
  468. }
  469. + if (!(mCategory.showSites(SiteSettingsCategory.Type.TIMEZONE_OVERRIDE))) {
  470. + screen.removePreference(screen.findPreference(TIMEOVERRIDE_INFO_TEXT));
  471. + }
  472. if (permissionBlockedByOs) {
  473. maybeShowOsWarning(screen);
  474. @@ -1025,6 +1077,15 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  475. triStateToggle.initialize(setting, descriptionIds);
  476. }
  477. + private void configureTimeOverrideStateToggle(
  478. + TimezoneOverrideSiteSettingsPreference timeOverrideStateToggle) {
  479. + timeOverrideStateToggle.setOnPreferenceChangeListener(this);
  480. + @ContentSettingValues
  481. + int setting = WebsitePreferenceBridge.getDefaultContentSetting(
  482. + getSiteSettingsDelegate().getBrowserContextHandle(), ContentSettingsType.TIMEZONE_OVERRIDE);
  483. + timeOverrideStateToggle.initialize(setting, getSiteSettingsDelegate().getBrowserContextHandle());
  484. + }
  485. +
  486. private void configureBinaryToggle(ChromeSwitchPreference binaryToggle, int contentType) {
  487. binaryToggle.setOnPreferenceChangeListener(this);
  488. binaryToggle.setTitle(ContentSettingsResources.getTitle(contentType));
  489. @@ -1108,9 +1169,11 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
  490. CharSequence[] descriptions = new String[2];
  491. descriptions[0] =
  492. - getString(ContentSettingsResources.getSiteSummary(ContentSettingValues.ALLOW));
  493. + getString(ContentSettingsResources.getSiteSummary(contentSettingsType,
  494. + ContentSettingValues.ALLOW));
  495. descriptions[1] =
  496. - getString(ContentSettingsResources.getSiteSummary(ContentSettingValues.BLOCK));
  497. + getString(ContentSettingsResources.getSiteSummary(contentSettingsType,
  498. + ContentSettingValues.BLOCK));
  499. return new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog)
  500. .setPositiveButton(R.string.cancel, null)
  501. 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
  502. --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
  503. +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
  504. @@ -132,6 +132,8 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
  505. return "popup_permission_list";
  506. case ContentSettingsType.SOUND:
  507. return "sound_permission_list";
  508. + case ContentSettingsType.TIMEZONE_OVERRIDE:
  509. + return "timezone_override_permission_list";
  510. case ContentSettingsType.AR:
  511. return "ar_permission_list";
  512. case ContentSettingsType.MEDIASTREAM_CAMERA:
  513. @@ -884,11 +886,13 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
  514. if (value == null) return;
  515. setUpPreferenceCommon(preference, value);
  516. + int content_type = getContentSettingsTypeFromPreferenceKey(preference.getKey());
  517. +
  518. ChromeSwitchPreference switchPreference = (ChromeSwitchPreference) preference;
  519. switchPreference.setChecked(value == ContentSettingValues.ALLOW);
  520. switchPreference.setSummary(isEmbargoed
  521. ? getString(R.string.automatically_blocked)
  522. - : getString(ContentSettingsResources.getCategorySummary(value)));
  523. + : getString(ContentSettingsResources.getCategorySummary(content_type, value)));
  524. switchPreference.setOnPreferenceChangeListener(this);
  525. @ContentSettingsType
  526. int contentType = getContentSettingsTypeFromPreferenceKey(preference.getKey());
  527. @@ -1080,7 +1084,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
  528. }
  529. mSite.setContentSetting(browserContextHandle, type, permission);
  530. - preference.setSummary(getString(ContentSettingsResources.getCategorySummary(permission)));
  531. + preference.setSummary(getString(ContentSettingsResources.getCategorySummary(type, permission)));
  532. preference.setIcon(getContentSettingsIcon(type, permission));
  533. if (mWebsiteSettingsObserver != null) {
  534. 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
  535. --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java
  536. +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java
  537. @@ -117,7 +117,7 @@ public class SiteSettings
  538. } else if (Type.AUTO_DARK_WEB_CONTENT == prefCategory) {
  539. p.setSummary(ContentSettingsResources.getAutoDarkWebContentListSummary(checked));
  540. } else if (requiresTriStateSetting) {
  541. - p.setSummary(ContentSettingsResources.getCategorySummary(setting));
  542. + p.setSummary(ContentSettingsResources.getCategorySummary(contentType, setting));
  543. } else {
  544. p.setSummary(ContentSettingsResources.getCategorySummary(contentType, checked));
  545. }
  546. 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
  547. --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java
  548. +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java
  549. @@ -43,7 +43,7 @@ public class SiteSettingsCategory {
  550. Type.JAVASCRIPT, Type.MICROPHONE, Type.NFC, Type.NOTIFICATIONS, Type.POPUPS,
  551. Type.PROTECTED_MEDIA, Type.SENSORS, Type.SOUND, Type.USB, Type.VIRTUAL_REALITY,
  552. Type.USE_STORAGE, Type.AUTO_DARK_WEB_CONTENT, Type.REQUEST_DESKTOP_SITE,
  553. - Type.FEDERATED_IDENTITY_API})
  554. + Type.FEDERATED_IDENTITY_API, Type.TIMEZONE_OVERRIDE})
  555. @Retention(RetentionPolicy.SOURCE)
  556. public @interface Type {
  557. // All updates here must also be reflected in {@link #preferenceKey(int)
  558. @@ -74,10 +74,11 @@ public class SiteSettingsCategory {
  559. int AUTO_DARK_WEB_CONTENT = 23;
  560. int REQUEST_DESKTOP_SITE = 24;
  561. int FEDERATED_IDENTITY_API = 25;
  562. + int TIMEZONE_OVERRIDE = 26;
  563. /**
  564. * Number of handled categories used for calculating array sizes.
  565. */
  566. - int NUM_ENTRIES = 26;
  567. + int NUM_ENTRIES = 27;
  568. }
  569. private final BrowserContextHandle mBrowserContextHandle;
  570. @@ -202,6 +203,8 @@ public class SiteSettingsCategory {
  571. return ContentSettingsType.USB_GUARD;
  572. case Type.VIRTUAL_REALITY:
  573. return ContentSettingsType.VR;
  574. + case Type.TIMEZONE_OVERRIDE:
  575. + return ContentSettingsType.TIMEZONE_OVERRIDE;
  576. // case Type.ALL_SITES
  577. // case Type.USE_STORAGE
  578. default:
  579. @@ -282,6 +285,8 @@ public class SiteSettingsCategory {
  580. return "use_storage";
  581. case Type.VIRTUAL_REALITY:
  582. return "virtual_reality";
  583. + case Type.TIMEZONE_OVERRIDE:
  584. + return "timezone_override";
  585. default:
  586. assert false;
  587. return "";
  588. 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
  589. --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java
  590. +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java
  591. @@ -124,4 +124,6 @@ public interface SiteSettingsDelegate {
  592. * Dismisses the Privacy Sandbox snackbar, if active.
  593. */
  594. void dismissPrivacySandboxSnackbar();
  595. +
  596. + void launchTimeZoneOverrideHelpAndFeedbackActivity(Activity currentActivity);
  597. }
  598. 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
  599. new file mode 100755
  600. --- /dev/null
  601. +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/TimezoneOverrideSiteSettingsPreference.java
  602. @@ -0,0 +1,193 @@
  603. +/*
  604. + This file is part of Bromite.
  605. +
  606. + Bromite is free software: you can redistribute it and/or modify
  607. + it under the terms of the GNU General Public License as published by
  608. + the Free Software Foundation, either version 3 of the License, or
  609. + (at your option) any later version.
  610. +
  611. + Bromite is distributed in the hope that it will be useful,
  612. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  613. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  614. + GNU General Public License for more details.
  615. +
  616. + You should have received a copy of the GNU General Public License
  617. + along with Bromite. If not, see <https://www.gnu.org/licenses/>.
  618. +*/
  619. +
  620. +package org.chromium.components.browser_ui.site_settings;
  621. +
  622. +import org.chromium.base.Log;
  623. +import android.content.Context;
  624. +import android.content.Intent;
  625. +import android.content.DialogInterface;
  626. +import android.view.View;
  627. +import android.widget.RadioGroup;
  628. +import android.widget.Button;
  629. +import android.widget.TextView;
  630. +import android.util.AttributeSet;
  631. +import android.widget.ArrayAdapter;
  632. +import android.widget.ListView;
  633. +import android.view.LayoutInflater;
  634. +import android.widget.AdapterView;
  635. +import android.graphics.Color;
  636. +
  637. +import androidx.preference.Preference;
  638. +import androidx.preference.PreferenceViewHolder;
  639. +import androidx.appcompat.app.AlertDialog;
  640. +
  641. +import org.chromium.content_public.browser.BrowserContextHandle;
  642. +import org.chromium.components.content_settings.ContentSettingValues;
  643. +import org.chromium.components.browser_ui.site_settings.WebsitePreferenceBridge;
  644. +import org.chromium.components.browser_ui.widget.RadioButtonWithDescription;
  645. +import org.chromium.components.browser_ui.widget.RadioButtonWithEditText;
  646. +import org.chromium.components.browser_ui.widget.TintedDrawable;
  647. +
  648. +import java.util.ArrayList;
  649. +import java.util.Arrays;
  650. +import java.util.TimeZone;
  651. +
  652. +/**
  653. + * TimezoneOverride Preference for SiteSettings.
  654. + */
  655. +public class TimezoneOverrideSiteSettingsPreference
  656. + extends Preference implements RadioGroup.OnCheckedChangeListener,
  657. + RadioButtonWithEditText.OnTextChangeListener {
  658. + private @ContentSettingValues int mSetting = ContentSettingValues.DEFAULT;
  659. + private RadioButtonWithDescription mAllowed;
  660. + private RadioButtonWithEditText mAsk;
  661. + private RadioButtonWithDescription mBlocked;
  662. + private RadioGroup mRadioGroup;
  663. + private TextView mSelectButton;
  664. +
  665. + private String currentSelected;
  666. +
  667. + private BrowserContextHandle mBrowserContextHandle;
  668. +
  669. + public TimezoneOverrideSiteSettingsPreference(Context context, AttributeSet attrs) {
  670. + super(context, attrs);
  671. +
  672. + setLayoutResource(R.layout.timezoneoverride_site_settings_preference);
  673. + setSelectable(false);
  674. + }
  675. +
  676. + public void initialize(@ContentSettingValues int setting, BrowserContextHandle browserContextHandle) {
  677. + mSetting = setting;
  678. + mBrowserContextHandle = browserContextHandle;
  679. + }
  680. +
  681. + public @ContentSettingValues int getCheckedSetting() {
  682. + return mSetting;
  683. + }
  684. +
  685. + @Override
  686. + public void onCheckedChanged(RadioGroup group, int checkedId) {
  687. + if (mAllowed.isChecked()) {
  688. + mSetting = ContentSettingValues.ALLOW;
  689. + } else if (mAsk.isChecked()) {
  690. + mSetting = ContentSettingValues.ASK;
  691. + } else if (mBlocked.isChecked()) {
  692. + mSetting = ContentSettingValues.BLOCK;
  693. + }
  694. +
  695. + callChangeListener(mSetting);
  696. + }
  697. +
  698. + @Override
  699. + public void onBindViewHolder(PreferenceViewHolder holder) {
  700. + super.onBindViewHolder(holder);
  701. +
  702. + mAllowed = (RadioButtonWithDescription) holder.findViewById(R.id.allowed);
  703. + mAsk = (RadioButtonWithEditText) holder.findViewById(R.id.ask);
  704. + mBlocked = (RadioButtonWithDescription) holder.findViewById(R.id.blocked);
  705. + mRadioGroup = (RadioGroup) holder.findViewById(R.id.radio_button_layout);
  706. + mRadioGroup.setOnCheckedChangeListener(this);
  707. +
  708. + mAsk.setPrimaryText(WebsitePreferenceBridge.getCustomTimezone(mBrowserContextHandle));
  709. + mAsk.addTextChangeListener(this);
  710. +
  711. + ListView listView = (ListView)holder.findViewById(R.id.listView);
  712. +
  713. + mSelectButton = (TextView) holder.findViewById(R.id.select_button);
  714. + mSelectButton.setOnClickListener(view -> {
  715. + showSelectTimeZoneDialog();
  716. + });
  717. +
  718. + RadioButtonWithDescription radioButton = findRadioButton(mSetting);
  719. + if (radioButton != null) radioButton.setChecked(true);
  720. + }
  721. +
  722. + private RadioButtonWithDescription findRadioButton(@ContentSettingValues int setting) {
  723. + if (setting == ContentSettingValues.ALLOW) {
  724. + return mAllowed;
  725. + } else if (setting == ContentSettingValues.ASK) {
  726. + return mAsk;
  727. + } else if (setting == ContentSettingValues.BLOCK) {
  728. + return mBlocked;
  729. + } else {
  730. + return null;
  731. + }
  732. + }
  733. +
  734. + public void onTextChanged(CharSequence newText) {
  735. + WebsitePreferenceBridge.setCustomTimezone(mBrowserContextHandle, newText.toString());
  736. + }
  737. +
  738. + private void showSelectTimeZoneDialog() {
  739. + LayoutInflater inflater =
  740. + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  741. + View view = inflater.inflate(R.layout.time_zone_select_dialog, null);
  742. +
  743. + ListView listView = view.findViewById(R.id.listView);
  744. + ArrayList<String> timezones = new ArrayList<>(Arrays.asList(TimeZone.getAvailableIDs()));
  745. + ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1, android.R.id.text1, timezones);
  746. + listView.setAdapter(adapter);
  747. +
  748. + currentSelected = String.valueOf(mAsk.getPrimaryText());
  749. + listView.post(new Runnable()
  750. + {
  751. + public void run()
  752. + {
  753. + for (int j = 0; j < timezones.size(); j++) {
  754. + if (currentSelected.equals(timezones.get(j))) {
  755. + listView.requestFocusFromTouch();
  756. + listView.setSelection(j);
  757. + adapter.notifyDataSetChanged();
  758. + break;
  759. + }
  760. + }
  761. + }
  762. + });
  763. +
  764. + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  765. + @Override
  766. + public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
  767. + currentSelected = timezones.get(i);
  768. + listView.setSelected(true);
  769. + }
  770. + });
  771. +
  772. + DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
  773. + @Override
  774. + public void onClick(DialogInterface dialog, int button) {
  775. + if (button == AlertDialog.BUTTON_POSITIVE) {
  776. + mAsk.setPrimaryText(currentSelected);
  777. + } else {
  778. + dialog.dismiss();
  779. + }
  780. + }
  781. + };
  782. +
  783. + AlertDialog.Builder alert =
  784. + new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog);
  785. + AlertDialog alertDialog =
  786. + alert.setTitle(R.string.website_settings_select_dialog_title)
  787. + .setView(view)
  788. + .setPositiveButton(
  789. + R.string.website_settings_select_dialog_button, onClickListener)
  790. + .setNegativeButton(R.string.cancel, onClickListener)
  791. + .create();
  792. + alertDialog.getDelegate().setHandleNativeActionModesEnabled(false);
  793. + alertDialog.show();
  794. + }
  795. +}
  796. 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
  797. --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java
  798. +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java
  799. @@ -229,6 +229,16 @@ public final class Website implements Serializable {
  800. } else {
  801. RecordUserAction.record("SoundContentSetting.UnmuteBy.SiteSettings");
  802. }
  803. + } else if (type == ContentSettingsType.TIMEZONE_OVERRIDE) {
  804. + // It is possible to set the permission without having an existing exception,
  805. + // because we can show the ALLOW state even when this permission is set to the
  806. + // default. In that case, just set an exception now to ALLOW to enable changing the
  807. + // permission.
  808. + if (exception == null) {
  809. + exception = new ContentSettingException(
  810. + ContentSettingsType.TIMEZONE_OVERRIDE, getAddress().getHost(), value, "");
  811. + setContentSettingException(type, exception);
  812. + }
  813. }
  814. // We want to call setContentSetting even after explicitly setting
  815. // mContentSettingException above because this will trigger the actual change
  816. 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
  817. --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java
  818. +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java
  819. @@ -68,6 +68,7 @@ public class WebsitePermissionsFetcher {
  820. case ContentSettingsType.POPUPS:
  821. case ContentSettingsType.REQUEST_DESKTOP_SITE:
  822. case ContentSettingsType.SOUND:
  823. + case ContentSettingsType.TIMEZONE_OVERRIDE:
  824. return WebsitePermissionsType.CONTENT_SETTING_EXCEPTION;
  825. case ContentSettingsType.AR:
  826. case ContentSettingsType.CLIPBOARD_READ_WRITE:
  827. @@ -148,6 +149,8 @@ public class WebsitePermissionsFetcher {
  828. for (@ContentSettingsType int type = 0; type < ContentSettingsType.NUM_TYPES; type++) {
  829. addFetcherForContentSettingsType(queue, type);
  830. }
  831. + queue.add(new ExceptionInfoFetcher(ContentSettingsType.TIMEZONE_OVERRIDE));
  832. +
  833. queue.add(new PermissionsAvailableCallbackRunner(callback));
  834. queue.next();
  835. }
  836. 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
  837. --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java
  838. +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java
  839. @@ -221,6 +221,8 @@ public class WebsitePreferenceBridge {
  840. switch (contentSettingsType) {
  841. case ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER:
  842. return true;
  843. + case ContentSettingsType.TIMEZONE_OVERRIDE:
  844. + return true;
  845. default:
  846. return false;
  847. }
  848. @@ -351,6 +353,14 @@ public class WebsitePreferenceBridge {
  849. contentSettingType, primaryPattern, secondaryPattern, setting);
  850. }
  851. + public static String getCustomTimezone(BrowserContextHandle browserContextHandle) {
  852. + return WebsitePreferenceBridgeJni.get().getCustomTimezone(browserContextHandle);
  853. + }
  854. +
  855. + public static void setCustomTimezone(BrowserContextHandle browserContextHandle, String timezone) {
  856. + WebsitePreferenceBridgeJni.get().setCustomTimezone(browserContextHandle, timezone);
  857. + }
  858. +
  859. @NativeMethods
  860. public interface Natives {
  861. boolean isNotificationEmbargoedForOrigin(
  862. @@ -412,5 +422,7 @@ public class WebsitePreferenceBridge {
  863. boolean isContentSettingManagedByCustodian(
  864. BrowserContextHandle browserContextHandle, int contentSettingType);
  865. boolean getLocationAllowedByPolicy(BrowserContextHandle browserContextHandle);
  866. + String getCustomTimezone(BrowserContextHandle browserContextHandle);
  867. + void setCustomTimezone(BrowserContextHandle browserContextHandle, String timezone);
  868. }
  869. }
  870. diff --git a/components/browser_ui/site_settings/android/website_preference_bridge.cc b/components/browser_ui/site_settings/android/website_preference_bridge.cc
  871. --- a/components/browser_ui/site_settings/android/website_preference_bridge.cc
  872. +++ b/components/browser_ui/site_settings/android/website_preference_bridge.cc
  873. @@ -900,3 +900,19 @@ static jboolean JNI_WebsitePreferenceBridge_GetLocationAllowedByPolicy(
  874. ->GetDefaultContentSetting(ContentSettingsType::GEOLOCATION,
  875. nullptr) == CONTENT_SETTING_ALLOW;
  876. }
  877. +
  878. +static void JNI_WebsitePreferenceBridge_SetCustomTimezone(
  879. + JNIEnv* env,
  880. + const JavaParamRef<jobject>& jbrowser_context_handle,
  881. + const JavaParamRef<jstring>& timezone) {
  882. + std::string new_timezone = ConvertJavaStringToUTF8(env, timezone);
  883. + GetHostContentSettingsMap(jbrowser_context_handle)->SetTimezoneOverrideValue(new_timezone);
  884. +}
  885. +
  886. +static base::android::ScopedJavaLocalRef<jstring> JNI_WebsitePreferenceBridge_GetCustomTimezone(
  887. + JNIEnv* env,
  888. + const JavaParamRef<jobject>& jbrowser_context_handle) {
  889. + std::string timezone;
  890. + GetHostContentSettingsMap(jbrowser_context_handle)->GetTimezoneOverrideValue(timezone);
  891. + return ConvertUTF8ToJavaString(env, timezone);
  892. +}
  893. diff --git a/components/browser_ui/strings/android/site_settings.grdp b/components/browser_ui/strings/android/site_settings.grdp
  894. --- a/components/browser_ui/strings/android/site_settings.grdp
  895. +++ b/components/browser_ui/strings/android/site_settings.grdp
  896. @@ -75,6 +75,9 @@
  897. <message name="IDS_AUTO_DARK_WEB_CONTENT_TITLE" desc="Title of the permission auto darken web content [CHAR_LIMIT=32]">
  898. Dark theme for sites
  899. </message>
  900. + <message name="IDS_TIMEZONE_OVERRIDE_PERMISSION_TITLE" desc="Title of the permission to use TimeZone Override [CHAR-LIMIT=32]">
  901. + Timezone override
  902. + </message>
  903. <message name="IDS_DESKTOP_SITE_TITLE" desc="Title of the permission to request the desktop view of a site by default [CHAR_LIMIT=32]">
  904. Desktop site
  905. </message>
  906. @@ -497,6 +500,38 @@
  907. Block sites from playing protected content
  908. </message>
  909. + <!-- Timezone override -->
  910. + <message name="IDS_WEBSITE_SETTINGS_TIMEOVERRIDE_INFO" desc="Primary text explaining the timezone override feature.">
  911. + Override timezone with a custom or random one, or use the system timezone
  912. + </message>
  913. + <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_ALLOWED_TEXT" desc="Primary text explaining that sites are allowed to access the system timezone.">
  914. + None (use system timezone)
  915. + </message>
  916. + <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_RANDOM_TEXT" desc="Primary text for random timezone override.">
  917. + Random
  918. + </message>
  919. + <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_ALLOWED" desc="Summary text explaining that sites are allowed to access the system timezone.">
  920. + System timezone
  921. + </message>
  922. + <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_CUSTOM" desc="Summary text explaining that sites use custom timezone.">
  923. + Custom timezone
  924. + </message>
  925. + <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_CUSTOM_HINT" desc="Hint text for edit custom timezone.">
  926. + Specify a custom timezone (default UTC)
  927. + </message>
  928. + <message name="IDS_WEBSITE_SETTINGS_CATEGORY_TIMEZONE_OVERRIDE_RANDOM" desc="Summary text for random timezone override.">
  929. + Random (for each page)
  930. + </message>
  931. + <message name="IDS_WEBSITE_SETTINGS_SELECT_BUTTON" desc="Primary button text for choosing a timezone from a list.">
  932. + Choose Timezone...
  933. + </message>
  934. + <message name="IDS_WEBSITE_SETTINGS_SELECT_DIALOG_TITLE" desc="Text of the dialog to choose a timezone.">
  935. + Choose Timezone
  936. + </message>
  937. + <message name="IDS_WEBSITE_SETTINGS_SELECT_DIALOG_BUTTON" desc="Primary button text in the dialog used to choose the custom timezone.">
  938. + Select
  939. + </message>
  940. +
  941. <!-- Sound -->
  942. <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.">
  943. diff --git a/components/content_settings/core/browser/content_settings_pref_provider.cc b/components/content_settings/core/browser/content_settings_pref_provider.cc
  944. --- a/components/content_settings/core/browser/content_settings_pref_provider.cc
  945. +++ b/components/content_settings/core/browser/content_settings_pref_provider.cc
  946. @@ -84,6 +84,8 @@ void PrefProvider::RegisterProfilePrefs(
  947. info->GetPrefRegistrationFlags());
  948. }
  949. + registry->RegisterStringPref(prefs::kContentSettingsCustomTimezone, std::string());
  950. +
  951. // Obsolete prefs ----------------------------------------------------------
  952. // These prefs have been removed, but need to be registered so they can
  953. @@ -169,6 +171,10 @@ PrefProvider::PrefProvider(PrefService* prefs,
  954. event_args->set_number_of_exceptions(
  955. num_exceptions); // PrefProvider::PrefProvider.
  956. });
  957. +
  958. + custom_timezone_ =
  959. + prefs_->GetString(
  960. + prefs::kContentSettingsCustomTimezone);
  961. }
  962. PrefProvider::~PrefProvider() {
  963. @@ -299,4 +305,14 @@ void PrefProvider::SetClockForTesting(base::Clock* clock) {
  964. clock_ = clock;
  965. }
  966. +void PrefProvider::GetPrefTimezoneOverrideValue(std::string& timezone) const {
  967. + timezone = custom_timezone_;
  968. +}
  969. +
  970. +void PrefProvider::SetPrefTimezoneOverrideValue(const std::string& timezone) {
  971. + prefs_->SetString(
  972. + prefs::kContentSettingsCustomTimezone, timezone);
  973. + custom_timezone_ = timezone;
  974. +}
  975. +
  976. } // namespace content_settings
  977. diff --git a/components/content_settings/core/browser/content_settings_pref_provider.h b/components/content_settings/core/browser/content_settings_pref_provider.h
  978. --- a/components/content_settings/core/browser/content_settings_pref_provider.h
  979. +++ b/components/content_settings/core/browser/content_settings_pref_provider.h
  980. @@ -67,6 +67,9 @@ class PrefProvider : public UserModifiableProvider {
  981. ContentSettingsPref* GetPref(ContentSettingsType type) const;
  982. + void GetPrefTimezoneOverrideValue(std::string& timezone) const;
  983. + void SetPrefTimezoneOverrideValue(const std::string& timezone);
  984. +
  985. private:
  986. friend class DeadlockCheckerObserver; // For testing.
  987. @@ -99,6 +102,7 @@ class PrefProvider : public UserModifiableProvider {
  988. base::ThreadChecker thread_checker_;
  989. raw_ptr<base::Clock> clock_;
  990. + std::string custom_timezone_;
  991. };
  992. } // namespace content_settings
  993. diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc
  994. --- a/components/content_settings/core/browser/content_settings_registry.cc
  995. +++ b/components/content_settings/core/browser/content_settings_registry.cc
  996. @@ -645,6 +645,18 @@ void ContentSettingsRegistry::Init() {
  997. ContentSettingsInfo::PERSISTENT,
  998. ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS);
  999. + Register(ContentSettingsType::TIMEZONE_OVERRIDE, "timezone-override", CONTENT_SETTING_ALLOW,
  1000. + WebsiteSettingsInfo::SYNCABLE,
  1001. + AllowlistedSchemes(kChromeUIScheme, kChromeDevToolsScheme),
  1002. + ValidSettings(CONTENT_SETTING_ALLOW, // use system time
  1003. + CONTENT_SETTING_ASK, // custom timezone, default UTC
  1004. + CONTENT_SETTING_BLOCK), // random
  1005. + WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
  1006. + WebsiteSettingsRegistry::PLATFORM_ANDROID,
  1007. + ContentSettingsInfo::INHERIT_IN_INCOGNITO,
  1008. + ContentSettingsInfo::PERSISTENT,
  1009. + ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS);
  1010. +
  1011. Register(ContentSettingsType::FEDERATED_IDENTITY_API, "webid-api",
  1012. CONTENT_SETTING_ALLOW, WebsiteSettingsInfo::UNSYNCABLE,
  1013. AllowlistedSchemes(),
  1014. diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc
  1015. --- a/components/content_settings/core/browser/content_settings_utils.cc
  1016. +++ b/components/content_settings/core/browser/content_settings_utils.cc
  1017. @@ -150,6 +150,13 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map,
  1018. &(rules->script_rules));
  1019. map->GetSettingsForOneType(ContentSettingsType::POPUPS,
  1020. &(rules->popup_redirect_rules));
  1021. +
  1022. + // pass custom timezone rules and value to the render process
  1023. + map->GetSettingsForOneType(ContentSettingsType::TIMEZONE_OVERRIDE,
  1024. + &(rules->timezone_override_rules));
  1025. + std::string timezone;
  1026. + map->GetTimezoneOverrideValue(timezone);
  1027. + rules->timezone_override_value = timezone;
  1028. }
  1029. bool IsMorePermissive(ContentSetting a, ContentSetting b) {
  1030. diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc
  1031. --- a/components/content_settings/core/browser/host_content_settings_map.cc
  1032. +++ b/components/content_settings/core/browser/host_content_settings_map.cc
  1033. @@ -599,6 +599,14 @@ void HostContentSettingsMap::SetClockForTesting(base::Clock* clock) {
  1034. provider->SetClockForTesting(clock);
  1035. }
  1036. +void HostContentSettingsMap::GetTimezoneOverrideValue(std::string& timezone) const {
  1037. + GetPrefProvider()->GetPrefTimezoneOverrideValue(timezone);
  1038. +}
  1039. +
  1040. +void HostContentSettingsMap::SetTimezoneOverrideValue(const std::string& timezone) {
  1041. + GetPrefProvider()->SetPrefTimezoneOverrideValue(timezone);
  1042. +}
  1043. +
  1044. void HostContentSettingsMap::RecordExceptionMetrics() {
  1045. auto* content_setting_registry =
  1046. content_settings::ContentSettingsRegistry::GetInstance();
  1047. diff --git a/components/content_settings/core/browser/host_content_settings_map.h b/components/content_settings/core/browser/host_content_settings_map.h
  1048. --- a/components/content_settings/core/browser/host_content_settings_map.h
  1049. +++ b/components/content_settings/core/browser/host_content_settings_map.h
  1050. @@ -334,6 +334,9 @@ class HostContentSettingsMap : public content_settings::Observer,
  1051. allow_invalid_secondary_pattern_for_testing_ = allow;
  1052. }
  1053. + void GetTimezoneOverrideValue(std::string& timezone) const;
  1054. + void SetTimezoneOverrideValue(const std::string& timezone);
  1055. +
  1056. private:
  1057. friend class base::RefCountedThreadSafe<HostContentSettingsMap>;
  1058. friend class content_settings::TestUtils;
  1059. diff --git a/components/content_settings/core/common/content_settings.cc b/components/content_settings/core/common/content_settings.cc
  1060. --- a/components/content_settings/core/common/content_settings.cc
  1061. +++ b/components/content_settings/core/common/content_settings.cc
  1062. @@ -190,7 +190,8 @@ bool RendererContentSettingRules::IsRendererContentSetting(
  1063. content_type == ContentSettingsType::CLIENT_HINTS ||
  1064. content_type == ContentSettingsType::POPUPS ||
  1065. content_type == ContentSettingsType::MIXEDSCRIPT ||
  1066. - content_type == ContentSettingsType::AUTO_DARK_WEB_CONTENT;
  1067. + content_type == ContentSettingsType::AUTO_DARK_WEB_CONTENT ||
  1068. + content_type == ContentSettingsType::TIMEZONE_OVERRIDE;
  1069. }
  1070. RendererContentSettingRules::RendererContentSettingRules() {}
  1071. diff --git a/components/content_settings/core/common/content_settings.h b/components/content_settings/core/common/content_settings.h
  1072. --- a/components/content_settings/core/common/content_settings.h
  1073. +++ b/components/content_settings/core/common/content_settings.h
  1074. @@ -80,6 +80,8 @@ struct RendererContentSettingRules {
  1075. ContentSettingsForOneType popup_redirect_rules;
  1076. ContentSettingsForOneType mixed_content_rules;
  1077. ContentSettingsForOneType auto_dark_content_rules;
  1078. + ContentSettingsForOneType timezone_override_rules;
  1079. + std::string timezone_override_value;
  1080. };
  1081. namespace content_settings {
  1082. diff --git a/components/content_settings/core/common/content_settings.mojom b/components/content_settings/core/common/content_settings.mojom
  1083. --- a/components/content_settings/core/common/content_settings.mojom
  1084. +++ b/components/content_settings/core/common/content_settings.mojom
  1085. @@ -78,4 +78,6 @@ struct RendererContentSettingRules {
  1086. array<ContentSettingPatternSource> popup_redirect_rules;
  1087. array<ContentSettingPatternSource> mixed_content_rules;
  1088. array<ContentSettingPatternSource> auto_dark_content_rules;
  1089. + array<ContentSettingPatternSource> timezone_override_rules;
  1090. + string timezone_override_value;
  1091. };
  1092. diff --git a/components/content_settings/core/common/content_settings_mojom_traits.cc b/components/content_settings/core/common/content_settings_mojom_traits.cc
  1093. --- a/components/content_settings/core/common/content_settings_mojom_traits.cc
  1094. +++ b/components/content_settings/core/common/content_settings_mojom_traits.cc
  1095. @@ -101,7 +101,9 @@ bool StructTraits<content_settings::mojom::RendererContentSettingRulesDataView,
  1096. data.ReadScriptRules(&out->script_rules) &&
  1097. data.ReadPopupRedirectRules(&out->popup_redirect_rules) &&
  1098. data.ReadMixedContentRules(&out->mixed_content_rules) &&
  1099. - data.ReadAutoDarkContentRules(&out->auto_dark_content_rules);
  1100. + data.ReadAutoDarkContentRules(&out->auto_dark_content_rules) &&
  1101. + data.ReadTimezoneOverrideRules(&out->timezone_override_rules) &&
  1102. + data.ReadTimezoneOverrideValue(&out->timezone_override_value);
  1103. }
  1104. } // namespace mojo
  1105. diff --git a/components/content_settings/core/common/content_settings_mojom_traits.h b/components/content_settings/core/common/content_settings_mojom_traits.h
  1106. --- a/components/content_settings/core/common/content_settings_mojom_traits.h
  1107. +++ b/components/content_settings/core/common/content_settings_mojom_traits.h
  1108. @@ -150,6 +150,16 @@ struct StructTraits<
  1109. return r.auto_dark_content_rules;
  1110. }
  1111. + static const std::vector<ContentSettingPatternSource>& timezone_override_rules(
  1112. + const RendererContentSettingRules& r) {
  1113. + return r.timezone_override_rules;
  1114. + }
  1115. +
  1116. + static const std::string& timezone_override_value(
  1117. + const RendererContentSettingRules& r) {
  1118. + return r.timezone_override_value;
  1119. + }
  1120. +
  1121. static bool Read(
  1122. content_settings::mojom::RendererContentSettingRulesDataView data,
  1123. RendererContentSettingRules* out);
  1124. diff --git a/components/content_settings/core/common/content_settings_types.h b/components/content_settings/core/common/content_settings_types.h
  1125. --- a/components/content_settings/core/common/content_settings_types.h
  1126. +++ b/components/content_settings/core/common/content_settings_types.h
  1127. @@ -226,6 +226,9 @@ enum class ContentSettingsType : int32_t {
  1128. // by the File System Access API.
  1129. FILE_SYSTEM_LAST_PICKED_DIRECTORY,
  1130. + // Content setting for timezone customization functionality.
  1131. + TIMEZONE_OVERRIDE,
  1132. +
  1133. // Controls access to the getDisplayMedia API when {preferCurrentTab: true}
  1134. // is specified.
  1135. // TODO(crbug.com/1150788): Also apply this when getDisplayMedia() is called
  1136. diff --git a/components/content_settings/core/common/pref_names.cc b/components/content_settings/core/common/pref_names.cc
  1137. --- a/components/content_settings/core/common/pref_names.cc
  1138. +++ b/components/content_settings/core/common/pref_names.cc
  1139. @@ -157,4 +157,7 @@ const char kQuietNotificationPermissionUiDisabledTime[] =
  1140. const char kNotificationsVibrateEnabled[] = "notifications.vibrate_enabled";
  1141. #endif
  1142. +const char kContentSettingsCustomTimezone[] =
  1143. + "profile.content_settings.custom_timezone";
  1144. +
  1145. } // namespace prefs
  1146. diff --git a/components/content_settings/core/common/pref_names.h b/components/content_settings/core/common/pref_names.h
  1147. --- a/components/content_settings/core/common/pref_names.h
  1148. +++ b/components/content_settings/core/common/pref_names.h
  1149. @@ -83,6 +83,8 @@ extern const char kQuietNotificationPermissionUiDisabledTime[];
  1150. extern const char kNotificationsVibrateEnabled[];
  1151. #endif
  1152. +extern const char kContentSettingsCustomTimezone[];
  1153. +
  1154. } // namespace prefs
  1155. #endif // COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_PREF_NAMES_H_
  1156. diff --git a/components/content_settings/renderer/content_settings_agent_impl.cc b/components/content_settings/renderer/content_settings_agent_impl.cc
  1157. --- a/components/content_settings/renderer/content_settings_agent_impl.cc
  1158. +++ b/components/content_settings/renderer/content_settings_agent_impl.cc
  1159. @@ -8,8 +8,10 @@
  1160. #include "base/bind.h"
  1161. #include "base/feature_list.h"
  1162. +#include "base/logging.h"
  1163. #include "base/metrics/histogram_macros.h"
  1164. #include "base/strings/string_number_conversions.h"
  1165. +#include "base/rand_util.h"
  1166. #include "components/content_settings/core/common/content_settings.h"
  1167. #include "components/content_settings/core/common/content_settings.mojom.h"
  1168. #include "components/content_settings/core/common/content_settings_pattern.h"
  1169. @@ -29,6 +31,10 @@
  1170. #include "third_party/blink/public/web/web_local_frame.h"
  1171. #include "third_party/blink/public/web/web_local_frame_client.h"
  1172. #include "third_party/blink/public/web/web_view.h"
  1173. +#include "third_party/blink/renderer/core/inspector/locale_controller.h"
  1174. +#include "third_party/blink/renderer/core/timezone/timezone_controller.h"
  1175. +#include "third_party/icu/source/common/unicode/strenum.h"
  1176. +#include "third_party/icu/source/i18n/unicode/timezone.h"
  1177. #include "url/gurl.h"
  1178. #include "url/origin.h"
  1179. #include "url/url_constants.h"
  1180. @@ -41,6 +47,8 @@ using blink::WebString;
  1181. using blink::WebURL;
  1182. using blink::WebView;
  1183. +std::unique_ptr<blink::TimeZoneController::TimeZoneOverride> timezone_override_;
  1184. +
  1185. namespace content_settings {
  1186. namespace {
  1187. @@ -357,6 +365,10 @@ bool ContentSettingsAgentImpl::AllowScript(bool enabled_per_settings) {
  1188. allow = allow || IsAllowlistedForContentSettings();
  1189. cached_script_permissions_[frame] = allow;
  1190. +
  1191. + if (allow)
  1192. + UpdateOverrides();
  1193. +
  1194. return allow;
  1195. }
  1196. @@ -487,4 +499,81 @@ bool ContentSettingsAgentImpl::IsAllowlistedForContentSettings() const {
  1197. return false;
  1198. }
  1199. +bool ContentSettingsAgentImpl::UpdateOverrides() {
  1200. + // Evaluate the content setting rules
  1201. + ContentSetting setting = CONTENT_SETTING_ALLOW;
  1202. +
  1203. + if (content_setting_rules_) {
  1204. + blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
  1205. +
  1206. + setting = GetContentSettingFromRules(
  1207. + content_setting_rules_->timezone_override_rules, frame,
  1208. + url::Origin(frame->GetDocument().GetSecurityOrigin()).GetURL());
  1209. + }
  1210. + return UpdateTimeZoneOverride(
  1211. + setting, content_setting_rules_->timezone_override_value);
  1212. + //&& UpdateLocaleOverride(setting);
  1213. +}
  1214. +
  1215. +bool ContentSettingsAgentImpl::UpdateTimeZoneOverride(
  1216. + ContentSetting setting,
  1217. + const std::string& timezone_override_value) {
  1218. + // base/i18n/icu_util.cc # 329
  1219. +
  1220. + /* timezone_id: third_party/icu/source/i18n/timezone.cpp
  1221. + We first try to lookup the zone ID in our system list. If this
  1222. + * fails, we try to parse it as a custom string GMT[+-]hh:mm. If
  1223. + * all else fails, we return GMT, which is probably not what the
  1224. + * user wants, but at least is a functioning TimeZone object.
  1225. + */
  1226. + String timezone_id;
  1227. +
  1228. + if (setting == CONTENT_SETTING_ALLOW) {
  1229. + // system time
  1230. + if (timezone_override_) {
  1231. + timezone_override_.reset();
  1232. + }
  1233. + return true;
  1234. + } else if (setting == CONTENT_SETTING_BLOCK) {
  1235. + // timezone random
  1236. + UErrorCode ec = U_ZERO_ERROR;
  1237. + int32_t rawOffset = base::RandInt(-12, 11) * 3600 * 1000;
  1238. + icu::StringEnumeration* timezones = icu::TimeZone::createEnumeration(
  1239. + rawOffset); // Obtain timezones by GMT timezone offset
  1240. + if (timezones) {
  1241. + const char* tzID;
  1242. + int32_t length;
  1243. + if ((tzID = timezones->next(&length, ec)) != NULL) {
  1244. + timezone_id = String(tzID);
  1245. + }
  1246. + delete timezones;
  1247. + }
  1248. + } else if (setting == CONTENT_SETTING_ASK) {
  1249. + if (timezone_override_value.empty())
  1250. + timezone_id = "Europe/London";
  1251. + else
  1252. + timezone_id = String(timezone_override_value.c_str());
  1253. + }
  1254. +
  1255. + if (blink::TimeZoneController::HasTimeZoneOverride() == false) {
  1256. + timezone_override_.reset();
  1257. + timezone_override_ =
  1258. + blink::TimeZoneController::SetTimeZoneOverride(timezone_id);
  1259. + if (!timezone_override_) {
  1260. + LOG(WARNING) << "UpdateTimeZoneOverride - Invalid timezone id '"
  1261. + << timezone_id << "'";
  1262. + return false;
  1263. + } else {
  1264. + LOG(INFO)
  1265. + << "UpdateTimeZoneOverride - setting to '"
  1266. + << timezone_id << "'";
  1267. + return true;
  1268. + }
  1269. + } else {
  1270. + LOG(INFO)
  1271. + << "UpdateTimeZoneOverride: already set";
  1272. + return false;
  1273. + }
  1274. +}
  1275. +
  1276. } // namespace content_settings
  1277. diff --git a/components/content_settings/renderer/content_settings_agent_impl.h b/components/content_settings/renderer/content_settings_agent_impl.h
  1278. --- a/components/content_settings/renderer/content_settings_agent_impl.h
  1279. +++ b/components/content_settings/renderer/content_settings_agent_impl.h
  1280. @@ -183,6 +183,10 @@ class ContentSettingsAgentImpl
  1281. std::unique_ptr<Delegate> delegate_;
  1282. mojo::AssociatedReceiverSet<mojom::ContentSettingsAgent> receivers_;
  1283. +
  1284. + bool UpdateOverrides();
  1285. + bool UpdateTimeZoneOverride(ContentSetting setting, const std::string& timezone_override_value);
  1286. + bool UpdateLocaleOverride(ContentSetting setting);
  1287. };
  1288. } // namespace content_settings
  1289. diff --git a/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java b/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java
  1290. --- a/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java
  1291. +++ b/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java
  1292. @@ -137,4 +137,7 @@ public class WebLayerSiteSettingsDelegate
  1293. @Override
  1294. public void dismissPrivacySandboxSnackbar() {}
  1295. +
  1296. + @Override
  1297. + public void launchTimeZoneOverrideHelpAndFeedbackActivity(Activity currentActivity) {}
  1298. }
  1299. --
  1300. 2.25.1