• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/chromeos/locale_change_guard.h"
6 
7 #include "ash/shell.h"
8 #include "ash/system/tray/system_tray.h"
9 #include "ash/system/tray/system_tray_notifier.h"
10 #include "base/bind.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/app/chrome_command_ids.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/chromeos/settings/device_settings_service.h"
17 #include "chrome/browser/lifetime/application_lifetime.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/ui/browser.h"
20 #include "chrome/browser/ui/browser_commands.h"
21 #include "chrome/browser/ui/host_desktop.h"
22 #include "chrome/common/pref_names.h"
23 #include "content/public/browser/notification_service.h"
24 #include "content/public/browser/notification_source.h"
25 #include "content/public/browser/user_metrics.h"
26 #include "content/public/browser/web_contents.h"
27 #include "grit/generated_resources.h"
28 #include "grit/theme_resources.h"
29 #include "ui/base/l10n/l10n_util.h"
30 
31 using base::UserMetricsAction;
32 using content::WebContents;
33 
34 namespace chromeos {
35 
LocaleChangeGuard(Profile * profile)36 LocaleChangeGuard::LocaleChangeGuard(Profile* profile)
37     : profile_(profile),
38       reverted_(false),
39       session_started_(false),
40       main_frame_loaded_(false) {
41   DCHECK(profile_);
42   registrar_.Add(this, chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
43                  content::NotificationService::AllSources());
44 }
45 
~LocaleChangeGuard()46 LocaleChangeGuard::~LocaleChangeGuard() {}
47 
OnLogin()48 void LocaleChangeGuard::OnLogin() {
49   registrar_.Add(this, chrome::NOTIFICATION_SESSION_STARTED,
50                  content::NotificationService::AllSources());
51   registrar_.Add(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
52                  content::NotificationService::AllBrowserContextsAndSources());
53 }
54 
RevertLocaleChange()55 void LocaleChangeGuard::RevertLocaleChange() {
56   if (profile_ == NULL ||
57       from_locale_.empty() ||
58       to_locale_.empty()) {
59     NOTREACHED();
60     return;
61   }
62   if (reverted_)
63     return;
64   reverted_ = true;
65   content::RecordAction(UserMetricsAction("LanguageChange_Revert"));
66   profile_->ChangeAppLocale(
67       from_locale_, Profile::APP_LOCALE_CHANGED_VIA_REVERT);
68   chrome::AttemptUserExit();
69 }
70 
RevertLocaleChangeCallback(const base::ListValue * list)71 void LocaleChangeGuard::RevertLocaleChangeCallback(
72     const base::ListValue* list) {
73   RevertLocaleChange();
74 }
75 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)76 void LocaleChangeGuard::Observe(int type,
77                                 const content::NotificationSource& source,
78                                 const content::NotificationDetails& details) {
79   if (profile_ == NULL) {
80     NOTREACHED();
81     return;
82   }
83   switch (type) {
84     case chrome::NOTIFICATION_SESSION_STARTED: {
85       session_started_ = true;
86       registrar_.Remove(this, chrome::NOTIFICATION_SESSION_STARTED,
87                         content::NotificationService::AllSources());
88       if (main_frame_loaded_)
89         Check();
90       break;
91     }
92     case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: {
93       if (profile_ ==
94           content::Source<WebContents>(source)->GetBrowserContext()) {
95         main_frame_loaded_ = true;
96         // We need to perform locale change check only once, so unsubscribe.
97         registrar_.Remove(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
98                           content::NotificationService::AllSources());
99         if (session_started_)
100           Check();
101       }
102       break;
103     }
104     case chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED: {
105       if (DeviceSettingsService::Get()->HasPrivateOwnerKey()) {
106         PrefService* local_state = g_browser_process->local_state();
107         if (local_state) {
108           PrefService* prefs = profile_->GetPrefs();
109           if (prefs == NULL) {
110             NOTREACHED();
111             return;
112           }
113           std::string owner_locale =
114               prefs->GetString(prefs::kApplicationLocale);
115           if (!owner_locale.empty())
116             local_state->SetString(prefs::kOwnerLocale, owner_locale);
117         }
118       }
119       break;
120     }
121     default: {
122       NOTREACHED();
123       break;
124     }
125   }
126 }
127 
Check()128 void LocaleChangeGuard::Check() {
129   std::string cur_locale = g_browser_process->GetApplicationLocale();
130   if (cur_locale.empty()) {
131     NOTREACHED();
132     return;
133   }
134 
135   PrefService* prefs = profile_->GetPrefs();
136   if (prefs == NULL) {
137     NOTREACHED();
138     return;
139   }
140 
141   std::string to_locale = prefs->GetString(prefs::kApplicationLocale);
142   if (to_locale != cur_locale) {
143     // This conditional branch can occur in cases like:
144     // (1) kApplicationLocale preference was modified by synchronization;
145     // (2) kApplicationLocale is managed by policy.
146     return;
147   }
148 
149   std::string from_locale = prefs->GetString(prefs::kApplicationLocaleBackup);
150   if (from_locale.empty() || from_locale == to_locale)
151     return;  // No locale change was detected, just exit.
152 
153   if (prefs->GetString(prefs::kApplicationLocaleAccepted) == to_locale)
154     return;  // Already accepted.
155 
156   // Locale change detected, showing notification.
157   if (from_locale_ != from_locale || to_locale_ != to_locale) {
158     // Falling back to showing message in current locale.
159     LOG(ERROR) <<
160         "Showing locale change notification in current (not previous) language";
161     PrepareChangingLocale(from_locale, to_locale);
162   }
163 
164   ash::Shell::GetInstance()->system_tray_notifier()->NotifyLocaleChanged(
165       this, cur_locale, from_locale_, to_locale_);
166 }
167 
AcceptLocaleChange()168 void LocaleChangeGuard::AcceptLocaleChange() {
169   if (profile_ == NULL ||
170       from_locale_.empty() ||
171       to_locale_.empty()) {
172     NOTREACHED();
173     return;
174   }
175 
176   // Check whether locale has been reverted or changed.
177   // If not: mark current locale as accepted.
178   if (reverted_)
179     return;
180   PrefService* prefs = profile_->GetPrefs();
181   if (prefs == NULL) {
182     NOTREACHED();
183     return;
184   }
185   if (prefs->GetString(prefs::kApplicationLocale) != to_locale_)
186     return;
187   content::RecordAction(UserMetricsAction("LanguageChange_Accept"));
188   prefs->SetString(prefs::kApplicationLocaleBackup, to_locale_);
189   prefs->SetString(prefs::kApplicationLocaleAccepted, to_locale_);
190 }
191 
PrepareChangingLocale(const std::string & from_locale,const std::string & to_locale)192 void LocaleChangeGuard::PrepareChangingLocale(
193     const std::string& from_locale, const std::string& to_locale) {
194   std::string cur_locale = g_browser_process->GetApplicationLocale();
195   if (!from_locale.empty())
196     from_locale_ = from_locale;
197   if (!to_locale.empty())
198     to_locale_ = to_locale;
199 
200   if (!from_locale_.empty() && !to_locale_.empty()) {
201     base::string16 from = l10n_util::GetDisplayNameForLocale(
202         from_locale_, cur_locale, true);
203     base::string16 to = l10n_util::GetDisplayNameForLocale(
204         to_locale_, cur_locale, true);
205 
206     title_text_ = l10n_util::GetStringUTF16(
207         IDS_OPTIONS_SETTINGS_SECTION_TITLE_LANGUAGE);
208     message_text_ = l10n_util::GetStringFUTF16(
209         IDS_LOCALE_CHANGE_MESSAGE, from, to);
210     revert_link_text_ = l10n_util::GetStringFUTF16(
211         IDS_LOCALE_CHANGE_REVERT_MESSAGE, from);
212   }
213 }
214 
215 }  // namespace chromeos
216