<commit_before>// 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/login/base_login_display_host.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/input_method_library.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/customization_document.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/chromeos/login/existing_user_controller.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/views_login_display_host.h"
#include "chrome/browser/chromeos/login/webui_login_display_host.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/system_access.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/common/pref_names.h"
#include "content/common/notification_service.h"
#include "content/common/notification_type.h"
#include "googleurl/src/gurl.h"
#include "third_party/cros/chromeos_wm_ipc_enums.h"
#include "ui/base/resource/resource_bundle.h"
#include "unicode/timezone.h"

// TODO(altimofeev): move to ViewsLoginDisplayHost
#include "chrome/browser/chromeos/login/views_oobe_display.h"


namespace {

// The delay of triggering initialization of the device policy subsystem
// after the login screen is initialized. This makes sure that device policy
// network requests are made while the system is idle waiting for user input.
const int64 kPolicyServiceInitializationDelayMilliseconds = 100;

// Determines the hardware keyboard from the given locale code
// and the OEM layout information, and saves it to "Locale State".
// The information will be used in input_method::GetHardwareInputMethodId().
void DetermineAndSaveHardwareKeyboard(const std::string& locale,
                                      const std::string& oem_layout) {
  std::string layout;
  if (!oem_layout.empty()) {
    // If the OEM layout information is provided, use it.
    layout = oem_layout;
  } else {
    // Otherwise, determine the hardware keyboard from the locale.
    std::vector<std::string> input_method_ids;
    if (chromeos::input_method::GetInputMethodIdsFromLanguageCode(
            locale,
            chromeos::input_method::kKeyboardLayoutsOnly,
            &input_method_ids)) {
      // The output list |input_method_ids| is sorted by popularity, hence
      // input_method_ids[0] now contains the most popular keyboard layout
      // for the given locale.
      layout = input_method_ids[0];
    }
  }

  if (!layout.empty()) {
    PrefService* prefs = g_browser_process->local_state();
    prefs->SetString(prefs::kHardwareKeyboardLayout, layout);
    // This asks the file thread to save the prefs (i.e. doesn't block).
    // The latest values of Local State reside in memory so we can safely
    // get the value of kHardwareKeyboardLayout even if the data is not
    // yet saved to disk.
    prefs->SavePersistentPrefs();
  }
}

}  // namespace

namespace chromeos {

// static
LoginDisplayHost* BaseLoginDisplayHost::default_host_ = NULL;

// BaseLoginDisplayHost --------------------------------------------------------

BaseLoginDisplayHost::BaseLoginDisplayHost(const gfx::Rect& background_bounds)
    : background_bounds_(background_bounds) {
  // We need to listen to APP_EXITING but not APP_TERMINATING because
  // APP_TERMINATING will never be fired as long as this keeps ref-count.
  // APP_EXITING is safe here because there will be no browser instance that
  // will block the shutdown.
  registrar_.Add(
      this,
      NotificationType::APP_EXITING,
      NotificationService::AllSources());
  DCHECK(default_host_ == NULL);
  default_host_ = this;

  // Add a reference count so the message loop won't exit when other
  // message loop clients (e.g. menus) do.
  g_browser_process->AddRefModule();
}

BaseLoginDisplayHost::~BaseLoginDisplayHost() {
  // A browser should already exist when destructor is called since
  // deletion is scheduled with MessageLoop::DeleteSoon() from
  // OnSessionStart(), so the browser will already have incremented
  // the reference count.
  g_browser_process->ReleaseModule();

  default_host_ = NULL;
}

// LoginDisplayHost implementation ---------------------------------------------

void BaseLoginDisplayHost::OnSessionStart() {
  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}

WizardController* BaseLoginDisplayHost::CreateWizardController() {
  // TODO(altimofeev): move this code to ViewsLoginDisplayHost when WebUI
  // implementation will always be used with WebUILoginDisplayHost.
  oobe_display_.reset(new ViewsOobeDisplay(background_bounds()));
  WizardController* wizard_controller  =
      new WizardController(this, oobe_display_.get());
  oobe_display_->SetScreenObserver(wizard_controller);
  return wizard_controller;
}

void BaseLoginDisplayHost::StartWizard(
    const std::string& first_screen_name,
    const GURL& start_url) {
  DVLOG(1) << "Starting wizard, first_screen_name: " << first_screen_name;
  // Create and show the wizard.
  // Note, dtor of the old WizardController should be called before ctor of the
  // new one, because "default_controller()" is updated there. So pure "reset()"
  // is done before new controller creation.
  wizard_controller_.reset();

  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAllowWebUIOobe)) {
    wizard_controller_.reset(CreateWizardController());
  } else {
    // Force views based implementation.
    wizard_controller_.reset(BaseLoginDisplayHost::CreateWizardController());
  }

  wizard_controller_->set_start_url(start_url);
  ShowBackground();
  if (!WizardController::IsDeviceRegistered())
    SetOobeProgressBarVisible(true);
  wizard_controller_->Init(first_screen_name);
}

void BaseLoginDisplayHost::StartSignInScreen() {
  oobe_display_.reset();

  DVLOG(1) << "Starting sign in screen";
  std::vector<chromeos::UserManager::User> users =
      chromeos::UserManager::Get()->GetUsers();

  // Fix for users who updated device and thus never passed register screen.
  // If we already have users, we assume that it is not a second part of
  // OOBE. See http://crosbug.com/6289
  if (!WizardController::IsDeviceRegistered() && !users.empty()) {
    VLOG(1) << "Mark device registered because there are remembered users: "
            << users.size();
    WizardController::MarkDeviceRegistered();
  }

  sign_in_controller_.reset();  // Only one controller in a time.
  sign_in_controller_.reset(new chromeos::ExistingUserController(this));
  ShowBackground();
  if (!WizardController::IsDeviceRegistered()) {
    SetOobeProgressBarVisible(true);
    SetOobeProgress(chromeos::BackgroundView::SIGNIN);
  }
  SetShutdownButtonEnabled(true);
  sign_in_controller_->Init(users);

  // Initiate services customization manifest fetching.
  ServicesCustomizationDocument::GetInstance()->StartFetching();

  // Initiate device policy fetching.
  g_browser_process->browser_policy_connector()->
      ScheduleServiceInitialization(
          kPolicyServiceInitializationDelayMilliseconds);
}

// BaseLoginDisplayHost --------------------------------------------------------

void BaseLoginDisplayHost::Observe(NotificationType type,
                                   const NotificationSource& source,
                                   const NotificationDetails& details) {
  CHECK(type == NotificationType::APP_EXITING);

  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
  MessageLoop::current()->Quit();
  registrar_.Remove(this,
                    NotificationType::APP_EXITING,
                    NotificationService::AllSources());
}

}  // namespace chromeos

// browser::ShowLoginWizard implementation -------------------------------------

namespace browser {

// Declared in browser_dialogs.h so that others don't need to depend on our .h.
// TODO(nkostylev): Split this into a smaller functions.
void ShowLoginWizard(const std::string& first_screen_name,
                     const gfx::Size& size) {<commit_msg>Reset notification registrar before posting delete task  This is a possible race and we may delete the object twice if signal is sent before login handler object gets deleted after login.  hypothetical fix for 16652<commit_after>// 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/login/base_login_display_host.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/input_method_library.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/customization_document.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/chromeos/login/existing_user_controller.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/views_login_display_host.h"
#include "chrome/browser/chromeos/login/webui_login_display_host.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/system_access.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/common/pref_names.h"
#include "content/common/notification_service.h"
#include "content/common/notification_type.h"
#include "googleurl/src/gurl.h"
#include "third_party/cros/chromeos_wm_ipc_enums.h"
#include "ui/base/resource/resource_bundle.h"
#include "unicode/timezone.h"

// TODO(altimofeev): move to ViewsLoginDisplayHost
#include "chrome/browser/chromeos/login/views_oobe_display.h"


namespace {

// The delay of triggering initialization of the device policy subsystem
// after the login screen is initialized. This makes sure that device policy
// network requests are made while the system is idle waiting for user input.
const int64 kPolicyServiceInitializationDelayMilliseconds = 100;

// Determines the hardware keyboard from the given locale code
// and the OEM layout information, and saves it to "Locale State".
// The information will be used in input_method::GetHardwareInputMethodId().
void DetermineAndSaveHardwareKeyboard(const std::string& locale,
                                      const std::string& oem_layout) {
  std::string layout;
  if (!oem_layout.empty()) {
    // If the OEM layout information is provided, use it.
    layout = oem_layout;
  } else {
    // Otherwise, determine the hardware keyboard from the locale.
    std::vector<std::string> input_method_ids;
    if (chromeos::input_method::GetInputMethodIdsFromLanguageCode(
            locale,
            chromeos::input_method::kKeyboardLayoutsOnly,
            &input_method_ids)) {
      // The output list |input_method_ids| is sorted by popularity, hence
      // input_method_ids[0] now contains the most popular keyboard layout
      // for the given locale.
      layout = input_method_ids[0];
    }
  }

  if (!layout.empty()) {
    PrefService* prefs = g_browser_process->local_state();
    prefs->SetString(prefs::kHardwareKeyboardLayout, layout);
    // This asks the file thread to save the prefs (i.e. doesn't block).
    // The latest values of Local State reside in memory so we can safely
    // get the value of kHardwareKeyboardLayout even if the data is not
    // yet saved to disk.
    prefs->SavePersistentPrefs();
  }
}

}  // namespace

namespace chromeos {

// static
LoginDisplayHost* BaseLoginDisplayHost::default_host_ = NULL;

// BaseLoginDisplayHost --------------------------------------------------------

BaseLoginDisplayHost::BaseLoginDisplayHost(const gfx::Rect& background_bounds)
    : background_bounds_(background_bounds) {
  // We need to listen to APP_EXITING but not APP_TERMINATING because
  // APP_TERMINATING will never be fired as long as this keeps ref-count.
  // APP_EXITING is safe here because there will be no browser instance that
  // will block the shutdown.
  registrar_.Add(
      this,
      NotificationType::APP_EXITING,
      NotificationService::AllSources());
  DCHECK(default_host_ == NULL);
  default_host_ = this;

  // Add a reference count so the message loop won't exit when other
  // message loop clients (e.g. menus) do.
  g_browser_process->AddRefModule();
}

BaseLoginDisplayHost::~BaseLoginDisplayHost() {
  // A browser should already exist when destructor is called since
  // deletion is scheduled with MessageLoop::DeleteSoon() from
  // OnSessionStart(), so the browser will already have incremented
  // the reference count.
  g_browser_process->ReleaseModule();

  default_host_ = NULL;
}

// LoginDisplayHost implementation ---------------------------------------------

void BaseLoginDisplayHost::OnSessionStart() {
  registrar_.RemoveAll();
  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}

WizardController* BaseLoginDisplayHost::CreateWizardController() {
  // TODO(altimofeev): move this code to ViewsLoginDisplayHost when WebUI
  // implementation will always be used with WebUILoginDisplayHost.
  oobe_display_.reset(new ViewsOobeDisplay(background_bounds()));
  WizardController* wizard_controller  =
      new WizardController(this, oobe_display_.get());
  oobe_display_->SetScreenObserver(wizard_controller);
  return wizard_controller;
}

void BaseLoginDisplayHost::StartWizard(
    const std::string& first_screen_name,
    const GURL& start_url) {
  DVLOG(1) << "Starting wizard, first_screen_name: " << first_screen_name;
  // Create and show the wizard.
  // Note, dtor of the old WizardController should be called before ctor of the
  // new one, because "default_controller()" is updated there. So pure "reset()"
  // is done before new controller creation.
  wizard_controller_.reset();

  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAllowWebUIOobe)) {
    wizard_controller_.reset(CreateWizardController());
  } else {
    // Force views based implementation.
    wizard_controller_.reset(BaseLoginDisplayHost::CreateWizardController());
  }

  wizard_controller_->set_start_url(start_url);
  ShowBackground();
  if (!WizardController::IsDeviceRegistered())
    SetOobeProgressBarVisible(true);
  wizard_controller_->Init(first_screen_name);
}

void BaseLoginDisplayHost::StartSignInScreen() {
  oobe_display_.reset();

  DVLOG(1) << "Starting sign in screen";
  std::vector<chromeos::UserManager::User> users =
      chromeos::UserManager::Get()->GetUsers();

  // Fix for users who updated device and thus never passed register screen.
  // If we already have users, we assume that it is not a second part of
  // OOBE. See http://crosbug.com/6289
  if (!WizardController::IsDeviceRegistered() && !users.empty()) {
    VLOG(1) << "Mark device registered because there are remembered users: "
            << users.size();
    WizardController::MarkDeviceRegistered();
  }

  sign_in_controller_.reset();  // Only one controller in a time.
  sign_in_controller_.reset(new chromeos::ExistingUserController(this));
  ShowBackground();
  if (!WizardController::IsDeviceRegistered()) {
    SetOobeProgressBarVisible(true);
    SetOobeProgress(chromeos::BackgroundView::SIGNIN);
  }
  SetShutdownButtonEnabled(true);
  sign_in_controller_->Init(users);

  // Initiate services customization manifest fetching.
  ServicesCustomizationDocument::GetInstance()->StartFetching();

  // Initiate device policy fetching.
  g_browser_process->browser_policy_connector()->
      ScheduleServiceInitialization(
          kPolicyServiceInitializationDelayMilliseconds);
}

// BaseLoginDisplayHost --------------------------------------------------------

void BaseLoginDisplayHost::Observe(NotificationType type,
                                   const NotificationSource& source,
                                   const NotificationDetails& details) {
  CHECK(type == NotificationType::APP_EXITING);

  registrar_.RemoveAll();
  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
  MessageLoop::current()->Quit();
}

}  // namespace chromeos

// browser::ShowLoginWizard implementation -------------------------------------

namespace browser {

// Declared in browser_dialogs.h so that others don't need to depend on our .h.
// TODO(nkostylev): Split this into a smaller functions.
void ShowLoginWizard(const std::string& first_screen_name,
                     const gfx::Size& size) {
{'fraction_non_alphanumeric': 0.12234984856277502, 'fraction_numerical': 0.0023429910280587463, 'mean_word_length': 3.9490950226244346, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2977767', 'n_tokens_mistral': 5024, 'n_tokens_neox': 4891, 'n_words': 1255}