Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/ui/webui/options2/chromeos/timezone_options_util.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/i18n/rtl.h" | |
| 10 #include "base/lazy_instance.h" | |
| 11 #include "base/string_util.h" | |
| 12 #include "base/stringprintf.h" | |
| 13 #include "base/synchronization/lock.h" | |
| 14 #include "base/utf_string_conversions.h" | |
| 15 #include "base/values.h" | |
| 16 #include "chrome/browser/chromeos/system/timezone_settings.h" | |
| 17 #include "grit/generated_resources.h" | |
| 18 #include "ui/base/l10n/l10n_util.h" | |
| 19 #include "unicode/calendar.h" | |
| 20 #include "unicode/timezone.h" | |
| 21 #include "unicode/ures.h" | |
| 22 #include "unicode/utypes.h" | |
| 23 | |
| 24 namespace { | |
| 25 | |
| 26 struct UResClose { | |
| 27 inline void operator() (UResourceBundle* b) const { | |
| 28 ures_close(b); | |
| 29 } | |
| 30 }; | |
| 31 | |
| 32 static base::LazyInstance<base::Lock>::Leaky | |
| 33 g_timezone_bundle_lock = LAZY_INSTANCE_INITIALIZER; | |
| 34 | |
| 35 string16 GetExemplarCity(const icu::TimeZone& zone) { | |
|
James Hawkins
2012/07/17 14:10:46
nit: Document method and param.
pneubeck2
2012/07/18 12:08:54
Done.
| |
| 36 // TODO(jungshik): After upgrading to ICU 4.6, use U_ICUDATA_ZONE | |
| 37 static const char* zone_bundle_name = NULL; | |
| 38 | |
| 39 // These will be leaked at the end. | |
| 40 static UResourceBundle *zone_bundle = NULL; | |
| 41 static UResourceBundle *zone_strings = NULL; | |
| 42 | |
| 43 UErrorCode status = U_ZERO_ERROR; | |
| 44 { | |
| 45 base::AutoLock lock(g_timezone_bundle_lock.Get()); | |
| 46 if (zone_bundle == NULL) | |
| 47 zone_bundle = ures_open(zone_bundle_name, uloc_getDefault(), &status); | |
| 48 | |
| 49 if (zone_strings == NULL) | |
| 50 zone_strings = ures_getByKey(zone_bundle, "zone_strings", NULL, &status); | |
| 51 } | |
| 52 | |
| 53 icu::UnicodeString zone_id; | |
| 54 zone.getID(zone_id); | |
| 55 std::string zone_id_str; | |
| 56 zone_id.toUTF8String(zone_id_str); | |
| 57 | |
| 58 // Resource keys for timezones use ':' in place of '/'. | |
| 59 ReplaceSubstringsAfterOffset(&zone_id_str, 0, "/", ":"); | |
| 60 scoped_ptr_malloc<UResourceBundle, UResClose> zone_item( | |
| 61 ures_getByKey(zone_strings, zone_id_str.c_str(), NULL, &status)); | |
| 62 icu::UnicodeString city; | |
| 63 if (!U_FAILURE(status)) { | |
| 64 city = icu::ures_getUnicodeStringByKey(zone_item.get(), "ec", &status); | |
| 65 if (U_SUCCESS(status)) | |
| 66 return string16(city.getBuffer(), city.length()); | |
| 67 } | |
| 68 | |
| 69 // Fallback case in case of failure. | |
| 70 ReplaceSubstringsAfterOffset(&zone_id_str, 0, ":", "/"); | |
| 71 // Take the last component of a timezone id (e.g. 'Baz' in 'Foo/Bar/Baz'). | |
| 72 // Depending on timezones, keeping all but the 1st component | |
| 73 // (e.g. Bar/Baz) may be better, but our current list does not have | |
| 74 // any timezone for which that's the case. | |
| 75 std::string::size_type slash_pos = zone_id_str.rfind('/'); | |
| 76 if (slash_pos != std::string::npos && slash_pos < zone_id_str.size()) | |
| 77 zone_id_str.erase(0, slash_pos + 1); | |
| 78 // zone id has '_' in place of ' '. | |
| 79 ReplaceSubstringsAfterOffset(&zone_id_str, 0, "_", " "); | |
| 80 return ASCIIToUTF16(zone_id_str); | |
| 81 } | |
| 82 | |
| 83 // Gets the given timezone's name for visualization. | |
| 84 string16 GetTimezoneName(const icu::TimeZone& timezone) { | |
| 85 // Instead of using the raw_offset, use the offset in effect now. | |
| 86 // For instance, US Pacific Time, the offset shown will be -7 in summer | |
| 87 // while it'll be -8 in winter. | |
| 88 int raw_offset, dst_offset; | |
| 89 UDate now = icu::Calendar::getNow(); | |
| 90 UErrorCode status = U_ZERO_ERROR; | |
| 91 timezone.getOffset(now, false, raw_offset, dst_offset, status); | |
| 92 DCHECK(U_SUCCESS(status)); | |
| 93 int offset = raw_offset + dst_offset; | |
| 94 // |offset| is in msec. | |
| 95 int minute_offset = std::abs(offset) / 60000; | |
| 96 int hour_offset = minute_offset / 60; | |
| 97 int min_remainder = minute_offset % 60; | |
| 98 // Some timezones have a non-integral hour offset. So, we need to use hh:mm | |
| 99 // form. | |
| 100 std::string offset_str = base::StringPrintf(offset >= 0 ? | |
| 101 "UTC+%d:%02d" : "UTC-%d:%02d", hour_offset, min_remainder); | |
| 102 | |
| 103 // TODO(jungshik): When coming up with a better list of timezones, we also | |
| 104 // have to come up with better 'display' names. One possibility is to list | |
| 105 // multiple cities (e.g. "Los Angeles, Vancouver .." in the order of | |
| 106 // the population of a country the city belongs to.). | |
| 107 // We can also think of using LONG_GENERIC or LOCATION once we upgrade | |
| 108 // to ICU 4.6. | |
| 109 // In the meantime, we use "LONG" name with "Exemplar City" to distinguish | |
| 110 // multiple timezones with the same "LONG" name but with different | |
| 111 // rules (e.g. US Mountain Time in Denver vs Phoenix). | |
| 112 icu::UnicodeString name; | |
| 113 timezone.getDisplayName(dst_offset != 0, icu::TimeZone::LONG, name); | |
| 114 string16 result(l10n_util::GetStringFUTF16( | |
| 115 IDS_OPTIONS_SETTINGS_TIMEZONE_DISPLAY_TEMPLATE, ASCIIToUTF16(offset_str), | |
| 116 string16(name.getBuffer(), name.length()), GetExemplarCity(timezone))); | |
| 117 base::i18n::AdjustStringForLocaleDirection(&result); | |
| 118 return result; | |
| 119 } | |
| 120 | |
| 121 } // namespace | |
| 122 | |
| 123 namespace options2 { | |
| 124 | |
| 125 // Creates a list of pairs of each timezone's ID and name. | |
| 126 scoped_ptr<base::ListValue> GetTimezoneList() { | |
| 127 const std::vector<icu::TimeZone*> &timezones = | |
| 128 chromeos::system::TimezoneSettings::GetInstance()->GetTimezoneList(); | |
| 129 scoped_ptr<base::ListValue> timezoneList(new base::ListValue()); | |
| 130 for (std::vector<icu::TimeZone*>::const_iterator iter = timezones.begin(); | |
| 131 iter != timezones.end(); ++iter) { | |
| 132 const icu::TimeZone* timezone = *iter; | |
| 133 base::ListValue* option = new base::ListValue(); | |
| 134 option->Append(Value::CreateStringValue( | |
| 135 chromeos::system::TimezoneSettings::GetTimezoneID(*timezone))); | |
| 136 option->Append(Value::CreateStringValue(GetTimezoneName(*timezone))); | |
| 137 timezoneList->Append(option); | |
| 138 } | |
| 139 return timezoneList.Pass(); | |
| 140 } | |
| 141 | |
| 142 } // namespace options2 | |
| OLD | NEW |