OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/app_list/app_list_service_impl.h" | 5 #include "chrome/browser/ui/app_list/app_list_service_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "apps/pref_names.h" | 9 #include "apps/pref_names.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/prefs/pref_service.h" | 12 #include "base/prefs/pref_service.h" |
13 #include "base/strings/string16.h" | 13 #include "base/strings/string16.h" |
14 #include "base/time/time.h" | 14 #include "base/time/time.h" |
15 #include "chrome/browser/apps/shortcut_manager.h" | 15 #include "chrome/browser/apps/shortcut_manager.h" |
16 #include "chrome/browser/apps/shortcut_manager_factory.h" | 16 #include "chrome/browser/apps/shortcut_manager_factory.h" |
17 #include "chrome/browser/browser_process.h" | 17 #include "chrome/browser/browser_process.h" |
18 #include "chrome/browser/browser_shutdown.h" | |
19 #include "chrome/browser/profiles/profile_manager.h" | 18 #include "chrome/browser/profiles/profile_manager.h" |
20 #include "chrome/browser/ui/app_list/keep_alive_service.h" | 19 #include "chrome/browser/ui/app_list/keep_alive_service.h" |
21 #include "chrome/browser/ui/app_list/keep_alive_service_impl.h" | 20 #include "chrome/browser/ui/app_list/keep_alive_service_impl.h" |
22 #include "chrome/browser/ui/app_list/profile_loader.h" | 21 #include "chrome/browser/ui/app_list/profile_loader.h" |
23 #include "chrome/browser/ui/app_list/profile_store.h" | 22 #include "chrome/browser/ui/app_list/profile_store.h" |
24 #include "chrome/common/chrome_constants.h" | 23 #include "chrome/common/chrome_constants.h" |
25 #include "chrome/common/chrome_switches.h" | 24 #include "chrome/common/chrome_switches.h" |
26 #include "chrome/common/pref_names.h" | 25 #include "chrome/common/pref_names.h" |
27 #include "content/public/browser/browser_thread.h" | 26 #include "content/public/browser/browser_thread.h" |
28 | 27 |
29 namespace { | 28 namespace { |
30 | 29 |
31 const int kDiscoverabilityTimeoutMinutes = 60; | |
32 | |
33 void SendAppListAppLaunch(int count) { | 30 void SendAppListAppLaunch(int count) { |
34 UMA_HISTOGRAM_CUSTOM_COUNTS( | 31 UMA_HISTOGRAM_CUSTOM_COUNTS( |
35 "Apps.AppListDailyAppLaunches", count, 1, 1000, 50); | 32 "Apps.AppListDailyAppLaunches", count, 1, 1000, 50); |
36 if (count > 0) | 33 if (count > 0) |
37 UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppToday", 1, 2); | 34 UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppToday", 1, 2); |
38 } | 35 } |
39 | 36 |
40 void SendAppListLaunch(int count) { | 37 void SendAppListLaunch(int count) { |
41 UMA_HISTOGRAM_CUSTOM_COUNTS( | 38 UMA_HISTOGRAM_CUSTOM_COUNTS( |
42 "Apps.AppListDailyLaunches", count, 1, 1000, 50); | 39 "Apps.AppListDailyLaunches", count, 1, 1000, 50); |
(...skipping 19 matching lines...) Expand all Loading... |
62 local_state->SetInteger(count_pref, 0); | 59 local_state->SetInteger(count_pref, 0); |
63 return true; | 60 return true; |
64 } | 61 } |
65 return false; | 62 return false; |
66 } | 63 } |
67 | 64 |
68 void RecordDailyEventFrequency( | 65 void RecordDailyEventFrequency( |
69 const char* last_ping_pref, | 66 const char* last_ping_pref, |
70 const char* count_pref, | 67 const char* count_pref, |
71 void (*send_callback)(int count)) { | 68 void (*send_callback)(int count)) { |
72 if (!g_browser_process) | |
73 return; // In a unit test. | |
74 | |
75 PrefService* local_state = g_browser_process->local_state(); | 69 PrefService* local_state = g_browser_process->local_state(); |
76 | 70 |
77 int count = local_state->GetInteger(count_pref); | 71 int count = local_state->GetInteger(count_pref); |
78 local_state->SetInteger(count_pref, count + 1); | 72 local_state->SetInteger(count_pref, count + 1); |
79 if (SendDailyEventFrequency(last_ping_pref, count_pref, send_callback)) { | 73 if (SendDailyEventFrequency(last_ping_pref, count_pref, send_callback)) { |
80 local_state->SetInteger(count_pref, 1); | 74 local_state->SetInteger(count_pref, 1); |
81 } | 75 } |
82 } | 76 } |
83 | 77 |
84 class ProfileStoreImpl : public ProfileStore { | 78 class ProfileStoreImpl : public ProfileStore { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 g_browser_process->profile_manager()->GetProfileInfoCache(); | 131 g_browser_process->profile_manager()->GetProfileInfoCache(); |
138 size_t profile_index = profile_info.GetIndexOfProfileWithPath(profile_path); | 132 size_t profile_index = profile_info.GetIndexOfProfileWithPath(profile_path); |
139 return profile_info.ProfileIsManagedAtIndex(profile_index); | 133 return profile_info.ProfileIsManagedAtIndex(profile_index); |
140 } | 134 } |
141 | 135 |
142 private: | 136 private: |
143 ProfileManager* profile_manager_; | 137 ProfileManager* profile_manager_; |
144 base::WeakPtrFactory<ProfileStoreImpl> weak_factory_; | 138 base::WeakPtrFactory<ProfileStoreImpl> weak_factory_; |
145 }; | 139 }; |
146 | 140 |
147 void RecordAppListDiscoverability(PrefService* local_state, | |
148 bool is_startup_check) { | |
149 // Since this task may be delayed, ensure it does not interfere with shutdown | |
150 // when they unluckily coincide. | |
151 if (browser_shutdown::IsTryingToQuit()) | |
152 return; | |
153 | |
154 int64 enable_time_value = local_state->GetInt64(prefs::kAppListEnableTime); | |
155 if (enable_time_value == 0) | |
156 return; // Already recorded or never enabled. | |
157 | |
158 base::Time app_list_enable_time = | |
159 base::Time::FromInternalValue(enable_time_value); | |
160 if (is_startup_check) { | |
161 // When checking at startup, only clear and record the "timeout" case, | |
162 // otherwise wait for a timeout. | |
163 base::TimeDelta time_remaining = | |
164 app_list_enable_time + | |
165 base::TimeDelta::FromMinutes(kDiscoverabilityTimeoutMinutes) - | |
166 base::Time::Now(); | |
167 if (time_remaining > base::TimeDelta()) { | |
168 base::MessageLoop::current()->PostDelayedTask( | |
169 FROM_HERE, | |
170 base::Bind(&RecordAppListDiscoverability, | |
171 base::Unretained(local_state), | |
172 false), | |
173 time_remaining); | |
174 return; | |
175 } | |
176 } | |
177 | |
178 local_state->SetInt64(prefs::kAppListEnableTime, 0); | |
179 | |
180 AppListService::AppListEnableSource enable_source = | |
181 static_cast<AppListService::AppListEnableSource>( | |
182 local_state->GetInteger(prefs::kAppListEnableMethod)); | |
183 if (enable_source == AppListService::ENABLE_FOR_APP_INSTALL) { | |
184 base::TimeDelta time_taken = base::Time::Now() - app_list_enable_time; | |
185 // This means the user "discovered" the app launcher naturally, after it was | |
186 // enabled on the first app install. Record how long it took to discover. | |
187 // Note that the last bucket is essentially "not discovered": subtract 1 | |
188 // minute to account for clock inaccuracy. | |
189 UMA_HISTOGRAM_CUSTOM_TIMES( | |
190 "Apps.AppListTimeToDiscover", | |
191 time_taken, | |
192 base::TimeDelta::FromSeconds(1), | |
193 base::TimeDelta::FromMinutes(kDiscoverabilityTimeoutMinutes - 1), | |
194 10 /* bucket_count */); | |
195 } | |
196 UMA_HISTOGRAM_ENUMERATION("Apps.AppListHowEnabled", | |
197 enable_source, | |
198 AppListService::ENABLE_NUM_ENABLE_SOURCES); | |
199 } | |
200 | |
201 } // namespace | 141 } // namespace |
202 | 142 |
| 143 // static |
203 void AppListServiceImpl::RecordAppListLaunch() { | 144 void AppListServiceImpl::RecordAppListLaunch() { |
204 RecordDailyEventFrequency(prefs::kLastAppListLaunchPing, | 145 RecordDailyEventFrequency(prefs::kLastAppListLaunchPing, |
205 prefs::kAppListLaunchCount, | 146 prefs::kAppListLaunchCount, |
206 &SendAppListLaunch); | 147 &SendAppListLaunch); |
207 RecordAppListDiscoverability(local_state_, false); | |
208 } | 148 } |
209 | 149 |
210 // static | 150 // static |
211 void AppListServiceImpl::RecordAppListAppLaunch() { | 151 void AppListServiceImpl::RecordAppListAppLaunch() { |
212 RecordDailyEventFrequency(prefs::kLastAppListAppLaunchPing, | 152 RecordDailyEventFrequency(prefs::kLastAppListAppLaunchPing, |
213 prefs::kAppListAppLaunchCount, | 153 prefs::kAppListAppLaunchCount, |
214 &SendAppListAppLaunch); | 154 &SendAppListAppLaunch); |
215 } | 155 } |
216 | 156 |
217 // static | 157 // static |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 } | 248 } |
309 } | 249 } |
310 | 250 |
311 void AppListServiceImpl::Show() { | 251 void AppListServiceImpl::Show() { |
312 profile_loader_->LoadProfileInvalidatingOtherLoads( | 252 profile_loader_->LoadProfileInvalidatingOtherLoads( |
313 GetProfilePath(profile_store_->GetUserDataDir()), | 253 GetProfilePath(profile_store_->GetUserDataDir()), |
314 base::Bind(&AppListServiceImpl::ShowForProfile, | 254 base::Bind(&AppListServiceImpl::ShowForProfile, |
315 weak_factory_.GetWeakPtr())); | 255 weak_factory_.GetWeakPtr())); |
316 } | 256 } |
317 | 257 |
318 void AppListServiceImpl::AutoShowForProfile(Profile* requested_profile) { | 258 void AppListServiceImpl::EnableAppList(Profile* initial_profile) { |
319 if (local_state_->GetInt64(prefs::kAppListEnableTime) != 0) { | |
320 // User has not yet discovered the app launcher. Update the enable method to | |
321 // indicate this. It will then be recorded in UMA. | |
322 local_state_->SetInteger(prefs::kAppListEnableMethod, | |
323 ENABLE_SHOWN_UNDISCOVERED); | |
324 } | |
325 ShowForProfile(requested_profile); | |
326 } | |
327 | |
328 void AppListServiceImpl::EnableAppList(Profile* initial_profile, | |
329 AppListEnableSource enable_source) { | |
330 SetProfilePath(initial_profile->GetPath()); | 259 SetProfilePath(initial_profile->GetPath()); |
331 if (local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)) | 260 if (local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)) |
332 return; | 261 return; |
333 | 262 |
334 local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, true); | 263 local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, true); |
335 CreateShortcut(); | 264 CreateShortcut(); |
336 | |
337 // UMA for launcher discoverability. | |
338 local_state_->SetInt64(prefs::kAppListEnableTime, | |
339 base::Time::Now().ToInternalValue()); | |
340 local_state_->SetInteger(prefs::kAppListEnableMethod, enable_source); | |
341 if (base::MessageLoop::current()) { | |
342 // Ensure a value is recorded if the user "never" shows the app list. Note | |
343 // there is no message loop in unit tests. | |
344 base::MessageLoop::current()->PostDelayedTask( | |
345 FROM_HERE, | |
346 base::Bind(&RecordAppListDiscoverability, | |
347 base::Unretained(local_state_), | |
348 false), | |
349 base::TimeDelta::FromMinutes(kDiscoverabilityTimeoutMinutes)); | |
350 } | |
351 | |
352 AppShortcutManager* shortcut_manager = | 265 AppShortcutManager* shortcut_manager = |
353 AppShortcutManagerFactory::GetForProfile(initial_profile); | 266 AppShortcutManagerFactory::GetForProfile(initial_profile); |
354 if (shortcut_manager) | 267 if (shortcut_manager) |
355 shortcut_manager->OnceOffCreateShortcuts(); | 268 shortcut_manager->OnceOffCreateShortcuts(); |
356 } | 269 } |
357 | 270 |
358 void AppListServiceImpl::InvalidatePendingProfileLoads() { | 271 void AppListServiceImpl::InvalidatePendingProfileLoads() { |
359 profile_loader_->InvalidatePendingProfileLoads(); | 272 profile_loader_->InvalidatePendingProfileLoads(); |
360 } | 273 } |
361 | 274 |
362 void AppListServiceImpl::PerformStartupChecks(Profile* initial_profile) { | 275 void AppListServiceImpl::HandleCommandLineFlags(Profile* initial_profile) { |
363 // Except in rare, once-off cases, this just checks that a pref is "0" and | |
364 // returns. | |
365 RecordAppListDiscoverability(local_state_, true); | |
366 | |
367 if (command_line_.HasSwitch(switches::kResetAppListInstallState)) | 276 if (command_line_.HasSwitch(switches::kResetAppListInstallState)) |
368 local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, false); | 277 local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, false); |
369 | 278 |
370 if (command_line_.HasSwitch(switches::kEnableAppList)) | 279 if (command_line_.HasSwitch(switches::kEnableAppList)) |
371 EnableAppList(initial_profile, ENABLE_VIA_COMMAND_LINE); | 280 EnableAppList(initial_profile); |
| 281 } |
372 | 282 |
373 if (!base::MessageLoop::current()) | 283 void AppListServiceImpl::SendUsageStats() { |
374 return; // In a unit test. | |
375 | |
376 // Send app list usage stats after a delay. | 284 // Send app list usage stats after a delay. |
377 const int kSendUsageStatsDelay = 5; | 285 const int kSendUsageStatsDelay = 5; |
378 base::MessageLoop::current()->PostDelayedTask( | 286 base::MessageLoop::current()->PostDelayedTask( |
379 FROM_HERE, | 287 FROM_HERE, |
380 base::Bind(&AppListServiceImpl::SendAppListStats), | 288 base::Bind(&AppListServiceImpl::SendAppListStats), |
381 base::TimeDelta::FromSeconds(kSendUsageStatsDelay)); | 289 base::TimeDelta::FromSeconds(kSendUsageStatsDelay)); |
382 } | 290 } |
OLD | NEW |