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(void (*callback
)()) {}
200 void AppListServiceImpl::HandleFirstRun() {}
202 void AppListServiceImpl::Init(Profile
* initial_profile
) {}
204 base::FilePath
AppListServiceImpl::GetProfilePath(
205 const base::FilePath
& user_data_dir
) {
206 std::string app_list_profile
;
207 if (local_state_
->HasPrefPath(prefs::kAppListProfile
))
208 app_list_profile
= local_state_
->GetString(prefs::kAppListProfile
);
210 // If the user has no profile preference for the app launcher, default to the
211 // last browser profile used.
212 if (app_list_profile
.empty() &&
213 local_state_
->HasPrefPath(prefs::kProfileLastUsed
)) {
214 app_list_profile
= local_state_
->GetString(prefs::kProfileLastUsed
);
217 // If there is no last used profile recorded, use the initial profile.
218 if (app_list_profile
.empty())
219 app_list_profile
= chrome::kInitialProfile
;
221 return user_data_dir
.AppendASCII(app_list_profile
);
224 void AppListServiceImpl::SetProfilePath(const base::FilePath
& profile_path
) {
225 // Ensure we don't set the pref to a managed user's profile path.
226 // TODO(calamity): Filter out managed profiles from the settings app so this
227 // can't get hit, so we can remove it.
228 if (profile_store_
->IsProfileManaged(profile_path
))
231 local_state_
->SetString(
232 prefs::kAppListProfile
,
233 profile_path
.BaseName().MaybeAsASCII());
236 void AppListServiceImpl::CreateShortcut() {}
238 // We need to watch for profile removal to keep kAppListProfile updated.
239 void AppListServiceImpl::OnProfileWillBeRemoved(
240 const base::FilePath
& profile_path
) {
241 // If the profile the app list uses just got deleted, reset it to the last
243 std::string app_list_last_profile
= local_state_
->GetString(
244 prefs::kAppListProfile
);
245 if (profile_path
.BaseName().MaybeAsASCII() == app_list_last_profile
) {
246 local_state_
->SetString(prefs::kAppListProfile
,
247 local_state_
->GetString(prefs::kProfileLastUsed
));
251 void AppListServiceImpl::Show() {
252 profile_loader_
->LoadProfileInvalidatingOtherLoads(
253 GetProfilePath(profile_store_
->GetUserDataDir()),
254 base::Bind(&AppListServiceImpl::ShowForProfile
,
255 weak_factory_
.GetWeakPtr()));
258 void AppListServiceImpl::EnableAppList(Profile
* initial_profile
) {
259 SetProfilePath(initial_profile
->GetPath());
260 if (local_state_
->GetBoolean(prefs::kAppLauncherHasBeenEnabled
))
263 local_state_
->SetBoolean(prefs::kAppLauncherHasBeenEnabled
, true);
265 AppShortcutManager
* shortcut_manager
=
266 AppShortcutManagerFactory::GetForProfile(initial_profile
);
267 if (shortcut_manager
)
268 shortcut_manager
->OnceOffCreateShortcuts();
271 void AppListServiceImpl::InvalidatePendingProfileLoads() {
272 profile_loader_
->InvalidatePendingProfileLoads();
275 void AppListServiceImpl::HandleCommandLineFlags(Profile
* initial_profile
) {
276 if (command_line_
.HasSwitch(switches::kResetAppListInstallState
))
277 local_state_
->SetBoolean(prefs::kAppLauncherHasBeenEnabled
, false);
279 if (command_line_
.HasSwitch(switches::kEnableAppList
))
280 EnableAppList(initial_profile
);
283 void AppListServiceImpl::SendUsageStats() {
284 // Send app list usage stats after a delay.
285 const int kSendUsageStatsDelay
= 5;
286 base::MessageLoop::current()->PostDelayedTask(
288 base::Bind(&AppListServiceImpl::SendAppListStats
),
289 base::TimeDelta::FromSeconds(kSendUsageStatsDelay
));