Upstream version 10.39.225.0
[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 !defined(USE_ATHENA)
44   // crbug.com/413914
45   if (g_instance) {
46     LOG(WARNING) << "First-run tutorial is running already.";
47     return;
48   }
49   g_instance = new FirstRunController();
50   g_instance->Init();
51 #endif
52 }
53
54 // static
55 void FirstRunController::Stop() {
56 #if !defined(USE_ATHENA)
57   if (!g_instance) {
58     LOG(WARNING) << "First-run tutorial is not running.";
59     return;
60   }
61   g_instance->Finalize();
62   base::MessageLoop::current()->DeleteSoon(FROM_HERE, g_instance);
63   g_instance = NULL;
64 #endif
65 }
66
67 FirstRunController* FirstRunController::GetInstanceForTest() {
68   return g_instance;
69 }
70
71 FirstRunController::FirstRunController()
72     : actor_(NULL),
73       current_step_index_(NONE_STEP_INDEX),
74       user_profile_(NULL) {
75 }
76
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());
82
83   shell_helper_.reset(ash::Shell::GetInstance()->CreateFirstRunHelper());
84   shell_helper_->AddObserver(this);
85
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();
92   view->RequestFocus();
93   web_contents_for_tests_ = view->GetWebContents();
94
95   if (actor_->IsInitialized())
96     OnActorInitialized();
97 }
98
99 void FirstRunController::Finalize() {
100   int furthest_step = current_step_index_ == NONE_STEP_INDEX
101                           ? steps_.size() - 1
102                           : current_step_index_;
103   UMA_HISTOGRAM_ENUMERATION("CrosFirstRun.FurthestStep",
104                             furthest_step,
105                             steps_.size());
106   UMA_HISTOGRAM_MEDIUM_TIMES("CrosFirstRun.TimeSpent",
107                              base::Time::Now() - start_time_);
108   if (GetCurrentStep())
109     GetCurrentStep()->OnBeforeHide();
110   steps_.clear();
111   if (actor_)
112     actor_->set_delegate(NULL);
113   actor_ = NULL;
114   shell_helper_->RemoveObserver(this);
115   shell_helper_.reset();
116 }
117
118 void FirstRunController::OnActorInitialized() {
119   RegisterSteps();
120   ShowNextStep();
121 }
122
123 void FirstRunController::OnNextButtonClicked(const std::string& step_name) {
124   DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
125   GetCurrentStep()->OnBeforeHide();
126   actor_->HideCurrentStep();
127 }
128
129 void FirstRunController::OnHelpButtonClicked() {
130   RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_KEEP_EXPLORING);
131   on_actor_finalized_ = base::Bind(chrome::ShowHelpForProfile,
132                                    user_profile_,
133                                    chrome::HOST_DESKTOP_TYPE_ASH,
134                                    chrome::HELP_SOURCE_MENU);
135   actor_->Finalize();
136 }
137
138 void FirstRunController::OnStepHidden(const std::string& step_name) {
139   DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
140   GetCurrentStep()->OnAfterHide();
141   if (!actor_->IsFinalizing())
142     ShowNextStep();
143 }
144
145 void FirstRunController::OnStepShown(const std::string& step_name) {
146   DCHECK(GetCurrentStep() && GetCurrentStep()->name() == step_name);
147 }
148
149 void FirstRunController::OnActorFinalized() {
150   if (!on_actor_finalized_.is_null())
151     on_actor_finalized_.Run();
152   Stop();
153 }
154
155 void FirstRunController::OnActorDestroyed() {
156   // Normally this shouldn't happen because we are implicitly controlling
157   // actor's lifetime.
158   NOTREACHED() <<
159     "FirstRunActor destroyed before FirstRunController::Finalize.";
160 }
161
162 void FirstRunController::OnCancelled() {
163   RecordCompletion(first_run::TUTORIAL_NOT_FINISHED);
164   Stop();
165 }
166
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_)));
174 }
175
176 void FirstRunController::ShowNextStep() {
177   AdvanceStep();
178   if (!GetCurrentStep()) {
179     actor_->Finalize();
180     RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_GOT_IT);
181     return;
182   }
183   GetCurrentStep()->Show();
184 }
185
186 void FirstRunController::AdvanceStep() {
187   if (current_step_index_ == NONE_STEP_INDEX)
188     current_step_index_ = 0;
189   else
190     ++current_step_index_;
191   if (current_step_index_ >= steps_.size())
192     current_step_index_ = NONE_STEP_INDEX;
193 }
194
195 first_run::Step* FirstRunController::GetCurrentStep() const {
196   return current_step_index_ != NONE_STEP_INDEX ?
197       steps_[current_step_index_].get() : NULL;
198 }
199
200 }  // namespace chromeos
201