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