root/chrome/browser/chromeos/locale_change_guard.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. main_frame_loaded_
  2. OnLogin
  3. RevertLocaleChange
  4. RevertLocaleChangeCallback
  5. Observe
  6. Check
  7. AcceptLocaleChange
  8. PrepareChangingLocale

// Copyright (c) 2012 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 "ash/shell.h"
#include "ash/system/tray/system_tray.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "base/bind.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"

using base::UserMetricsAction;
using content::WebContents;

namespace chromeos {

LocaleChangeGuard::LocaleChangeGuard(Profile* profile)
    : profile_(profile),
      reverted_(false),
      session_started_(false),
      main_frame_loaded_(false) {
  DCHECK(profile_);
  registrar_.Add(this, chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
                 content::NotificationService::AllSources());
}

LocaleChangeGuard::~LocaleChangeGuard() {}

void LocaleChangeGuard::OnLogin() {
  registrar_.Add(this, chrome::NOTIFICATION_SESSION_STARTED,
                 content::NotificationService::AllSources());
  registrar_.Add(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
                 content::NotificationService::AllBrowserContextsAndSources());
}

void LocaleChangeGuard::RevertLocaleChange() {
  if (profile_ == NULL ||
      from_locale_.empty() ||
      to_locale_.empty()) {
    NOTREACHED();
    return;
  }
  if (reverted_)
    return;
  reverted_ = true;
  content::RecordAction(UserMetricsAction("LanguageChange_Revert"));
  profile_->ChangeAppLocale(
      from_locale_, Profile::APP_LOCALE_CHANGED_VIA_REVERT);
  chrome::AttemptUserExit();
}

void LocaleChangeGuard::RevertLocaleChangeCallback(
    const base::ListValue* list) {
  RevertLocaleChange();
}

void LocaleChangeGuard::Observe(int type,
                                const content::NotificationSource& source,
                                const content::NotificationDetails& details) {
  if (profile_ == NULL) {
    NOTREACHED();
    return;
  }
  switch (type) {
    case chrome::NOTIFICATION_SESSION_STARTED: {
      session_started_ = true;
      registrar_.Remove(this, chrome::NOTIFICATION_SESSION_STARTED,
                        content::NotificationService::AllSources());
      if (main_frame_loaded_)
        Check();
      break;
    }
    case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: {
      if (profile_ ==
          content::Source<WebContents>(source)->GetBrowserContext()) {
        main_frame_loaded_ = true;
        // We need to perform locale change check only once, so unsubscribe.
        registrar_.Remove(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
                          content::NotificationService::AllSources());
        if (session_started_)
          Check();
      }
      break;
    }
    case chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED: {
      if (DeviceSettingsService::Get()->HasPrivateOwnerKey()) {
        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);
        }
      }
      break;
    }
    default: {
      NOTREACHED();
      break;
    }
  }
}

void LocaleChangeGuard::Check() {
  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);
  }

  ash::Shell::GetInstance()->system_tray_notifier()->NotifyLocaleChanged(
      this, cur_locale, from_locale_, to_locale_);
}

void LocaleChangeGuard::AcceptLocaleChange() {
  if (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;
  content::RecordAction(UserMetricsAction("LanguageChange_Accept"));
  prefs->SetString(prefs::kApplicationLocaleBackup, to_locale_);
  prefs->SetString(prefs::kApplicationLocaleAccepted, to_locale_);
}

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()) {
    base::string16 from = l10n_util::GetDisplayNameForLocale(
        from_locale_, cur_locale, true);
    base::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);
  }
}

}  // namespace chromeos

/* [<][>][^][v][top][bottom][index][help] */