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.
5 #include "chrome/browser/ui/app_list/app_list_service_impl.h"
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/apps/shortcut_manager.h"
16 #include "chrome/browser/apps/shortcut_manager_factory.h"
17 #include "chrome/browser/browser_process.h"
18 #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_impl.h"
21 #include "chrome/browser/ui/app_list/profile_loader.h"
22 #include "chrome/browser/ui/app_list/profile_store.h"
23 #include "chrome/common/chrome_constants.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/pref_names.h"
26 #include "content/public/browser/browser_thread.h"
30 void SendAppListAppLaunch(int count) {
31 UMA_HISTOGRAM_CUSTOM_COUNTS(
32 "Apps.AppListDailyAppLaunches", count, 1, 1000, 50);
34 UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppToday", 1, 2);
37 void SendAppListLaunch(int count) {
38 UMA_HISTOGRAM_CUSTOM_COUNTS(
39 "Apps.AppListDailyLaunches", count, 1, 1000, 50);
41 UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppListToday", 1, 2);
44 bool SendDailyEventFrequency(
45 const char* last_ping_pref,
46 const char* count_pref,
47 void (*send_callback)(int count)) {
48 PrefService* local_state = g_browser_process->local_state();
50 base::Time now = base::Time::Now();
51 base::Time last = base::Time::FromInternalValue(local_state->GetInt64(
53 int days = (now - last).InDays();
55 send_callback(local_state->GetInteger(count_pref));
56 local_state->SetInt64(
58 (last + base::TimeDelta::FromDays(days)).ToInternalValue());
59 local_state->SetInteger(count_pref, 0);
65 void RecordDailyEventFrequency(
66 const char* last_ping_pref,
67 const char* count_pref,
68 void (*send_callback)(int count)) {
69 PrefService* local_state = g_browser_process->local_state();
71 int count = local_state->GetInteger(count_pref);
72 local_state->SetInteger(count_pref, count + 1);
73 if (SendDailyEventFrequency(last_ping_pref, count_pref, send_callback)) {
74 local_state->SetInteger(count_pref, 1);
78 class ProfileStoreImpl : public ProfileStore {
80 explicit ProfileStoreImpl(ProfileManager* profile_manager)
81 : profile_manager_(profile_manager),
85 virtual void AddProfileObserver(ProfileInfoCacheObserver* observer) OVERRIDE {
86 profile_manager_->GetProfileInfoCache().AddObserver(observer);
89 virtual void LoadProfileAsync(
90 const base::FilePath& path,
91 base::Callback<void(Profile*)> callback) OVERRIDE {
92 profile_manager_->CreateProfileAsync(
94 base::Bind(&ProfileStoreImpl::OnProfileCreated,
95 weak_factory_.GetWeakPtr(),
102 void OnProfileCreated(base::Callback<void(Profile*)> callback,
104 Profile::CreateStatus status) {
106 case Profile::CREATE_STATUS_CREATED:
108 case Profile::CREATE_STATUS_INITIALIZED:
109 callback.Run(profile);
111 case Profile::CREATE_STATUS_LOCAL_FAIL:
112 case Profile::CREATE_STATUS_REMOTE_FAIL:
113 case Profile::CREATE_STATUS_CANCELED:
115 case Profile::MAX_CREATE_STATUS:
121 virtual Profile* GetProfileByPath(const base::FilePath& path) OVERRIDE {
122 return profile_manager_->GetProfileByPath(path);
125 virtual base::FilePath GetUserDataDir() OVERRIDE {
126 return profile_manager_->user_data_dir();
129 virtual bool IsProfileManaged(const base::FilePath& profile_path) OVERRIDE {
130 ProfileInfoCache& profile_info =
131 g_browser_process->profile_manager()->GetProfileInfoCache();
132 size_t profile_index = profile_info.GetIndexOfProfileWithPath(profile_path);
133 return profile_info.ProfileIsManagedAtIndex(profile_index);
137 ProfileManager* profile_manager_;
138 base::WeakPtrFactory<ProfileStoreImpl> weak_factory_;
144 void AppListServiceImpl::RecordAppListLaunch() {
145 RecordDailyEventFrequency(prefs::kLastAppListLaunchPing,
146 prefs::kAppListLaunchCount,
151 void AppListServiceImpl::RecordAppListAppLaunch() {
152 RecordDailyEventFrequency(prefs::kLastAppListAppLaunchPing,
153 prefs::kAppListAppLaunchCount,
154 &SendAppListAppLaunch);
158 void AppListServiceImpl::SendAppListStats() {
159 if (!g_browser_process || g_browser_process->IsShuttingDown())
162 SendDailyEventFrequency(prefs::kLastAppListLaunchPing,
163 prefs::kAppListLaunchCount,
165 SendDailyEventFrequency(prefs::kLastAppListAppLaunchPing,
166 prefs::kAppListAppLaunchCount,
167 &SendAppListAppLaunch);
170 AppListServiceImpl::AppListServiceImpl()
171 : profile_store_(new ProfileStoreImpl(
172 g_browser_process->profile_manager())),
174 command_line_(*CommandLine::ForCurrentProcess()),
175 local_state_(g_browser_process->local_state()),
176 profile_loader_(new ProfileLoader(
177 profile_store_.get(),
178 scoped_ptr<KeepAliveService>(new KeepAliveServiceImpl))) {
179 profile_store_->AddProfileObserver(this);
182 AppListServiceImpl::AppListServiceImpl(
183 const CommandLine& command_line,
184 PrefService* local_state,
185 scoped_ptr<ProfileStore> profile_store,
186 scoped_ptr<KeepAliveService> keep_alive_service)
187 : profile_store_(profile_store.Pass()),
189 command_line_(command_line),
190 local_state_(local_state),
191 profile_loader_(new ProfileLoader(
192 profile_store_.get(), keep_alive_service.Pass())) {
193 profile_store_->AddProfileObserver(this);
196 AppListServiceImpl::~AppListServiceImpl() {}
198 void AppListServiceImpl::SetAppListNextPaintCallback(
199 const base::Closure& callback) {}
201 void AppListServiceImpl::HandleFirstRun() {}
203 void AppListServiceImpl::Init(Profile* initial_profile) {}
205 base::FilePath AppListServiceImpl::GetProfilePath(
206 const base::FilePath& user_data_dir) {
207 std::string app_list_profile;
208 if (local_state_->HasPrefPath(prefs::kAppListProfile))
209 app_list_profile = local_state_->GetString(prefs::kAppListProfile);
211 // If the user has no profile preference for the app launcher, default to the
212 // last browser profile used.
213 if (app_list_profile.empty() &&
214 local_state_->HasPrefPath(prefs::kProfileLastUsed)) {
215 app_list_profile = local_state_->GetString(prefs::kProfileLastUsed);
218 // If there is no last used profile recorded, use the initial profile.
219 if (app_list_profile.empty())
220 app_list_profile = chrome::kInitialProfile;
222 return user_data_dir.AppendASCII(app_list_profile);
225 void AppListServiceImpl::SetProfilePath(const base::FilePath& profile_path) {
226 // Ensure we don't set the pref to a managed user's profile path.
227 // TODO(calamity): Filter out managed profiles from the settings app so this
228 // can't get hit, so we can remove it.
229 if (profile_store_->IsProfileManaged(profile_path))
232 local_state_->SetString(
233 prefs::kAppListProfile,
234 profile_path.BaseName().MaybeAsASCII());
237 void AppListServiceImpl::CreateShortcut() {}
239 // We need to watch for profile removal to keep kAppListProfile updated.
240 void AppListServiceImpl::OnProfileWillBeRemoved(
241 const base::FilePath& profile_path) {
242 // If the profile the app list uses just got deleted, reset it to the last
244 std::string app_list_last_profile = local_state_->GetString(
245 prefs::kAppListProfile);
246 if (profile_path.BaseName().MaybeAsASCII() == app_list_last_profile) {
247 local_state_->SetString(prefs::kAppListProfile,
248 local_state_->GetString(prefs::kProfileLastUsed));
252 void AppListServiceImpl::Show() {
253 profile_loader_->LoadProfileInvalidatingOtherLoads(
254 GetProfilePath(profile_store_->GetUserDataDir()),
255 base::Bind(&AppListServiceImpl::ShowForProfile,
256 weak_factory_.GetWeakPtr()));
259 void AppListServiceImpl::EnableAppList(Profile* initial_profile) {
260 SetProfilePath(initial_profile->GetPath());
261 if (local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled))
264 local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, true);
266 AppShortcutManagerFactory::GetForProfile(initial_profile)->
267 OnceOffCreateShortcuts();
270 void AppListServiceImpl::InvalidatePendingProfileLoads() {
271 profile_loader_->InvalidatePendingProfileLoads();
274 void AppListServiceImpl::HandleCommandLineFlags(Profile* initial_profile) {
275 if (command_line_.HasSwitch(switches::kEnableAppList))
276 EnableAppList(initial_profile);
278 if (command_line_.HasSwitch(switches::kResetAppListInstallState))
279 local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, false);
282 void AppListServiceImpl::SendUsageStats() {
283 // Send app list usage stats after a delay.
284 const int kSendUsageStatsDelay = 5;
285 base::MessageLoop::current()->PostDelayedTask(
287 base::Bind(&AppListServiceImpl::SendAppListStats),
288 base::TimeDelta::FromSeconds(kSendUsageStatsDelay));