app_list_service_impl.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/app_list/app_list_service_impl.h" 6 7#include <string> 8 9#include "apps/pref_names.h" 10#include "base/command_line.h" 11#include "base/metrics/histogram.h" 12#include "base/prefs/pref_service.h" 13#include "base/strings/string16.h" 14#include "base/time/time.h" 15#include "chrome/browser/browser_process.h" 16#include "chrome/browser/profiles/profile_manager.h" 17#include "chrome/browser/ui/app_list/keep_alive_service.h" 18#include "chrome/browser/ui/app_list/keep_alive_service_impl.h" 19#include "chrome/browser/ui/app_list/profile_loader.h" 20#include "chrome/browser/ui/app_list/profile_store.h" 21#include "chrome/common/chrome_constants.h" 22#include "chrome/common/chrome_switches.h" 23#include "chrome/common/pref_names.h" 24#include "content/public/browser/browser_thread.h" 25 26namespace { 27 28void SendAppListAppLaunch(int count) { 29 UMA_HISTOGRAM_CUSTOM_COUNTS( 30 "Apps.AppListDailyAppLaunches", count, 1, 1000, 50); 31 if (count > 0) 32 UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppToday", 1, 2); 33} 34 35void SendAppListLaunch(int count) { 36 UMA_HISTOGRAM_CUSTOM_COUNTS( 37 "Apps.AppListDailyLaunches", count, 1, 1000, 50); 38 if (count > 0) 39 UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppListToday", 1, 2); 40} 41 42bool SendDailyEventFrequency( 43 const char* last_ping_pref, 44 const char* count_pref, 45 void (*send_callback)(int count)) { 46 PrefService* local_state = g_browser_process->local_state(); 47 48 base::Time now = base::Time::Now(); 49 base::Time last = base::Time::FromInternalValue(local_state->GetInt64( 50 last_ping_pref)); 51 int days = (now - last).InDays(); 52 if (days > 0) { 53 send_callback(local_state->GetInteger(count_pref)); 54 local_state->SetInt64( 55 last_ping_pref, 56 (last + base::TimeDelta::FromDays(days)).ToInternalValue()); 57 local_state->SetInteger(count_pref, 0); 58 return true; 59 } 60 return false; 61} 62 63void RecordDailyEventFrequency( 64 const char* last_ping_pref, 65 const char* count_pref, 66 void (*send_callback)(int count)) { 67 PrefService* local_state = g_browser_process->local_state(); 68 69 int count = local_state->GetInteger(count_pref); 70 local_state->SetInteger(count_pref, count + 1); 71 if (SendDailyEventFrequency(last_ping_pref, count_pref, send_callback)) { 72 local_state->SetInteger(count_pref, 1); 73 } 74} 75 76class ProfileStoreImpl : public ProfileStore { 77 public: 78 explicit ProfileStoreImpl(ProfileManager* profile_manager) 79 : profile_manager_(profile_manager), 80 weak_factory_(this) { 81 } 82 83 virtual void AddProfileObserver(ProfileInfoCacheObserver* observer) OVERRIDE { 84 profile_manager_->GetProfileInfoCache().AddObserver(observer); 85 } 86 87 virtual void LoadProfileAsync( 88 const base::FilePath& path, 89 base::Callback<void(Profile*)> callback) OVERRIDE { 90 profile_manager_->CreateProfileAsync( 91 path, 92 base::Bind(&ProfileStoreImpl::OnProfileCreated, 93 weak_factory_.GetWeakPtr(), 94 callback), 95 base::string16(), 96 base::string16(), 97 std::string()); 98 } 99 100 void OnProfileCreated(base::Callback<void(Profile*)> callback, 101 Profile* profile, 102 Profile::CreateStatus status) { 103 switch (status) { 104 case Profile::CREATE_STATUS_CREATED: 105 break; 106 case Profile::CREATE_STATUS_INITIALIZED: 107 callback.Run(profile); 108 break; 109 case Profile::CREATE_STATUS_LOCAL_FAIL: 110 case Profile::CREATE_STATUS_REMOTE_FAIL: 111 case Profile::CREATE_STATUS_CANCELED: 112 break; 113 case Profile::MAX_CREATE_STATUS: 114 NOTREACHED(); 115 break; 116 } 117 } 118 119 virtual Profile* GetProfileByPath(const base::FilePath& path) OVERRIDE { 120 return profile_manager_->GetProfileByPath(path); 121 } 122 123 virtual base::FilePath GetUserDataDir() OVERRIDE { 124 return profile_manager_->user_data_dir(); 125 } 126 127 virtual bool IsProfileManaged(const base::FilePath& profile_path) OVERRIDE { 128 ProfileInfoCache& profile_info = 129 g_browser_process->profile_manager()->GetProfileInfoCache(); 130 size_t profile_index = profile_info.GetIndexOfProfileWithPath(profile_path); 131 return profile_info.ProfileIsManagedAtIndex(profile_index); 132 } 133 134 private: 135 ProfileManager* profile_manager_; 136 base::WeakPtrFactory<ProfileStoreImpl> weak_factory_; 137}; 138 139} // namespace 140 141// static 142void AppListServiceImpl::RecordAppListLaunch() { 143 RecordDailyEventFrequency(prefs::kLastAppListLaunchPing, 144 prefs::kAppListLaunchCount, 145 &SendAppListLaunch); 146} 147 148// static 149void AppListServiceImpl::RecordAppListAppLaunch() { 150 RecordDailyEventFrequency(prefs::kLastAppListAppLaunchPing, 151 prefs::kAppListAppLaunchCount, 152 &SendAppListAppLaunch); 153} 154 155// static 156void AppListServiceImpl::SendAppListStats() { 157 if (!g_browser_process || g_browser_process->IsShuttingDown()) 158 return; 159 160 SendDailyEventFrequency(prefs::kLastAppListLaunchPing, 161 prefs::kAppListLaunchCount, 162 &SendAppListLaunch); 163 SendDailyEventFrequency(prefs::kLastAppListAppLaunchPing, 164 prefs::kAppListAppLaunchCount, 165 &SendAppListAppLaunch); 166} 167 168AppListServiceImpl::AppListServiceImpl() 169 : profile_store_(new ProfileStoreImpl( 170 g_browser_process->profile_manager())), 171 weak_factory_(this), 172 command_line_(*CommandLine::ForCurrentProcess()), 173 local_state_(g_browser_process->local_state()), 174 profile_loader_(new ProfileLoader( 175 profile_store_.get(), 176 scoped_ptr<KeepAliveService>(new KeepAliveServiceImpl))) { 177 profile_store_->AddProfileObserver(this); 178} 179 180AppListServiceImpl::AppListServiceImpl( 181 const CommandLine& command_line, 182 PrefService* local_state, 183 scoped_ptr<ProfileStore> profile_store, 184 scoped_ptr<KeepAliveService> keep_alive_service) 185 : profile_store_(profile_store.Pass()), 186 weak_factory_(this), 187 command_line_(command_line), 188 local_state_(local_state), 189 profile_loader_(new ProfileLoader( 190 profile_store_.get(), keep_alive_service.Pass())) { 191 profile_store_->AddProfileObserver(this); 192} 193 194AppListServiceImpl::~AppListServiceImpl() {} 195 196void AppListServiceImpl::SetAppListNextPaintCallback( 197 const base::Closure& callback) {} 198 199void AppListServiceImpl::HandleFirstRun() {} 200 201void AppListServiceImpl::Init(Profile* initial_profile) {} 202 203base::FilePath AppListServiceImpl::GetProfilePath( 204 const base::FilePath& user_data_dir) { 205 std::string app_list_profile; 206 if (local_state_->HasPrefPath(prefs::kAppListProfile)) 207 app_list_profile = local_state_->GetString(prefs::kAppListProfile); 208 209 // If the user has no profile preference for the app launcher, default to the 210 // last browser profile used. 211 if (app_list_profile.empty() && 212 local_state_->HasPrefPath(prefs::kProfileLastUsed)) { 213 app_list_profile = local_state_->GetString(prefs::kProfileLastUsed); 214 } 215 216 // If there is no last used profile recorded, use the initial profile. 217 if (app_list_profile.empty()) 218 app_list_profile = chrome::kInitialProfile; 219 220 return user_data_dir.AppendASCII(app_list_profile); 221} 222 223void AppListServiceImpl::SetProfilePath(const base::FilePath& profile_path) { 224 // Ensure we don't set the pref to a managed user's profile path. 225 // TODO(calamity): Filter out managed profiles from the settings app so this 226 // can't get hit, so we can remove it. 227 if (profile_store_->IsProfileManaged(profile_path)) 228 return; 229 230 local_state_->SetString( 231 prefs::kAppListProfile, 232 profile_path.BaseName().MaybeAsASCII()); 233} 234 235void AppListServiceImpl::CreateShortcut() {} 236 237// We need to watch for profile removal to keep kAppListProfile updated. 238void AppListServiceImpl::OnProfileWillBeRemoved( 239 const base::FilePath& profile_path) { 240 // If the profile the app list uses just got deleted, reset it to the last 241 // used profile. 242 std::string app_list_last_profile = local_state_->GetString( 243 prefs::kAppListProfile); 244 if (profile_path.BaseName().MaybeAsASCII() == app_list_last_profile) { 245 local_state_->SetString(prefs::kAppListProfile, 246 local_state_->GetString(prefs::kProfileLastUsed)); 247 } 248} 249 250void AppListServiceImpl::Show() { 251 profile_loader_->LoadProfileInvalidatingOtherLoads( 252 GetProfilePath(profile_store_->GetUserDataDir()), 253 base::Bind(&AppListServiceImpl::ShowForProfile, 254 weak_factory_.GetWeakPtr())); 255} 256 257void AppListServiceImpl::EnableAppList(Profile* initial_profile) { 258 SetProfilePath(initial_profile->GetPath()); 259 if (local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)) 260 return; 261 262 local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, true); 263 CreateShortcut(); 264} 265 266void AppListServiceImpl::InvalidatePendingProfileLoads() { 267 profile_loader_->InvalidatePendingProfileLoads(); 268} 269 270void AppListServiceImpl::HandleCommandLineFlags(Profile* initial_profile) { 271 if (command_line_.HasSwitch(switches::kEnableAppList)) 272 EnableAppList(initial_profile); 273 274 if (command_line_.HasSwitch(switches::kResetAppListInstallState)) 275 local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, false); 276} 277 278void AppListServiceImpl::SendUsageStats() { 279 // Send app list usage stats after a delay. 280 const int kSendUsageStatsDelay = 5; 281 base::MessageLoop::current()->PostDelayedTask( 282 FROM_HERE, 283 base::Bind(&AppListServiceImpl::SendAppListStats), 284 base::TimeDelta::FromSeconds(kSendUsageStatsDelay)); 285} 286