Home | History | Annotate | Download | only in app_list
      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 
     22 namespace {
     23 
     24 void 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 
     31 void 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 
     38 bool 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 
     59 void 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 
     72 bool HasAppListEnabledPreference() {
     73   PrefService* local_state = g_browser_process->local_state();
     74   return local_state->GetBoolean(apps::prefs::kAppLauncherHasBeenEnabled);
     75 }
     76 
     77 void 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
     85 void AppListServiceImpl::RecordAppListLaunch() {
     86   RecordDailyEventFrequency(prefs::kLastAppListLaunchPing,
     87                             prefs::kAppListLaunchCount,
     88                             &SendAppListLaunch);
     89 }
     90 
     91 // static
     92 void AppListServiceImpl::RecordAppListAppLaunch() {
     93   RecordDailyEventFrequency(prefs::kLastAppListAppLaunchPing,
     94                             prefs::kAppListAppLaunchCount,
     95                             &SendAppListAppLaunch);
     96 }
     97 
     98 // static
     99 void 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 
    111 AppListServiceImpl::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 
    121 AppListServiceImpl::~AppListServiceImpl() {}
    122 
    123 void AppListServiceImpl::HandleFirstRun() {}
    124 
    125 void AppListServiceImpl::Init(Profile* initial_profile) {}
    126 
    127 base::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 
    150 void AppListServiceImpl::SetProfilePath(const base::FilePath& profile_path) {
    151   g_browser_process->local_state()->SetString(
    152       prefs::kAppListProfile,
    153       profile_path.BaseName().MaybeAsASCII());
    154 }
    155 
    156 AppListControllerDelegate* AppListServiceImpl::CreateControllerDelegate() {
    157   return NULL;
    158 }
    159 
    160 void AppListServiceImpl::CreateShortcut() {}
    161 void AppListServiceImpl::OnSigninStatusChanged() {}
    162 
    163 // We need to watch for profile removal to keep kAppListProfile updated.
    164 void 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 
    177 void AppListServiceImpl::Observe(
    178     int type,
    179     const content::NotificationSource& source,
    180     const content::NotificationDetails& details) {
    181   OnSigninStatusChanged();
    182 }
    183 
    184 void 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 
    191 void AppListServiceImpl::EnableAppList(Profile* initial_profile) {
    192   SetProfilePath(initial_profile->GetPath());
    193   if (HasAppListEnabledPreference())
    194     return;
    195 
    196   SetAppListEnabledPreference(true);
    197   CreateShortcut();
    198 }
    199 
    200 Profile* AppListServiceImpl::GetCurrentAppListProfile() {
    201   return profile();
    202 }
    203 
    204 void 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 
    218 void AppListServiceImpl::InvalidatePendingProfileLoads() {
    219   profile_loader_.InvalidatePendingProfileLoads();
    220 }
    221 
    222 void 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