app_list_service_impl.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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 "apps/pref_names.h"
8#include "base/command_line.h"
9#include "base/metrics/histogram.h"
10#include "base/prefs/pref_service.h"
11#include "base/time/time.h"
12#include "chrome/browser/browser_process.h"
13#include "chrome/browser/profiles/profile_manager.h"
14#include "chrome/common/chrome_constants.h"
15#include "chrome/common/chrome_switches.h"
16#include "chrome/common/pref_names.h"
17#include "content/public/browser/browser_thread.h"
18
19namespace {
20
21void SendAppListAppLaunch(int count) {
22  UMA_HISTOGRAM_CUSTOM_COUNTS(
23      "Apps.AppListDailyAppLaunches", count, 1, 1000, 50);
24  if (count > 0)
25    UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppToday", 1, 2);
26}
27
28void SendAppListLaunch(int count) {
29  UMA_HISTOGRAM_CUSTOM_COUNTS(
30      "Apps.AppListDailyLaunches", count, 1, 1000, 50);
31  if (count > 0)
32    UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppListToday", 1, 2);
33}
34
35bool SendDailyEventFrequency(
36    const char* last_ping_pref,
37    const char* count_pref,
38    void (*send_callback)(int count)) {
39  PrefService* local_state = g_browser_process->local_state();
40
41  base::Time now = base::Time::Now();
42  base::Time last = base::Time::FromInternalValue(local_state->GetInt64(
43      last_ping_pref));
44  int days = (now - last).InDays();
45  if (days > 0) {
46    send_callback(local_state->GetInteger(count_pref));
47    local_state->SetInt64(
48        last_ping_pref,
49        (last + base::TimeDelta::FromDays(days)).ToInternalValue());
50    local_state->SetInteger(count_pref, 0);
51    return true;
52  }
53  return false;
54}
55
56void RecordDailyEventFrequency(
57    const char* last_ping_pref,
58    const char* count_pref,
59    void (*send_callback)(int count)) {
60  PrefService* local_state = g_browser_process->local_state();
61
62  int count = local_state->GetInteger(count_pref);
63  local_state->SetInteger(count_pref, count + 1);
64  if (SendDailyEventFrequency(last_ping_pref, count_pref, send_callback)) {
65    local_state->SetInteger(count_pref, 1);
66  }
67}
68
69bool HasAppListEnabledPreference() {
70  PrefService* local_state = g_browser_process->local_state();
71  return local_state->GetBoolean(apps::prefs::kAppLauncherHasBeenEnabled);
72}
73
74void SetAppListEnabledPreference(bool enabled) {
75  PrefService* local_state = g_browser_process->local_state();
76  local_state->SetBoolean(apps::prefs::kAppLauncherHasBeenEnabled, enabled);
77}
78
79}  // namespace
80
81// static
82void AppListServiceImpl::RecordAppListLaunch() {
83  RecordDailyEventFrequency(prefs::kLastAppListLaunchPing,
84                            prefs::kAppListLaunchCount,
85                            &SendAppListLaunch);
86}
87
88// static
89void AppListServiceImpl::RecordAppListAppLaunch() {
90  RecordDailyEventFrequency(prefs::kLastAppListAppLaunchPing,
91                            prefs::kAppListAppLaunchCount,
92                            &SendAppListAppLaunch);
93}
94
95// static
96void AppListServiceImpl::SendAppListStats() {
97  if (!g_browser_process || g_browser_process->IsShuttingDown())
98    return;
99
100  SendDailyEventFrequency(prefs::kLastAppListLaunchPing,
101                          prefs::kAppListLaunchCount,
102                          &SendAppListLaunch);
103  SendDailyEventFrequency(prefs::kLastAppListAppLaunchPing,
104                          prefs::kAppListAppLaunchCount,
105                          &SendAppListAppLaunch);
106}
107
108AppListServiceImpl::AppListServiceImpl()
109    : profile_(NULL),
110      profile_load_sequence_id_(0),
111      pending_profile_loads_(0),
112      weak_factory_(this),
113      profile_loader_(g_browser_process->profile_manager()) {
114  ProfileManager* profile_manager = g_browser_process->profile_manager();
115  profile_manager->GetProfileInfoCache().AddObserver(this);
116}
117
118AppListServiceImpl::~AppListServiceImpl() {}
119
120void AppListServiceImpl::SetAppListNextPaintCallback(
121    const base::Closure& callback) {}
122
123void AppListServiceImpl::HandleFirstRun() {}
124
125void AppListServiceImpl::Init(Profile* initial_profile) {}
126
127base::FilePath AppListServiceImpl::GetProfilePath(
128    const base::FilePath& user_data_dir) {
129  PrefService* local_state = g_browser_process->local_state();
130  DCHECK(local_state);
131
132  std::string app_list_profile;
133  if (local_state->HasPrefPath(prefs::kAppListProfile))
134    app_list_profile = local_state->GetString(prefs::kAppListProfile);
135
136  // If the user has no profile preference for the app launcher, default to the
137  // last browser profile used.
138  if (app_list_profile.empty() &&
139      local_state->HasPrefPath(prefs::kProfileLastUsed)) {
140    app_list_profile = local_state->GetString(prefs::kProfileLastUsed);
141  }
142
143  // If there is no last used profile recorded, use the initial profile.
144  if (app_list_profile.empty())
145    app_list_profile = chrome::kInitialProfile;
146
147  return user_data_dir.AppendASCII(app_list_profile);
148}
149
150void AppListServiceImpl::SetProfilePath(const base::FilePath& profile_path) {
151  // Ensure we don't set the pref to a managed user's profile path.
152  ProfileInfoCache& profile_info =
153      g_browser_process->profile_manager()->GetProfileInfoCache();
154  size_t profile_index = profile_info.GetIndexOfProfileWithPath(profile_path);
155  if (profile_info.ProfileIsManagedAtIndex(profile_index))
156    return;
157
158  g_browser_process->local_state()->SetString(
159      prefs::kAppListProfile,
160      profile_path.BaseName().MaybeAsASCII());
161}
162
163void AppListServiceImpl::CreateShortcut() {}
164
165// We need to watch for profile removal to keep kAppListProfile updated.
166void AppListServiceImpl::OnProfileWillBeRemoved(
167    const base::FilePath& profile_path) {
168  // If the profile the app list uses just got deleted, reset it to the last
169  // used profile.
170  PrefService* local_state = g_browser_process->local_state();
171  std::string app_list_last_profile = local_state->GetString(
172      prefs::kAppListProfile);
173  if (profile_path.BaseName().MaybeAsASCII() == app_list_last_profile) {
174    local_state->SetString(prefs::kAppListProfile,
175        local_state->GetString(prefs::kProfileLastUsed));
176  }
177}
178
179void AppListServiceImpl::Show() {
180  profile_loader_.LoadProfileInvalidatingOtherLoads(
181      GetProfilePath(g_browser_process->profile_manager()->user_data_dir()),
182      base::Bind(&AppListServiceImpl::ShowForProfile,
183                 weak_factory_.GetWeakPtr()));
184}
185
186void AppListServiceImpl::EnableAppList(Profile* initial_profile) {
187  SetProfilePath(initial_profile->GetPath());
188  if (HasAppListEnabledPreference())
189    return;
190
191  SetAppListEnabledPreference(true);
192  CreateShortcut();
193}
194
195Profile* AppListServiceImpl::GetCurrentAppListProfile() {
196  return profile();
197}
198
199void AppListServiceImpl::SetProfile(Profile* new_profile) {
200  profile_ = new_profile;
201}
202
203void AppListServiceImpl::InvalidatePendingProfileLoads() {
204  profile_loader_.InvalidatePendingProfileLoads();
205}
206
207void AppListServiceImpl::HandleCommandLineFlags(Profile* initial_profile) {
208  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAppList))
209    EnableAppList(initial_profile);
210
211  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableAppList))
212    SetAppListEnabledPreference(false);
213
214  // Send app list usage stats after a delay.
215  const int kSendUsageStatsDelay = 5;
216  base::MessageLoop::current()->PostDelayedTask(
217      FROM_HERE,
218      base::Bind(&AppListServiceImpl::SendAppListStats),
219      base::TimeDelta::FromSeconds(kSendUsageStatsDelay));
220}
221