diff --git a/DEPS b/DEPS index 10f69cb..eb957e5 100644 --- a/DEPS +++ b/DEPS
@@ -74,7 +74,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'f5beefd34df7360f7ffa219434d11d481bd72efc', + 'skia_revision': 'df8408836be0c1389e5f927352665a4216d3b3a0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -330,7 +330,7 @@ }, 'src/third_party/ffmpeg': - Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '1e816bccb5ff0b778ab2765b4fa8b888a121a200', + Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '252244150ad759fe86470f40642514bf2a7aec98', 'src/third_party/findbugs': { 'url': Var('chromium_git') + '/chromium/deps/findbugs.git' + '@' + '4275d9ac8610db6b1bc9a5e887f97e41b33fac67',
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index e47e1f6..7622e11d 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -1218,6 +1218,36 @@ <message name="IDS_SETTINGS_DATE_TIME" desc="Name of the settings page which displays date and time preferences."> Date and time </message> + <message name="IDS_SETTINGS_TIME_ZONE_BUTTON" desc="Label for the button that opens time zone settings page."> + Time zone + </message> + <message name="IDS_SETTINGS_TIME_ZONE_SUBPAGE_TITLE" desc="The title of the dialog that allows user to control different time zone settings."> + Time zone + </message> + <message name="IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_DISABLED" desc="Display name for the automatic time zone detection mode which disables automatic detection."> + Automatic time zone detection is disabled + </message> + <message name="IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_IP_ONLY_DEFAULT" desc="Display name for the automatic time zone detection mode which enables time zone detection sending unprecise location to Google servers. Default means that this is the default time zone detection mode."> + Set automatically using your general location (default) + </message> + <message name="IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_IP_ONLY_DESCRIPTION" desc="Display name for the automatic time zone detection mode which enables time zone detection by requesting user location from Google servers based on device IP address. Default means that this is the default time zone detection mode."> + Use your IP address to determine location + </message> + <message name="IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_SEND_WIFI_AP" desc="Display name for the automatic time zone detection mode which enables time zone detection sending list of visible WiFi Access Point names to Google servers."> + Set automatically using your WiFi network + </message> + <message name="IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_SEND_WIFI_AP_DESCRIPTION" desc="Description for the automatic time zone detection mode which enables time zone detection sending list of visible WiFi Access Point names to Google servers."> + Use WiFi network to determine location + </message> + <message name="IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_SEND_ALL_INFO" desc="Display name for the automatic time zone detection mode which enables time zone detection sending list of visible WiFi and Cellular Access Point names to Google servers."> + Set automatically using your accurate location + </message> + <message name="IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_SEND_ALL_INFO_DESCRIPTION" desc="Description for the automatic time zone detection mode which enables time zone detection sending list of visible WiFi and Cellular Access Point names to Google servers."> + Use WiFi or cellular network to determine location + </message> + <message name="IDS_SETTINGS_TIME_ZONE_DETECTION_SELECT_YOUR_TIME_ZONE" desc="Option name in the list of automatic time zone detection modes that turns automatic detection off, and suggests user to select time zone from the displayed drop-down list."> + Choose from list + </message> <message name="IDS_SETTINGS_TIME_ZONE" desc="Label for the picker which allows users to choose their time zone."> Time zone: </message>
diff --git a/chrome/browser/chromeos/settings/system_settings_provider.cc b/chrome/browser/chromeos/settings/system_settings_provider.cc index 02b9d11..29baa3b 100644 --- a/chrome/browser/chromeos/settings/system_settings_provider.cc +++ b/chrome/browser/chromeos/settings/system_settings_provider.cc
@@ -23,6 +23,8 @@ new base::Value(timezone_settings->GetCurrentTimezoneID())); per_user_timezone_enabled_value_.reset( new base::Value(system::PerUserTimezoneEnabled())); + fine_grained_time_zone_enabled_value_.reset( + new base::Value(system::FineGrainedTimeZoneDetectionEnabled())); } SystemSettingsProvider::~SystemSettingsProvider() { @@ -45,6 +47,7 @@ system::TimezoneSettings::GetInstance()->SetTimezoneFromID(timezone_id); } // kPerUserTimezoneEnabled is read-only. + // kFineGrainedTimeZoneResolveEnabled is read-only. } const base::Value* SystemSettingsProvider::Get(const std::string& path) const { @@ -54,6 +57,9 @@ if (path == kPerUserTimezoneEnabled) return per_user_timezone_enabled_value_.get(); + if (path == kFineGrainedTimeZoneResolveEnabled) + return fine_grained_time_zone_enabled_value_.get(); + return NULL; } @@ -64,7 +70,8 @@ } bool SystemSettingsProvider::HandlesSetting(const std::string& path) const { - return path == kSystemTimezone || path == kPerUserTimezoneEnabled; + return path == kSystemTimezone || path == kPerUserTimezoneEnabled || + path == kFineGrainedTimeZoneResolveEnabled; } void SystemSettingsProvider::TimezoneChanged(const icu::TimeZone& timezone) {
diff --git a/chrome/browser/chromeos/settings/system_settings_provider.h b/chrome/browser/chromeos/settings/system_settings_provider.h index c72b60f..e9ccb17 100644 --- a/chrome/browser/chromeos/settings/system_settings_provider.h +++ b/chrome/browser/chromeos/settings/system_settings_provider.h
@@ -40,6 +40,7 @@ std::unique_ptr<base::Value> timezone_value_; std::unique_ptr<base::Value> per_user_timezone_enabled_value_; + std::unique_ptr<base::Value> fine_grained_time_zone_enabled_value_; DISALLOW_COPY_AND_ASSIGN(SystemSettingsProvider); };
diff --git a/chrome/browser/chromeos/system/timezone_resolver_manager.cc b/chrome/browser/chromeos/system/timezone_resolver_manager.cc index 6e807aa..6dd464d 100644 --- a/chrome/browser/chromeos/system/timezone_resolver_manager.cc +++ b/chrome/browser/chromeos/system/timezone_resolver_manager.cc
@@ -85,26 +85,12 @@ return result; } -// Convert kResolveTimezoneByGeolocationMethod / -// kResolveDeviceTimezoneByGeolocationMethod preference value to -// TimeZoneResolveMethod. Defaults to DISABLED for unknown values. -TimeZoneResolverManager::TimeZoneResolveMethod TimeZoneResolveMethodFromInt( - int value) { - if (value < 0 || - value >= - static_cast<int>( - TimeZoneResolverManager::TimeZoneResolveMethod::METHODS_NUMBER)) { - return TimeZoneResolverManager::TimeZoneResolveMethod::DISABLED; - } - - return static_cast<TimeZoneResolverManager::TimeZoneResolveMethod>(value); -} - // Returns service configuration for the user. ServiceConfiguration GetServiceConfigurationFromUserPrefs( const PrefService* user_prefs) { - return TimeZoneResolveMethodFromInt(user_prefs->GetInteger( - prefs::kResolveTimezoneByGeolocationMethod)) == + return TimeZoneResolverManager::TimeZoneResolveMethodFromInt( + user_prefs->GetInteger( + prefs::kResolveTimezoneByGeolocationMethod)) == TimeZoneResolverManager::TimeZoneResolveMethod::DISABLED ? SHOULD_STOP : SHOULD_START; @@ -128,7 +114,8 @@ if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kLoginUser)) return SHOULD_STOP; - return TimeZoneResolveMethodFromInt(device_pref->GetValue()->GetInt()) == + return TimeZoneResolverManager::TimeZoneResolveMethodFromInt( + device_pref->GetValue()->GetInt()) == TimeZoneResolverManager::TimeZoneResolveMethod::DISABLED ? SHOULD_STOP : SHOULD_START; @@ -245,6 +232,26 @@ // static TimeZoneResolverManager::TimeZoneResolveMethod +TimeZoneResolverManager::TimeZoneResolveMethodFromInt(int value) { + if (value < 0 || + value >= static_cast<int>(TimeZoneResolveMethod::METHODS_NUMBER)) { + return TimeZoneResolveMethod::DISABLED; + } + + const TimeZoneResolveMethod method = + static_cast<TimeZoneResolveMethod>(value); + + if (FineGrainedTimeZoneDetectionEnabled()) + return method; + + if (method == TimeZoneResolveMethod::DISABLED) + return TimeZoneResolveMethod::DISABLED; + + return TimeZoneResolveMethod::IP_ONLY; +} + +// static +TimeZoneResolverManager::TimeZoneResolveMethod TimeZoneResolverManager::GetEffectiveUserTimeZoneResolveMethod( const PrefService* user_prefs, bool check_policy) {
diff --git a/chrome/browser/chromeos/system/timezone_resolver_manager.h b/chrome/browser/chromeos/system/timezone_resolver_manager.h index a3e49e0..30b4599 100644 --- a/chrome/browser/chromeos/system/timezone_resolver_manager.h +++ b/chrome/browser/chromeos/system/timezone_resolver_manager.h
@@ -50,6 +50,11 @@ // all configuration data. bool TimeZoneResolverShouldBeRunning(); + // Convert kResolveTimezoneByGeolocationMethod / + // kResolveDeviceTimezoneByGeolocationMethod preference value to + // TimeZoneResolveMethod. Defaults to DISABLED for unknown values. + static TimeZoneResolveMethod TimeZoneResolveMethodFromInt(int value); + // Returns user preference value if time zone is not managed. // Otherwise returns effective time zone resolve method. // If |check_policy| is true, effective method calculation will also
diff --git a/chrome/browser/chromeos/system/timezone_util.cc b/chrome/browser/chromeos/system/timezone_util.cc index 4f50fcd..e6df712 100644 --- a/chrome/browser/chromeos/system/timezone_util.cc +++ b/chrome/browser/chromeos/system/timezone_util.cc
@@ -188,7 +188,8 @@ } bool IsTimezonePrefsManaged(const std::string& pref_name) { - DCHECK(pref_name == prefs::kUserTimezone || + DCHECK(pref_name == chromeos::kSystemTimezone || + pref_name == prefs::kUserTimezone || pref_name == prefs::kResolveTimezoneByGeolocationMethod); std::string policy_timezone; @@ -197,6 +198,14 @@ return true; } + // System time zone preference is managed only if kSystemTimezonePolicy + // present, which we checked above. + // + // kSystemTimezoneAutomaticDetectionPolicy (see below) controls only user + // time zone preference, and user time zone resolve preference. + if (pref_name == chromeos::kSystemTimezone) + return false; + const PrefService* local_state = g_browser_process->local_state(); if (!local_state->IsManagedPreference( prefs::kSystemTimezoneAutomaticDetectionPolicy)) { @@ -337,5 +346,10 @@ NOTREACHED(); } +bool FineGrainedTimeZoneDetectionEnabled() { + return !base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableFineGrainedTimeZoneDetection); +} + } // namespace system } // namespace chromeos
diff --git a/chrome/browser/chromeos/system/timezone_util.h b/chrome/browser/chromeos/system/timezone_util.h index ec391de3..4e5712fd 100644 --- a/chrome/browser/chromeos/system/timezone_util.h +++ b/chrome/browser/chromeos/system/timezone_util.h
@@ -56,6 +56,9 @@ // This is called from UI code to apply user-selected time zone. void SetTimezoneFromUI(Profile* profile, const std::string& timezone_id); +// Returns true if fine-grained time zone detection is enabled. +bool FineGrainedTimeZoneDetectionEnabled(); + } // namespace system } // namespace chromeos
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index e622b3e9..ea1bdfce 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -332,10 +332,14 @@ settings_private::PrefType::PREF_TYPE_STRING; (*s_whitelist)[prefs::kUserTimezone] = settings_private::PrefType::PREF_TYPE_STRING; - (*s_whitelist)[::prefs::kResolveTimezoneByGeolocationMethod] = + (*s_whitelist)[prefs::kResolveTimezoneByGeolocationMethod] = settings_private::PrefType::PREF_TYPE_NUMBER; (*s_whitelist)[chromeos::kPerUserTimezoneEnabled] = settings_private::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)[chromeos::kFineGrainedTimeZoneResolveEnabled] = + settings_private::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)[prefs::kSystemTimezoneAutomaticDetectionPolicy] = + settings_private::PrefType::PREF_TYPE_NUMBER; // Ash settings. (*s_whitelist)[ash::prefs::kEnableStylusTools] = @@ -639,7 +643,19 @@ if (!value->GetAsDouble(&double_value)) return PREF_TYPE_MISMATCH; - pref_service->SetInteger(pref_name, static_cast<int>(double_value)); + bool value_set = false; +#if defined(OS_CHROMEOS) + if (pref_name == ::prefs::kResolveTimezoneByGeolocationMethod) { + pref_service->SetInteger( + pref_name, + static_cast<int>(chromeos::system::TimeZoneResolverManager:: + TimeZoneResolveMethodFromInt( + static_cast<int>(double_value)))); + value_set = true; + } +#endif + if (!value_set) + pref_service->SetInteger(pref_name, static_cast<int>(double_value)); break; } case base::Value::Type::STRING: { @@ -739,9 +755,9 @@ return false; if (IsPrivilegedCrosSetting(pref_name)) return true; - if (chromeos::system::PerUserTimezoneEnabled() && - (pref_name == prefs::kUserTimezone || - pref_name == prefs::kResolveTimezoneByGeolocationMethod)) { + if (pref_name == chromeos::kSystemTimezone || + pref_name == prefs::kUserTimezone || + pref_name == prefs::kResolveTimezoneByGeolocationMethod) { return chromeos::system::IsTimezonePrefsManaged(pref_name); } return false;
diff --git a/chrome/browser/resources/settings/date_time_page/compiled_resources2.gyp b/chrome/browser/resources/settings/date_time_page/compiled_resources2.gyp index 0da9b33..ad752f8 100644 --- a/chrome/browser/resources/settings/date_time_page/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/date_time_page/compiled_resources2.gyp
@@ -6,13 +6,46 @@ { 'target_name': 'date_time_page', 'dependencies': [ - '../controls/compiled_resources2.gyp:settings_dropdown_menu', + '../compiled_resources2.gyp:route', '../prefs/compiled_resources2.gyp:prefs_behavior', '../prefs/compiled_resources2.gyp:prefs_types', '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_indicator_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior', + 'date_time_types', + 'timezone_selector', + 'timezone_subpage', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { + 'target_name': 'date_time_types', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { + 'target_name': 'timezone_selector', + 'dependencies': [ + '../controls/compiled_resources2.gyp:settings_dropdown_menu', + '../prefs/compiled_resources2.gyp:prefs_behavior', + '../prefs/compiled_resources2.gyp:prefs_types', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', + 'date_time_types', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { + 'target_name': 'timezone_subpage', + 'dependencies': [ + '../prefs/compiled_resources2.gyp:prefs_behavior', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + 'date_time_types', + 'timezone_selector', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], },
diff --git a/chrome/browser/resources/settings/date_time_page/date_time_page.html b/chrome/browser/resources/settings/date_time_page/date_time_page.html index f208780..2a869b67 100644 --- a/chrome/browser/resources/settings/date_time_page/date_time_page.html +++ b/chrome/browser/resources/settings/date_time_page/date_time_page.html
@@ -1,16 +1,21 @@ <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/html/cr.html"> -<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html"> +<link rel="import" href="chrome://resources/html/cr.html"> +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> -<link rel="import" href="../controls/settings_dropdown_menu.html"> <link rel="import" href="../controls/settings_toggle_button.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="../prefs/prefs_behavior.html"> <link rel="import" href="../prefs/prefs_types.html"> +<link rel="import" href="../route.html"> +<link rel="import" href="../settings_page/settings_subpage.html"> <link rel="import" href="../settings_shared_css.html"> +<link rel="import" href="date_time_types.html"> +<link rel="import" href="timezone_selector.html"> +<link rel="import" href="timezone_subpage.html"> <dom-module id="settings-date-time-page"> <template> @@ -19,8 +24,11 @@ padding: 0; } - settings-dropdown-menu { - --md-select-width: 400px; + #timeZoneButton { + display: flex; + flex-direction: column; + justify-content: center; + width: 100%; } paper-toggle-button { @@ -31,67 +39,90 @@ -webkit-margin-start: var(--settings-controlled-by-spacing); } </style> - <div class="settings-box first"> - <div id="timezoneGeolocateToggleLabel" class="start"> - $i18n{timeZoneGeolocation} - </div> - <template is="dom-if" if="[[hasTimeZoneAutoDetectPolicy_]]" restamp> - <cr-policy-indicator indicator-type="devicePolicy" - icon-aria-label="$i18n{timeZoneGeolocation}"> - </cr-policy-indicator> - </template> - <paper-toggle-button - id="timeZoneAutoDetect" - aria-label="$i18n{timeZoneGeolocation}" - checked="[[timeZoneAutoDetect_]]" - disabled="[[hasTimeZoneAutoDetectPolicy_]]" - on-change="onTimeZoneAutoDetectChange_"> - </paper-toggle-button> - </div> - <div class="settings-box continuation embedded"> - <template is="dom-if" restamp - if="[[!prefs.cros.flags.per_user_timezone_enabled.value]]"> - <settings-dropdown-menu pref="{{prefs.cros.system.timezone}}" - label="$i18n{timeZone}" - menu-options="[[timeZoneList_]]" - disabled="[[timeZoneAutoDetect_]]"> - </settings-dropdown-menu> - </template> - <template is="dom-if" restamp - if="[[prefs.cros.flags.per_user_timezone_enabled.value]]"> - <template is="dom-if" if="[[!isUserTimeZoneSelectorHidden_( - prefs.settings.timezone, - prefs.settings.resolve_timezone_by_geolocation_method.value)]]" + <settings-animated-pages id="pages" section="dateTime" + focus-config="[[focusConfig_]]"> + <neon-animatable id="main" route-path="default"> + <template is="dom-if" + if="[[!prefs.cros.flags.fine_grained_time_zone_detection_enabled.value]]" restamp> - <settings-dropdown-menu id="userTimeZoneSelector" - pref="{{prefs.settings.timezone}}" - label="$i18n{timeZone}" - menu-options="[[timeZoneList_]]"> - </settings-dropdown-menu> + <div class="settings-box first"> + <div id="timezoneGeolocateToggleLabel" class="start"> + $i18n{timeZoneGeolocation} + </div> + <template is="dom-if" + if="[[hasTimeZoneAutoDetectPolicyRestriction_]]" restamp> + <cr-policy-indicator indicator-type="devicePolicy" + icon-aria-label="$i18n{timeZoneGeolocation}"> + </cr-policy-indicator> + </template> + <paper-toggle-button + id="timeZoneAutoDetect" + aria-label="$i18n{timeZoneGeolocation}" + checked="[[timeZoneAutoDetect_]]" + disabled="[[hasTimeZoneAutoDetectPolicyRestriction_]]" + on-change="onTimeZoneAutoDetectChange_"> + </paper-toggle-button> + </div> </template> - <template is="dom-if" if="[[isUserTimeZoneSelectorHidden_( - prefs.settings.timezone, - prefs.settings.resolve_timezone_by_geolocation_method.value)]]" + <template is="dom-if" + if="[[prefs.cros.flags.fine_grained_time_zone_detection_enabled.value]]" restamp> - <settings-dropdown-menu id="systemTimezoneSelector" - pref="{{prefs.cros.system.timezone}}" - label="$i18n{timeZone}" - menu-options="[[timeZoneList_]]" - disabled> - </settings-dropdown-menu> + <div id="timeZoneSettingsTrigger" class="settings-box first" + on-tap="onTimeZoneSettings_" actionable> + <div id="timeZoneButton" class="two-line"> + $i18n{timeZoneButton} + <div class="secondary"> + <div hidden="[[timeZoneAutoDetect_]]"> + [[activeTimeZoneDisplayName]] + </div> + <div hidden="[[!timeZoneAutoDetect_]]"> + [[getTimeZoneAutoDetectMethodDisplayName_( + timeZoneAutoDetectMethod_)]] + </div> + </div> + </div> + <template is="dom-if" + if="[[hasTimeZoneAutoDetectPolicyRestriction_]]" restamp> + <cr-policy-indicator indicator-type="devicePolicy" + icon-aria-label="$i18n{timeZoneGeolocation}" + hidden="[[!hasTimeZoneAutoDetectPolicyRestriction_]]"> + </cr-policy-indicator> + </template> + <button class="subpage-arrow" + disabled="[[hasTimeZoneAutoDetectPolicyRestriction_]]" + is="paper-icon-button-light" + aria-label="$i18n{timeZoneButton}"></button> + </div> </template> + <div class="settings-box continuation embedded" + hidden="[[prefs.cros.flags.fine_grained_time_zone_detection_enabled.value]]"> + <timezone-selector prefs="{{prefs}}" + time-zone-auto-detect="[[timeZoneAutoDetect_]]" + active-time-zone-display-name="{{activeTimeZoneDisplayName}}"> + </timezone-selector> + </div> + <settings-toggle-button + pref="{{prefs.settings.clock.use_24hour_clock}}" + label="$i18n{use24HourClock}"> + </settings-toggle-button> + <div class="settings-box" id="setDateTime" actionable + on-tap="onSetDateTimeTap_" hidden$="[[!canSetDateTime_]]"> + <div class="start">$i18n{setDateTime}</div> + <button class="subpage-arrow" is="paper-icon-button-light" + aria-label="$i18n{setDateTime}"></button> + </div> + </neon-animatable> + <template is="dom-if" route-path="/dateTime/timeZone"> + <settings-subpage data-route="DATETIME_TIMEZONE_SUBPAGE" + associated-control="[[$$('#timeZoneSettingsTrigger')]]" + page-title="$i18n{timeZoneSubpageTitle}"> + <timezone-subpage id="timezoneSubpage" prefs="{{prefs}}" + time-zone-auto-detect="[[timeZoneAutoDetect_]]" + active-time-zone-display-name="{{activeTimeZoneDisplayName}}"> + </timezone-subpage> + </settings-subpage> </template> - </div> - <settings-toggle-button - pref="{{prefs.settings.clock.use_24hour_clock}}" - label="$i18n{use24HourClock}"> - </settings-toggle-button> - <div class="settings-box" id="setDateTime" actionable - on-tap="onSetDateTimeTap_" hidden$="[[!canSetDateTime_]]"> - <div class="start">$i18n{setDateTime}</div> - <button class="subpage-arrow" is="paper-icon-button-light" - aria-label="$i18n{setDateTime}"></button> - </div> + </settings-animated-pages> </template> <script src="date_time_page.js"></script> </dom-module>
diff --git a/chrome/browser/resources/settings/date_time_page/date_time_page.js b/chrome/browser/resources/settings/date_time_page/date_time_page.js index 484e71be..09badd2 100644 --- a/chrome/browser/resources/settings/date_time_page/date_time_page.js +++ b/chrome/browser/resources/settings/date_time_page/date_time_page.js
@@ -8,49 +8,24 @@ * settings. */ -cr.exportPath('settings'); - -/** - * Describes the status of the auto-detect policy. - * @enum {number} - */ -settings.TimeZoneAutoDetectPolicy = { - NONE: 0, - FORCED_ON: 1, - FORCED_OFF: 2, -}; - -/** - * Describes values of prefs.settings.resolve_timezone_by_geolocation_method. - * Must be kept in sync with TimeZoneResolverManager::TimeZoneResolveMethod - * enum. - * @enum {number} - */ -settings.TimeZoneAutoDetectMethod = { - DISABLED: 0, - IP_ONLY: 1, - SEND_WIFI_ACCESS_POINTS: 2, - SEND_ALL_LOCATION_INFO: 3 -}; - Polymer({ is: 'settings-date-time-page', - behaviors: [PrefsBehavior, WebUIListenerBehavior], + behaviors: [I18nBehavior, PrefsBehavior, WebUIListenerBehavior], properties: { /** - * The time zone auto-detect policy. - * @private {settings.TimeZoneAutoDetectPolicy} + * The effective policy restriction on time zone automatic detection. + * @private {settings.TimeZoneAutoDetectPolicyRestriction} */ - timeZoneAutoDetectPolicy_: { - type: Boolean, + timeZoneAutoDetectPolicyRestriction_: { + type: Number, value: function() { if (!loadTimeData.valueExists('timeZoneAutoDetectValueFromPolicy')) - return settings.TimeZoneAutoDetectPolicy.NONE; + return settings.TimeZoneAutoDetectPolicyRestriction.NONE; return loadTimeData.getBoolean('timeZoneAutoDetectValueFromPolicy') ? - settings.TimeZoneAutoDetectPolicy.FORCED_ON : - settings.TimeZoneAutoDetectPolicy.FORCED_OFF; + settings.TimeZoneAutoDetectPolicyRestriction.FORCED_ON : + settings.TimeZoneAutoDetectPolicyRestriction.FORCED_OFF; }, }, @@ -58,37 +33,32 @@ * Whether a policy controls the time zone auto-detect setting. * @private */ - hasTimeZoneAutoDetectPolicy_: { + hasTimeZoneAutoDetectPolicyRestriction_: { type: Boolean, - computed: - 'computeHasTimeZoneAutoDetectPolicy_(timeZoneAutoDetectPolicy_)', + computed: 'computeHasTimeZoneAutoDetectPolicy_(' + + 'timeZoneAutoDetectPolicyRestriction_)', }, /** - * The effective time zone auto-detect setting. + * The effective time zone auto-detect enabled/disabled status. * @private */ timeZoneAutoDetect_: { type: Boolean, computed: 'computeTimeZoneAutoDetect_(' + - 'timeZoneAutoDetectPolicy_,' + + 'timeZoneAutoDetectPolicyRestriction_,' + 'prefs.settings.resolve_timezone_by_geolocation_method.value)', }, /** - * Initialized with the current time zone so the menu displays the - * correct value. The full option list is fetched lazily if necessary by - * maybeGetTimeZoneList_. - * @private {!DropdownMenuOptionList} + * The effective time zone auto-detect method. + * @private {settings.TimeZoneAutoDetectMethod} */ - timeZoneList_: { - type: Array, - value: function() { - return [{ - name: loadTimeData.getString('timeZoneName'), - value: loadTimeData.getString('timeZoneID'), - }]; - }, + timeZoneAutoDetectMethod_: { + type: Number, + computed: 'computeTimeZoneAutoDetectMethod_(' + + 'hasTimeZoneAutoDetectPolicyRestriction_,' + + 'prefs.settings.resolve_timezone_by_geolocation_method.value)', }, /** @@ -100,14 +70,29 @@ type: Boolean, value: false, }, - }, - observers: [ - 'maybeGetTimeZoneListPerUser_(' + - 'prefs.settings.timezone.value, timeZoneAutoDetect_)', - 'maybeGetTimeZoneListPerSystem_(' + - 'prefs.cros.system.timezone.value, timeZoneAutoDetect_)', - ], + /** + * This is used to get current time zone display name from + * <timezone-selector> via bi-directional binding. + */ + activeTimeZoneDisplayName: { + type: String, + value: loadTimeData.getString('timeZoneName'), + }, + + /** @private {!Map<string, string>} */ + focusConfig_: { + type: Object, + value: function() { + var map = new Map(); + if (settings.routes.DATETIME_TIMEZONE_SUBPAGE) + map.set( + settings.routes.DATETIME_TIMEZONE_SUBPAGE.path, + '#timeZoneSettingsTrigger .subpage-arrow'); + return map; + }, + }, + }, /** @override */ attached: function() { @@ -118,7 +103,6 @@ 'can-set-date-time-changed', this.onCanSetDateTimeChanged_.bind(this)); chrome.send('dateTimePageReady'); - this.maybeGetTimeZoneList_(); }, /** @@ -129,11 +113,12 @@ */ onTimeZoneAutoDetectPolicyChanged_: function(managed, valueFromPolicy) { if (managed) { - this.timeZoneAutoDetectPolicy_ = valueFromPolicy ? - settings.TimeZoneAutoDetectPolicy.FORCED_ON : - settings.TimeZoneAutoDetectPolicy.FORCED_OFF; + this.timeZoneAutoDetectPolicyRestriction_ = valueFromPolicy ? + settings.TimeZoneAutoDetectPolicyRestriction.FORCED_ON : + settings.TimeZoneAutoDetectPolicyRestriction.FORCED_OFF; } else { - this.timeZoneAutoDetectPolicy_ = settings.TimeZoneAutoDetectPolicy.NONE; + this.timeZoneAutoDetectPolicyRestriction_ = + settings.TimeZoneAutoDetectPolicyRestriction.NONE; } }, @@ -162,107 +147,100 @@ }, /** - * @param {settings.TimeZoneAutoDetectPolicy} timeZoneAutoDetectPolicy + * @param {settings.TimeZoneAutoDetectPolicyRestriction} policyValue * @return {boolean} * @private */ - computeHasTimeZoneAutoDetectPolicy_: function(timeZoneAutoDetectPolicy) { - return timeZoneAutoDetectPolicy != settings.TimeZoneAutoDetectPolicy.NONE; + computeHasTimeZoneAutoDetectPolicy_: function(policyValue) { + return policyValue != settings.TimeZoneAutoDetectPolicyRestriction.NONE; }, /** - * @param {settings.TimeZoneAutoDetectPolicy} timeZoneAutoDetectPolicy + * @param {settings.TimeZoneAutoDetectPolicyRestriction} policyValue * @param {settings.TimeZoneAutoDetectMethod} prefValue * prefs.settings.resolve_timezone_by_geolocation_method.value * @return {boolean} Whether time zone auto-detect is enabled. * @private */ - computeTimeZoneAutoDetect_: function(timeZoneAutoDetectPolicy, prefValue) { - switch (timeZoneAutoDetectPolicy) { - case settings.TimeZoneAutoDetectPolicy.NONE: + computeTimeZoneAutoDetect_: function(policyValue, prefValue) { + switch (policyValue) { + case settings.TimeZoneAutoDetectPolicyRestriction.NONE: return prefValue != settings.TimeZoneAutoDetectMethod.DISABLED; - case settings.TimeZoneAutoDetectPolicy.FORCED_ON: + case settings.TimeZoneAutoDetectPolicyRestriction.FORCED_ON: return true; - case settings.TimeZoneAutoDetectPolicy.FORCED_OFF: + case settings.TimeZoneAutoDetectPolicyRestriction.FORCED_OFF: return false; default: - assertNotReached(); + console.error('Unknown policy value "' + policyValue + '".'); + return false; } }, /** - * Fetches the list of time zones if necessary. - * @param {boolean=} perUserTimeZoneMode Expected value of per-user time zone. - * @private - */ - maybeGetTimeZoneList_: function(perUserTimeZoneMode) { - if (typeof(perUserTimeZoneMode) !== 'undefined') { - /* This method is called as observer. Skip if if current mode does not - * match expected. - */ - if (perUserTimeZoneMode != - this.getPref('cros.flags.per_user_timezone_enabled').value) { - return; - } - } - // Only fetch the list once. - if (this.timeZoneList_.length > 1 || !CrSettingsPrefs.isInitialized) - return; - - // If auto-detect is enabled, we only need the current time zone. - if (this.timeZoneAutoDetect_) { - var isPerUserTimezone = - this.getPref('cros.flags.per_user_timezone_enabled').value; - if (this.timeZoneList_[0].value == - (isPerUserTimezone ? this.getPref('settings.timezone').value : - this.getPref('cros.system.timezone').value)) { - return; - } - } - - cr.sendWithPromise('getTimeZones').then(this.setTimeZoneList_.bind(this)); - }, - - /** - * Prefs observer for Per-user time zone enabled mode. - * @private - */ - maybeGetTimeZoneListPerUser_: function() { - this.maybeGetTimeZoneList_(true); - }, - - /** - * Prefs observer for Per-user time zone disabled mode. - * @private - */ - maybeGetTimeZoneListPerSystem_: function() { - this.maybeGetTimeZoneList_(false); - }, - - /** - * Converts the C++ response into an array of menu options. - * @param {!Array<!Array<string>>} timeZones C++ time zones response. - * @private - */ - setTimeZoneList_: function(timeZones) { - this.timeZoneList_ = timeZones.map(function(timeZonePair) { - return { - name: timeZonePair[1], - value: timeZonePair[0], - }; - }); - }, - - /** - * Computes visibility of user timezone preference. - * @param {?chrome.settingsPrivate.PrefObject} prefUserTimezone - * pref.settings.timezone + * Computes effective time zone detection method. + * @param {Boolean} hasTimeZoneAutoDetectPolicyRestriction + * this.hasTimeZoneAutoDetectPolicyRestriction_ * @param {settings.TimeZoneAutoDetectMethod} prefResolveValue * prefs.settings.resolve_timezone_by_geolocation_method.value + * @return {settings.TimeZoneAutoDetectMethod} * @private */ - isUserTimeZoneSelectorHidden_: function(prefUserTimezone, prefResolveValue) { - return (prefUserTimezone && prefUserTimezone.controlledBy != null) || - prefResolveValue != settings.TimeZoneAutoDetectMethod.DISABLED; + computeTimeZoneAutoDetectMethod_: function( + hasTimeZoneAutoDetectPolicyRestriction, prefResolveValue) { + if (hasTimeZoneAutoDetectPolicyRestriction) { + // timeZoneAutoDetectPolicyRestriction_ actually depends on several time + // policies and chrome flags. So we ignore real policy value if it is + // disabled. + if (this.timeZoneAutoDetectPolicyRestriction_ == + settings.TimeZoneAutoDetectPolicyRestriction.FORCED_OFF) { + return settings.TimeZoneAutoDetectMethod.DISABLED; + } + + var policyValue = /** @type{settings.SystemTimezoneProto} */ ( + this.getPref('settings.resolve_device_timezone_by_geolocation_policy') + .value); + + switch (policyValue) { + case settings.SystemTimezoneProto.USERS_DECIDE: + console.error('Unexpected policy value "' + policyValue + '".'); + return settings.TimeZoneAutoDetectMethod.DISABLED; + case settings.SystemTimezoneProto.DISABLED: + return settings.TimeZoneAutoDetectMethod.DISABLED; + case settings.SystemTimezoneProto.IP_ONLY: + return settings.TimeZoneAutoDetectMethod.IP_ONLY; + case settings.SystemTimezoneProto.SEND_WIFI_ACCESS_POINTS: + return settings.TimeZoneAutoDetectMethod.SEND_WIFI_ACCESS_POINTS; + case settings.SystemTimezoneProto.SEND_ALL_LOCATION_INFO: + return settings.TimeZoneAutoDetectMethod.SEND_ALL_LOCATION_INFO; + default: + return settings.TimeZoneAutoDetectMethod.DISABLED; + } + } + return prefResolveValue; + }, + + /** + * Returns display name of the given time zone detection method. + * @param {settings.TimeZoneAutoDetectMethod} method + * this.timeZoneAutoDetectMethod_ value. + * @return {string} + * @private + */ + getTimeZoneAutoDetectMethodDisplayName_: function(method) { + var id = ([ + 'setTimeZoneAutomaticallyDisabled', + 'setTimeZoneAutomaticallyIpOnlyDefault', + 'setTimeZoneAutomaticallyWithWiFiAccessPointsData', + 'setTimeZoneAutomaticallyWithAllLocationInfo' + ])[method]; + if (id) + return this.i18n(id); + + return ''; + }, + + onTimeZoneSettings_: function() { + // TODO(alemate): revise this once UI mocks are finished. + settings.navigateTo(settings.routes.DATETIME_TIMEZONE_SUBPAGE); }, });
diff --git a/chrome/browser/resources/settings/date_time_page/date_time_types.html b/chrome/browser/resources/settings/date_time_page/date_time_types.html new file mode 100644 index 0000000..b3ecb80 --- /dev/null +++ b/chrome/browser/resources/settings/date_time_page/date_time_types.html
@@ -0,0 +1,2 @@ +<link rel="import" href="chrome://resources/html/cr.html"> +<script src="date_time_types.js"></script>
diff --git a/chrome/browser/resources/settings/date_time_page/date_time_types.js b/chrome/browser/resources/settings/date_time_page/date_time_types.js new file mode 100644 index 0000000..241d9b2 --- /dev/null +++ b/chrome/browser/resources/settings/date_time_page/date_time_types.js
@@ -0,0 +1,48 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview + * This defines some types for settings-date-time-page. + */ + +cr.exportPath('settings'); + +/** + * Describes the effective policy restriction on time zone automatic detection. + * @enum {number} + */ +settings.TimeZoneAutoDetectPolicyRestriction = { + NONE: 0, + FORCED_ON: 1, + FORCED_OFF: 2, +}; + +/** + * Describes values of prefs.settings.resolve_timezone_by_geolocation_method. + * Must be kept in sync with TimeZoneResolverManager::TimeZoneResolveMethod + * enum. + * @enum {number} + */ +settings.TimeZoneAutoDetectMethod = { + DISABLED: 0, + IP_ONLY: 1, + SEND_WIFI_ACCESS_POINTS: 2, + SEND_ALL_LOCATION_INFO: 3 +}; + +/** + * Describes values of prefs.settings. + * resolve_device_timezone_by_geolocation_policy + * Must be kept in sync with enterprise_management::SystemTimezoneProto + * enum. + * @enum {number} + */ +settings.SystemTimezoneProto = { + USERS_DECIDE: 0, + DISABLED: 1, + IP_ONLY: 2, + SEND_WIFI_ACCESS_POINTS: 3, + SEND_ALL_LOCATION_INFO: 4, +};
diff --git a/chrome/browser/resources/settings/date_time_page/timezone_selector.html b/chrome/browser/resources/settings/date_time_page/timezone_selector.html new file mode 100644 index 0000000..10e0312 --- /dev/null +++ b/chrome/browser/resources/settings/date_time_page/timezone_selector.html
@@ -0,0 +1,52 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="../controls/settings_dropdown_menu.html"> +<link rel="import" href="../i18n_setup.html"> +<link rel="import" href="../prefs/prefs_behavior.html"> +<link rel="import" href="../prefs/prefs_types.html"> +<link rel="import" href="../settings_shared_css.html"> +<link rel="import" href="date_time_types.html"> + +<dom-module id="timezone-selector"> + <template> + <style include="settings-shared"> + settings-dropdown-menu { + --md-select-width: 400px; + } + </style> + <template is="dom-if" restamp + if="[[!prefs.cros.flags.per_user_timezone_enabled.value]]"> + <settings-dropdown-menu pref="{{prefs.cros.system.timezone}}" + label="$i18n{timeZoneColon}" + menu-options="[[timeZoneList_]]" + disabled="[[timeZoneAutoDetect]]"> + </settings-dropdown-menu> + </template> + <template is="dom-if" restamp + if="[[prefs.cros.flags.per_user_timezone_enabled.value]]"> + <template is="dom-if" if="[[!isUserTimeZoneSelectorHidden_( + prefs.settings.timezone, + prefs.settings.resolve_timezone_by_geolocation_method.value)]]" + restamp> + <settings-dropdown-menu id="userTimeZoneSelector" + pref="{{prefs.settings.timezone}}" + label="$i18n{timeZoneColon}" + menu-options="[[timeZoneList_]]"> + </settings-dropdown-menu> + </template> + <template is="dom-if" if="[[isUserTimeZoneSelectorHidden_( + prefs.settings.timezone, + prefs.settings.resolve_timezone_by_geolocation_method.value)]]" + restamp> + <settings-dropdown-menu id="systemTimezoneSelector" + pref="{{prefs.cros.system.timezone}}" + label="$i18n{timeZoneColon}" + menu-options="[[timeZoneList_]]" + disabled> + </settings-dropdown-menu> + </template> + </template> + </template> + <script src="timezone_selector.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/settings/date_time_page/timezone_selector.js b/chrome/browser/resources/settings/date_time_page/timezone_selector.js new file mode 100644 index 0000000..e6559db6f --- /dev/null +++ b/chrome/browser/resources/settings/date_time_page/timezone_selector.js
@@ -0,0 +1,153 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview 'timezone-selector' is the time zone selector dropdown. + */ +(function() { +'use strict'; + +Polymer({ + is: 'timezone-selector', + + behaviors: [I18nBehavior, PrefsBehavior], + + properties: { + /** + * If time zone auto detectoin is enabled. + */ + timeZoneAutoDetect: Boolean, + + /** + * This stores active time zone display name to be used in other UI + * via bi-directional binding. + */ + activeTimeZoneDisplayName: { + type: String, + notify: true, + }, + + /** + * Initialized with the current time zone so the menu displays the + * correct value. The full option list is fetched lazily if necessary by + * maybeGetTimeZoneList_. + * @private {!DropdownMenuOptionList} + */ + timeZoneList_: { + type: Array, + value: function() { + return [{ + name: loadTimeData.getString('timeZoneName'), + value: loadTimeData.getString('timeZoneID'), + }]; + }, + }, + }, + + observers: [ + 'maybeGetTimeZoneListPerUser_(' + + 'prefs.settings.timezone.value, timeZoneAutoDetect)', + 'maybeGetTimeZoneListPerSystem_(' + + 'prefs.cros.system.timezone.value, timeZoneAutoDetect)', + 'updateActiveTimeZoneName_(prefs.cros.system.timezone.value)', + ], + + /** @override */ + attached: function() { + this.maybeGetTimeZoneList_(); + }, + + /** + * Fetches the list of time zones if necessary. + * @param {boolean=} perUserTimeZoneMode Expected value of per-user time zone. + * @private + */ + maybeGetTimeZoneList_: function(perUserTimeZoneMode) { + if (typeof(perUserTimeZoneMode) !== 'undefined') { + /* This method is called as observer. Skip if if current mode does not + * match expected. + */ + if (perUserTimeZoneMode != + this.getPref('cros.flags.per_user_timezone_enabled').value) { + return; + } + } + // Only fetch the list once. + if (this.timeZoneList_.length > 1 || !CrSettingsPrefs.isInitialized) + return; + + // If auto-detect is enabled, we only need the current time zone. + if (this.timeZoneAutoDetect) { + var isPerUserTimezone = + this.getPref('cros.flags.per_user_timezone_enabled').value; + if (this.timeZoneList_[0].value == + (isPerUserTimezone ? this.getPref('settings.timezone').value : + this.getPref('cros.system.timezone').value)) { + return; + } + } + + cr.sendWithPromise('getTimeZones').then(this.setTimeZoneList_.bind(this)); + }, + + /** + * Prefs observer for Per-user time zone enabled mode. + * @private + */ + maybeGetTimeZoneListPerUser_: function() { + this.maybeGetTimeZoneList_(true); + }, + + /** + * Prefs observer for Per-user time zone disabled mode. + * @private + */ + maybeGetTimeZoneListPerSystem_: function() { + this.maybeGetTimeZoneList_(false); + }, + + /** + * Converts the C++ response into an array of menu options. + * @param {!Array<!Array<string>>} timeZones C++ time zones response. + * @private + */ + setTimeZoneList_: function(timeZones) { + this.timeZoneList_ = timeZones.map(function(timeZonePair) { + return { + name: timeZonePair[1], + value: timeZonePair[0], + }; + }); + this.updateActiveTimeZoneName_( + /** @type {!String} */ (this.getPref('cros.system.timezone').value)); + }, + + /** + * Updates active time zone display name when changed. + * @param {!String} activeTimeZoneId value of cros.system.timezone preference. + * @private + */ + updateActiveTimeZoneName_: function(activeTimeZoneId) { + var activeTimeZone = this.timeZoneList_.find( + (timeZone) => timeZone.value == activeTimeZoneId); + if (activeTimeZone) + this.activeTimeZoneDisplayName = activeTimeZone.name; + }, + + + /** + * Computes visibility of user timezone preference. + * @param {?chrome.settingsPrivate.PrefObject} prefUserTimezone + * pref.settings.timezone + * @param {settings.TimeZoneAutoDetectMethod} prefResolveValue + * prefs.settings.resolve_timezone_by_geolocation_method.value + * @return {boolean} + * @private + */ + isUserTimeZoneSelectorHidden_: function(prefUserTimezone, prefResolveValue) { + return (prefUserTimezone && prefUserTimezone.controlledBy != null) || + prefResolveValue != settings.TimeZoneAutoDetectMethod.DISABLED; + }, +}); +})();
diff --git a/chrome/browser/resources/settings/date_time_page/timezone_subpage.html b/chrome/browser/resources/settings/date_time_page/timezone_subpage.html new file mode 100644 index 0000000..200f175f --- /dev/null +++ b/chrome/browser/resources/settings/date_time_page/timezone_subpage.html
@@ -0,0 +1,54 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="../controls/controlled_radio_button.html"> +<link rel="import" href="../controls/settings_radio_group.html"> +<link rel="import" href="../prefs/prefs.html"> +<link rel="import" href="../prefs/prefs_behavior.html"> +<link rel="import" href="../settings_shared_css.html"> +<link rel="import" href="date_time_types.html"> + +<dom-module id="timezone-subpage"> + <template> + <style include="settings-shared"> + .block { + display: block; + } + </style> + <div class="settings-box block first"> + <settings-radio-group id="timeZoneRadioGroup" + pref="{{prefs.settings.resolve_timezone_by_geolocation_method}}"> + <controlled-radio-button + name="[[timezoneAutodetectMethodValues_.IP_ONLY]]" + pref="[[prefs.settings.resolve_timezone_by_geolocation_method]]" + label="$i18n{setTimeZoneAutomaticallyIpOnlyDefault}" + no-extension-indicator> + <div class="secondary"> + $i18n{setTimeZoneAutomaticallyIpOnlyDefaultDescription} + </div> + </controlled-radio-button> + <controlled-radio-button + name="[[timezoneAutodetectMethodValues_.SEND_ALL_LOCATION_INFO]]" + pref="[[prefs.settings.resolve_timezone_by_geolocation_method]]" + label="$i18n{setTimeZoneAutomaticallyWithAllLocationInfo}" + no-extension-indicator> + <div class="secondary"> + $i18n{setTimeZoneAutomaticallyWithAllLocationInfoDescription} + </div> + </controlled-radio-button> + <controlled-radio-button + name="[[timezoneAutodetectMethodValues_.DISABLED]]" + pref="[[prefs.settings.resolve_timezone_by_geolocation_method]]" + label="$i18n{selectYourTimeZone}" + no-extension-indicator> + </controlled-radio-button> + </settings-radio-group> + </div> + <div class="settings-box block"> + <timezone-selector prefs="{{prefs}}" + time-zone-auto-detect="[[timeZoneAutoDetect]]" + active-time-zone-display-name="{{activeTimeZoneDisplayName}}"> + </timezone-selector> + </div> + </template> + <script src="timezone_subpage.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/settings/date_time_page/timezone_subpage.js b/chrome/browser/resources/settings/date_time_page/timezone_subpage.js new file mode 100644 index 0000000..96109be8 --- /dev/null +++ b/chrome/browser/resources/settings/date_time_page/timezone_subpage.js
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview 'timezone-subpage' is the collapsible section containing + * time zone settings. + */ +(function() { +'use strict'; + +Polymer({ + is: 'timezone-subpage', + + behaviors: [PrefsBehavior], + + properties: { + /** + * This is <timezone-selector> parameter. + */ + activeTimeZoneDisplayName: { + type: String, + notify: true, + }, + + /** + * The effective time zone auto-detect enabled/disabled status. + */ + timeZoneAutoDetect: Boolean, + + /** + * settings.TimeZoneAutoDetectMethod values. + * @private {!Object<settings.TimeZoneAutoDetectMethod, number>} + */ + timezoneAutodetectMethodValues_: Object, + + }, + + attached: function() { + this.timezoneAutodetectMethodValues_ = settings.TimeZoneAutoDetectMethod; + }, +}); +})();
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js index 1641ef1..102c11f 100644 --- a/chrome/browser/resources/settings/route.js +++ b/chrome/browser/resources/settings/route.js
@@ -25,6 +25,7 @@ * CLOUD_PRINTERS: (undefined|!settings.Route), * CUPS_PRINTERS: (undefined|!settings.Route), * DATETIME: (undefined|!settings.Route), + * DATETIME_TIMEZONE_SUBPAGE: (undefined|!settings.Route), * DEFAULT_BROWSER: (undefined|!settings.Route), * DETAILED_BUILD_INFO: (undefined|!settings.Route), * DEVICE: (undefined|!settings.Route), @@ -333,6 +334,8 @@ // <if expr="chromeos"> if (pageVisibility.dateTime !== false) { r.DATETIME = r.ADVANCED.createSection('/dateTime', 'dateTime'); + r.DATETIME_TIMEZONE_SUBPAGE = + r.DATETIME.createChild('/dateTime/timeZone'); } // </if>
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index c07ee64c..81e1223 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -1108,6 +1108,24 @@ <structure name="IDR_SETTINGS_DATE_TIME_PAGE_JS" file="date_time_page/date_time_page.js" type="chrome_html" /> + <structure name="IDR_SETTINGS_DATE_TIME_TYPES_HTML" + file="date_time_page/date_time_types.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_DATE_TIME_TYPES_JS" + file="date_time_page/date_time_types.js" + type="chrome_html" /> + <structure name="IDR_SETTINGS_TIMEZONE_SELECTOR_HTML" + file="date_time_page/timezone_selector.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_TIMEZONE_SELECTOR_JS" + file="date_time_page/timezone_selector.js" + type="chrome_html" /> + <structure name="IDR_SETTINGS_TIMEZONE_SUBPAGE_HTML" + file="date_time_page/timezone_subpage.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_TIMEZONE_SUBPAGE_JS" + file="date_time_page/timezone_subpage.js" + type="chrome_html" /> <structure name="IDR_SETTINGS_INTERNET_CONFIG_HTML" file="internet_page/internet_config.html" type="chrome_html" />
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 476949f..d00c0ba 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -835,8 +835,26 @@ void AddDateTimeStrings(content::WebUIDataSource* html_source) { LocalizedString localized_strings[] = { {"dateTimePageTitle", IDS_SETTINGS_DATE_TIME}, - {"timeZone", IDS_SETTINGS_TIME_ZONE}, + {"timeZoneColon", IDS_SETTINGS_TIME_ZONE}, {"timeZoneGeolocation", IDS_SETTINGS_TIME_ZONE_GEOLOCATION}, + {"timeZoneButton", IDS_SETTINGS_TIME_ZONE_BUTTON}, + {"timeZoneSubpageTitle", IDS_SETTINGS_TIME_ZONE_SUBPAGE_TITLE}, + {"setTimeZoneAutomaticallyDisabled", + IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_DISABLED}, + {"setTimeZoneAutomaticallyIpOnlyDefault", + IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_IP_ONLY_DEFAULT}, + {"setTimeZoneAutomaticallyIpOnlyDefaultDescription", + IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_IP_ONLY_DESCRIPTION}, + {"setTimeZoneAutomaticallyWithWiFiAccessPointsData", + IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_SEND_WIFI_AP}, + {"setTimeZoneAutomaticallyWithWiFiAccessPointsDataDescription", + IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_SEND_WIFI_AP_DESCRIPTION}, + {"setTimeZoneAutomaticallyWithAllLocationInfo", + IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_SEND_ALL_INFO}, + {"setTimeZoneAutomaticallyWithAllLocationInfoDescription", + IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_SEND_ALL_INFO_DESCRIPTION}, + {"selectYourTimeZone", + IDS_SETTINGS_TIME_ZONE_DETECTION_SELECT_YOUR_TIME_ZONE}, {"use24HourClock", IDS_SETTINGS_USE_24_HOUR_CLOCK}, {"setDateTime", IDS_SETTINGS_SET_DATE_TIME}, };
diff --git a/chrome/test/data/webui/settings/date_time_page_tests.js b/chrome/test/data/webui/settings/date_time_page_tests.js index 3c6c94f..76329f3a 100644 --- a/chrome/test/data/webui/settings/date_time_page_tests.js +++ b/chrome/test/data/webui/settings/date_time_page_tests.js
@@ -14,13 +14,18 @@ }, }, flags: { - // TODO(alemate): This test should be run for both values of this - // option. + // TODO(alemate): This test should be run for all possible + // combinations of values of these options. per_user_timezone_enabled: { key: 'cros.flags.per_user_timezone_enabled', type: chrome.settingsPrivate.PrefType.BOOLEAN, value: true, }, + fine_grained_time_zone_detection_enabled: { + key: 'cros.flags.fine_grained_time_zone_detection_enabled', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, }, }, settings: { @@ -36,6 +41,11 @@ type: settings.TimeZoneAutoDetectMethod, value: settings.TimeZoneAutoDetectMethod.IP_ONLY, }, + resolve_device_timezone_by_geolocation_policy: { + key: 'settings.resolve_device_timezone_by_geolocation_policy', + type: settings.SystemTimezoneProto, + value: settings.SystemTimezoneProto.USERS_DECIDE, + }, timezone: { key: 'settings.timezone', type: chrome.settingsPrivate.PrefType.STRING, @@ -55,6 +65,17 @@ prefsCopy.settings.resolve_timezone_by_geolocation_method.value = valueFromPolicy ? settings.TimeZoneAutoDetectMethod.IP_ONLY : settings.TimeZoneAutoDetectMethod.DISABLED; + prefsCopy.settings.resolve_timezone_by_geolocation_method.controlledBy = + chrome.settingsPrivate.ControlledBy.USER_POLICY; + prefsCopy.settings.resolve_timezone_by_geolocation_method.enforcement = + chrome.settingsPrivate.Enforcement.ENFORCED; + prefsCopy.settings.resolve_device_timezone_by_geolocation_policy.value = + valueFromPolicy ? settings.SystemTimezoneProto.IP_ONLY : + settings.SystemTimezoneProto.DISABLED; + prefsCopy.settings.resolve_device_timezone_by_geolocation_policy + .controlledBy = chrome.settingsPrivate.ControlledBy.DEVICE_POLICY; + prefsCopy.settings.resolve_device_timezone_by_geolocation_policy + .enforcement = chrome.settingsPrivate.Enforcement.ENFORCED; prefsCopy.settings.timezone.controlledBy = chrome.settingsPrivate.ControlledBy.USER_POLICY; prefsCopy.settings.timezone.enforcement = @@ -90,6 +111,20 @@ timeZoneID: timeZone[0], timeZoneName: timeZone[1], controlledSettingPolicy: 'This setting is enforced by your administrator', + setTimeZoneAutomaticallyDisabled: + 'Automatic time zone detection disabled.', + setTimeZoneAutomaticallyIpOnlyDefault: + 'Automatic time zone detection IP-only.', + setTimeZoneAutomaticallyIpOnlyDefaultDescription: + 'Automatic time zone detection IP-only description.', + setTimeZoneAutomaticallyWithWiFiAccessPointsData: + 'Automatic time zone detection with WiFi AP', + setTimeZoneAutomaticallyWithWiFiAccessPointsDataDescription: + 'Automatic time zone detection with WiFi AP description', + setTimeZoneAutomaticallyWithAllLocationInfo: + 'Automatic time zone detection with all location info', + setTimeZoneAutomaticallyWithAllLocationInfoDescription: + 'Automatic time zone detection with all location info description', }; if (hasPolicy) @@ -106,6 +141,7 @@ document.body.appendChild(dateTime); cr.webUIListenerCallback( 'time-zone-auto-detect-policy', hasPolicy, opt_autoDetectPolicyValue); + return dateTime; } @@ -155,9 +191,19 @@ PolymerTest.clearBody(); }); - function verifyAutoDetectSetting(autoDetect, managed) { + function popuateSubpage() { + var timeZoneSettingsSubmenuButton = + dateTime.$$('#timeZoneSettingsTrigger'); + MockInteractions.tap(timeZoneSettingsSubmenuButton); Polymer.dom.flush(); - var selector = dateTime.$$('#userTimeZoneSelector'); + } + + function getTimeZoneSelector(id) { + return dateTime.$$('timezone-selector').$$(id); + } + + function verifyAutoDetectSetting(autoDetect, managed) { + var selector = getTimeZoneSelector('#userTimeZoneSelector'); var selectorHidden = selector ? selector.hidden : true; assertEquals(managed || autoDetect, selectorHidden); @@ -168,7 +214,6 @@ } function verifyPolicy(policy) { - Polymer.dom.flush(); var indicator = dateTime.$$('cr-policy-indicator'); if (indicator && indicator.style.display == 'none') indicator = null; @@ -186,9 +231,9 @@ } function verifyTimeZonesPopulated(populated) { - Polymer.dom.flush(); - var userTimezoneDropdown = dateTime.$$('#userTimeZoneSelector'); - var systemTimezoneDropdown = dateTime.$$('#systemTimezoneSelector'); + var userTimezoneDropdown = getTimeZoneSelector('#userTimeZoneSelector'); + var systemTimezoneDropdown = + getTimeZoneSelector('#systemTimezoneSelector'); var dropdown = userTimezoneDropdown ? userTimezoneDropdown : systemTimezoneDropdown; @@ -203,7 +248,6 @@ updatePrefsWithPolicy(dateTime.prefs, managed, valueFromPolicy); cr.webUIListenerCallback( 'time-zone-auto-detect-policy', managed, valueFromPolicy); - Polymer.dom.flush(); } test('auto-detect on', function(done) { @@ -213,12 +257,14 @@ assertTrue(dateTimePageReadyCalled); assertFalse(getTimeZonesCalled); + Polymer.dom.flush(); verifyAutoDetectSetting(true, false); verifyTimeZonesPopulated(false); verifyPolicy(false); // Disable auto-detect. MockInteractions.tap(dateTime.$$('#timeZoneAutoDetect')); + Polymer.dom.flush(); verifyAutoDetectSetting(false, false); assertTrue(getTimeZonesCalled); @@ -230,21 +276,26 @@ test('auto-detect off', function(done) { dateTime = initializeDateTime(getFakePrefs(), false); - dateTime.set( - 'prefs.settings.resolve_timezone_by_geolocation_method.value', - settings.TimeZoneAutoDetectMethod.DISABLED); - - assertTrue(dateTimePageReadyCalled); - assertTrue(getTimeZonesCalled); - - verifyAutoDetectSetting(false, false); - verifyPolicy(false); + setTimeout(function() { + dateTime.set( + 'prefs.settings.resolve_timezone_by_geolocation_method.value', + settings.TimeZoneAutoDetectMethod.DISABLED); + }); setTimeout(function() { + assertTrue(dateTimePageReadyCalled); + assertTrue(getTimeZonesCalled); + + verifyAutoDetectSetting(false, false); + verifyPolicy(false); + verifyTimeZonesPopulated(true); // Enable auto-detect. MockInteractions.tap(dateTime.$$('#timeZoneAutoDetect')); + }); + + setTimeout(function() { verifyAutoDetectSetting(true); done(); }); @@ -253,29 +304,36 @@ test('auto-detect forced on', function(done) { var prefs = getFakePrefs(); dateTime = initializeDateTime(prefs, true, true); - dateTime.set( - 'prefs.settings.resolve_timezone_by_geolocation_method.value', - settings.TimeZoneAutoDetectMethod.DISABLED); - - assertTrue(dateTimePageReadyCalled); - assertFalse(getTimeZonesCalled); - - verifyAutoDetectSetting(true, true); - verifyTimeZonesPopulated(false); - verifyPolicy(true); - - // Cannot disable auto-detect. - MockInteractions.tap(dateTime.$$('#timeZoneAutoDetect')); - verifyAutoDetectSetting(true, true); - assertFalse(getTimeZonesCalled); - - // Update the policy: force auto-detect off. - updatePolicy(dateTime, true, false); - verifyAutoDetectSetting(false, true); - verifyPolicy(true); - - assertTrue(getTimeZonesCalled); setTimeout(function() { + dateTime.set( + 'prefs.settings.resolve_timezone_by_geolocation_method.value', + settings.TimeZoneAutoDetectMethod.DISABLED); + }); + + setTimeout(function() { + assertTrue(dateTimePageReadyCalled); + assertFalse(getTimeZonesCalled); + + verifyAutoDetectSetting(true, true); + verifyTimeZonesPopulated(false); + verifyPolicy(true); + + // Cannot disable auto-detect. + MockInteractions.tap(dateTime.$$('#timeZoneAutoDetect')); + }); + + setTimeout(function() { + verifyAutoDetectSetting(true, true); + assertFalse(getTimeZonesCalled); + + // Update the policy: force auto-detect off. + updatePolicy(dateTime, true, false); + }); + setTimeout(function() { + verifyAutoDetectSetting(false, true); + verifyPolicy(true); + + assertTrue(getTimeZonesCalled); verifyTimeZonesPopulated(true); done(); }); @@ -285,22 +343,25 @@ var prefs = getFakePrefs(); dateTime = initializeDateTime(prefs, true, false); - assertTrue(dateTimePageReadyCalled); - assertTrue(getTimeZonesCalled); - - verifyAutoDetectSetting(false, true); - verifyPolicy(true); - setTimeout(function() { + assertTrue(dateTimePageReadyCalled); + assertTrue(getTimeZonesCalled); + + verifyAutoDetectSetting(false, true); + verifyPolicy(true); verifyTimeZonesPopulated(true); // Remove the policy so user's preference takes effect. - updatePolicy(dateTime, false); + updatePolicy(dateTime, false, false); + }); + setTimeout(function() { verifyAutoDetectSetting(true, false); verifyPolicy(false); // User can disable auto-detect. MockInteractions.tap(dateTime.$$('#timeZoneAutoDetect')); + }); + setTimeout(function() { verifyAutoDetectSetting(false, false); done(); }); @@ -315,20 +376,24 @@ showSetDateTimeUICalled = true; }); - var setDateTimeButton = dateTime.$$('#setDateTime'); - assertEquals(0, setDateTimeButton.offsetHeight); + setTimeout(function() { + var setDateTimeButton = dateTime.$$('#setDateTime'); + assertEquals(0, setDateTimeButton.offsetHeight); - // Make the date and time editable. - cr.webUIListenerCallback('can-set-date-time-changed', true); - assertGT(setDateTimeButton.offsetHeight, 0); + // Make the date and time editable. + cr.webUIListenerCallback('can-set-date-time-changed', true); + assertGT(setDateTimeButton.offsetHeight, 0); - assertFalse(showSetDateTimeUICalled); - MockInteractions.tap(setDateTimeButton); - assertTrue(showSetDateTimeUICalled); + assertFalse(showSetDateTimeUICalled); + MockInteractions.tap(setDateTimeButton); + }); + setTimeout(function() { + assertTrue(showSetDateTimeUICalled); - // Make the date and time not editable. - cr.webUIListenerCallback('can-set-date-time-changed', false); - assertEquals(setDateTimeButton.offsetHeight, 0); + // Make the date and time not editable. + cr.webUIListenerCallback('can-set-date-time-changed', false); + assertEquals(setDateTimeButton.offsetHeight, 0); + }); }); }); })();
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc index 1c3d77e..7c225c2 100644 --- a/chromeos/chromeos_switches.cc +++ b/chromeos/chromeos_switches.cc
@@ -528,6 +528,10 @@ // Disables per-user timezone. const char kDisablePerUserTimezone[] = "disable-per-user-timezone"; +// Disables fine grained time zone detection. +const char kDisableFineGrainedTimeZoneDetection[] = + "disable-fine-grained-time-zone-detection"; + bool WakeOnWifiEnabled() { return !base::CommandLine::ForCurrentProcess()->HasSwitch(kDisableWakeOnWifi); }
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h index d24a02c..f796c37c 100644 --- a/chromeos/chromeos_switches.h +++ b/chromeos/chromeos_switches.h
@@ -98,6 +98,7 @@ CHROMEOS_EXPORT extern const char kEnableTouchpadThreeFingerClick[]; CHROMEOS_EXPORT extern const char kEnableFileManagerTouchMode[]; CHROMEOS_EXPORT extern const char kDisableFileManagerTouchMode[]; +CHROMEOS_EXPORT extern const char kDisableFineGrainedTimeZoneDetection[]; CHROMEOS_EXPORT extern const char kEnableVideoPlayerChromecastSupport[]; CHROMEOS_EXPORT extern const char kEnableVoiceInteraction[]; CHROMEOS_EXPORT extern const char kEnableZipArchiverPacker[];
diff --git a/chromeos/settings/cros_settings_names.cc b/chromeos/settings/cros_settings_names.cc index a112571..3f8ad30 100644 --- a/chromeos/settings/cros_settings_names.cc +++ b/chromeos/settings/cros_settings_names.cc
@@ -248,6 +248,11 @@ // A boolean pref that matches enable-per-user-time-zone chrome://flags value. const char kPerUserTimezoneEnabled[] = "cros.flags.per_user_timezone_enabled"; +// A boolean pref that matches enable-fine-graned-time-zone-detection +// chrome://flags value. +const char kFineGrainedTimeZoneResolveEnabled[] = + "cros.flags.fine_grained_time_zone_detection_enabled"; + // A dictionary pref containing time intervals and ignored policies. // It's used to allow less restricted usage of Chrome OS during off-hours. // This pref is set by an admin policy.
diff --git a/chromeos/settings/cros_settings_names.h b/chromeos/settings/cros_settings_names.h index 13d0589..ad4431d 100644 --- a/chromeos/settings/cros_settings_names.h +++ b/chromeos/settings/cros_settings_names.h
@@ -120,6 +120,7 @@ CHROMEOS_EXPORT extern const char kDeviceLoginScreenInputMethods[]; CHROMEOS_EXPORT extern const char kPerUserTimezoneEnabled[]; +CHROMEOS_EXPORT extern const char kFineGrainedTimeZoneResolveEnabled[]; CHROMEOS_EXPORT extern const char kDeviceOffHours[];
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index 30e25bc..455b8e8d 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -1237,7 +1237,8 @@ #endif // Ensure a video with an unsupported audio track still results in the video -// stream being demuxed. +// stream being demuxed. Because we disable the speex parser for ogg, the audio +// track won't even show up to the demuxer. // // Android has no Theora support, so this test doesn't work. #if !defined(OS_ANDROID) @@ -1245,8 +1246,6 @@ CreateDemuxerWithStrictMediaLog("speex_audio_vorbis_video.ogv"); EXPECT_MEDIA_LOG(SimpleCreatedFFmpegDemuxerStream("video")); - EXPECT_MEDIA_LOG(FailedToCreateValidDecoderConfigFromStream("audio")); - EXPECT_MEDIA_LOG(SkippingUnsupportedStream("audio")); // TODO(wolenetz): Use a matcher that verifies more of the event parameters // than FoundStream. See https://crbug.com/749178.
diff --git a/media/filters/ffmpeg_glue.cc b/media/filters/ffmpeg_glue.cc index 7f992284a..0aa86ed 100644 --- a/media/filters/ffmpeg_glue.cc +++ b/media/filters/ffmpeg_glue.cc
@@ -129,6 +129,10 @@ // Ensures we can read out various metadata bits like vp8 alpha. format_context_->flags |= AVFMT_FLAG_KEEP_SIDE_DATA; + // Ensures format parsing errors will bail out. From an audit on 11/2017, all + // instances were real failures. Solves bugs like http://crbug.com/710791. + format_context_->error_recognition |= AV_EF_EXPLODE; + format_context_->pb = avio_context_.get(); }
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index def3f7a..fc72cf32 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1675,6 +1675,7 @@ "loader/resource/MockImageResourceObserver.h", "loader/resource/MultipartImageResourceParserTest.cpp", "origin_trials/OriginTrialContextTest.cpp", + "page/AutoscrollControllerTest.cpp", "page/ChromeClientImplTest.cpp", "page/ChromeClientTest.cpp", "page/DragControllerTest.cpp",
diff --git a/third_party/WebKit/Source/core/page/AutoscrollController.cpp b/third_party/WebKit/Source/core/page/AutoscrollController.cpp index d86303d..6a226b8 100644 --- a/third_party/WebKit/Source/core/page/AutoscrollController.cpp +++ b/third_party/WebKit/Source/core/page/AutoscrollController.cpp
@@ -333,8 +333,14 @@ return; } event_handler.UpdateSelectionForMouseDrag(); - ScheduleMainThreadAnimation(); - autoscroll_layout_object_->Autoscroll(selection_point); + + // UpdateSelectionForMouseDrag may call layout to cancel auto scroll + // animation. + if (autoscroll_type_ != kNoAutoscroll) { + DCHECK(autoscroll_layout_object_); + ScheduleMainThreadAnimation(); + autoscroll_layout_object_->Autoscroll(selection_point); + } break; case kNoAutoscroll: case kAutoscrollForMiddleClick: @@ -347,4 +353,8 @@ autoscroll_layout_object_->GetFrame()->View()); } +bool AutoscrollController::IsAutoscrolling() const { + return (autoscroll_type_ != kNoAutoscroll); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/page/AutoscrollController.h b/third_party/WebKit/Source/core/page/AutoscrollController.h index 51a22eb7..1f754cb 100644 --- a/third_party/WebKit/Source/core/page/AutoscrollController.h +++ b/third_party/WebKit/Source/core/page/AutoscrollController.h
@@ -26,6 +26,7 @@ #ifndef AutoscrollController_h #define AutoscrollController_h +#include "base/gtest_prod_util.h" #include "core/CoreExport.h" #include "platform/geometry/FloatPoint.h" #include "platform/geometry/FloatSize.h" @@ -97,6 +98,9 @@ private: explicit AutoscrollController(Page&); + // For test. + bool IsAutoscrolling() const; + Member<Page> page_; AutoscrollType autoscroll_type_ = kNoAutoscroll; @@ -111,6 +115,9 @@ FloatPoint middle_click_autoscroll_start_pos_global_; FloatSize last_velocity_; MiddleClickMode middle_click_mode_ = kMiddleClickInitial; + + FRIEND_TEST_ALL_PREFIXES(AutoscrollControllerTest, + CrashWhenLayoutStopAnimationBeforeScheduleAnimation); }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/page/AutoscrollControllerTest.cpp b/third_party/WebKit/Source/core/page/AutoscrollControllerTest.cpp new file mode 100644 index 0000000..a321031e --- /dev/null +++ b/third_party/WebKit/Source/core/page/AutoscrollControllerTest.cpp
@@ -0,0 +1,81 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/dom/Element.h" +#include "core/input/EventHandler.h" +#include "core/page/AutoscrollController.h" +#include "core/page/Page.h" +#include "core/testing/sim/SimDisplayItemList.h" +#include "core/testing/sim/SimRequest.h" +#include "core/testing/sim/SimTest.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { + +class AutoscrollControllerTest : public SimTest { + public: + AutoscrollController& GetAutoscrollController() { + return WebView().GetPage()->GetAutoscrollController(); + } +}; + +// Ensure Autoscroll not crash by layout called in UpdateSelectionForMouseDrag. +TEST_F(AutoscrollControllerTest, + CrashWhenLayoutStopAnimationBeforeScheduleAnimation) { + WebView().Resize(WebSize(800, 600)); + WebView().SetBaseBackgroundColorOverride(SK_ColorTRANSPARENT); + SimRequest request("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + request.Complete(R"HTML( + <!DOCTYPE html> + <style> + #scrollable { + overflow: auto; + width: 10px; + height: 10px; + } + </style> + <div id='scrollable'> + <p id='p'>Some text here for selection autoscroll.</p> + <p>Some text here for selection autoscroll.</p> + <p>Some text here for selection autoscroll.</p> + <p>Some text here for selection autoscroll.</p> + <p>Some text here for selection autoscroll.</p> + <p>Some text here for selection autoscroll.</p> + <p>Some text here for selection autoscroll.</p> + <p>Some text here for selection autoscroll.</p> + </div> + )HTML"); + + Compositor().BeginFrame(); + + AutoscrollController& controller = GetAutoscrollController(); + Document& document = GetDocument(); + + Element* scrollable = document.getElementById("scrollable"); + DCHECK(scrollable); + DCHECK(scrollable->GetLayoutObject()); + + WebMouseEvent event(WebInputEvent::kMouseDown, WebFloatPoint(5, 5), + WebFloatPoint(5, 5), WebPointerProperties::Button::kLeft, + 0, WebInputEvent::Modifiers::kLeftButtonDown, + TimeTicks::Now().InSeconds()); + event.SetFrameScale(1); + + GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(event); + + controller.StartAutoscrollForSelection(scrollable->GetLayoutObject()); + + DCHECK(controller.IsAutoscrolling()); + + // Hide scrollable here will cause UpdateSelectionForMouseDrag stop animation. + scrollable->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueNone); + + // BeginFrame will call AutoscrollController::Animate. + Compositor().BeginFrame(); + + EXPECT_FALSE(controller.IsAutoscrolling()); +} + +} // namespace blink