- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / app_list / app_list_service_impl.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/ui/app_list/app_list_service_impl.h"
6
7 #include <string>
8
9 #include "apps/pref_names.h"
10 #include "base/command_line.h"
11 #include "base/metrics/histogram.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/string16.h"
14 #include "base/time/time.h"
15 #include "chrome/browser/apps/shortcut_manager.h"
16 #include "chrome/browser/apps/shortcut_manager_factory.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/profiles/profile_manager.h"
19 #include "chrome/browser/ui/app_list/keep_alive_service.h"
20 #include "chrome/browser/ui/app_list/keep_alive_service_impl.h"
21 #include "chrome/browser/ui/app_list/profile_loader.h"
22 #include "chrome/browser/ui/app_list/profile_store.h"
23 #include "chrome/common/chrome_constants.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/pref_names.h"
26 #include "content/public/browser/browser_thread.h"
27
28 namespace {
29
30 void SendAppListAppLaunch(int count) {
31   UMA_HISTOGRAM_CUSTOM_COUNTS(
32       "Apps.AppListDailyAppLaunches", count, 1, 1000, 50);
33   if (count > 0)
34     UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppToday", 1, 2);
35 }
36
37 void SendAppListLaunch(int count) {
38   UMA_HISTOGRAM_CUSTOM_COUNTS(
39       "Apps.AppListDailyLaunches", count, 1, 1000, 50);
40   if (count > 0)
41     UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppListToday", 1, 2);
42 }
43
44 bool SendDailyEventFrequency(
45     const char* last_ping_pref,
46     const char* count_pref,
47     void (*send_callback)(int count)) {
48   PrefService* local_state = g_browser_process->local_state();
49
50   base::Time now = base::Time::Now();
51   base::Time last = base::Time::FromInternalValue(local_state->GetInt64(
52       last_ping_pref));
53   int days = (now - last).InDays();
54   if (days > 0) {
55     send_callback(local_state->GetInteger(count_pref));
56     local_state->SetInt64(
57         last_ping_pref,
58         (last + base::TimeDelta::FromDays(days)).ToInternalValue());
59     local_state->SetInteger(count_pref, 0);
60     return true;
61   }
62   return false;
63 }
64
65 void RecordDailyEventFrequency(
66     const char* last_ping_pref,
67     const char* count_pref,
68     void (*send_callback)(int count)) {
69   PrefService* local_state = g_browser_process->local_state();
70
71   int count = local_state->GetInteger(count_pref);
72   local_state->SetInteger(count_pref, count + 1);
73   if (SendDailyEventFrequency(last_ping_pref, count_pref, send_callback)) {
74     local_state->SetInteger(count_pref, 1);
75   }
76 }
77
78 class ProfileStoreImpl : public ProfileStore {
79  public:
80   explicit ProfileStoreImpl(ProfileManager* profile_manager)
81       : profile_manager_(profile_manager),
82         weak_factory_(this) {
83   }
84
85   virtual void AddProfileObserver(ProfileInfoCacheObserver* observer) OVERRIDE {
86     profile_manager_->GetProfileInfoCache().AddObserver(observer);
87   }
88
89   virtual void LoadProfileAsync(
90       const base::FilePath& path,
91       base::Callback<void(Profile*)> callback) OVERRIDE {
92     profile_manager_->CreateProfileAsync(
93         path,
94         base::Bind(&ProfileStoreImpl::OnProfileCreated,
95                    weak_factory_.GetWeakPtr(),
96                    callback),
97         base::string16(),
98         base::string16(),
99         std::string());
100   }
101
102   void OnProfileCreated(base::Callback<void(Profile*)> callback,
103                         Profile* profile,
104                         Profile::CreateStatus status) {
105     switch (status) {
106       case Profile::CREATE_STATUS_CREATED:
107         break;
108       case Profile::CREATE_STATUS_INITIALIZED:
109         callback.Run(profile);
110         break;
111       case Profile::CREATE_STATUS_LOCAL_FAIL:
112       case Profile::CREATE_STATUS_REMOTE_FAIL:
113       case Profile::CREATE_STATUS_CANCELED:
114         break;
115       case Profile::MAX_CREATE_STATUS:
116         NOTREACHED();
117         break;
118     }
119   }
120
121   virtual Profile* GetProfileByPath(const base::FilePath& path) OVERRIDE {
122     return profile_manager_->GetProfileByPath(path);
123   }
124
125   virtual base::FilePath GetUserDataDir() OVERRIDE {
126     return profile_manager_->user_data_dir();
127   }
128
129   virtual bool IsProfileManaged(const base::FilePath& profile_path) OVERRIDE {
130     ProfileInfoCache& profile_info =
131         g_browser_process->profile_manager()->GetProfileInfoCache();
132     size_t profile_index = profile_info.GetIndexOfProfileWithPath(profile_path);
133     return profile_info.ProfileIsManagedAtIndex(profile_index);
134   }
135
136  private:
137   ProfileManager* profile_manager_;
138   base::WeakPtrFactory<ProfileStoreImpl> weak_factory_;
139 };
140
141 }  // namespace
142
143 // static
144 void AppListServiceImpl::RecordAppListLaunch() {
145   RecordDailyEventFrequency(prefs::kLastAppListLaunchPing,
146                             prefs::kAppListLaunchCount,
147                             &SendAppListLaunch);
148 }
149
150 // static
151 void AppListServiceImpl::RecordAppListAppLaunch() {
152   RecordDailyEventFrequency(prefs::kLastAppListAppLaunchPing,
153                             prefs::kAppListAppLaunchCount,
154                             &SendAppListAppLaunch);
155 }
156
157 // static
158 void AppListServiceImpl::SendAppListStats() {
159   if (!g_browser_process || g_browser_process->IsShuttingDown())
160     return;
161
162   SendDailyEventFrequency(prefs::kLastAppListLaunchPing,
163                           prefs::kAppListLaunchCount,
164                           &SendAppListLaunch);
165   SendDailyEventFrequency(prefs::kLastAppListAppLaunchPing,
166                           prefs::kAppListAppLaunchCount,
167                           &SendAppListAppLaunch);
168 }
169
170 AppListServiceImpl::AppListServiceImpl()
171     : profile_store_(new ProfileStoreImpl(
172           g_browser_process->profile_manager())),
173       weak_factory_(this),
174       command_line_(*CommandLine::ForCurrentProcess()),
175       local_state_(g_browser_process->local_state()),
176       profile_loader_(new ProfileLoader(
177           profile_store_.get(),
178           scoped_ptr<KeepAliveService>(new KeepAliveServiceImpl))) {
179   profile_store_->AddProfileObserver(this);
180 }
181
182 AppListServiceImpl::AppListServiceImpl(
183     const CommandLine& command_line,
184     PrefService* local_state,
185     scoped_ptr<ProfileStore> profile_store,
186     scoped_ptr<KeepAliveService> keep_alive_service)
187     : profile_store_(profile_store.Pass()),
188       weak_factory_(this),
189       command_line_(command_line),
190       local_state_(local_state),
191       profile_loader_(new ProfileLoader(
192           profile_store_.get(), keep_alive_service.Pass())) {
193   profile_store_->AddProfileObserver(this);
194 }
195
196 AppListServiceImpl::~AppListServiceImpl() {}
197
198 void AppListServiceImpl::SetAppListNextPaintCallback(
199     const base::Closure& callback) {}
200
201 void AppListServiceImpl::HandleFirstRun() {}
202
203 void AppListServiceImpl::Init(Profile* initial_profile) {}
204
205 base::FilePath AppListServiceImpl::GetProfilePath(
206     const base::FilePath& user_data_dir) {
207   std::string app_list_profile;
208   if (local_state_->HasPrefPath(prefs::kAppListProfile))
209     app_list_profile = local_state_->GetString(prefs::kAppListProfile);
210
211   // If the user has no profile preference for the app launcher, default to the
212   // last browser profile used.
213   if (app_list_profile.empty() &&
214       local_state_->HasPrefPath(prefs::kProfileLastUsed)) {
215     app_list_profile = local_state_->GetString(prefs::kProfileLastUsed);
216   }
217
218   // If there is no last used profile recorded, use the initial profile.
219   if (app_list_profile.empty())
220     app_list_profile = chrome::kInitialProfile;
221
222   return user_data_dir.AppendASCII(app_list_profile);
223 }
224
225 void AppListServiceImpl::SetProfilePath(const base::FilePath& profile_path) {
226   // Ensure we don't set the pref to a managed user's profile path.
227   // TODO(calamity): Filter out managed profiles from the settings app so this
228   // can't get hit, so we can remove it.
229   if (profile_store_->IsProfileManaged(profile_path))
230     return;
231
232   local_state_->SetString(
233       prefs::kAppListProfile,
234       profile_path.BaseName().MaybeAsASCII());
235 }
236
237 void AppListServiceImpl::CreateShortcut() {}
238
239 // We need to watch for profile removal to keep kAppListProfile updated.
240 void AppListServiceImpl::OnProfileWillBeRemoved(
241     const base::FilePath& profile_path) {
242   // If the profile the app list uses just got deleted, reset it to the last
243   // used profile.
244   std::string app_list_last_profile = local_state_->GetString(
245       prefs::kAppListProfile);
246   if (profile_path.BaseName().MaybeAsASCII() == app_list_last_profile) {
247     local_state_->SetString(prefs::kAppListProfile,
248         local_state_->GetString(prefs::kProfileLastUsed));
249   }
250 }
251
252 void AppListServiceImpl::Show() {
253   profile_loader_->LoadProfileInvalidatingOtherLoads(
254       GetProfilePath(profile_store_->GetUserDataDir()),
255       base::Bind(&AppListServiceImpl::ShowForProfile,
256                  weak_factory_.GetWeakPtr()));
257 }
258
259 void AppListServiceImpl::EnableAppList(Profile* initial_profile) {
260   SetProfilePath(initial_profile->GetPath());
261   if (local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled))
262     return;
263
264   local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, true);
265   CreateShortcut();
266   AppShortcutManagerFactory::GetForProfile(initial_profile)->
267       OnceOffCreateShortcuts();
268 }
269
270 void AppListServiceImpl::InvalidatePendingProfileLoads() {
271   profile_loader_->InvalidatePendingProfileLoads();
272 }
273
274 void AppListServiceImpl::HandleCommandLineFlags(Profile* initial_profile) {
275   if (command_line_.HasSwitch(switches::kEnableAppList))
276     EnableAppList(initial_profile);
277
278   if (command_line_.HasSwitch(switches::kResetAppListInstallState))
279     local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, false);
280 }
281
282 void AppListServiceImpl::SendUsageStats() {
283   // Send app list usage stats after a delay.
284   const int kSendUsageStatsDelay = 5;
285   base::MessageLoop::current()->PostDelayedTask(
286       FROM_HERE,
287       base::Bind(&AppListServiceImpl::SendAppListStats),
288       base::TimeDelta::FromSeconds(kSendUsageStatsDelay));
289 }