02b8cf18f3bdc038baa9618b612688b698a4fee7
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / first_run / first_run_controller.cc
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.
4
5 #include "chrome/browser/chromeos/first_run/first_run_controller.h"
6
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"
20
21 namespace {
22
23 size_t NONE_STEP_INDEX = std::numeric_limits<size_t>::max();
24
25 // Instance of currently running controller, or NULL if controller is not
26 // running now.
27 chromeos::FirstRunController* g_instance;
28
29 void RecordCompletion(chromeos::first_run::TutorialCompletion type) {
30   UMA_HISTOGRAM_ENUMERATION("CrosFirstRun.TutorialCompletion",
31                             type,
32                             chromeos::first_run::TUTORIAL_COMPLETION_SIZE);
33 }
34
35 }  // namespace
36
37 namespace chromeos {
38
39 FirstRunController::~FirstRunController() {}
40
41 // static
42 void FirstRunController::Start() {
43   if (g_instance) {
44     LOG(WARNING) << "First-run tutorial is running already.";
45     return;
46   }
47   g_instance = new FirstRunController();
48   g_instance->Init();
49 }
50
51 // static
52 void FirstRunController::Stop() {
53   if (!g_instance) {
54     LOG(WARNING) << "First-run tutorial is not running.";
55     return;
56   }
57   g_instance->Finalize();
58   base::MessageLoop::current()->DeleteSoon(FROM_HERE, g_instance);
59   g_instance = NULL;
60 }
61
62 FirstRunController* FirstRunController::GetInstanceForTest() {
63   return g_instance;
64 }
65
66 FirstRunController::FirstRunController()
67     : actor_(NULL),
68       current_step_index_(NONE_STEP_INDEX),
69       user_profile_(NULL) {
70 }
71
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());
77
78   shell_helper_.reset(ash::Shell::GetInstance()->CreateFirstRunHelper());
79   shell_helper_->AddObserver(this);
80
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();
89
90   if (actor_->IsInitialized())
91     OnActorInitialized();
92 }
93
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();
111 }
112
113 void FirstRunController::OnActorInitialized() {
114   RegisterSteps();
115   ShowNextStep();
116 }
117
118 void FirstRunController::OnNextButtonClicked(const std::string& step_name) {
119   DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
120   GetCurrentStep()->OnBeforeHide();
121   actor_->HideCurrentStep();
122 }
123
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();
131 }
132
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();
138 }
139
140 void FirstRunController::OnStepShown(const std::string& step_name) {
141   DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
142 }
143
144 void FirstRunController::OnActorFinalized() {
145   if (!on_actor_finalized_.is_null())
146     on_actor_finalized_.Run();
147   Stop();
148 }
149
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.";
155 }
156
157 void FirstRunController::OnCancelled() {
158   RecordCompletion(first_run::TUTORIAL_NOT_FINISHED);
159   Stop();
160 }
161
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_)));
169 }
170
171 void FirstRunController::ShowNextStep() {
172   AdvanceStep();
173   if (!GetCurrentStep()) {
174     actor_->Finalize();
175     RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_GOT_IT);
176     return;
177   }
178   GetCurrentStep()->Show();
179 }
180
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;
188 }
189
190 first_run::Step* FirstRunController::GetCurrentStep() const {
191   return current_step_index_ != NONE_STEP_INDEX ?
192       steps_[current_step_index_].get() : NULL;
193 }
194
195 }  // namespace chromeos
196