diff options
author | stevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-10 21:59:26 +0000 |
---|---|---|
committer | stevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-10 21:59:26 +0000 |
commit | 833a6bf23035005db6526096fa1e1c3ffdcf49f6 (patch) | |
tree | 576a249d3a01f2f3fa291fdccfc2ef8627d6689e /chromeos/settings | |
parent | f54e768523cab56eb160ee463241ef29f46e77cd (diff) | |
download | chromium_src-833a6bf23035005db6526096fa1e1c3ffdcf49f6.zip chromium_src-833a6bf23035005db6526096fa1e1c3ffdcf49f6.tar.gz chromium_src-833a6bf23035005db6526096fa1e1c3ffdcf49f6.tar.bz2 |
Move some cros settings code to chromeos/settings
BUG=270135
For numerous #include changes:
TBR=sky@chromium.org
Review URL: https://codereview.chromium.org/26732002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@228017 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/settings')
-rw-r--r-- | chromeos/settings/cros_settings_names.cc | 140 | ||||
-rw-r--r-- | chromeos/settings/cros_settings_names.h | 85 | ||||
-rw-r--r-- | chromeos/settings/cros_settings_provider.cc | 46 | ||||
-rw-r--r-- | chromeos/settings/cros_settings_provider.h | 79 | ||||
-rw-r--r-- | chromeos/settings/timezone_settings.cc | 440 | ||||
-rw-r--r-- | chromeos/settings/timezone_settings.h | 53 |
6 files changed, 843 insertions, 0 deletions
diff --git a/chromeos/settings/cros_settings_names.cc b/chromeos/settings/cros_settings_names.cc new file mode 100644 index 0000000..a82a254 --- /dev/null +++ b/chromeos/settings/cros_settings_names.cc @@ -0,0 +1,140 @@ +// Copyright 2013 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 "chromeos/settings/cros_settings_names.h" + +namespace chromeos { + +const char kCrosSettingsPrefix[] = "cros."; + +// All cros.accounts.* settings are stored in SignedSettings. +const char kAccountsPrefAllowGuest[] = "cros.accounts.allowBWSI"; +const char kAccountsPrefAllowNewUser[] = "cros.accounts.allowGuest"; +const char kAccountsPrefShowUserNamesOnSignIn[] + = "cros.accounts.showUserNamesOnSignIn"; +const char kAccountsPrefUsers[] = "cros.accounts.users"; +const char kAccountsPrefEphemeralUsersEnabled[] = + "cros.accounts.ephemeralUsersEnabled"; +const char kAccountsPrefDeviceLocalAccounts[] = + "cros.accounts.deviceLocalAccounts"; +const char kAccountsPrefDeviceLocalAccountsKeyId[] = + "id"; +const char kAccountsPrefDeviceLocalAccountsKeyType[] = + "type"; +const char kAccountsPrefDeviceLocalAccountsKeyKioskAppId[] = + "kiosk_app_id"; +const char kAccountsPrefDeviceLocalAccountAutoLoginId[] = + "cros.accounts.deviceLocalAccountAutoLoginId"; +const char kAccountsPrefDeviceLocalAccountAutoLoginDelay[] = + "cros.accounts.deviceLocalAccountAutoLoginDelay"; +const char kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled[] = + "cros.accounts.deviceLocalAccountAutoLoginBailoutEnabled"; +const char kAccountsPrefSupervisedUsersEnabled[] = + "cros.accounts.supervisedUsersEnabled"; + +// All cros.signed.* settings are stored in SignedSettings. +const char kSignedDataRoamingEnabled[] = "cros.signed.data_roaming_enabled"; + +// True if auto-update was disabled by the system administrator. +const char kUpdateDisabled[] = "cros.system.updateDisabled"; + +// A list of strings which specifies allowed connection types for +// update. +const char kAllowedConnectionTypesForUpdate[] = + "cros.system.allowedConnectionTypesForUpdate"; + +// The first constant refers to the user setting editable in the UI. The second +// refers to the timezone policy. This seperation is necessary to allow the user +// to temporarily change the timezone for the current session and reset it to +// the policy's value on logout. +const char kSystemTimezone[] = "cros.system.timezone"; +const char kSystemTimezonePolicy[] = "cros.system.timezone_policy"; + +// Value of kUse24HourClock user preference of device' owner. +// ChromeOS device uses this setting on login screen. +const char kSystemUse24HourClock[] = "cros.system.use_24hour_clock"; + +const char kDeviceOwner[] = "cros.device.owner"; + +const char kStatsReportingPref[] = "cros.metrics.reportingEnabled"; + +const char kReleaseChannel[] = "cros.system.releaseChannel"; +const char kReleaseChannelDelegated[] = "cros.system.releaseChannelDelegated"; + +// A boolean pref that indicates whether OS & firmware version info should be +// reported along with device policy requests. +const char kReportDeviceVersionInfo[] = + "cros.device_status.report_version_info"; + +// A boolean pref that indicates whether device activity times should be +// recorded and reported along with device policy requests. +const char kReportDeviceActivityTimes[] = + "cros.device_status.report_activity_times"; + +// A boolean pref that indicates whether the state of the dev mode switch at +// boot should be reported along with device policy requests. +const char kReportDeviceBootMode[] = "cros.device_status.report_boot_mode"; + +// A boolean pref that indicates whether the current location should be reported +// along with device policy requests. +const char kReportDeviceLocation[] = "cros.device_status.report_location"; + +// Determines whether the device reports network interface types and addresses +// in device status reports to the device management server. +const char kReportDeviceNetworkInterfaces[] = + "cros.device_status.report_network_interfaces"; + +// A list of dictionaries, each detailing one extension to install as part of +// the AppPack and including the following fields: +// "extension-id": ID of the extension to install +// "update-url": URL to check the extension's version and download location +// "key-checksum": checksum of the extension's CRX public key, encoded in hex. +const char kAppPack[] = "cros.app_pack"; +const char kAppPackKeyExtensionId[] = "extension-id"; +const char kAppPackKeyUpdateUrl[] = "update-url"; + +// Values from the ScreenSaver proto. Defines the extension ID of the screen +// saver extension and the timeout before the screen saver should be started. +const char kScreenSaverExtensionId[] = "cros.screen_saver.extension_id"; +const char kScreenSaverTimeout[] = "cros.screen_saver.timeout"; + +// Values from the ForcedLogoutTimeouts proto. Defines the timeouts before a +// user is logged out after some period of inactivity as well as the duration of +// a warning message informing the user about the pending logout. +const char kIdleLogoutTimeout[] = "cros.idle_logout.timeout"; +const char kIdleLogoutWarningDuration[] = "cros.idle_logout.warning_duration"; + +// Defines the set of URLs to be opened on login to the anonymous account used +// if the device is in KIOSK mode. +const char kStartUpUrls[] = "cros.start_up_urls"; + +// This policy should not appear in the protobuf ever but is used internally to +// signal that we are running in a "safe-mode" for policy recovery. +const char kPolicyMissingMitigationMode[] = + "cros.internal.policy_mitigation_mode"; + +// A boolean pref that indicates whether users are allowed to redeem offers +// through Chrome OS Registration. +const char kAllowRedeemChromeOsRegistrationOffers[] = + "cros.echo.allow_redeem_chrome_os_registration_offers"; + +// A list pref storing the flags that need to be applied to the browser upon +// start-up. +const char kStartUpFlags[] = "cros.startup_flags"; + +// A string pref for the restrict parameter to be appended to the Variations URL +// when pinging the Variations server. +const char kVariationsRestrictParameter[] = + "cros.variations_restrict_parameter"; + +// A boolean pref that indicates whether enterprise attestation is enabled for +// the device. +const char kDeviceAttestationEnabled[] = "cros.device.attestation_enabled"; + +// A boolean pref that indicates whether attestation for content protection is +// enabled for the device. +const char kAttestationForContentProtectionEnabled[] = + "cros.device.attestation_for_content_protection_enabled"; + +} // namespace chromeos diff --git a/chromeos/settings/cros_settings_names.h b/chromeos/settings/cros_settings_names.h new file mode 100644 index 0000000..b0971dd --- /dev/null +++ b/chromeos/settings/cros_settings_names.h @@ -0,0 +1,85 @@ +// Copyright 2013 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. + +#ifndef CHROMEOS_SETTINGS_CROS_SETTINGS_NAMES_H_ +#define CHROMEOS_SETTINGS_CROS_SETTINGS_NAMES_H_ + +#include "chromeos/chromeos_export.h" + +namespace chromeos { + +CHROMEOS_EXPORT extern const char kCrosSettingsPrefix[]; + +CHROMEOS_EXPORT extern const char kAccountsPrefAllowGuest[]; +CHROMEOS_EXPORT extern const char kAccountsPrefAllowNewUser[]; +CHROMEOS_EXPORT extern const char kAccountsPrefShowUserNamesOnSignIn[]; +CHROMEOS_EXPORT extern const char kAccountsPrefUsers[]; +CHROMEOS_EXPORT extern const char kAccountsPrefEphemeralUsersEnabled[]; +CHROMEOS_EXPORT extern const char kAccountsPrefDeviceLocalAccounts[]; +CHROMEOS_EXPORT extern const char kAccountsPrefDeviceLocalAccountsKeyId[]; +CHROMEOS_EXPORT extern const char kAccountsPrefDeviceLocalAccountsKeyType[]; +CHROMEOS_EXPORT extern const char + kAccountsPrefDeviceLocalAccountsKeyKioskAppId[]; +CHROMEOS_EXPORT extern const char + kAccountsPrefDeviceLocalAccountAutoLoginId[]; +CHROMEOS_EXPORT extern const char + kAccountsPrefDeviceLocalAccountAutoLoginDelay[]; +CHROMEOS_EXPORT extern const char + kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled[]; +CHROMEOS_EXPORT extern const char kAccountsPrefSupervisedUsersEnabled[]; + +CHROMEOS_EXPORT extern const char kSignedDataRoamingEnabled[]; + +CHROMEOS_EXPORT extern const char kUpdateDisabled[]; +CHROMEOS_EXPORT extern const char kAllowedConnectionTypesForUpdate[]; + +CHROMEOS_EXPORT extern const char kSystemTimezonePolicy[]; +CHROMEOS_EXPORT extern const char kSystemTimezone[]; +CHROMEOS_EXPORT extern const char kSystemUse24HourClock[]; + +CHROMEOS_EXPORT extern const char kDeviceOwner[]; + +CHROMEOS_EXPORT extern const char kStatsReportingPref[]; + +CHROMEOS_EXPORT extern const char kReleaseChannel[]; +CHROMEOS_EXPORT extern const char kReleaseChannelDelegated[]; + +CHROMEOS_EXPORT extern const char kReportDeviceVersionInfo[]; +CHROMEOS_EXPORT extern const char kReportDeviceActivityTimes[]; +CHROMEOS_EXPORT extern const char kReportDeviceBootMode[]; +CHROMEOS_EXPORT extern const char kReportDeviceLocation[]; +CHROMEOS_EXPORT extern const char kReportDeviceNetworkInterfaces[]; + +CHROMEOS_EXPORT extern const char kAppPack[]; +CHROMEOS_EXPORT extern const char kAppPackKeyExtensionId[]; +CHROMEOS_EXPORT extern const char kAppPackKeyUpdateUrl[]; + +CHROMEOS_EXPORT extern const char kScreenSaverExtensionId[]; +CHROMEOS_EXPORT extern const char kScreenSaverTimeout[]; + +CHROMEOS_EXPORT extern const char kIdleLogoutTimeout[]; +CHROMEOS_EXPORT extern const char kIdleLogoutWarningDuration[]; + +CHROMEOS_EXPORT extern const char kStartUpUrls[]; + +CHROMEOS_EXPORT extern const char kPolicyMissingMitigationMode[]; + +CHROMEOS_EXPORT extern const char kAllowRedeemChromeOsRegistrationOffers[]; + +CHROMEOS_EXPORT extern const char kStartUpFlags[]; + +CHROMEOS_EXPORT extern const char kKioskAppSettingsPrefix[]; +CHROMEOS_EXPORT extern const int kKioskAppSettingsPrefixLength; +CHROMEOS_EXPORT extern const char kKioskApps[]; +CHROMEOS_EXPORT extern const char kKioskAutoLaunch[]; +CHROMEOS_EXPORT extern const char kKioskDisableBailoutShortcut[]; + +CHROMEOS_EXPORT extern const char kVariationsRestrictParameter[]; + +CHROMEOS_EXPORT extern const char kDeviceAttestationEnabled[]; +CHROMEOS_EXPORT extern const char kAttestationForContentProtectionEnabled[]; + +} // namespace chromeos + +#endif // CHROMEOS_SETTINGS_CROS_SETTINGS_NAMES_H_ diff --git a/chromeos/settings/cros_settings_provider.cc b/chromeos/settings/cros_settings_provider.cc new file mode 100644 index 0000000..66ca64c --- /dev/null +++ b/chromeos/settings/cros_settings_provider.cc @@ -0,0 +1,46 @@ +// Copyright 2013 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 "chromeos/settings/cros_settings_provider.h" + +#include "base/command_line.h" +#include "base/logging.h" +#include "base/strings/string_util.h" +#include "base/values.h" +#include "chromeos/chromeos_switches.h" + +namespace chromeos { + +CrosSettingsProvider::CrosSettingsProvider( + const NotifyObserversCallback& notify_cb) + : notify_cb_(notify_cb) { +} + +CrosSettingsProvider::~CrosSettingsProvider() { +} + +void CrosSettingsProvider::Set(const std::string& path, + const base::Value& value) { + // We don't allow changing any of the cros settings without prefix + // "cros.session." in the guest mode. + // It should not reach here from UI in the guest mode, but just in case. + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession) && + !::StartsWithASCII(path, "cros.session.", true)) { + LOG(ERROR) << "Ignoring the guest request to change: " << path; + return; + } + DoSet(path, value); +} + +void CrosSettingsProvider::NotifyObservers(const std::string& path) { + if (!notify_cb_.is_null()) + notify_cb_.Run(path); +} + +void CrosSettingsProvider::SetNotifyObserversCallback( + const NotifyObserversCallback& notify_cb) { + notify_cb_ = notify_cb; +} + +}; // namespace chromeos diff --git a/chromeos/settings/cros_settings_provider.h b/chromeos/settings/cros_settings_provider.h new file mode 100644 index 0000000..491113b --- /dev/null +++ b/chromeos/settings/cros_settings_provider.h @@ -0,0 +1,79 @@ +// Copyright 2013 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. + +#ifndef CHROMEOS_SETTINGS_CROS_SETTINGS_PROVIDER_H_ +#define CHROMEOS_SETTINGS_CROS_SETTINGS_PROVIDER_H_ + +#include <string> + +#include "base/callback.h" +#include "chromeos/chromeos_export.h" + +namespace base { +class Value; +} + +namespace chromeos { + +class CHROMEOS_EXPORT CrosSettingsProvider { + public: + // The callback type that is called to notify the CrosSettings observers + // about a setting change. + typedef base::Callback<void(const std::string&)> NotifyObserversCallback; + + // Possible results of a trusted check. + enum TrustedStatus { + // The trusted values were populated in the cache and can be accessed + // until the next iteration of the message loop. + TRUSTED, + // Either a store or a load operation is in progress. The provided + // callback will be invoked once the verification has finished. + TEMPORARILY_UNTRUSTED, + // The verification of the trusted store has failed permanently. The + // client should assume this state final and further checks for + // trustedness will fail at least until the browser restarts. + PERMANENTLY_UNTRUSTED, + }; + + // Creates a new provider instance. |notify_cb| will be used to notify + // about setting changes. + explicit CrosSettingsProvider(const NotifyObserversCallback& notify_cb); + virtual ~CrosSettingsProvider(); + + // Sets |in_value| to given |path| in cros settings. + void Set(const std::string& path, const base::Value& in_value); + + // Gets settings value of given |path| to |out_value|. + virtual const base::Value* Get(const std::string& path) const = 0; + + // Requests the provider to fetch its values from a trusted store, if it + // hasn't done so yet. Returns TRUSTED if the values returned by this provider + // are trusted during the current loop cycle. Otherwise returns + // TEMPORARILY_UNTRUSTED, and |callback| will be invoked later when trusted + // values become available, PrepareTrustedValues() should be tried again in + // that case. Returns PERMANENTLY_UNTRUSTED if a permanent error has occurred. + virtual TrustedStatus PrepareTrustedValues( + const base::Closure& callback) = 0; + + // Gets the namespace prefix provided by this provider. + virtual bool HandlesSetting(const std::string& path) const = 0; + + void SetNotifyObserversCallback(const NotifyObserversCallback& notify_cb); + + protected: + // Notifies the observers about a setting change. + void NotifyObservers(const std::string& path); + + private: + // Does the real job for Set(). + virtual void DoSet(const std::string& path, + const base::Value& in_value) = 0; + + // Callback used to notify about setting changes. + NotifyObserversCallback notify_cb_; +}; + +} // namespace chromeos + +#endif // CHROMEOS_SETTINGS_CROS_SETTINGS_PROVIDER_H_ diff --git a/chromeos/settings/timezone_settings.cc b/chromeos/settings/timezone_settings.cc new file mode 100644 index 0000000..1adcf13 --- /dev/null +++ b/chromeos/settings/timezone_settings.cc @@ -0,0 +1,440 @@ +// Copyright 2013 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 "chromeos/settings/timezone_settings.h" + +#include <string> + +#include "base/bind.h" +#include "base/file_util.h" +#include "base/files/file_path.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/singleton.h" +#include "base/observer_list.h" +#include "base/stl_util.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/sys_info.h" +#include "base/task_runner.h" +#include "base/threading/worker_pool.h" +#include "third_party/icu/source/i18n/unicode/timezone.h" + +namespace { + +// The filepath to the timezone file that symlinks to the actual timezone file. +const char kTimezoneSymlink[] = "/var/lib/timezone/localtime"; +const char kTimezoneSymlink2[] = "/var/lib/timezone/localtime2"; + +// The directory that contains all the timezone files. So for timezone +// "US/Pacific", the actual timezone file is: "/usr/share/zoneinfo/US/Pacific" +const char kTimezoneFilesDir[] = "/usr/share/zoneinfo/"; + +// Fallback time zone ID used in case of an unexpected error. +const char kFallbackTimeZoneId[] = "America/Los_Angeles"; + +// TODO(jungshik): Using Enumerate method in ICU gives 600+ timezones. +// Even after filtering out duplicate entries with a strict identity check, +// we still have 400+ zones. Relaxing the criteria for the timezone +// identity is likely to cut down the number to < 100. Until we +// come up with a better list, we hard-code the following list. It came from +// from Android initially, but more entries have been added. +static const char* kTimeZones[] = { + "Pacific/Midway", + "Pacific/Honolulu", + "America/Anchorage", + "America/Los_Angeles", + "America/Vancouver", + "America/Tijuana", + "America/Phoenix", + "America/Denver", + "America/Edmonton", + "America/Chihuahua", + "America/Regina", + "America/Costa_Rica", + "America/Chicago", + "America/Mexico_City", + "America/Winnipeg", + "America/Bogota", + "America/New_York", + "America/Toronto", + "America/Caracas", + "America/Barbados", + "America/Halifax", + "America/Manaus", + "America/Santiago", + "America/St_Johns", + "America/Sao_Paulo", + "America/Araguaina", + "America/Argentina/Buenos_Aires", + "America/Argentina/San_Luis", + "America/Montevideo", + "America/Godthab", + "Atlantic/South_Georgia", + "Atlantic/Cape_Verde", + "Atlantic/Azores", + "Africa/Casablanca", + "Europe/London", + "Europe/Dublin", + "Europe/Amsterdam", + "Europe/Belgrade", + "Europe/Berlin", + "Europe/Brussels", + "Europe/Madrid", + "Europe/Paris", + "Europe/Rome", + "Europe/Stockholm", + "Europe/Sarajevo", + "Europe/Vienna", + "Europe/Warsaw", + "Europe/Zurich", + "Africa/Windhoek", + "Africa/Lagos", + "Africa/Brazzaville", + "Africa/Cairo", + "Africa/Harare", + "Africa/Maputo", + "Africa/Johannesburg", + "Europe/Helsinki", + "Europe/Athens", + "Asia/Amman", + "Asia/Beirut", + "Asia/Jerusalem", + "Europe/Minsk", + "Asia/Baghdad", + "Asia/Riyadh", + "Asia/Kuwait", + "Africa/Nairobi", + "Asia/Tehran", + "Europe/Moscow", + "Asia/Dubai", + "Asia/Tbilisi", + "Indian/Mauritius", + "Asia/Baku", + "Asia/Yerevan", + "Asia/Kabul", + "Asia/Karachi", + "Asia/Ashgabat", + "Asia/Oral", + "Asia/Calcutta", + "Asia/Colombo", + "Asia/Katmandu", + "Asia/Yekaterinburg", + "Asia/Almaty", + "Asia/Dhaka", + "Asia/Rangoon", + "Asia/Bangkok", + "Asia/Jakarta", + "Asia/Omsk", + "Asia/Novosibirsk", + "Asia/Shanghai", + "Asia/Hong_Kong", + "Asia/Kuala_Lumpur", + "Asia/Singapore", + "Asia/Manila", + "Asia/Taipei", + "Asia/Makassar", + "Asia/Krasnoyarsk", + "Australia/Perth", + "Australia/Eucla", + "Asia/Irkutsk", + "Asia/Seoul", + "Asia/Tokyo", + "Asia/Jayapura", + "Australia/Adelaide", + "Australia/Darwin", + "Australia/Brisbane", + "Australia/Hobart", + "Australia/Sydney", + "Asia/Yakutsk", + "Pacific/Guam", + "Pacific/Port_Moresby", + "Asia/Vladivostok", + "Asia/Sakhalin", + "Asia/Magadan", + "Pacific/Auckland", + "Pacific/Fiji", + "Pacific/Majuro", + "Pacific/Tongatapu", + "Pacific/Apia", + "Pacific/Kiritimati", +}; + +std::string GetTimezoneIDAsString() { + // Compare with chromiumos/src/platform/init/ui.conf which fixes certain + // incorrect states of the timezone symlink on startup. Thus errors occuring + // here should be rather contrived. + + // Look at kTimezoneSymlink, see which timezone we are symlinked to. + char buf[256]; + const ssize_t len = readlink(kTimezoneSymlink, buf, + sizeof(buf)-1); + if (len == -1) { + LOG(ERROR) << "GetTimezoneID: Cannot read timezone symlink " + << kTimezoneSymlink; + return std::string(); + } + + std::string timezone(buf, len); + // Remove kTimezoneFilesDir from the beginning. + if (timezone.find(kTimezoneFilesDir) != 0) { + LOG(ERROR) << "GetTimezoneID: Timezone symlink is wrong " + << timezone; + return std::string(); + } + + return timezone.substr(strlen(kTimezoneFilesDir)); +} + +void SetTimezoneIDFromString(const std::string& id) { + // Change the kTimezoneSymlink symlink to the path for this timezone. + // We want to do this in an atomic way. So we are going to create the symlink + // at kTimezoneSymlink2 and then move it to kTimezoneSymlink + + base::FilePath timezone_symlink(kTimezoneSymlink); + base::FilePath timezone_symlink2(kTimezoneSymlink2); + base::FilePath timezone_file(kTimezoneFilesDir + id); + + // Make sure timezone_file exists. + if (!base::PathExists(timezone_file)) { + LOG(ERROR) << "SetTimezoneID: Cannot find timezone file " + << timezone_file.value(); + return; + } + + // Delete old symlink2 if it exists. + base::DeleteFile(timezone_symlink2, false); + + // Create new symlink2. + if (symlink(timezone_file.value().c_str(), + timezone_symlink2.value().c_str()) == -1) { + LOG(ERROR) << "SetTimezoneID: Unable to create symlink " + << timezone_symlink2.value() << " to " << timezone_file.value(); + return; + } + + // Move symlink2 to symlink. + if (!base::ReplaceFile(timezone_symlink2, timezone_symlink, NULL)) { + LOG(ERROR) << "SetTimezoneID: Unable to move symlink " + << timezone_symlink2.value() << " to " + << timezone_symlink.value(); + } +} + +// Common code of the TimezoneSettings implementations. +class TimezoneSettingsBaseImpl : public chromeos::system::TimezoneSettings { + public: + virtual ~TimezoneSettingsBaseImpl(); + + // TimezoneSettings implementation: + virtual const icu::TimeZone& GetTimezone() OVERRIDE; + virtual string16 GetCurrentTimezoneID() OVERRIDE; + virtual void SetTimezoneFromID(const string16& timezone_id) OVERRIDE; + virtual void AddObserver(Observer* observer) OVERRIDE; + virtual void RemoveObserver(Observer* observer) OVERRIDE; + virtual const std::vector<icu::TimeZone*>& GetTimezoneList() const OVERRIDE; + + protected: + TimezoneSettingsBaseImpl(); + + // Returns |timezone| if it is an element of |timezones_|. + // Otherwise, returns a timezone from |timezones_|, if such exists, that has + // the same rule as the given |timezone|. + // Otherwise, returns NULL. + // Note multiple timezones with the same time zone offset may exist + // e.g. + // US/Pacific == America/Los_Angeles + const icu::TimeZone* GetKnownTimezoneOrNull( + const icu::TimeZone& timezone) const; + + ObserverList<Observer> observers_; + std::vector<icu::TimeZone*> timezones_; + scoped_ptr<icu::TimeZone> timezone_; + + private: + DISALLOW_COPY_AND_ASSIGN(TimezoneSettingsBaseImpl); +}; + +// The TimezoneSettings implementation used in production. +class TimezoneSettingsImpl : public TimezoneSettingsBaseImpl { + public: + // TimezoneSettings implementation: + virtual void SetTimezone(const icu::TimeZone& timezone) OVERRIDE; + + static TimezoneSettingsImpl* GetInstance(); + + private: + friend struct DefaultSingletonTraits<TimezoneSettingsImpl>; + + TimezoneSettingsImpl(); + + DISALLOW_COPY_AND_ASSIGN(TimezoneSettingsImpl); +}; + +// The stub TimezoneSettings implementation used on Linux desktop. +class TimezoneSettingsStubImpl : public TimezoneSettingsBaseImpl { + public: + // TimezoneSettings implementation: + virtual void SetTimezone(const icu::TimeZone& timezone) OVERRIDE; + + static TimezoneSettingsStubImpl* GetInstance(); + + private: + friend struct DefaultSingletonTraits<TimezoneSettingsStubImpl>; + + TimezoneSettingsStubImpl(); + + DISALLOW_COPY_AND_ASSIGN(TimezoneSettingsStubImpl); +}; + +TimezoneSettingsBaseImpl::~TimezoneSettingsBaseImpl() { + STLDeleteElements(&timezones_); +} + +const icu::TimeZone& TimezoneSettingsBaseImpl::GetTimezone() { + return *timezone_.get(); +} + +string16 TimezoneSettingsBaseImpl::GetCurrentTimezoneID() { + return chromeos::system::TimezoneSettings::GetTimezoneID(GetTimezone()); +} + +void TimezoneSettingsBaseImpl::SetTimezoneFromID(const string16& timezone_id) { + scoped_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone( + icu::UnicodeString(timezone_id.c_str(), timezone_id.size()))); + SetTimezone(*timezone); +} + +void TimezoneSettingsBaseImpl::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void TimezoneSettingsBaseImpl::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +const std::vector<icu::TimeZone*>& +TimezoneSettingsBaseImpl::GetTimezoneList() const { + return timezones_; +} + +TimezoneSettingsBaseImpl::TimezoneSettingsBaseImpl() { + for (size_t i = 0; i < arraysize(kTimeZones); ++i) { + timezones_.push_back(icu::TimeZone::createTimeZone( + icu::UnicodeString(kTimeZones[i], -1, US_INV))); + } +} + +const icu::TimeZone* TimezoneSettingsBaseImpl::GetKnownTimezoneOrNull( + const icu::TimeZone& timezone) const { + const icu::TimeZone* known_timezone = NULL; + for (std::vector<icu::TimeZone*>::const_iterator iter = timezones_.begin(); + iter != timezones_.end(); ++iter) { + const icu::TimeZone* entry = *iter; + if (*entry == timezone) + return entry; + if (entry->hasSameRules(timezone)) + known_timezone = entry; + } + + // May return NULL if we did not find a matching timezone in our list. + return known_timezone; +} + +void TimezoneSettingsImpl::SetTimezone(const icu::TimeZone& timezone) { + // Replace |timezone| by a known timezone with the same rules. If none exists + // go on with |timezone|. + const icu::TimeZone* known_timezone = GetKnownTimezoneOrNull(timezone); + if (!known_timezone) + known_timezone = &timezone; + + timezone_.reset(known_timezone->clone()); + std::string id = UTF16ToUTF8(GetTimezoneID(*known_timezone)); + VLOG(1) << "Setting timezone to " << id; + // It's safe to change the timezone config files in the background as the + // following operations don't depend on the completion of the config change. + base::WorkerPool::GetTaskRunner(true /* task is slow */)-> + PostTask(FROM_HERE, base::Bind(&SetTimezoneIDFromString, id)); + icu::TimeZone::setDefault(*known_timezone); + FOR_EACH_OBSERVER(Observer, observers_, TimezoneChanged(*known_timezone)); +} + +// static +TimezoneSettingsImpl* TimezoneSettingsImpl::GetInstance() { + return Singleton<TimezoneSettingsImpl, + DefaultSingletonTraits<TimezoneSettingsImpl> >::get(); +} + +TimezoneSettingsImpl::TimezoneSettingsImpl() { + std::string id = GetTimezoneIDAsString(); + if (id.empty()) { + id = kFallbackTimeZoneId; + LOG(ERROR) << "Got an empty string for timezone, default to '" << id; + } + + timezone_.reset(icu::TimeZone::createTimeZone( + icu::UnicodeString::fromUTF8(id))); + + // Store a known timezone equivalent to id in |timezone_|. + const icu::TimeZone* known_timezone = GetKnownTimezoneOrNull(*timezone_); + if (known_timezone != NULL && *known_timezone != *timezone_) + // Not necessary to update the filesystem because |known_timezone| has the + // same rules. + timezone_.reset(known_timezone->clone()); + + icu::TimeZone::setDefault(*timezone_); + VLOG(1) << "Timezone initially set to " << id; +} + +void TimezoneSettingsStubImpl::SetTimezone(const icu::TimeZone& timezone) { + // Replace |timezone| by a known timezone with the same rules. If none exists + // go on with |timezone|. + const icu::TimeZone* known_timezone = GetKnownTimezoneOrNull(timezone); + if (!known_timezone) + known_timezone = &timezone; + + timezone_.reset(known_timezone->clone()); + icu::TimeZone::setDefault(*known_timezone); + FOR_EACH_OBSERVER(Observer, observers_, TimezoneChanged(*known_timezone)); +} + +// static +TimezoneSettingsStubImpl* TimezoneSettingsStubImpl::GetInstance() { + return Singleton<TimezoneSettingsStubImpl, + DefaultSingletonTraits<TimezoneSettingsStubImpl> >::get(); +} + +TimezoneSettingsStubImpl::TimezoneSettingsStubImpl() { + timezone_.reset(icu::TimeZone::createDefault()); + const icu::TimeZone* known_timezone = GetKnownTimezoneOrNull(*timezone_); + if (known_timezone != NULL && *known_timezone != *timezone_) + timezone_.reset(known_timezone->clone()); +} + +} // namespace + +namespace chromeos { +namespace system { + +TimezoneSettings::Observer::~Observer() {} + +// static +TimezoneSettings* TimezoneSettings::GetInstance() { + if (base::SysInfo::IsRunningOnChromeOS()) { + return TimezoneSettingsImpl::GetInstance(); + } else { + return TimezoneSettingsStubImpl::GetInstance(); + } +} + +// static +string16 TimezoneSettings::GetTimezoneID(const icu::TimeZone& timezone) { + icu::UnicodeString id; + timezone.getID(id); + return string16(id.getBuffer(), id.length()); +} + +} // namespace system +} // namespace chromeos diff --git a/chromeos/settings/timezone_settings.h b/chromeos/settings/timezone_settings.h new file mode 100644 index 0000000..c0d9555 --- /dev/null +++ b/chromeos/settings/timezone_settings.h @@ -0,0 +1,53 @@ +// Copyright 2013 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. + +#ifndef CHROMEOS_SETTINGS_TIMEZONE_SETTINGS_H_ +#define CHROMEOS_SETTINGS_TIMEZONE_SETTINGS_H_ + +#include <vector> + +#include "base/strings/string16.h" +#include "chromeos/settings/cros_settings_provider.h" +#include "third_party/icu/source/i18n/unicode/timezone.h" + +namespace chromeos { +namespace system { + +// This interface provides access to Chrome OS timezone settings. +class CHROMEOS_EXPORT TimezoneSettings { + public: + class Observer { + public: + // Called when the timezone has changed. |timezone| is non-null. + virtual void TimezoneChanged(const icu::TimeZone& timezone) = 0; + protected: + virtual ~Observer(); + }; + + static TimezoneSettings* GetInstance(); + + // Returns the current timezone as an icu::Timezone object. + virtual const icu::TimeZone& GetTimezone() = 0; + virtual string16 GetCurrentTimezoneID() = 0; + + // Sets the current timezone and notifies all Observers. + virtual void SetTimezone(const icu::TimeZone& timezone) = 0; + virtual void SetTimezoneFromID(const string16& timezone_id) = 0; + + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + virtual const std::vector<icu::TimeZone*>& GetTimezoneList() const = 0; + + // Gets timezone ID which is also used as timezone pref value. + static string16 GetTimezoneID(const icu::TimeZone& timezone); + + protected: + virtual ~TimezoneSettings() {} +}; + +} // namespace system +} // namespace chromeos + +#endif // CHROMEOS_SETTINGS_TIMEZONE_SETTINGS_H_ |