Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / chromeos / locale_change_guard.cc
blob14f61d3d4e2838eab385639b7320f64b32e5ae9b
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.
5 #include "chrome/browser/chromeos/locale_change_guard.h"
7 #include <algorithm>
9 #include "ash/shell.h"
10 #include "ash/system/tray/system_tray.h"
11 #include "ash/system/tray/system_tray_notifier.h"
12 #include "base/bind.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/app/chrome_command_ids.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/chromeos/settings/device_settings_service.h"
19 #include "chrome/browser/lifetime/application_lifetime.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_commands.h"
23 #include "chrome/browser/ui/host_desktop.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/grit/generated_resources.h"
26 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/notification_source.h"
28 #include "content/public/browser/user_metrics.h"
29 #include "content/public/browser/web_contents.h"
30 #include "ui/base/l10n/l10n_util.h"
32 using base::UserMetricsAction;
33 using content::WebContents;
35 namespace chromeos {
37 namespace {
39 // This is the list of languages that do not require user notification when
40 // locale is switched automatically between regions within the same language.
42 // New language in kAcceptLanguageList should be added either here or to
43 // to the exception list in unit test.
44 const char* const kSkipShowNotificationLanguages[4] = {"en", "de", "fr", "it"};
46 } // anonymous namespace
48 LocaleChangeGuard::LocaleChangeGuard(Profile* profile)
49 : profile_(profile),
50 reverted_(false),
51 session_started_(false),
52 main_frame_loaded_(false) {
53 DCHECK(profile_);
54 registrar_.Add(this, chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
55 content::NotificationService::AllSources());
58 LocaleChangeGuard::~LocaleChangeGuard() {}
60 void LocaleChangeGuard::OnLogin() {
61 registrar_.Add(this, chrome::NOTIFICATION_SESSION_STARTED,
62 content::NotificationService::AllSources());
63 registrar_.Add(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
64 content::NotificationService::AllBrowserContextsAndSources());
67 void LocaleChangeGuard::RevertLocaleChange() {
68 if (profile_ == NULL ||
69 from_locale_.empty() ||
70 to_locale_.empty()) {
71 NOTREACHED();
72 return;
74 if (reverted_)
75 return;
76 reverted_ = true;
77 content::RecordAction(UserMetricsAction("LanguageChange_Revert"));
78 profile_->ChangeAppLocale(
79 from_locale_, Profile::APP_LOCALE_CHANGED_VIA_REVERT);
80 chrome::AttemptUserExit();
83 void LocaleChangeGuard::RevertLocaleChangeCallback(
84 const base::ListValue* list) {
85 RevertLocaleChange();
88 void LocaleChangeGuard::Observe(int type,
89 const content::NotificationSource& source,
90 const content::NotificationDetails& details) {
91 if (profile_ == NULL) {
92 NOTREACHED();
93 return;
95 switch (type) {
96 case chrome::NOTIFICATION_SESSION_STARTED: {
97 session_started_ = true;
98 registrar_.Remove(this, chrome::NOTIFICATION_SESSION_STARTED,
99 content::NotificationService::AllSources());
100 if (main_frame_loaded_)
101 Check();
102 break;
104 case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: {
105 if (profile_ ==
106 content::Source<WebContents>(source)->GetBrowserContext()) {
107 main_frame_loaded_ = true;
108 // We need to perform locale change check only once, so unsubscribe.
109 registrar_.Remove(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
110 content::NotificationService::AllSources());
111 if (session_started_)
112 Check();
114 break;
116 case chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED: {
117 if (DeviceSettingsService::Get()->HasPrivateOwnerKey()) {
118 PrefService* local_state = g_browser_process->local_state();
119 if (local_state) {
120 PrefService* prefs = profile_->GetPrefs();
121 if (prefs == NULL) {
122 NOTREACHED();
123 return;
125 std::string owner_locale =
126 prefs->GetString(prefs::kApplicationLocale);
127 if (!owner_locale.empty())
128 local_state->SetString(prefs::kOwnerLocale, owner_locale);
131 break;
133 default: {
134 NOTREACHED();
135 break;
140 void LocaleChangeGuard::Check() {
141 std::string cur_locale = g_browser_process->GetApplicationLocale();
142 if (cur_locale.empty()) {
143 NOTREACHED();
144 return;
147 PrefService* prefs = profile_->GetPrefs();
148 if (prefs == NULL) {
149 NOTREACHED();
150 return;
153 std::string to_locale = prefs->GetString(prefs::kApplicationLocale);
154 if (to_locale != cur_locale) {
155 // This conditional branch can occur in cases like:
156 // (1) kApplicationLocale preference was modified by synchronization;
157 // (2) kApplicationLocale is managed by policy.
158 return;
161 std::string from_locale = prefs->GetString(prefs::kApplicationLocaleBackup);
162 if (from_locale.empty() || from_locale == to_locale)
163 return; // No locale change was detected, just exit.
165 if (prefs->GetString(prefs::kApplicationLocaleAccepted) == to_locale)
166 return; // Already accepted.
168 // Locale change detected.
169 if (!ShouldShowLocaleChangeNotification(from_locale, to_locale))
170 return;
172 // Showing notification.
173 if (from_locale_ != from_locale || to_locale_ != to_locale) {
174 // Falling back to showing message in current locale.
175 LOG(ERROR) <<
176 "Showing locale change notification in current (not previous) language";
177 PrepareChangingLocale(from_locale, to_locale);
180 ash::Shell::GetInstance()->system_tray_notifier()->NotifyLocaleChanged(
181 this, cur_locale, from_locale_, to_locale_);
184 void LocaleChangeGuard::AcceptLocaleChange() {
185 if (profile_ == NULL ||
186 from_locale_.empty() ||
187 to_locale_.empty()) {
188 NOTREACHED();
189 return;
192 // Check whether locale has been reverted or changed.
193 // If not: mark current locale as accepted.
194 if (reverted_)
195 return;
196 PrefService* prefs = profile_->GetPrefs();
197 if (prefs == NULL) {
198 NOTREACHED();
199 return;
201 if (prefs->GetString(prefs::kApplicationLocale) != to_locale_)
202 return;
203 content::RecordAction(UserMetricsAction("LanguageChange_Accept"));
204 prefs->SetString(prefs::kApplicationLocaleBackup, to_locale_);
205 prefs->SetString(prefs::kApplicationLocaleAccepted, to_locale_);
208 void LocaleChangeGuard::PrepareChangingLocale(
209 const std::string& from_locale, const std::string& to_locale) {
210 std::string cur_locale = g_browser_process->GetApplicationLocale();
211 if (!from_locale.empty())
212 from_locale_ = from_locale;
213 if (!to_locale.empty())
214 to_locale_ = to_locale;
216 if (!from_locale_.empty() && !to_locale_.empty()) {
217 base::string16 from = l10n_util::GetDisplayNameForLocale(
218 from_locale_, cur_locale, true);
219 base::string16 to = l10n_util::GetDisplayNameForLocale(
220 to_locale_, cur_locale, true);
222 title_text_ = l10n_util::GetStringUTF16(
223 IDS_OPTIONS_SETTINGS_SECTION_TITLE_LANGUAGE);
224 message_text_ = l10n_util::GetStringFUTF16(
225 IDS_LOCALE_CHANGE_MESSAGE, from, to);
226 revert_link_text_ = l10n_util::GetStringFUTF16(
227 IDS_LOCALE_CHANGE_REVERT_MESSAGE, from);
231 // static
232 bool LocaleChangeGuard::ShouldShowLocaleChangeNotification(
233 const std::string& from_locale,
234 const std::string& to_locale) {
235 const std::string from_lang = l10n_util::GetLanguage(from_locale);
236 const std::string to_lang = l10n_util::GetLanguage(to_locale);
238 if (from_locale == to_locale)
239 return false;
241 if (from_lang != to_lang)
242 return true;
244 const char* const* begin = kSkipShowNotificationLanguages;
245 const char* const* end = kSkipShowNotificationLanguages +
246 arraysize(kSkipShowNotificationLanguages);
248 return std::find(begin, end, from_lang) == end;
251 // static
252 const char* const*
253 LocaleChangeGuard::GetSkipShowNotificationLanguagesForTesting() {
254 return kSkipShowNotificationLanguages;
257 // static
258 size_t LocaleChangeGuard::GetSkipShowNotificationLanguagesSizeForTesting() {
259 return arraysize(kSkipShowNotificationLanguages);
262 } // namespace chromeos