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