1 // Copyright 2013 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.
5 #include "chrome/browser/chromeos/first_run/first_run_controller.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/histogram.h"
11 #include "chrome/browser/chromeos/first_run/first_run_view.h"
12 #include "chrome/browser/chromeos/first_run/metrics.h"
13 #include "chrome/browser/chromeos/first_run/steps/app_list_step.h"
14 #include "chrome/browser/chromeos/first_run/steps/help_step.h"
15 #include "chrome/browser/chromeos/first_run/steps/tray_step.h"
16 #include "chrome/browser/chromeos/profiles/profile_helper.h"
17 #include "chrome/browser/ui/chrome_pages.h"
18 #include "components/user_manager/user_manager.h"
19 #include "ui/views/widget/widget.h"
23 size_t NONE_STEP_INDEX = std::numeric_limits<size_t>::max();
25 // Instance of currently running controller, or NULL if controller is not
27 chromeos::FirstRunController* g_instance;
29 void RecordCompletion(chromeos::first_run::TutorialCompletion type) {
30 UMA_HISTOGRAM_ENUMERATION("CrosFirstRun.TutorialCompletion",
32 chromeos::first_run::TUTORIAL_COMPLETION_SIZE);
39 FirstRunController::~FirstRunController() {}
42 void FirstRunController::Start() {
43 #if !defined(USE_ATHENA)
46 LOG(WARNING) << "First-run tutorial is running already.";
49 g_instance = new FirstRunController();
55 void FirstRunController::Stop() {
56 #if !defined(USE_ATHENA)
58 LOG(WARNING) << "First-run tutorial is not running.";
61 g_instance->Finalize();
62 base::MessageLoop::current()->DeleteSoon(FROM_HERE, g_instance);
67 FirstRunController* FirstRunController::GetInstanceForTest() {
71 FirstRunController::FirstRunController()
73 current_step_index_(NONE_STEP_INDEX),
77 void FirstRunController::Init() {
78 start_time_ = base::Time::Now();
79 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
80 user_profile_ = ProfileHelper::Get()->GetProfileByUserUnsafe(
81 user_manager->GetActiveUser());
83 shell_helper_.reset(ash::Shell::GetInstance()->CreateFirstRunHelper());
84 shell_helper_->AddObserver(this);
86 FirstRunView* view = new FirstRunView();
87 view->Init(user_profile_);
88 shell_helper_->GetOverlayWidget()->SetContentsView(view);
89 actor_ = view->GetActor();
90 actor_->set_delegate(this);
91 shell_helper_->GetOverlayWidget()->Show();
93 web_contents_for_tests_ = view->GetWebContents();
95 if (actor_->IsInitialized())
99 void FirstRunController::Finalize() {
100 int furthest_step = current_step_index_ == NONE_STEP_INDEX
102 : current_step_index_;
103 UMA_HISTOGRAM_ENUMERATION("CrosFirstRun.FurthestStep",
106 UMA_HISTOGRAM_MEDIUM_TIMES("CrosFirstRun.TimeSpent",
107 base::Time::Now() - start_time_);
108 if (GetCurrentStep())
109 GetCurrentStep()->OnBeforeHide();
112 actor_->set_delegate(NULL);
114 shell_helper_->RemoveObserver(this);
115 shell_helper_.reset();
118 void FirstRunController::OnActorInitialized() {
123 void FirstRunController::OnNextButtonClicked(const std::string& step_name) {
124 DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
125 GetCurrentStep()->OnBeforeHide();
126 actor_->HideCurrentStep();
129 void FirstRunController::OnHelpButtonClicked() {
130 RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_KEEP_EXPLORING);
131 on_actor_finalized_ = base::Bind(chrome::ShowHelpForProfile,
133 chrome::HOST_DESKTOP_TYPE_ASH,
134 chrome::HELP_SOURCE_MENU);
138 void FirstRunController::OnStepHidden(const std::string& step_name) {
139 DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
140 GetCurrentStep()->OnAfterHide();
141 if (!actor_->IsFinalizing())
145 void FirstRunController::OnStepShown(const std::string& step_name) {
146 DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
149 void FirstRunController::OnActorFinalized() {
150 if (!on_actor_finalized_.is_null())
151 on_actor_finalized_.Run();
155 void FirstRunController::OnActorDestroyed() {
156 // Normally this shouldn't happen because we are implicitly controlling
159 "FirstRunActor destroyed before FirstRunController::Finalize.";
162 void FirstRunController::OnCancelled() {
163 RecordCompletion(first_run::TUTORIAL_NOT_FINISHED);
167 void FirstRunController::RegisterSteps() {
168 steps_.push_back(make_linked_ptr(
169 new first_run::AppListStep(shell_helper_.get(), actor_)));
170 steps_.push_back(make_linked_ptr(
171 new first_run::TrayStep(shell_helper_.get(), actor_)));
172 steps_.push_back(make_linked_ptr(
173 new first_run::HelpStep(shell_helper_.get(), actor_)));
176 void FirstRunController::ShowNextStep() {
178 if (!GetCurrentStep()) {
180 RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_GOT_IT);
183 GetCurrentStep()->Show();
186 void FirstRunController::AdvanceStep() {
187 if (current_step_index_ == NONE_STEP_INDEX)
188 current_step_index_ = 0;
190 ++current_step_index_;
191 if (current_step_index_ >= steps_.size())
192 current_step_index_ = NONE_STEP_INDEX;
195 first_run::Step* FirstRunController::GetCurrentStep() const {
196 return current_step_index_ != NONE_STEP_INDEX ?
197 steps_[current_step_index_].get() : NULL;
200 } // namespace chromeos