• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "base/utf_string_conversions.h"
8 #include "chrome/app/chrome_command_ids.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/chromeos/login/user_manager.h"
11 #include "chrome/browser/metrics/user_metrics.h"
12 #include "chrome/browser/notifications/notification_delegate.h"
13 #include "chrome/browser/prefs/pref_service.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/common/pref_names.h"
17 #include "content/browser/tab_contents/tab_contents.h"
18 #include "content/common/notification_service.h"
19 #include "content/common/notification_source.h"
20 #include "grit/generated_resources.h"
21 #include "grit/theme_resources.h"
22 #include "ui/base/l10n/l10n_util.h"
23 
24 namespace chromeos {
25 
26 class LocaleChangeGuard::Delegate : public NotificationDelegate {
27  public:
Delegate(chromeos::LocaleChangeGuard * master)28   explicit Delegate(chromeos::LocaleChangeGuard* master) : master_(master) {}
29   void Close(bool by_user);
Display()30   void Display() {}
Error()31   void Error() {}
Click()32   void Click() {}
33   std::string id() const;
34 
35  private:
36   chromeos::LocaleChangeGuard* master_;
37 
38   DISALLOW_COPY_AND_ASSIGN(Delegate);
39 };
40 
LocaleChangeGuard(Profile * profile)41 LocaleChangeGuard::LocaleChangeGuard(Profile* profile)
42     : profile_(profile),
43       note_(NULL),
44       reverted_(false) {
45   DCHECK(profile_);
46   registrar_.Add(this, NotificationType::OWNERSHIP_CHECKED,
47                  NotificationService::AllSources());
48 }
49 
OnLogin()50 void LocaleChangeGuard::OnLogin() {
51   registrar_.Add(this, NotificationType::LOAD_COMPLETED_MAIN_FRAME,
52                  NotificationService::AllSources());
53 }
54 
RevertLocaleChange(const ListValue * list)55 void LocaleChangeGuard::RevertLocaleChange(const ListValue* list) {
56   if (note_ == NULL ||
57       profile_ == NULL ||
58       from_locale_.empty() ||
59       to_locale_.empty()) {
60     NOTREACHED();
61     return;
62   }
63   if (reverted_)
64     return;
65   reverted_ = true;
66   UserMetrics::RecordAction(UserMetricsAction("LanguageChange_Revert"));
67   profile_->ChangeAppLocale(
68       from_locale_, Profile::APP_LOCALE_CHANGED_VIA_REVERT);
69 
70   Browser* browser = Browser::GetTabbedBrowser(profile_, false);
71   if (browser)
72     browser->ExecuteCommand(IDC_EXIT);
73 }
74 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)75 void LocaleChangeGuard::Observe(NotificationType type,
76                                 const NotificationSource& source,
77                                 const NotificationDetails& details) {
78   if (profile_ == NULL) {
79     NOTREACHED();
80     return;
81   }
82   switch (type.value) {
83     case NotificationType::LOAD_COMPLETED_MAIN_FRAME: {
84       // We need to perform locale change check only once, so unsubscribe.
85       registrar_.Remove(this, NotificationType::LOAD_COMPLETED_MAIN_FRAME,
86                         NotificationService::AllSources());
87       Check();
88       break;
89     }
90     case NotificationType::OWNERSHIP_CHECKED: {
91       if (UserManager::Get()->current_user_is_owner()) {
92         PrefService* local_state = g_browser_process->local_state();
93         if (local_state) {
94           PrefService* prefs = profile_->GetPrefs();
95           if (prefs == NULL) {
96             NOTREACHED();
97             return;
98           }
99           std::string owner_locale =
100               prefs->GetString(prefs::kApplicationLocale);
101           if (!owner_locale.empty()) {
102             local_state->SetString(prefs::kOwnerLocale, owner_locale);
103             local_state->ScheduleSavePersistentPrefs();
104           }
105         }
106       }
107       break;
108     }
109     default: {
110       NOTREACHED();
111       break;
112     }
113   }
114 }
115 
Check()116 void LocaleChangeGuard::Check() {
117   if (note_ != NULL) {
118     // Somehow we are invoked more than once. Once is enough.
119     return;
120   }
121 
122   std::string cur_locale = g_browser_process->GetApplicationLocale();
123   if (cur_locale.empty()) {
124     NOTREACHED();
125     return;
126   }
127 
128   PrefService* prefs = profile_->GetPrefs();
129   if (prefs == NULL) {
130     NOTREACHED();
131     return;
132   }
133 
134   std::string to_locale = prefs->GetString(prefs::kApplicationLocale);
135   if (to_locale != cur_locale) {
136     // This conditional branch can occur in cases like:
137     // (1) kApplicationLocale preference was modified by synchronization;
138     // (2) kApplicationLocale is managed by policy.
139     return;
140   }
141 
142   std::string from_locale = prefs->GetString(prefs::kApplicationLocaleBackup);
143   if (from_locale.empty() || from_locale == to_locale)
144     return;  // No locale change was detected, just exit.
145 
146   if (prefs->GetString(prefs::kApplicationLocaleAccepted) == to_locale)
147     return;  // Already accepted.
148 
149   // Locale change detected, showing notification.
150   if (from_locale_ != from_locale || to_locale_ != to_locale) {
151     // Falling back to showing message in current locale.
152     LOG(ERROR) <<
153         "Showing locale change notification in current (not previous) language";
154     PrepareChangingLocale(from_locale, to_locale);
155   }
156   note_.reset(new chromeos::SystemNotification(
157       profile_,
158       new Delegate(this),
159       IDR_NOTIFICATION_LOCALE_CHANGE,
160       title_text_));
161   note_->Show(
162       message_text_, revert_link_text_,
163       NewCallback(this, &LocaleChangeGuard::RevertLocaleChange),
164       true,  // urgent
165       false);  // non-sticky
166 }
167 
AcceptLocaleChange()168 void LocaleChangeGuard::AcceptLocaleChange() {
169   if (note_ == NULL ||
170       profile_ == NULL ||
171       from_locale_.empty() ||
172       to_locale_.empty()) {
173     NOTREACHED();
174     return;
175   }
176 
177   // Check whether locale has been reverted or changed.
178   // If not: mark current locale as accepted.
179   if (reverted_)
180     return;
181   PrefService* prefs = profile_->GetPrefs();
182   if (prefs == NULL) {
183     NOTREACHED();
184     return;
185   }
186   if (prefs->GetString(prefs::kApplicationLocale) != to_locale_)
187     return;
188   UserMetrics::RecordAction(UserMetricsAction("LanguageChange_Accept"));
189   prefs->SetString(prefs::kApplicationLocaleBackup, to_locale_);
190   prefs->SetString(prefs::kApplicationLocaleAccepted, to_locale_);
191   prefs->ScheduleSavePersistentPrefs();
192 }
193 
PrepareChangingLocale(const std::string & from_locale,const std::string & to_locale)194 void LocaleChangeGuard::PrepareChangingLocale(
195     const std::string& from_locale, const std::string& to_locale) {
196   std::string cur_locale = g_browser_process->GetApplicationLocale();
197   if (!from_locale.empty())
198     from_locale_ = from_locale;
199   if (!to_locale.empty())
200     to_locale_ = to_locale;
201 
202   if (!from_locale_.empty() && !to_locale_.empty()) {
203     string16 from = l10n_util::GetDisplayNameForLocale(
204         from_locale_, cur_locale, true);
205     string16 to = l10n_util::GetDisplayNameForLocale(
206         to_locale_, cur_locale, true);
207 
208     title_text_ = l10n_util::GetStringUTF16(
209         IDS_OPTIONS_SETTINGS_SECTION_TITLE_LANGUAGE);
210     message_text_ = l10n_util::GetStringFUTF16(
211         IDS_LOCALE_CHANGE_MESSAGE, from, to);
212     revert_link_text_ = l10n_util::GetStringFUTF16(
213         IDS_LOCALE_CHANGE_REVERT_MESSAGE, from);
214   }
215 }
216 
Close(bool by_user)217 void LocaleChangeGuard::Delegate::Close(bool by_user) {
218   if (by_user)
219     master_->AcceptLocaleChange();
220 }
221 
id() const222 std::string LocaleChangeGuard::Delegate::id() const {
223   // Arbitrary unique Id.
224   return "8c386938-1e3f-11e0-ac7b-18a90520e2e5";
225 }
226 
227 }  // namespace chromeos
228