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" |
18 #include "chrome/browser/profiles/profile_manager.h" | 19 #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.h" |
20 #include "chrome/browser/ui/app_list/keep_alive_service_impl.h" | 21 #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_loader.h" |
22 #include "chrome/browser/ui/app_list/profile_store.h" | 23 #include "chrome/browser/ui/app_list/profile_store.h" |
23 #include "chrome/common/chrome_constants.h" | 24 #include "chrome/common/chrome_constants.h" |
24 #include "chrome/common/chrome_switches.h" | 25 #include "chrome/common/chrome_switches.h" |
25 #include "chrome/common/pref_names.h" | 26 #include "chrome/common/pref_names.h" |
26 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
27 | 28 |
28 namespace { | 29 namespace { |
29 | 30 |
| 31 const int kDiscoverabilityTimeoutMinutes = 60; |
| 32 |
30 void SendAppListAppLaunch(int count) { | 33 void SendAppListAppLaunch(int count) { |
31 UMA_HISTOGRAM_CUSTOM_COUNTS( | 34 UMA_HISTOGRAM_CUSTOM_COUNTS( |
32 "Apps.AppListDailyAppLaunches", count, 1, 1000, 50); | 35 "Apps.AppListDailyAppLaunches", count, 1, 1000, 50); |
33 if (count > 0) | 36 if (count > 0) |
34 UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppToday", 1, 2); | 37 UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppToday", 1, 2); |
35 } | 38 } |
36 | 39 |
37 void SendAppListLaunch(int count) { | 40 void SendAppListLaunch(int count) { |
38 UMA_HISTOGRAM_CUSTOM_COUNTS( | 41 UMA_HISTOGRAM_CUSTOM_COUNTS( |
39 "Apps.AppListDailyLaunches", count, 1, 1000, 50); | 42 "Apps.AppListDailyLaunches", count, 1, 1000, 50); |
(...skipping 19 matching lines...) Expand all Loading... |
59 local_state->SetInteger(count_pref, 0); | 62 local_state->SetInteger(count_pref, 0); |
60 return true; | 63 return true; |
61 } | 64 } |
62 return false; | 65 return false; |
63 } | 66 } |
64 | 67 |
65 void RecordDailyEventFrequency( | 68 void RecordDailyEventFrequency( |
66 const char* last_ping_pref, | 69 const char* last_ping_pref, |
67 const char* count_pref, | 70 const char* count_pref, |
68 void (*send_callback)(int count)) { | 71 void (*send_callback)(int count)) { |
| 72 if (!g_browser_process) |
| 73 return; // In a unit test. |
| 74 |
69 PrefService* local_state = g_browser_process->local_state(); | 75 PrefService* local_state = g_browser_process->local_state(); |
70 | 76 |
71 int count = local_state->GetInteger(count_pref); | 77 int count = local_state->GetInteger(count_pref); |
72 local_state->SetInteger(count_pref, count + 1); | 78 local_state->SetInteger(count_pref, count + 1); |
73 if (SendDailyEventFrequency(last_ping_pref, count_pref, send_callback)) { | 79 if (SendDailyEventFrequency(last_ping_pref, count_pref, send_callback)) { |
74 local_state->SetInteger(count_pref, 1); | 80 local_state->SetInteger(count_pref, 1); |
75 } | 81 } |
76 } | 82 } |
77 | 83 |
78 class ProfileStoreImpl : public ProfileStore { | 84 class ProfileStoreImpl : public ProfileStore { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 g_browser_process->profile_manager()->GetProfileInfoCache(); | 137 g_browser_process->profile_manager()->GetProfileInfoCache(); |
132 size_t profile_index = profile_info.GetIndexOfProfileWithPath(profile_path); | 138 size_t profile_index = profile_info.GetIndexOfProfileWithPath(profile_path); |
133 return profile_info.ProfileIsManagedAtIndex(profile_index); | 139 return profile_info.ProfileIsManagedAtIndex(profile_index); |
134 } | 140 } |
135 | 141 |
136 private: | 142 private: |
137 ProfileManager* profile_manager_; | 143 ProfileManager* profile_manager_; |
138 base::WeakPtrFactory<ProfileStoreImpl> weak_factory_; | 144 base::WeakPtrFactory<ProfileStoreImpl> weak_factory_; |
139 }; | 145 }; |
140 | 146 |
| 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 |
141 } // namespace | 201 } // namespace |
142 | 202 |
143 // static | |
144 void AppListServiceImpl::RecordAppListLaunch() { | 203 void AppListServiceImpl::RecordAppListLaunch() { |
145 RecordDailyEventFrequency(prefs::kLastAppListLaunchPing, | 204 RecordDailyEventFrequency(prefs::kLastAppListLaunchPing, |
146 prefs::kAppListLaunchCount, | 205 prefs::kAppListLaunchCount, |
147 &SendAppListLaunch); | 206 &SendAppListLaunch); |
| 207 RecordAppListDiscoverability(local_state_, false); |
148 } | 208 } |
149 | 209 |
150 // static | 210 // static |
151 void AppListServiceImpl::RecordAppListAppLaunch() { | 211 void AppListServiceImpl::RecordAppListAppLaunch() { |
152 RecordDailyEventFrequency(prefs::kLastAppListAppLaunchPing, | 212 RecordDailyEventFrequency(prefs::kLastAppListAppLaunchPing, |
153 prefs::kAppListAppLaunchCount, | 213 prefs::kAppListAppLaunchCount, |
154 &SendAppListAppLaunch); | 214 &SendAppListAppLaunch); |
155 } | 215 } |
156 | 216 |
157 // static | 217 // static |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 } | 308 } |
249 } | 309 } |
250 | 310 |
251 void AppListServiceImpl::Show() { | 311 void AppListServiceImpl::Show() { |
252 profile_loader_->LoadProfileInvalidatingOtherLoads( | 312 profile_loader_->LoadProfileInvalidatingOtherLoads( |
253 GetProfilePath(profile_store_->GetUserDataDir()), | 313 GetProfilePath(profile_store_->GetUserDataDir()), |
254 base::Bind(&AppListServiceImpl::ShowForProfile, | 314 base::Bind(&AppListServiceImpl::ShowForProfile, |
255 weak_factory_.GetWeakPtr())); | 315 weak_factory_.GetWeakPtr())); |
256 } | 316 } |
257 | 317 |
258 void AppListServiceImpl::EnableAppList(Profile* initial_profile) { | 318 void AppListServiceImpl::AutoShowForProfile(Profile* requested_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) { |
259 SetProfilePath(initial_profile->GetPath()); | 330 SetProfilePath(initial_profile->GetPath()); |
260 if (local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)) | 331 if (local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)) |
261 return; | 332 return; |
262 | 333 |
263 local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, true); | 334 local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, true); |
264 CreateShortcut(); | 335 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 |
265 AppShortcutManager* shortcut_manager = | 352 AppShortcutManager* shortcut_manager = |
266 AppShortcutManagerFactory::GetForProfile(initial_profile); | 353 AppShortcutManagerFactory::GetForProfile(initial_profile); |
267 if (shortcut_manager) | 354 if (shortcut_manager) |
268 shortcut_manager->OnceOffCreateShortcuts(); | 355 shortcut_manager->OnceOffCreateShortcuts(); |
269 } | 356 } |
270 | 357 |
271 void AppListServiceImpl::InvalidatePendingProfileLoads() { | 358 void AppListServiceImpl::InvalidatePendingProfileLoads() { |
272 profile_loader_->InvalidatePendingProfileLoads(); | 359 profile_loader_->InvalidatePendingProfileLoads(); |
273 } | 360 } |
274 | 361 |
275 void AppListServiceImpl::HandleCommandLineFlags(Profile* initial_profile) { | 362 void AppListServiceImpl::PerformStartupChecks(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 |
276 if (command_line_.HasSwitch(switches::kResetAppListInstallState)) | 367 if (command_line_.HasSwitch(switches::kResetAppListInstallState)) |
277 local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, false); | 368 local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, false); |
278 | 369 |
279 if (command_line_.HasSwitch(switches::kEnableAppList)) | 370 if (command_line_.HasSwitch(switches::kEnableAppList)) |
280 EnableAppList(initial_profile); | 371 EnableAppList(initial_profile, ENABLE_VIA_COMMAND_LINE); |
281 } | |
282 | 372 |
283 void AppListServiceImpl::SendUsageStats() { | 373 if (!base::MessageLoop::current()) |
| 374 return; // In a unit test. |
| 375 |
284 // Send app list usage stats after a delay. | 376 // Send app list usage stats after a delay. |
285 const int kSendUsageStatsDelay = 5; | 377 const int kSendUsageStatsDelay = 5; |
286 base::MessageLoop::current()->PostDelayedTask( | 378 base::MessageLoop::current()->PostDelayedTask( |
287 FROM_HERE, | 379 FROM_HERE, |
288 base::Bind(&AppListServiceImpl::SendAppListStats), | 380 base::Bind(&AppListServiceImpl::SendAppListStats), |
289 base::TimeDelta::FromSeconds(kSendUsageStatsDelay)); | 381 base::TimeDelta::FromSeconds(kSendUsageStatsDelay)); |
290 } | 382 } |
OLD | NEW |