root/chrome/browser/chromeos/first_run/first_run_controller.cc

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

DEFINITIONS

This source file includes following definitions.
  1. RecordCompletion
  2. Start
  3. Stop
  4. GetInstanceForTest
  5. user_profile_
  6. Init
  7. Finalize
  8. OnActorInitialized
  9. OnNextButtonClicked
  10. OnHelpButtonClicked
  11. OnStepHidden
  12. OnStepShown
  13. OnActorFinalized
  14. OnActorDestroyed
  15. OnCancelled
  16. RegisterSteps
  17. ShowNextStep
  18. AdvanceStep
  19. GetCurrentStep

// Copyright 2013 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/first_run/first_run_controller.h"

#include "ash/shell.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/chromeos/first_run/first_run_view.h"
#include "chrome/browser/chromeos/first_run/metrics.h"
#include "chrome/browser/chromeos/first_run/steps/app_list_step.h"
#include "chrome/browser/chromeos/first_run/steps/help_step.h"
#include "chrome/browser/chromeos/first_run/steps/tray_step.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "ui/views/widget/widget.h"

namespace {

size_t NONE_STEP_INDEX = std::numeric_limits<size_t>::max();

// Instance of currently running controller, or NULL if controller is not
// running now.
chromeos::FirstRunController* g_instance;

void RecordCompletion(chromeos::first_run::TutorialCompletion type) {
  UMA_HISTOGRAM_ENUMERATION("CrosFirstRun.TutorialCompletion",
                            type,
                            chromeos::first_run::TUTORIAL_COMPLETION_SIZE);
}

}  // namespace

namespace chromeos {

FirstRunController::~FirstRunController() {}

// static
void FirstRunController::Start() {
  if (g_instance) {
    LOG(WARNING) << "First-run tutorial is running already.";
    return;
  }
  g_instance = new FirstRunController();
  g_instance->Init();
}

// static
void FirstRunController::Stop() {
  if (!g_instance) {
    LOG(WARNING) << "First-run tutorial is not running.";
    return;
  }
  g_instance->Finalize();
  base::MessageLoop::current()->DeleteSoon(FROM_HERE, g_instance);
  g_instance = NULL;
}

FirstRunController* FirstRunController::GetInstanceForTest() {
  return g_instance;
}

FirstRunController::FirstRunController()
    : actor_(NULL),
      current_step_index_(NONE_STEP_INDEX),
      user_profile_(NULL) {
}

void FirstRunController::Init() {
  start_time_ = base::Time::Now();
  UserManager* user_manager = UserManager::Get();
  user_profile_ = user_manager->GetProfileByUser(user_manager->GetActiveUser());

  shell_helper_.reset(ash::Shell::GetInstance()->CreateFirstRunHelper());
  shell_helper_->AddObserver(this);

  FirstRunView* view = new FirstRunView();
  view->Init(user_profile_);
  shell_helper_->GetOverlayWidget()->SetContentsView(view);
  actor_ = view->GetActor();
  actor_->set_delegate(this);
  shell_helper_->GetOverlayWidget()->Show();
  view->RequestFocus();
  web_contents_for_tests_ = view->GetWebContents();

  if (actor_->IsInitialized())
    OnActorInitialized();
}

void FirstRunController::Finalize() {
  int furthest_step = current_step_index_ == NONE_STEP_INDEX
                          ? steps_.size() - 1
                          : current_step_index_;
  UMA_HISTOGRAM_ENUMERATION("CrosFirstRun.FurthestStep",
                            furthest_step,
                            steps_.size());
  UMA_HISTOGRAM_MEDIUM_TIMES("CrosFirstRun.TimeSpent",
                             base::Time::Now() - start_time_);
  if (GetCurrentStep())
    GetCurrentStep()->OnBeforeHide();
  steps_.clear();
  if (actor_)
    actor_->set_delegate(NULL);
  actor_ = NULL;
  shell_helper_->RemoveObserver(this);
  shell_helper_.reset();
}

void FirstRunController::OnActorInitialized() {
  RegisterSteps();
  ShowNextStep();
}

void FirstRunController::OnNextButtonClicked(const std::string& step_name) {
  DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
  GetCurrentStep()->OnBeforeHide();
  actor_->HideCurrentStep();
}

void FirstRunController::OnHelpButtonClicked() {
  RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_KEEP_EXPLORING);
  on_actor_finalized_ = base::Bind(chrome::ShowHelpForProfile,
                                   user_profile_,
                                   chrome::HOST_DESKTOP_TYPE_ASH,
                                   chrome::HELP_SOURCE_MENU);
  actor_->Finalize();
}

void FirstRunController::OnStepHidden(const std::string& step_name) {
  DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
  GetCurrentStep()->OnAfterHide();
  if (!actor_->IsFinalizing())
    ShowNextStep();
}

void FirstRunController::OnStepShown(const std::string& step_name) {
  DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
}

void FirstRunController::OnActorFinalized() {
  if (!on_actor_finalized_.is_null())
    on_actor_finalized_.Run();
  Stop();
}

void FirstRunController::OnActorDestroyed() {
  // Normally this shouldn't happen because we are implicitly controlling
  // actor's lifetime.
  NOTREACHED() <<
    "FirstRunActor destroyed before FirstRunController::Finalize.";
}

void FirstRunController::OnCancelled() {
  RecordCompletion(first_run::TUTORIAL_NOT_FINISHED);
  Stop();
}

void FirstRunController::RegisterSteps() {
  steps_.push_back(make_linked_ptr(
      new first_run::AppListStep(shell_helper_.get(), actor_)));
  steps_.push_back(make_linked_ptr(
      new first_run::TrayStep(shell_helper_.get(), actor_)));
  steps_.push_back(make_linked_ptr(
      new first_run::HelpStep(shell_helper_.get(), actor_)));
}

void FirstRunController::ShowNextStep() {
  AdvanceStep();
  if (!GetCurrentStep()) {
    actor_->Finalize();
    RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_GOT_IT);
    return;
  }
  GetCurrentStep()->Show();
}

void FirstRunController::AdvanceStep() {
  if (current_step_index_ == NONE_STEP_INDEX)
    current_step_index_ = 0;
  else
    ++current_step_index_;
  if (current_step_index_ >= steps_.size())
    current_step_index_ = NONE_STEP_INDEX;
}

first_run::Step* FirstRunController::GetCurrentStep() const {
  return current_step_index_ != NONE_STEP_INDEX ?
      steps_[current_step_index_].get() : NULL;
}

}  // namespace chromeos


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