Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / chromeos / first_run / first_run_controller.cc
blob02b8cf18f3bdc038baa9618b612688b698a4fee7
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"
7 #include "ash/shell.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"
21 namespace {
23 size_t NONE_STEP_INDEX = std::numeric_limits<size_t>::max();
25 // Instance of currently running controller, or NULL if controller is not
26 // running now.
27 chromeos::FirstRunController* g_instance;
29 void RecordCompletion(chromeos::first_run::TutorialCompletion type) {
30 UMA_HISTOGRAM_ENUMERATION("CrosFirstRun.TutorialCompletion",
31 type,
32 chromeos::first_run::TUTORIAL_COMPLETION_SIZE);
35 } // namespace
37 namespace chromeos {
39 FirstRunController::~FirstRunController() {}
41 // static
42 void FirstRunController::Start() {
43 if (g_instance) {
44 LOG(WARNING) << "First-run tutorial is running already.";
45 return;
47 g_instance = new FirstRunController();
48 g_instance->Init();
51 // static
52 void FirstRunController::Stop() {
53 if (!g_instance) {
54 LOG(WARNING) << "First-run tutorial is not running.";
55 return;
57 g_instance->Finalize();
58 base::MessageLoop::current()->DeleteSoon(FROM_HERE, g_instance);
59 g_instance = NULL;
62 FirstRunController* FirstRunController::GetInstanceForTest() {
63 return g_instance;
66 FirstRunController::FirstRunController()
67 : actor_(NULL),
68 current_step_index_(NONE_STEP_INDEX),
69 user_profile_(NULL) {
72 void FirstRunController::Init() {
73 start_time_ = base::Time::Now();
74 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
75 user_profile_ = ProfileHelper::Get()->GetProfileByUserUnsafe(
76 user_manager->GetActiveUser());
78 shell_helper_.reset(ash::Shell::GetInstance()->CreateFirstRunHelper());
79 shell_helper_->AddObserver(this);
81 FirstRunView* view = new FirstRunView();
82 view->Init(user_profile_);
83 shell_helper_->GetOverlayWidget()->SetContentsView(view);
84 actor_ = view->GetActor();
85 actor_->set_delegate(this);
86 shell_helper_->GetOverlayWidget()->Show();
87 view->RequestFocus();
88 web_contents_for_tests_ = view->GetWebContents();
90 if (actor_->IsInitialized())
91 OnActorInitialized();
94 void FirstRunController::Finalize() {
95 int furthest_step = current_step_index_ == NONE_STEP_INDEX
96 ? steps_.size() - 1
97 : current_step_index_;
98 UMA_HISTOGRAM_ENUMERATION("CrosFirstRun.FurthestStep",
99 furthest_step,
100 steps_.size());
101 UMA_HISTOGRAM_MEDIUM_TIMES("CrosFirstRun.TimeSpent",
102 base::Time::Now() - start_time_);
103 if (GetCurrentStep())
104 GetCurrentStep()->OnBeforeHide();
105 steps_.clear();
106 if (actor_)
107 actor_->set_delegate(NULL);
108 actor_ = NULL;
109 shell_helper_->RemoveObserver(this);
110 shell_helper_.reset();
113 void FirstRunController::OnActorInitialized() {
114 RegisterSteps();
115 ShowNextStep();
118 void FirstRunController::OnNextButtonClicked(const std::string& step_name) {
119 DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
120 GetCurrentStep()->OnBeforeHide();
121 actor_->HideCurrentStep();
124 void FirstRunController::OnHelpButtonClicked() {
125 RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_KEEP_EXPLORING);
126 on_actor_finalized_ = base::Bind(chrome::ShowHelpForProfile,
127 user_profile_,
128 chrome::HOST_DESKTOP_TYPE_ASH,
129 chrome::HELP_SOURCE_MENU);
130 actor_->Finalize();
133 void FirstRunController::OnStepHidden(const std::string& step_name) {
134 DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
135 GetCurrentStep()->OnAfterHide();
136 if (!actor_->IsFinalizing())
137 ShowNextStep();
140 void FirstRunController::OnStepShown(const std::string& step_name) {
141 DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
144 void FirstRunController::OnActorFinalized() {
145 if (!on_actor_finalized_.is_null())
146 on_actor_finalized_.Run();
147 Stop();
150 void FirstRunController::OnActorDestroyed() {
151 // Normally this shouldn't happen because we are implicitly controlling
152 // actor's lifetime.
153 NOTREACHED() <<
154 "FirstRunActor destroyed before FirstRunController::Finalize.";
157 void FirstRunController::OnCancelled() {
158 RecordCompletion(first_run::TUTORIAL_NOT_FINISHED);
159 Stop();
162 void FirstRunController::RegisterSteps() {
163 steps_.push_back(make_linked_ptr(
164 new first_run::AppListStep(shell_helper_.get(), actor_)));
165 steps_.push_back(make_linked_ptr(
166 new first_run::TrayStep(shell_helper_.get(), actor_)));
167 steps_.push_back(make_linked_ptr(
168 new first_run::HelpStep(shell_helper_.get(), actor_)));
171 void FirstRunController::ShowNextStep() {
172 AdvanceStep();
173 if (!GetCurrentStep()) {
174 actor_->Finalize();
175 RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_GOT_IT);
176 return;
178 GetCurrentStep()->Show();
181 void FirstRunController::AdvanceStep() {
182 if (current_step_index_ == NONE_STEP_INDEX)
183 current_step_index_ = 0;
184 else
185 ++current_step_index_;
186 if (current_step_index_ >= steps_.size())
187 current_step_index_ = NONE_STEP_INDEX;
190 first_run::Step* FirstRunController::GetCurrentStep() const {
191 return current_step_index_ != NONE_STEP_INDEX ?
192 steps_[current_step_index_].get() : NULL;
195 } // namespace chromeos