| // Copyright (c) 2011 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 "chrome/browser/chromeos/locale_change_guard.h" |
| |
| #include "base/utf_string_conversions.h" |
| #include "chrome/app/chrome_command_ids.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/chromeos/login/user_manager.h" |
| #include "chrome/browser/metrics/user_metrics.h" |
| #include "chrome/browser/notifications/notification_delegate.h" |
| #include "chrome/browser/prefs/pref_service.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/common/pref_names.h" |
| #include "content/browser/tab_contents/tab_contents.h" |
| #include "content/common/notification_service.h" |
| #include "content/common/notification_source.h" |
| #include "grit/generated_resources.h" |
| #include "grit/theme_resources.h" |
| #include "ui/base/l10n/l10n_util.h" |
| |
| namespace chromeos { |
| |
| class LocaleChangeGuard::Delegate : public NotificationDelegate { |
| public: |
| explicit Delegate(chromeos::LocaleChangeGuard* master) : master_(master) {} |
| void Close(bool by_user); |
| void Display() {} |
| void Error() {} |
| void Click() {} |
| std::string id() const; |
| |
| private: |
| chromeos::LocaleChangeGuard* master_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Delegate); |
| }; |
| |
| LocaleChangeGuard::LocaleChangeGuard(Profile* profile) |
| : profile_(profile), |
| note_(NULL), |
| reverted_(false) { |
| DCHECK(profile_); |
| registrar_.Add(this, NotificationType::OWNERSHIP_CHECKED, |
| NotificationService::AllSources()); |
| } |
| |
| void LocaleChangeGuard::OnLogin() { |
| registrar_.Add(this, NotificationType::LOAD_COMPLETED_MAIN_FRAME, |
| NotificationService::AllSources()); |
| } |
| |
| void LocaleChangeGuard::RevertLocaleChange(const ListValue* list) { |
| if (note_ == NULL || |
| profile_ == NULL || |
| from_locale_.empty() || |
| to_locale_.empty()) { |
| NOTREACHED(); |
| return; |
| } |
| if (reverted_) |
| return; |
| reverted_ = true; |
| UserMetrics::RecordAction(UserMetricsAction("LanguageChange_Revert")); |
| profile_->ChangeAppLocale( |
| from_locale_, Profile::APP_LOCALE_CHANGED_VIA_REVERT); |
| |
| Browser* browser = Browser::GetTabbedBrowser(profile_, false); |
| if (browser) |
| browser->ExecuteCommand(IDC_EXIT); |
| } |
| |
| void LocaleChangeGuard::Observe(NotificationType type, |
| const NotificationSource& source, |
| const NotificationDetails& details) { |
| if (profile_ == NULL) { |
| NOTREACHED(); |
| return; |
| } |
| switch (type.value) { |
| case NotificationType::LOAD_COMPLETED_MAIN_FRAME: { |
| // We need to perform locale change check only once, so unsubscribe. |
| registrar_.Remove(this, NotificationType::LOAD_COMPLETED_MAIN_FRAME, |
| NotificationService::AllSources()); |
| Check(); |
| break; |
| } |
| case NotificationType::OWNERSHIP_CHECKED: { |
| if (UserManager::Get()->current_user_is_owner()) { |
| PrefService* local_state = g_browser_process->local_state(); |
| if (local_state) { |
| PrefService* prefs = profile_->GetPrefs(); |
| if (prefs == NULL) { |
| NOTREACHED(); |
| return; |
| } |
| std::string owner_locale = |
| prefs->GetString(prefs::kApplicationLocale); |
| if (!owner_locale.empty()) { |
| local_state->SetString(prefs::kOwnerLocale, owner_locale); |
| local_state->ScheduleSavePersistentPrefs(); |
| } |
| } |
| } |
| break; |
| } |
| default: { |
| NOTREACHED(); |
| break; |
| } |
| } |
| } |
| |
| void LocaleChangeGuard::Check() { |
| if (note_ != NULL) { |
| // Somehow we are invoked more than once. Once is enough. |
| return; |
| } |
| |
| std::string cur_locale = g_browser_process->GetApplicationLocale(); |
| if (cur_locale.empty()) { |
| NOTREACHED(); |
| return; |
| } |
| |
| PrefService* prefs = profile_->GetPrefs(); |
| if (prefs == NULL) { |
| NOTREACHED(); |
| return; |
| } |
| |
| std::string to_locale = prefs->GetString(prefs::kApplicationLocale); |
| if (to_locale != cur_locale) { |
| // This conditional branch can occur in cases like: |
| // (1) kApplicationLocale preference was modified by synchronization; |
| // (2) kApplicationLocale is managed by policy. |
| return; |
| } |
| |
| std::string from_locale = prefs->GetString(prefs::kApplicationLocaleBackup); |
| if (from_locale.empty() || from_locale == to_locale) |
| return; // No locale change was detected, just exit. |
| |
| if (prefs->GetString(prefs::kApplicationLocaleAccepted) == to_locale) |
| return; // Already accepted. |
| |
| // Locale change detected, showing notification. |
| if (from_locale_ != from_locale || to_locale_ != to_locale) { |
| // Falling back to showing message in current locale. |
| LOG(ERROR) << |
| "Showing locale change notification in current (not previous) language"; |
| PrepareChangingLocale(from_locale, to_locale); |
| } |
| note_.reset(new chromeos::SystemNotification( |
| profile_, |
| new Delegate(this), |
| IDR_NOTIFICATION_LOCALE_CHANGE, |
| title_text_)); |
| note_->Show( |
| message_text_, revert_link_text_, |
| NewCallback(this, &LocaleChangeGuard::RevertLocaleChange), |
| true, // urgent |
| false); // non-sticky |
| } |
| |
| void LocaleChangeGuard::AcceptLocaleChange() { |
| if (note_ == NULL || |
| profile_ == NULL || |
| from_locale_.empty() || |
| to_locale_.empty()) { |
| NOTREACHED(); |
| return; |
| } |
| |
| // Check whether locale has been reverted or changed. |
| // If not: mark current locale as accepted. |
| if (reverted_) |
| return; |
| PrefService* prefs = profile_->GetPrefs(); |
| if (prefs == NULL) { |
| NOTREACHED(); |
| return; |
| } |
| if (prefs->GetString(prefs::kApplicationLocale) != to_locale_) |
| return; |
| UserMetrics::RecordAction(UserMetricsAction("LanguageChange_Accept")); |
| prefs->SetString(prefs::kApplicationLocaleBackup, to_locale_); |
| prefs->SetString(prefs::kApplicationLocaleAccepted, to_locale_); |
| prefs->ScheduleSavePersistentPrefs(); |
| } |
| |
| void LocaleChangeGuard::PrepareChangingLocale( |
| const std::string& from_locale, const std::string& to_locale) { |
| std::string cur_locale = g_browser_process->GetApplicationLocale(); |
| if (!from_locale.empty()) |
| from_locale_ = from_locale; |
| if (!to_locale.empty()) |
| to_locale_ = to_locale; |
| |
| if (!from_locale_.empty() && !to_locale_.empty()) { |
| string16 from = l10n_util::GetDisplayNameForLocale( |
| from_locale_, cur_locale, true); |
| string16 to = l10n_util::GetDisplayNameForLocale( |
| to_locale_, cur_locale, true); |
| |
| title_text_ = l10n_util::GetStringUTF16( |
| IDS_OPTIONS_SETTINGS_SECTION_TITLE_LANGUAGE); |
| message_text_ = l10n_util::GetStringFUTF16( |
| IDS_LOCALE_CHANGE_MESSAGE, from, to); |
| revert_link_text_ = l10n_util::GetStringFUTF16( |
| IDS_LOCALE_CHANGE_REVERT_MESSAGE, from); |
| } |
| } |
| |
| void LocaleChangeGuard::Delegate::Close(bool by_user) { |
| if (by_user) |
| master_->AcceptLocaleChange(); |
| } |
| |
| std::string LocaleChangeGuard::Delegate::id() const { |
| // Arbitrary unique Id. |
| return "8c386938-1e3f-11e0-ac7b-18a90520e2e5"; |
| } |
| |
| } // namespace chromeos |