158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// found in the LICENSE file.
458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/first_run/first_run_controller.h"
658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ash/shell.h"
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/logging.h"
958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/message_loop/message_loop.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram.h"
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/first_run/first_run_view.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chromeos/first_run/metrics.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/chromeos/first_run/steps/app_list_step.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/chromeos/first_run/steps/help_step.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/chromeos/first_run/steps/tray_step.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/chromeos/profiles/profile_helper.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/chrome_pages.h"
186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/user_manager/user_manager.h"
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/views/widget/widget.h"
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace {
2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)size_t NONE_STEP_INDEX = std::numeric_limits<size_t>::max();
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Instance of currently running controller, or NULL if controller is not
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// running now.
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)chromeos::FirstRunController* g_instance;
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RecordCompletion(chromeos::first_run::TutorialCompletion type) {
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("CrosFirstRun.TutorialCompletion",
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            type,
32effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            chromeos::first_run::TUTORIAL_COMPLETION_SIZE);
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace
3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace chromeos {
3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)FirstRunController::~FirstRunController() {}
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void FirstRunController::Start() {
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if !defined(USE_ATHENA)
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // crbug.com/413914
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (g_instance) {
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LOG(WARNING) << "First-run tutorial is running already.";
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  g_instance = new FirstRunController();
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  g_instance->Init();
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void FirstRunController::Stop() {
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if !defined(USE_ATHENA)
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!g_instance) {
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LOG(WARNING) << "First-run tutorial is not running.";
5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  g_instance->Finalize();
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::MessageLoop::current()->DeleteSoon(FROM_HERE, g_instance);
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  g_instance = NULL;
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FirstRunController* FirstRunController::GetInstanceForTest() {
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return g_instance;
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)FirstRunController::FirstRunController()
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : actor_(NULL),
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      current_step_index_(NONE_STEP_INDEX),
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      user_profile_(NULL) {
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void FirstRunController::Init() {
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  start_time_ = base::Time::Now();
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  user_profile_ = ProfileHelper::Get()->GetProfileByUserUnsafe(
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      user_manager->GetActiveUser());
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  shell_helper_.reset(ash::Shell::GetInstance()->CreateFirstRunHelper());
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  shell_helper_->AddObserver(this);
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FirstRunView* view = new FirstRunView();
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  view->Init(user_profile_);
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  shell_helper_->GetOverlayWidget()->SetContentsView(view);
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  actor_ = view->GetActor();
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  actor_->set_delegate(this);
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  shell_helper_->GetOverlayWidget()->Show();
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  view->RequestFocus();
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  web_contents_for_tests_ = view->GetWebContents();
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (actor_->IsInitialized())
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    OnActorInitialized();
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void FirstRunController::Finalize() {
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int furthest_step = current_step_index_ == NONE_STEP_INDEX
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          ? steps_.size() - 1
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          : current_step_index_;
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("CrosFirstRun.FurthestStep",
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            furthest_step,
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            steps_.size());
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UMA_HISTOGRAM_MEDIUM_TIMES("CrosFirstRun.TimeSpent",
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             base::Time::Now() - start_time_);
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (GetCurrentStep())
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    GetCurrentStep()->OnBeforeHide();
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  steps_.clear();
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (actor_)
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    actor_->set_delegate(NULL);
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  actor_ = NULL;
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  shell_helper_->RemoveObserver(this);
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  shell_helper_.reset();
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void FirstRunController::OnActorInitialized() {
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RegisterSteps();
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ShowNextStep();
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void FirstRunController::OnNextButtonClicked(const std::string& step_name) {
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetCurrentStep()->OnBeforeHide();
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  actor_->HideCurrentStep();
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void FirstRunController::OnHelpButtonClicked() {
130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_KEEP_EXPLORING);
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  on_actor_finalized_ = base::Bind(chrome::ShowHelpForProfile,
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   user_profile_,
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   chrome::HOST_DESKTOP_TYPE_ASH,
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   chrome::HELP_SOURCE_MENU);
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  actor_->Finalize();
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FirstRunController::OnStepHidden(const std::string& step_name) {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetCurrentStep()->OnAfterHide();
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!actor_->IsFinalizing())
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ShowNextStep();
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FirstRunController::OnStepShown(const std::string& step_name) {
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FirstRunController::OnActorFinalized() {
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!on_actor_finalized_.is_null())
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    on_actor_finalized_.Run();
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Stop();
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void FirstRunController::OnActorDestroyed() {
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Normally this shouldn't happen because we are implicitly controlling
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // actor's lifetime.
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NOTREACHED() <<
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "FirstRunActor destroyed before FirstRunController::Finalize.";
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FirstRunController::OnCancelled() {
163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  RecordCompletion(first_run::TUTORIAL_NOT_FINISHED);
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Stop();
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void FirstRunController::RegisterSteps() {
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  steps_.push_back(make_linked_ptr(
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new first_run::AppListStep(shell_helper_.get(), actor_)));
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  steps_.push_back(make_linked_ptr(
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new first_run::TrayStep(shell_helper_.get(), actor_)));
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  steps_.push_back(make_linked_ptr(
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new first_run::HelpStep(shell_helper_.get(), actor_)));
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void FirstRunController::ShowNextStep() {
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AdvanceStep();
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!GetCurrentStep()) {
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    actor_->Finalize();
180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_GOT_IT);
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetCurrentStep()->Show();
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void FirstRunController::AdvanceStep() {
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (current_step_index_ == NONE_STEP_INDEX)
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    current_step_index_ = 0;
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  else
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ++current_step_index_;
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (current_step_index_ >= steps_.size())
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    current_step_index_ = NONE_STEP_INDEX;
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)first_run::Step* FirstRunController::GetCurrentStep() const {
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return current_step_index_ != NONE_STEP_INDEX ?
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      steps_[current_step_index_].get() : NULL;
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace chromeos
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
202