Index: chrome/browser/ui/app_list/app_list_service_impl.cc |
diff --git a/chrome/browser/ui/app_list/app_list_service_impl.cc b/chrome/browser/ui/app_list/app_list_service_impl.cc |
index 043da34896f22c3d8a14cce14981d3f0535f6bdb..0a133c59929e1a9edd0f476d6f56cb20d118e2d6 100644 |
--- a/chrome/browser/ui/app_list/app_list_service_impl.cc |
+++ b/chrome/browser/ui/app_list/app_list_service_impl.cc |
@@ -15,6 +15,7 @@ |
#include "chrome/browser/apps/shortcut_manager.h" |
#include "chrome/browser/apps/shortcut_manager_factory.h" |
#include "chrome/browser/browser_process.h" |
+#include "chrome/browser/browser_shutdown.h" |
#include "chrome/browser/profiles/profile_manager.h" |
#include "chrome/browser/ui/app_list/keep_alive_service.h" |
#include "chrome/browser/ui/app_list/keep_alive_service_impl.h" |
@@ -27,6 +28,8 @@ |
namespace { |
+const int kDiscoverabilityTimeoutMinutes = 60; |
+ |
void SendAppListAppLaunch(int count) { |
UMA_HISTOGRAM_CUSTOM_COUNTS( |
"Apps.AppListDailyAppLaunches", count, 1, 1000, 50); |
@@ -66,6 +69,9 @@ void RecordDailyEventFrequency( |
const char* last_ping_pref, |
const char* count_pref, |
void (*send_callback)(int count)) { |
+ if (!g_browser_process) |
+ return; // In a unit test. |
+ |
PrefService* local_state = g_browser_process->local_state(); |
int count = local_state->GetInteger(count_pref); |
@@ -138,13 +144,67 @@ class ProfileStoreImpl : public ProfileStore { |
base::WeakPtrFactory<ProfileStoreImpl> weak_factory_; |
}; |
+void RecordAppListDiscoverability(PrefService* local_state, |
+ bool is_startup_check) { |
+ // Since this task may be delayed, ensure it does not interfere with shutdown |
+ // when they unluckily coincide. |
+ if (browser_shutdown::IsTryingToQuit()) |
+ return; |
+ |
+ int64 enable_time_value = local_state->GetInt64(prefs::kAppListEnableTime); |
+ if (enable_time_value == 0) |
+ return; // Already recorded or never enabled. |
+ |
+ base::Time app_list_enable_time = |
+ base::Time::FromInternalValue(enable_time_value); |
+ if (is_startup_check) { |
+ // When checking at startup, only clear and record the "timeout" case, |
+ // otherwise wait for a timeout. |
+ base::TimeDelta time_remaining = |
+ app_list_enable_time + |
+ base::TimeDelta::FromMinutes(kDiscoverabilityTimeoutMinutes) - |
+ base::Time::Now(); |
+ if (time_remaining > base::TimeDelta()) { |
+ base::MessageLoop::current()->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&RecordAppListDiscoverability, |
+ base::Unretained(local_state), |
+ false), |
+ time_remaining); |
+ return; |
+ } |
+ } |
+ |
+ local_state->SetInt64(prefs::kAppListEnableTime, 0); |
+ |
+ AppListService::AppListEnableSource enable_source = |
+ static_cast<AppListService::AppListEnableSource>( |
+ local_state->GetInteger(prefs::kAppListEnableMethod)); |
+ if (enable_source == AppListService::ENABLE_FOR_APP_INSTALL) { |
+ base::TimeDelta time_taken = base::Time::Now() - app_list_enable_time; |
+ // This means the user "discovered" the app launcher naturally, after it was |
+ // enabled on the first app install. Record how long it took to discover. |
+ // Note that the last bucket is essentially "not discovered": subtract 1 |
+ // minute to account for clock inaccuracy. |
+ UMA_HISTOGRAM_CUSTOM_TIMES( |
+ "Apps.AppListTimeToDiscover", |
+ time_taken, |
+ base::TimeDelta::FromSeconds(1), |
+ base::TimeDelta::FromMinutes(kDiscoverabilityTimeoutMinutes - 1), |
+ 10 /* bucket_count */); |
+ } |
+ UMA_HISTOGRAM_ENUMERATION("Apps.AppListHowEnabled", |
+ enable_source, |
+ AppListService::ENABLE_NUM_ENABLE_SOURCES); |
+} |
+ |
} // namespace |
-// static |
void AppListServiceImpl::RecordAppListLaunch() { |
RecordDailyEventFrequency(prefs::kLastAppListLaunchPing, |
prefs::kAppListLaunchCount, |
&SendAppListLaunch); |
+ RecordAppListDiscoverability(local_state_, false); |
} |
// static |
@@ -255,13 +315,40 @@ void AppListServiceImpl::Show() { |
weak_factory_.GetWeakPtr())); |
} |
-void AppListServiceImpl::EnableAppList(Profile* initial_profile) { |
+void AppListServiceImpl::AutoShowForProfile(Profile* requested_profile) { |
+ if (local_state_->GetInt64(prefs::kAppListEnableTime) != 0) { |
+ // User has not yet discovered the app launcher. Update the enable method to |
+ // indicate this. It will then be recorded in UMA. |
+ local_state_->SetInteger(prefs::kAppListEnableMethod, |
+ ENABLE_SHOWN_UNDISCOVERED); |
+ } |
+ ShowForProfile(requested_profile); |
+} |
+ |
+void AppListServiceImpl::EnableAppList(Profile* initial_profile, |
+ AppListEnableSource enable_source) { |
SetProfilePath(initial_profile->GetPath()); |
if (local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)) |
return; |
local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, true); |
CreateShortcut(); |
+ |
+ // UMA for launcher discoverability. |
+ local_state_->SetInt64(prefs::kAppListEnableTime, |
+ base::Time::Now().ToInternalValue()); |
+ local_state_->SetInteger(prefs::kAppListEnableMethod, enable_source); |
+ if (base::MessageLoop::current()) { |
+ // Ensure a value is recorded if the user "never" shows the app list. Note |
+ // there is no message loop in unit tests. |
+ base::MessageLoop::current()->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&RecordAppListDiscoverability, |
+ base::Unretained(local_state_), |
+ false), |
+ base::TimeDelta::FromMinutes(kDiscoverabilityTimeoutMinutes)); |
+ } |
+ |
AppShortcutManager* shortcut_manager = |
AppShortcutManagerFactory::GetForProfile(initial_profile); |
if (shortcut_manager) |
@@ -272,15 +359,20 @@ void AppListServiceImpl::InvalidatePendingProfileLoads() { |
profile_loader_->InvalidatePendingProfileLoads(); |
} |
-void AppListServiceImpl::HandleCommandLineFlags(Profile* initial_profile) { |
+void AppListServiceImpl::PerformStartupChecks(Profile* initial_profile) { |
+ // Except in rare, once-off cases, this just checks that a pref is "0" and |
+ // returns. |
+ RecordAppListDiscoverability(local_state_, true); |
+ |
if (command_line_.HasSwitch(switches::kResetAppListInstallState)) |
local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, false); |
if (command_line_.HasSwitch(switches::kEnableAppList)) |
- EnableAppList(initial_profile); |
-} |
+ EnableAppList(initial_profile, ENABLE_VIA_COMMAND_LINE); |
+ |
+ if (!base::MessageLoop::current()) |
+ return; // In a unit test. |
-void AppListServiceImpl::SendUsageStats() { |
// Send app list usage stats after a delay. |
const int kSendUsageStatsDelay = 5; |
base::MessageLoop::current()->PostDelayedTask( |