app_list_service_impl.cc revision ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16
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/chrome_notification_types.h"
14#include "chrome/browser/profiles/profile_manager.h"
15#include "chrome/common/chrome_constants.h"
16#include "chrome/common/chrome_switches.h"
17#include "chrome/common/pref_names.h"
18#include "content/public/browser/browser_thread.h"
19#include "content/public/browser/notification_details.h"
20#include "content/public/browser/notification_source.h"
21
22namespace {
23
24void SendAppListAppLaunch(int count) {
25  UMA_HISTOGRAM_CUSTOM_COUNTS(
26      "Apps.AppListDailyAppLaunches", count, 1, 1000, 50);
27  if (count > 0)
28    UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppToday", 1, 2);
29}
30
31void SendAppListLaunch(int count) {
32  UMA_HISTOGRAM_CUSTOM_COUNTS(
33      "Apps.AppListDailyLaunches", count, 1, 1000, 50);
34  if (count > 0)
35    UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppListToday", 1, 2);
36}
37
38bool SendDailyEventFrequency(
39    const char* last_ping_pref,
40    const char* count_pref,
41    void (*send_callback)(int count)) {
42  PrefService* local_state = g_browser_process->local_state();
43
44  base::Time now = base::Time::Now();
45  base::Time last = base::Time::FromInternalValue(local_state->GetInt64(
46      last_ping_pref));
47  int days = (now - last).InDays();
48  if (days > 0) {
49    send_callback(local_state->GetInteger(count_pref));
50    local_state->SetInt64(
51        last_ping_pref,
52        (last + base::TimeDelta::FromDays(days)).ToInternalValue());
53    local_state->SetInteger(count_pref, 0);
54    return true;
55  }
56  return false;
57}
58
59void RecordDailyEventFrequency(
60    const char* last_ping_pref,
61    const char* count_pref,
62    void (*send_callback)(int count)) {
63  PrefService* local_state = g_browser_process->local_state();
64
65  int count = local_state->GetInteger(count_pref);
66  local_state->SetInteger(count_pref, count + 1);
67  if (SendDailyEventFrequency(last_ping_pref, count_pref, send_callback)) {
68    local_state->SetInteger(count_pref, 1);
69  }
70}
71
72bool HasAppListEnabledPreference() {
73  PrefService* local_state = g_browser_process->local_state();
74  return local_state->GetBoolean(apps::prefs::kAppLauncherHasBeenEnabled);
75}
76
77void SetAppListEnabledPreference(bool enabled) {
78  PrefService* local_state = g_browser_process->local_state();
79  local_state->SetBoolean(apps::prefs::kAppLauncherHasBeenEnabled, enabled);
80}
81
82}  // namespace
83
84// static
85void AppListServiceImpl::RecordAppListLaunch() {
86  RecordDailyEventFrequency(prefs::kLastAppListLaunchPing,
87                            prefs::kAppListLaunchCount,
88                            &SendAppListLaunch);
89}
90
91// static
92void AppListServiceImpl::RecordAppListAppLaunch() {
93  RecordDailyEventFrequency(prefs::kLastAppListAppLaunchPing,
94                            prefs::kAppListAppLaunchCount,
95                            &SendAppListAppLaunch);
96}
97
98// static
99void AppListServiceImpl::SendAppListStats() {
100  if (!g_browser_process || g_browser_process->IsShuttingDown())
101    return;
102
103  SendDailyEventFrequency(prefs::kLastAppListLaunchPing,
104                          prefs::kAppListLaunchCount,
105                          &SendAppListLaunch);
106  SendDailyEventFrequency(prefs::kLastAppListAppLaunchPing,
107                          prefs::kAppListAppLaunchCount,
108                          &SendAppListAppLaunch);
109}
110
111AppListServiceImpl::AppListServiceImpl()
112    : profile_(NULL),
113      profile_load_sequence_id_(0),
114      pending_profile_loads_(0),
115      weak_factory_(this),
116      profile_loader_(g_browser_process->profile_manager()) {
117  ProfileManager* profile_manager = g_browser_process->profile_manager();
118  profile_manager->GetProfileInfoCache().AddObserver(this);
119}
120
121AppListServiceImpl::~AppListServiceImpl() {}
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  g_browser_process->local_state()->SetString(
152      prefs::kAppListProfile,
153      profile_path.BaseName().MaybeAsASCII());
154}
155
156AppListControllerDelegate* AppListServiceImpl::CreateControllerDelegate() {
157  return NULL;
158}
159
160void AppListServiceImpl::CreateShortcut() {}
161void AppListServiceImpl::OnSigninStatusChanged() {}
162
163// We need to watch for profile removal to keep kAppListProfile updated.
164void AppListServiceImpl::OnProfileWillBeRemoved(
165    const base::FilePath& profile_path) {
166  // If the profile the app list uses just got deleted, reset it to the last
167  // used profile.
168  PrefService* local_state = g_browser_process->local_state();
169  std::string app_list_last_profile = local_state->GetString(
170      prefs::kAppListProfile);
171  if (profile_path.BaseName().MaybeAsASCII() == app_list_last_profile) {
172    local_state->SetString(prefs::kAppListProfile,
173        local_state->GetString(prefs::kProfileLastUsed));
174  }
175}
176
177void AppListServiceImpl::Observe(
178    int type,
179    const content::NotificationSource& source,
180    const content::NotificationDetails& details) {
181  OnSigninStatusChanged();
182}
183
184void AppListServiceImpl::Show() {
185  profile_loader_.LoadProfileInvalidatingOtherLoads(
186      GetProfilePath(g_browser_process->profile_manager()->user_data_dir()),
187      base::Bind(&AppListServiceImpl::ShowForProfile,
188                 weak_factory_.GetWeakPtr()));
189}
190
191void AppListServiceImpl::EnableAppList(Profile* initial_profile) {
192  SetProfilePath(initial_profile->GetPath());
193  if (HasAppListEnabledPreference())
194    return;
195
196  SetAppListEnabledPreference(true);
197  CreateShortcut();
198}
199
200Profile* AppListServiceImpl::GetCurrentAppListProfile() {
201  return profile();
202}
203
204void AppListServiceImpl::SetProfile(Profile* new_profile) {
205  registrar_.RemoveAll();
206  profile_ = new_profile;
207  if (!profile_)
208    return;
209
210  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
211                 content::Source<Profile>(profile_));
212  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
213                 content::Source<Profile>(profile_));
214  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
215                 content::Source<Profile>(profile_));
216}
217
218void AppListServiceImpl::InvalidatePendingProfileLoads() {
219  profile_loader_.InvalidatePendingProfileLoads();
220}
221
222void AppListServiceImpl::HandleCommandLineFlags(Profile* initial_profile) {
223  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAppList))
224    EnableAppList(initial_profile);
225
226  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableAppList))
227    SetAppListEnabledPreference(false);
228}
229