12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/app_list/app_list_service.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/command_line.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/metrics/histogram.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
10bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/process_info.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/common/chrome_switches.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/pref_names.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)enum StartupType {
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  COLD_START,
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  WARM_START,
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  WARM_START_FAST,
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// For when an app list show request is received via CommandLine. Indicates
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// whether the Profile the app list was previously showing was the SAME, OTHER
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// or NONE with respect to the new Profile to show.
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdochenum ProfileLoadState {
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PROFILE_LOADED_SAME,
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PROFILE_LOADED_OTHER,
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PROFILE_LOADED_NONE,
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch};
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)base::Time GetOriginalProcessStartTime(const CommandLine& command_line) {
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (command_line.HasSwitch(switches::kOriginalProcessStartTime)) {
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string start_time_string =
363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        command_line.GetSwitchValueASCII(switches::kOriginalProcessStartTime);
373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 remote_start_time;
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::StringToInt64(start_time_string, &remote_start_time);
393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return base::Time::FromInternalValue(remote_start_time);
403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// base::CurrentProcessInfo::CreationTime() is only defined on some
433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// platforms.
443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return base::CurrentProcessInfo::CreationTime();
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#else
473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return base::Time();
4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#endif
493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)StartupType GetStartupType(const CommandLine& command_line) {
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // The presence of kOriginalProcessStartTime implies that another process
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // has sent us its command line to handle, ie: we are already running.
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (command_line.HasSwitch(switches::kOriginalProcessStartTime)) {
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return command_line.HasSwitch(switches::kFastStart) ?
563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        WARM_START_FAST : WARM_START;
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return COLD_START;
593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// The time the process that caused the app list to be shown started. This isn't
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// necessarily the currently executing process as we may be processing a command
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// line given to a short-lived Chrome instance.
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)int64 g_original_process_start_time;
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// The type of startup the the current app list show has gone through.
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)StartupType g_app_show_startup_type;
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// The state of the active app list profile at the most recent launch.
70116680a4aac90f2aa7413d9095a592090648e557Ben MurdochProfileLoadState g_profile_load_state;
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RecordFirstPaintTiming() {
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::Time start_time(
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Time::FromInternalValue(g_original_process_start_time));
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::TimeDelta elapsed = base::Time::Now() - start_time;
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  switch (g_app_show_startup_type) {
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case COLD_START:
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DCHECK_EQ(PROFILE_LOADED_NONE, g_profile_load_state);
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      UMA_HISTOGRAM_LONG_TIMES("Startup.AppListFirstPaintColdStart", elapsed);
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case WARM_START:
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // For warm starts, only record showing the same profile. "NONE" should
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // only occur in the first 30 seconds after startup. "OTHER" only occurs
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // for multi-profile cases. In these cases, timings are also affected by
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // whether or not a profile has been loaded from disk, which makes the
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // profile load asynchronous and skews results unpredictably.
87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (g_profile_load_state == PROFILE_LOADED_SAME)
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        UMA_HISTOGRAM_LONG_TIMES("Startup.AppListFirstPaintWarmStart", elapsed);
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case WARM_START_FAST:
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (g_profile_load_state == PROFILE_LOADED_SAME) {
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        UMA_HISTOGRAM_LONG_TIMES("Startup.AppListFirstPaintWarmStartFast",
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 elapsed);
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid RecordStartupInfo(AppListService* service,
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                       const CommandLine& command_line,
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                       Profile* launch_profile) {
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::Time start_time = GetOriginalProcessStartTime(command_line);
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (start_time.is_null())
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::TimeDelta elapsed = base::Time::Now() - start_time;
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  StartupType startup_type = GetStartupType(command_line);
108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  switch (startup_type) {
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case COLD_START:
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      UMA_HISTOGRAM_LONG_TIMES("Startup.ShowAppListColdStart", elapsed);
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case WARM_START:
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      UMA_HISTOGRAM_LONG_TIMES("Startup.ShowAppListWarmStart", elapsed);
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case WARM_START_FAST:
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      UMA_HISTOGRAM_LONG_TIMES("Startup.ShowAppListWarmStartFast", elapsed);
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  g_original_process_start_time = start_time.ToInternalValue();
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  g_app_show_startup_type = startup_type;
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  Profile* current_profile = service->GetCurrentAppListProfile();
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!current_profile)
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    g_profile_load_state = PROFILE_LOADED_NONE;
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  else if (current_profile == launch_profile)
127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    g_profile_load_state = PROFILE_LOADED_SAME;
128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  else
129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    g_profile_load_state = PROFILE_LOADED_OTHER;
130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  service->SetAppListNextPaintCallback(RecordFirstPaintTiming);
132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppListService::RegisterPrefs(PrefRegistrySimple* registry) {
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterInt64Pref(prefs::kLastAppListLaunchPing, 0);
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterIntegerPref(prefs::kAppListLaunchCount, 0);
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterInt64Pref(prefs::kLastAppListAppLaunchPing, 0);
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterIntegerPref(prefs::kAppListAppLaunchCount, 0);
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterStringPref(prefs::kAppListProfile, std::string());
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  registry->RegisterBooleanPref(prefs::kAppLauncherIsEnabled, false);
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  registry->RegisterBooleanPref(prefs::kAppLauncherHasBeenEnabled, false);
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  registry->RegisterIntegerPref(prefs::kAppListEnableMethod,
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                ENABLE_NOT_RECORDED);
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  registry->RegisterInt64Pref(prefs::kAppListEnableTime, 0);
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#if defined(OS_MACOSX)
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  registry->RegisterIntegerPref(prefs::kAppLauncherShortcutVersion, 0);
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Identifies whether we should show the app launcher promo or not.
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Note that a field trial also controls the showing, so the promo won't show
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // unless the pref is set AND the field trial is set to a proper group.
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  registry->RegisterBooleanPref(prefs::kShowAppLauncherPromo, true);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool AppListService::HandleLaunchCommandLine(
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::CommandLine& command_line,
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    Profile* launch_profile) {
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  InitAll(launch_profile);
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!command_line.HasSwitch(switches::kShowAppList))
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // The --show-app-list switch is used for shortcuts on the native desktop.
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  AppListService* service = Get(chrome::HOST_DESKTOP_TYPE_NATIVE);
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(service);
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  RecordStartupInfo(service, command_line, launch_profile);
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  service->ShowForProfile(launch_profile);
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
174