| 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 |