Home | History | Annotate | Download | only in chromeos
      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 
     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 
     46 LocaleChangeGuard::~LocaleChangeGuard() {}
     47 
     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 
     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 
     71 void LocaleChangeGuard::RevertLocaleChangeCallback(
     72     const base::ListValue* list) {
     73   RevertLocaleChange();
     74 }
     75 
     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 
    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 
    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 
    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