app_list_service_impl.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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 "base/metrics/histogram.h"
8#include "base/prefs/pref_service.h"
9#include "base/time/time.h"
10#include "chrome/browser/browser_process.h"
11#include "chrome/browser/chrome_notification_types.h"
12#include "chrome/browser/profiles/profile_manager.h"
13#include "chrome/common/chrome_constants.h"
14#include "chrome/common/pref_names.h"
15#include "content/public/browser/browser_thread.h"
16#include "content/public/browser/notification_details.h"
17#include "content/public/browser/notification_source.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
69}  // namespace
70
71// static
72void AppListServiceImpl::RecordAppListLaunch() {
73  RecordDailyEventFrequency(prefs::kLastAppListLaunchPing,
74                            prefs::kAppListLaunchCount,
75                            &SendAppListLaunch);
76}
77
78// static
79void AppListServiceImpl::RecordAppListAppLaunch() {
80  RecordDailyEventFrequency(prefs::kLastAppListAppLaunchPing,
81                            prefs::kAppListAppLaunchCount,
82                            &SendAppListAppLaunch);
83}
84
85// static
86void AppListServiceImpl::SendAppListStats() {
87  if (!g_browser_process || g_browser_process->IsShuttingDown())
88    return;
89
90  SendDailyEventFrequency(prefs::kLastAppListLaunchPing,
91                          prefs::kAppListLaunchCount,
92                          &SendAppListLaunch);
93  SendDailyEventFrequency(prefs::kLastAppListAppLaunchPing,
94                          prefs::kAppListAppLaunchCount,
95                          &SendAppListAppLaunch);
96}
97
98AppListServiceImpl::AppListServiceImpl()
99    : profile_(NULL),
100      profile_load_sequence_id_(0),
101      pending_profile_loads_(0),
102      weak_factory_(this),
103      profile_loader_(g_browser_process->profile_manager()) {
104  ProfileManager* profile_manager = g_browser_process->profile_manager();
105  profile_manager->GetProfileInfoCache().AddObserver(this);
106}
107
108AppListServiceImpl::~AppListServiceImpl() {}
109
110void AppListServiceImpl::Init(Profile* initial_profile) {}
111
112base::FilePath AppListServiceImpl::GetProfilePath(
113    const base::FilePath& user_data_dir) {
114  PrefService* local_state = g_browser_process->local_state();
115  DCHECK(local_state);
116
117  std::string app_list_profile;
118  if (local_state->HasPrefPath(prefs::kAppListProfile))
119    app_list_profile = local_state->GetString(prefs::kAppListProfile);
120
121  // If the user has no profile preference for the app launcher, default to the
122  // last browser profile used.
123  if (app_list_profile.empty() &&
124      local_state->HasPrefPath(prefs::kProfileLastUsed))
125    app_list_profile = local_state->GetString(prefs::kProfileLastUsed);
126
127  std::string profile_path = app_list_profile.empty() ?
128      chrome::kInitialProfile :
129      app_list_profile;
130
131  return user_data_dir.AppendASCII(profile_path);
132}
133
134AppListControllerDelegate* AppListServiceImpl::CreateControllerDelegate() {
135  return NULL;
136}
137
138void AppListServiceImpl::OnSigninStatusChanged() {}
139
140// We need to watch for profile removal to keep kAppListProfile updated.
141void AppListServiceImpl::OnProfileWillBeRemoved(
142    const base::FilePath& profile_path) {
143  // If the profile the app list uses just got deleted, reset it to the last
144  // used profile.
145  PrefService* local_state = g_browser_process->local_state();
146  std::string app_list_last_profile = local_state->GetString(
147      prefs::kAppListProfile);
148  if (profile_path.BaseName().MaybeAsASCII() == app_list_last_profile) {
149    local_state->SetString(prefs::kAppListProfile,
150        local_state->GetString(prefs::kProfileLastUsed));
151  }
152}
153
154void AppListServiceImpl::Observe(
155    int type,
156    const content::NotificationSource& source,
157    const content::NotificationDetails& details) {
158  OnSigninStatusChanged();
159}
160
161void AppListServiceImpl::SetAppListProfile(
162    const base::FilePath& profile_file_path) {
163  profile_loader_.LoadProfileInvalidatingOtherLoads(
164      profile_file_path, base::Bind(&AppListServiceImpl::ShowAppList,
165                                    weak_factory_.GetWeakPtr()));
166}
167
168void AppListServiceImpl::ShowForSavedProfile() {
169  SetAppListProfile(GetProfilePath(
170      g_browser_process->profile_manager()->user_data_dir()));
171}
172
173Profile* AppListServiceImpl::GetCurrentAppListProfile() {
174  return profile();
175}
176
177void AppListServiceImpl::SetProfile(Profile* new_profile) {
178  registrar_.RemoveAll();
179  profile_ = new_profile;
180  if (!profile_)
181    return;
182
183  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
184                 content::Source<Profile>(profile_));
185  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
186                 content::Source<Profile>(profile_));
187  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
188                 content::Source<Profile>(profile_));
189}
190
191void AppListServiceImpl::InvalidatePendingProfileLoads() {
192  profile_loader_.InvalidatePendingProfileLoads();
193}
194
195void AppListServiceImpl::SaveProfilePathToLocalState(
196    const base::FilePath& profile_file_path) {
197  g_browser_process->local_state()->SetString(
198      prefs::kAppListProfile,
199      profile_file_path.BaseName().MaybeAsASCII());
200}
201