chrome_browser_main_chromeos.cc revision 558790d6acca3451cf3a6b497803a5f07d0bec58
1// Copyright (c) 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/chromeos/chrome_browser_main_chromeos.h"
6
7#include <string>
8#include <vector>
9
10#include "ash/ash_switches.h"
11#include "ash/shell.h"
12#include "base/bind.h"
13#include "base/callback.h"
14#include "base/chromeos/chromeos_version.h"
15#include "base/command_line.h"
16#include "base/file_util.h"
17#include "base/lazy_instance.h"
18#include "base/linux_util.h"
19#include "base/message_loop/message_loop.h"
20#include "base/path_service.h"
21#include "base/prefs/pref_service.h"
22#include "base/strings/string_number_conversions.h"
23#include "base/strings/string_split.h"
24#include "chrome/browser/browser_process.h"
25#include "chrome/browser/browser_process_platform_part_chromeos.h"
26#include "chrome/browser/chrome_notification_types.h"
27#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
28#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
29#include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h"
30#include "chrome/browser/chromeos/app_mode/kiosk_app_launcher.h"
31#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
32#include "chrome/browser/chromeos/audio/audio_handler.h"
33#include "chrome/browser/chromeos/boot_times_loader.h"
34#include "chrome/browser/chromeos/contacts/contact_manager.h"
35#include "chrome/browser/chromeos/cros/cert_library.h"
36#include "chrome/browser/chromeos/dbus/cros_dbus_service.h"
37#include "chrome/browser/chromeos/display/display_configuration_observer.h"
38#include "chrome/browser/chromeos/extensions/default_app_order.h"
39#include "chrome/browser/chromeos/external_metrics.h"
40#include "chrome/browser/chromeos/imageburner/burn_manager.h"
41#include "chrome/browser/chromeos/input_method/input_method_configuration.h"
42#include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_idle_logout.h"
43#include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_screensaver.h"
44#include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
45#include "chrome/browser/chromeos/login/authenticator.h"
46#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
47#include "chrome/browser/chromeos/login/login_utils.h"
48#include "chrome/browser/chromeos/login/login_wizard.h"
49#include "chrome/browser/chromeos/login/screen_locker.h"
50#include "chrome/browser/chromeos/login/startup_utils.h"
51#include "chrome/browser/chromeos/login/user_manager.h"
52#include "chrome/browser/chromeos/login/wallpaper_manager.h"
53#include "chrome/browser/chromeos/login/wizard_controller.h"
54#include "chrome/browser/chromeos/memory/oom_priority_manager.h"
55#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
56#include "chrome/browser/chromeos/net/cros_network_change_notifier_factory.h"
57#include "chrome/browser/chromeos/net/network_change_notifier_network_library.h"
58#include "chrome/browser/chromeos/net/network_portal_detector.h"
59#include "chrome/browser/chromeos/power/brightness_observer.h"
60#include "chrome/browser/chromeos/power/idle_action_warning_observer.h"
61#include "chrome/browser/chromeos/power/peripheral_battery_observer.h"
62#include "chrome/browser/chromeos/power/power_button_observer.h"
63#include "chrome/browser/chromeos/power/power_prefs.h"
64#include "chrome/browser/chromeos/power/resume_observer.h"
65#include "chrome/browser/chromeos/power/screen_lock_observer.h"
66#include "chrome/browser/chromeos/power/suspend_observer.h"
67#include "chrome/browser/chromeos/power/user_activity_notifier.h"
68#include "chrome/browser/chromeos/power/video_activity_notifier.h"
69#include "chrome/browser/chromeos/profiles/profile_helper.h"
70#include "chrome/browser/chromeos/screensaver/screensaver_controller.h"
71#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
72#include "chrome/browser/chromeos/settings/device_settings_service.h"
73#include "chrome/browser/chromeos/settings/owner_key_util.h"
74#include "chrome/browser/chromeos/swap_metrics.h"
75#include "chrome/browser/chromeos/system/statistics_provider.h"
76#include "chrome/browser/chromeos/system_key_event_listener.h"
77#include "chrome/browser/chromeos/upgrade_detector_chromeos.h"
78#include "chrome/browser/chromeos/web_socket_proxy_controller.h"
79#include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h"
80#include "chrome/browser/defaults.h"
81#include "chrome/browser/metrics/metrics_service.h"
82#include "chrome/browser/net/chrome_network_delegate.h"
83#include "chrome/browser/policy/browser_policy_connector.h"
84#include "chrome/browser/profiles/profile.h"
85#include "chrome/browser/profiles/profile_manager.h"
86#include "chrome/browser/rlz/rlz.h"
87#include "chrome/common/chrome_paths.h"
88#include "chrome/common/chrome_switches.h"
89#include "chrome/common/chrome_version_info.h"
90#include "chrome/common/logging_chrome.h"
91#include "chrome/common/pref_names.h"
92#include "chromeos/audio/audio_devices_pref_handler.h"
93#include "chromeos/audio/audio_pref_handler.h"
94#include "chromeos/audio/cras_audio_handler.h"
95#include "chromeos/chromeos_paths.h"
96#include "chromeos/chromeos_switches.h"
97#include "chromeos/cryptohome/async_method_caller.h"
98#include "chromeos/cryptohome/cryptohome_library.h"
99#include "chromeos/dbus/dbus_thread_manager.h"
100#include "chromeos/dbus/power_policy_controller.h"
101#include "chromeos/dbus/session_manager_client.h"
102#include "chromeos/disks/disk_mount_manager.h"
103#include "chromeos/ime/input_method_manager.h"
104#include "chromeos/ime/xkeyboard.h"
105#include "chromeos/login/login_state.h"
106#include "chromeos/network/network_change_notifier_chromeos.h"
107#include "chromeos/network/network_change_notifier_factory_chromeos.h"
108#include "chromeos/network/network_handler.h"
109#include "content/public/browser/browser_thread.h"
110#include "content/public/browser/notification_service.h"
111#include "content/public/browser/power_save_blocker.h"
112#include "content/public/common/main_function_params.h"
113#include "grit/platform_locale_settings.h"
114#include "net/base/network_change_notifier.h"
115#include "net/url_request/url_request.h"
116#include "net/url_request/url_request_context_getter.h"
117
118// Exclude X11 dependents for ozone
119#if defined(USE_X11)
120#include "chrome/browser/chromeos/device_uma.h"
121#endif
122
123namespace chromeos {
124
125namespace {
126
127void ChromeOSVersionCallback(const std::string& version) {
128  base::SetLinuxDistro(std::string("CrOS ") + version);
129}
130
131class MessageLoopObserver : public base::MessageLoopForUI::Observer {
132  virtual base::EventStatus WillProcessEvent(
133      const base::NativeEvent& event) OVERRIDE {
134    return base::EVENT_CONTINUE;
135  }
136
137  virtual void DidProcessEvent(
138      const base::NativeEvent& event) OVERRIDE {
139  }
140};
141
142static base::LazyInstance<MessageLoopObserver> g_message_loop_observer =
143    LAZY_INSTANCE_INITIALIZER;
144
145// Login -----------------------------------------------------------------------
146
147// Class is used to login using passed username and password.
148// The instance will be deleted upon success or failure.
149class StubLogin : public LoginStatusConsumer,
150                  public LoginUtils::Delegate {
151 public:
152  StubLogin(std::string username, std::string password)
153      : pending_requests_(false),
154        profile_prepared_(false) {
155    authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
156    authenticator_.get()->AuthenticateToLogin(
157        g_browser_process->profile_manager()->GetDefaultProfile(),
158        UserContext(username,
159                    password,
160                    std::string()));  // auth_code
161  }
162
163  virtual ~StubLogin() {
164    LoginUtils::Get()->DelegateDeleted(this);
165  }
166
167  virtual void OnLoginFailure(const LoginFailure& error) OVERRIDE {
168    LOG(ERROR) << "Login Failure: " << error.GetErrorString();
169    delete this;
170  }
171
172  virtual void OnLoginSuccess(const UserContext& user_context,
173                              bool pending_requests,
174                              bool using_oauth) OVERRIDE {
175    pending_requests_ = pending_requests;
176    if (!profile_prepared_) {
177      // Will call OnProfilePrepared in the end.
178      LoginUtils::Get()->PrepareProfile(user_context,
179                                        std::string(),  // display_email
180                                        using_oauth,
181                                        false,          // has_cookies
182                                        true,           // has_active_session
183                                        this);
184    } else if (!pending_requests) {
185      delete this;
186    }
187  }
188
189  // LoginUtils::Delegate implementation:
190  virtual void OnProfilePrepared(Profile* profile) OVERRIDE {
191    profile_prepared_ = true;
192    LoginUtils::Get()->DoBrowserLaunch(profile, NULL);
193    if (!pending_requests_)
194      delete this;
195  }
196
197  scoped_refptr<Authenticator> authenticator_;
198  bool pending_requests_;
199  bool profile_prepared_;
200};
201
202bool ShouldAutoLaunchKioskApp(const CommandLine& command_line) {
203  KioskAppManager* app_manager = KioskAppManager::Get();
204  return command_line.HasSwitch(switches::kLoginManager) &&
205      !command_line.HasSwitch(switches::kForceLoginManagerInTests) &&
206      app_manager->IsAutoLaunchEnabled() &&
207      KioskAppLaunchError::Get() == KioskAppLaunchError::NONE;
208}
209
210void OptionallyRunChromeOSLoginManager(const CommandLine& parsed_command_line,
211                                       Profile* profile) {
212  if (parsed_command_line.HasSwitch(switches::kLoginManager)) {
213    const std::string first_screen =
214        parsed_command_line.HasSwitch(switches::kLoginScreen) ?
215            WizardController::kLoginScreenName : std::string();
216    ShowLoginWizard(first_screen);
217
218    if (KioskModeSettings::Get()->IsKioskModeEnabled())
219      InitializeKioskModeScreensaver();
220
221    // Reset reboot after update flag when login screen is shown.
222    if (!g_browser_process->browser_policy_connector()->
223        IsEnterpriseManaged()) {
224      PrefService* local_state = g_browser_process->local_state();
225      local_state->ClearPref(prefs::kRebootAfterUpdate);
226    }
227  } else if (parsed_command_line.HasSwitch(switches::kLoginUser) &&
228             parsed_command_line.HasSwitch(switches::kLoginPassword)) {
229    BootTimesLoader::Get()->RecordLoginAttempted();
230    new StubLogin(
231        parsed_command_line.GetSwitchValueASCII(switches::kLoginUser),
232        parsed_command_line.GetSwitchValueASCII(switches::kLoginPassword));
233  } else {
234    if (!parsed_command_line.HasSwitch(::switches::kTestName)) {
235      // We did not log in (we crashed or are debugging), so we need to
236      // restore Sync.
237      LoginUtils::Get()->RestoreAuthenticationSession(profile);
238    }
239  }
240}
241
242void RunAutoLaunchKioskApp() {
243  // KioskAppLauncher deletes itself when done.
244  (new KioskAppLauncher(KioskAppManager::Get(),
245                        KioskAppManager::Get()->GetAutoLaunchApp()))->Start();
246
247  // Login screen is skipped but 'login-prompt-visible' signal is still needed.
248  LOG(INFO) << "Kiosk app auto launch >> login-prompt-visible";
249  DBusThreadManager::Get()->GetSessionManagerClient()->
250      EmitLoginPromptVisible();
251}
252
253}  // namespace
254
255namespace internal {
256
257// Wrapper class for initializing dbus related services and shutting them
258// down. This gets instantiated in a scoped_ptr so that shutdown methods in the
259// destructor will get called if and only if this has been instantiated.
260class DBusServices {
261 public:
262  explicit DBusServices(const content::MainFunctionParams& parameters)
263      : network_library_initialized_(false) {
264    if (!base::chromeos::IsRunningOnChromeOS()) {
265      // Override this path on the desktop, so that the user policy key can be
266      // stored by the stub SessionManagerClient.
267      base::FilePath user_data_dir;
268      if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
269        PathService::Override(chromeos::DIR_USER_POLICY_KEYS,
270                              user_data_dir.AppendASCII("stub_user_policy"));
271      }
272    }
273
274    // Initialize DBusThreadManager for the browser. This must be done after
275    // the main message loop is started, as it uses the message loop.
276    DBusThreadManager::Initialize();
277    CrosDBusService::Initialize();
278
279    LoginState::Initialize();
280    CryptohomeLibrary::Initialize();
281    CertLoader::Initialize();
282
283    // This function and SystemKeyEventListener use InputMethodManager.
284    chromeos::input_method::Initialize(
285        content::BrowserThread::GetMessageLoopProxyForThread(
286            content::BrowserThread::UI),
287        content::BrowserThread::GetMessageLoopProxyForThread(
288            content::BrowserThread::FILE));
289    disks::DiskMountManager::Initialize();
290    cryptohome::AsyncMethodCaller::Initialize();
291
292    // Initialize NetworkLibrary only for the browser, unless running tests
293    // (which do their own NetworkLibrary setup with
294    // ScopedStubNetworkLibraryEnabler in InProcessBrowserTest).
295    if (!parameters.ui_task) {
296      const bool use_stub = !base::chromeos::IsRunningOnChromeOS();
297      NetworkLibrary::Initialize(use_stub);
298      network_library_initialized_ = true;
299    }
300
301    // Always initialize these handlers which should not conflict with
302    // NetworkLibrary.
303    NetworkHandler::Initialize();
304    CertLibrary::Initialize();
305
306    // Initialize the network change notifier for Chrome OS. The network
307    // change notifier starts to monitor changes from the power manager and
308    // the network manager.
309    if (!CommandLine::ForCurrentProcess()->HasSwitch(
310            chromeos::switches::kDisableNewNetworkChangeNotifier)) {
311      NetworkChangeNotifierFactoryChromeos::GetInstance()->Initialize();
312    } else {
313      CrosNetworkChangeNotifierFactory::GetInstance()->Init();
314    }
315
316    // Likewise, initialize the upgrade detector for Chrome OS. The upgrade
317    // detector starts to monitor changes from the update engine.
318    UpgradeDetectorChromeos::GetInstance()->Init();
319
320    if (base::chromeos::IsRunningOnChromeOS()) {
321      // Disable Num Lock on X start up for http://crosbug.com/29169.
322      input_method::InputMethodManager::Get()->GetXKeyboard()->
323          SetNumLockEnabled(false);
324    }
325
326    // Initialize the device settings service so that we'll take actions per
327    // signals sent from the session manager. This needs to happen before
328    // g_browser_process initializes BrowserPolicyConnector.
329    DeviceSettingsService::Initialize();
330    DeviceSettingsService::Get()->SetSessionManager(
331        DBusThreadManager::Get()->GetSessionManagerClient(),
332        OwnerKeyUtil::Create());
333    ConnectivityStateHelper::Initialize();
334  }
335
336  ~DBusServices() {
337    ConnectivityStateHelper::Shutdown();
338
339    CertLibrary::Shutdown();
340    NetworkHandler::Shutdown();
341    if (network_library_initialized_)
342      NetworkLibrary::Shutdown();
343
344    cryptohome::AsyncMethodCaller::Shutdown();
345    disks::DiskMountManager::Shutdown();
346    input_method::Shutdown();
347
348    CryptohomeLibrary::Shutdown();
349    LoginState::Shutdown();
350
351    CrosDBusService::Shutdown();
352
353    // NOTE: This must only be called if Initialize() was called.
354    DBusThreadManager::Shutdown();
355  }
356
357 private:
358  bool network_library_initialized_;
359
360  DISALLOW_COPY_AND_ASSIGN(DBusServices);
361};
362
363}  //  namespace internal
364
365// ChromeBrowserMainPartsChromeos ----------------------------------------------
366
367ChromeBrowserMainPartsChromeos::ChromeBrowserMainPartsChromeos(
368    const content::MainFunctionParams& parameters)
369    : ChromeBrowserMainPartsLinux(parameters) {
370}
371
372ChromeBrowserMainPartsChromeos::~ChromeBrowserMainPartsChromeos() {
373  if (KioskModeSettings::Get()->IsKioskModeEnabled())
374    ShutdownKioskModeScreensaver();
375
376  // To be precise, logout (browser shutdown) is not yet done, but the
377  // remaining work is negligible, hence we say LogoutDone here.
378  BootTimesLoader::Get()->AddLogoutTimeMarker("LogoutDone", false);
379  BootTimesLoader::Get()->WriteLogoutTimes();
380}
381
382// content::BrowserMainParts and ChromeBrowserMainExtraParts overrides ---------
383
384void ChromeBrowserMainPartsChromeos::PreEarlyInitialization() {
385  CommandLine* singleton_command_line = CommandLine::ForCurrentProcess();
386
387  if (parsed_command_line().HasSwitch(switches::kGuestSession)) {
388    // Disable sync and extensions if we're in "browse without sign-in" mode.
389    singleton_command_line->AppendSwitch(::switches::kDisableSync);
390    singleton_command_line->AppendSwitch(::switches::kDisableExtensions);
391    browser_defaults::bookmarks_enabled = false;
392  }
393
394  // If we're not running on real ChromeOS hardware (or under VM), and are not
395  // showing the login manager or attempting a command line login, login with a
396  // stub user.
397  if (!base::chromeos::IsRunningOnChromeOS() &&
398      !parsed_command_line().HasSwitch(switches::kLoginManager) &&
399      !parsed_command_line().HasSwitch(switches::kLoginUser) &&
400      !parsed_command_line().HasSwitch(switches::kGuestSession)) {
401    singleton_command_line->AppendSwitchASCII(
402        switches::kLoginUser, UserManager::kStubUser);
403    if (!parsed_command_line().HasSwitch(switches::kLoginProfile)) {
404      // This must be kept in sync with TestingProfile::kTestUserProfileDir.
405      singleton_command_line->AppendSwitchASCII(
406          switches::kLoginProfile, "test-user");
407    }
408    LOG(INFO) << "Running as stub user with profile dir: "
409              << singleton_command_line->GetSwitchValuePath(
410                  switches::kLoginProfile).value();
411  }
412
413  // Initialize the statistics provider, which will ensure that the Chrome
414  // channel info is read and made available early.
415  system::StatisticsProvider::GetInstance()->Init();
416
417  ChromeBrowserMainPartsLinux::PreEarlyInitialization();
418}
419
420void ChromeBrowserMainPartsChromeos::PreMainMessageLoopStart() {
421  // Replace the default NetworkChangeNotifierFactory with ChromeOS specific
422  // implementation. This must be done before BrowserMainLoop calls
423  // net::NetworkChangeNotifier::Create() in MainMessageLoopStart().
424  net::NetworkChangeNotifierFactory* network_change_factory;
425  // Note: At the time this is called, we have not processed about:flags
426  // so this requires that the network handler flag was passed in at the command
427  // line.
428  if (!CommandLine::ForCurrentProcess()->HasSwitch(
429          chromeos::switches::kDisableNewNetworkChangeNotifier)) {
430    LOG(WARNING) << "Using new connection change notifier.";
431    network_change_factory = new NetworkChangeNotifierFactoryChromeos();
432  } else {
433    network_change_factory = new CrosNetworkChangeNotifierFactory();
434  }
435  net::NetworkChangeNotifier::SetFactory(network_change_factory);
436  ChromeBrowserMainPartsLinux::PreMainMessageLoopStart();
437}
438
439void ChromeBrowserMainPartsChromeos::PostMainMessageLoopStart() {
440  base::MessageLoopForUI* message_loop = base::MessageLoopForUI::current();
441  message_loop->AddObserver(g_message_loop_observer.Pointer());
442
443  dbus_services_.reset(new internal::DBusServices(parameters()));
444
445  ChromeBrowserMainPartsLinux::PostMainMessageLoopStart();
446}
447
448// Threads are initialized between MainMessageLoopStart and MainMessageLoopRun.
449// about_flags settings are applied in ChromeBrowserMainParts::PreCreateThreads.
450void ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun() {
451  // Set the crypto thread after the IO thread has been created/started.
452  CertLoader::Get()->SetCryptoTaskRunner(
453      content::BrowserThread::GetMessageLoopProxyForThread(
454          content::BrowserThread::IO));
455
456  if (ash::switches::UseNewAudioHandler()) {
457    CrasAudioHandler::Initialize(
458        AudioDevicesPrefHandler::Create(g_browser_process->local_state()));
459  } else {
460    AudioHandler::Initialize(
461       AudioPrefHandler::Create(g_browser_process->local_state()));
462  }
463
464  if (!StartupUtils::IsOobeCompleted())
465    system::StatisticsProvider::GetInstance()->LoadOemManifest();
466
467  base::FilePath downloads_directory;
468  CHECK(PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &downloads_directory));
469  imageburner::BurnManager::Initialize(
470      downloads_directory, g_browser_process->system_request_context());
471
472  // Listen for system key events so that the user will be able to adjust the
473  // volume on the login screen, if Chrome is running on Chrome OS
474  // (i.e. not Linux desktop), and in non-test mode.
475  // Note: SystemKeyEventListener depends on the DBus thread.
476  if (base::chromeos::IsRunningOnChromeOS() &&
477      !parameters().ui_task) {  // ui_task is non-NULL when running tests.
478    SystemKeyEventListener::Initialize();
479  }
480
481  DeviceOAuth2TokenServiceFactory::Initialize();
482
483  ChromeBrowserMainPartsLinux::PreMainMessageLoopRun();
484}
485
486void ChromeBrowserMainPartsChromeos::PreProfileInit() {
487  // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
488  // -- immediately before Profile creation().
489
490  // Now that the file thread exists we can record our stats.
491  BootTimesLoader::Get()->RecordChromeMainStats();
492
493  // Trigger prefetching of ownership status.
494  DeviceSettingsService::Get()->Load();
495
496  // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
497  // -- just before CreateProfile().
498
499  UserManager::Initialize();
500
501  // Initialize the screen locker now so that it can receive
502  // LOGIN_USER_CHANGED notification from UserManager.
503  if (KioskModeSettings::Get()->IsKioskModeEnabled()) {
504    KioskModeIdleLogout::Initialize();
505  } else {
506    ScreenLocker::InitClass();
507  }
508
509  // This forces the ProfileManager to be created and register for the
510  // notification it needs to track the logged in user.
511  g_browser_process->profile_manager();
512
513  // ProfileHelper has to be initialized after UserManager instance is created.
514  g_browser_process->platform_part()->profile_helper()->Initialize();
515
516  // TODO(abarth): Should this move to InitializeNetworkOptions()?
517  // Allow access to file:// on ChromeOS for tests.
518  if (parsed_command_line().HasSwitch(::switches::kAllowFileAccess))
519    ChromeNetworkDelegate::AllowAccessToAllFiles();
520
521  if (parsed_command_line().HasSwitch(::switches::kEnableContacts)) {
522    contact_manager_.reset(new contacts::ContactManager());
523    contact_manager_->Init();
524  }
525
526  // There are two use cases for kLoginUser:
527  //   1) if passed in tandem with kLoginPassword, to drive a "StubLogin"
528  //   2) if passed alone, to signal that the indicated user has already
529  //      logged in and we should behave accordingly.
530  // This handles case 2.
531  bool immediate_login =
532      parsed_command_line().HasSwitch(switches::kLoginUser) &&
533      !parsed_command_line().HasSwitch(switches::kLoginPassword);
534  if (immediate_login){
535    // Redirects Chrome logging to the user data dir.
536    logging::RedirectChromeLogging(parsed_command_line());
537
538    // Load the default app order synchronously for restarting case.
539    app_order_loader_.reset(
540        new default_app_order::ExternalLoader(false /* async */));
541  }
542
543  if (!app_order_loader_) {
544    app_order_loader_.reset(
545        new default_app_order::ExternalLoader(true /* async */));
546  }
547
548  // Initialize magnification manager before ash tray is created. And this must
549  // be placed after UserManager::SessionStarted();
550  AccessibilityManager::Initialize();
551  MagnificationManager::Initialize();
552
553  // Add observers for WallpaperManager. This depends on PowerManagerClient,
554  // TimezoneSettings and CrosSettings.
555  WallpaperManager::Get()->AddObservers();
556
557  cros_version_loader_.GetVersion(VersionLoader::VERSION_FULL,
558                                  base::Bind(&ChromeOSVersionCallback),
559                                  &tracker_);
560
561  // Make sure that wallpaper boot transition and other delays in OOBE
562  // are disabled for tests and kiosk app launch by default.
563  // Individual tests may enable them if they want.
564  if (parsed_command_line().HasSwitch(::switches::kTestType) ||
565      ShouldAutoLaunchKioskApp(parsed_command_line())) {
566    WizardController::SetZeroDelays();
567  }
568
569  power_prefs_.reset(new PowerPrefs(
570      DBusThreadManager::Get()->GetPowerPolicyController()));
571
572  // In Aura builds this will initialize ash::Shell.
573  ChromeBrowserMainPartsLinux::PreProfileInit();
574
575  if (immediate_login) {
576    std::string username =
577        parsed_command_line().GetSwitchValueASCII(switches::kLoginUser);
578    UserManager* user_manager = UserManager::Get();
579    // In case of multi-profiles --login-profile will contain user_id_hash.
580    std::string username_hash =
581        parsed_command_line().GetSwitchValueASCII(switches::kLoginProfile);
582    user_manager->UserLoggedIn(username, username_hash, true);
583    VLOG(1) << "Relaunching browser for user: " << username
584            << " with hash: " << username_hash;
585  }
586}
587
588void ChromeBrowserMainPartsChromeos::PostProfileInit() {
589  // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
590  // -- just after CreateProfile().
591
592  // Restarting Chrome inside existing user session. Possible cases:
593  // 1. Chrome is restarted after crash.
594  // 2. Chrome is started in browser_tests skipping the login flow
595  // 3. Chrome is started on dev machine
596  //    i.e. not on Chrome OS device w/o login flow.
597  if (parsed_command_line().HasSwitch(switches::kLoginUser) &&
598      !parsed_command_line().HasSwitch(switches::kLoginPassword)) {
599    // This is done in LoginUtils::OnProfileCreated during normal login.
600    LoginUtils::Get()->InitRlzDelayed(profile());
601
602    // Send the PROFILE_PREPARED notification and call SessionStarted()
603    // so that the Launcher and other Profile dependent classes are created.
604    content::NotificationService::current()->Notify(
605        chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
606        content::NotificationService::AllSources(),
607        content::Details<Profile>(profile()));
608    UserManager::Get()->SessionStarted();
609
610    // Now is the good time to retrieve other logged in users for this session.
611    // First user has been already marked as logged in and active in
612    // PreProfileInit(). Chrome should tread other user in a session as active
613    // in the background.
614    UserManager::Get()->RestoreActiveSessions();
615  }
616
617  // Start loading the machine statistics. Note: if we start loading machine
618  // statistics early in PreEarlyInitialization() then the crossystem tool
619  // sometimes hangs for unknown reasons, see http://crbug.com/167671.
620  // Also we must start loading no later than this point, because login manager
621  // may call GetMachineStatistic() during startup, see crbug.com/170635.
622  system::StatisticsProvider::GetInstance()->StartLoadingMachineStatistics();
623
624  // Tests should be able to tune login manager before showing it.
625  // Thus only show login manager in normal (non-testing) mode.
626  if (!parameters().ui_task ||
627      parsed_command_line().HasSwitch(switches::kForceLoginManagerInTests)) {
628    if (ShouldAutoLaunchKioskApp(parsed_command_line())) {
629      RunAutoLaunchKioskApp();
630    } else {
631      OptionallyRunChromeOSLoginManager(parsed_command_line(), profile());
632    }
633  }
634
635  // These observers must be initialized after the profile because
636  // they use the profile to dispatch extension events.
637  //
638  // Initialize the brightness observer so that we'll display an onscreen
639  // indication of brightness changes during login.
640  brightness_observer_.reset(new BrightnessObserver());
641  resume_observer_.reset(new ResumeObserver());
642  screen_lock_observer_.reset(new ScreenLockObserver());
643  if (CommandLine::ForCurrentProcess()->HasSwitch(
644      switches::kEnableScreensaverExtensions)) {
645    screensaver_controller_.reset(new ScreensaverController());
646  }
647  suspend_observer_.reset(new SuspendObserver());
648  if (KioskModeSettings::Get()->IsKioskModeEnabled()) {
649    retail_mode_power_save_blocker_ = content::PowerSaveBlocker::Create(
650        content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
651        "Retail mode");
652  }
653
654  peripheral_battery_observer_.reset(new PeripheralBatteryObserver());
655
656  // Initialize the network portal detector for Chrome OS. The network
657  // portal detector starts to listen for notifications from
658  // NetworkLibrary about changes in the NetworkManager and initiates
659  // captive portal detection for active networks.
660  NetworkPortalDetector* detector = NetworkPortalDetector::GetInstance();
661  if (NetworkPortalDetector::IsEnabledInCommandLine() && detector) {
662    detector->Init();
663#if defined(GOOGLE_CHROME_BUILD)
664    bool is_official_build = true;
665#else
666    bool is_official_build = false;
667#endif
668    // Enable portal detector if EULA was previously accepted or if
669    // this is an unofficial build.
670    if (!is_official_build || StartupUtils::IsEulaAccepted())
671      detector->Enable(true);
672  }
673
674  display_configuration_observer_.reset(
675      new DisplayConfigurationObserver());
676
677  g_browser_process->platform_part()->InitializeAutomaticRebootManager();
678
679  // This observer cannot be created earlier because it requires the shell to be
680  // available.
681  idle_action_warning_observer_.reset(new IdleActionWarningObserver());
682
683  ChromeBrowserMainPartsLinux::PostProfileInit();
684}
685
686void ChromeBrowserMainPartsChromeos::PreBrowserStart() {
687  // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
688  // -- just before MetricsService::LogNeedForCleanShutdown().
689
690  g_browser_process->metrics_service()->StartExternalMetrics();
691
692  // Listen for XI_HierarchyChanged events. Note: if this is moved to
693  // PreMainMessageLoopRun() then desktopui_PageCyclerTests fail for unknown
694  // reasons, see http://crosbug.com/24833.
695  XInputHierarchyChangedEventListener::GetInstance();
696
697#if defined(USE_X11)
698  // Start the CrOS input device UMA watcher
699  DeviceUMA::GetInstance();
700#endif
701
702  // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
703  // -- immediately after ChildProcess::WaitForDebugger().
704
705  // Swap metrics watcher must be installed before browser is activated.
706  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSwapMetrics))
707    swap_metrics_.reset(new SwapMetrics);
708
709  // Start the out-of-memory priority manager here so that we give the most
710  // amount of time for the other services to start up before we start
711  // adjusting the oom priority.
712  g_browser_process->platform_part()->oom_priority_manager()->Start();
713
714  ChromeBrowserMainPartsLinux::PreBrowserStart();
715}
716
717void ChromeBrowserMainPartsChromeos::PostBrowserStart() {
718  // These are dependent on the ash::Shell singleton already having been
719  // initialized.
720  power_button_observer_.reset(new PowerButtonObserver);
721  user_activity_notifier_.reset(new UserActivityNotifier);
722  video_activity_notifier_.reset(new VideoActivityNotifier);
723
724  ChromeBrowserMainPartsLinux::PostBrowserStart();
725}
726
727// Shut down services before the browser process, etc are destroyed.
728void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
729  BootTimesLoader::Get()->AddLogoutTimeMarker("UIMessageLoopEnded", true);
730
731  g_browser_process->platform_part()->oom_priority_manager()->Stop();
732
733  swap_metrics_.reset();
734
735  // Stops LoginUtils background fetchers. This is needed because IO thread is
736  // going to stop soon after this function. The pending background jobs could
737  // cause it to crash during shutdown.
738  LoginUtils::Get()->StopBackgroundFetchers();
739
740  // Stops all in-flight OAuth2 token fetchers before the IO thread stops.
741  DeviceOAuth2TokenServiceFactory::Shutdown();
742
743  // Shutdown the upgrade detector for Chrome OS. The upgrade detector
744  // stops monitoring changes from the update engine.
745  if (UpgradeDetectorChromeos::GetInstance())
746    UpgradeDetectorChromeos::GetInstance()->Shutdown();
747
748  // Shutdown the network change notifier for Chrome OS. The network
749  // change notifier stops monitoring changes from the power manager and
750  // the network manager.
751  if (CrosNetworkChangeNotifierFactory::GetInstance())
752    CrosNetworkChangeNotifierFactory::GetInstance()->Shutdown();
753  if (NetworkChangeNotifierFactoryChromeos::GetInstance())
754    NetworkChangeNotifierFactoryChromeos::GetInstance()->Shutdown();
755
756  NetworkPortalDetector* detector = NetworkPortalDetector::GetInstance();
757  if (NetworkPortalDetector::IsEnabledInCommandLine() && detector)
758    detector->Shutdown();
759
760  // Tell DeviceSettingsService to stop talking to session_manager. Do not
761  // shutdown DeviceSettingsService yet, it might still be accessed by
762  // BrowserPolicyConnector (owned by g_browser_process).
763  DeviceSettingsService::Get()->UnsetSessionManager();
764
765  // We should remove observers attached to D-Bus clients before
766  // DBusThreadManager is shut down.
767  screen_lock_observer_.reset();
768  suspend_observer_.reset();
769  resume_observer_.reset();
770  brightness_observer_.reset();
771  retail_mode_power_save_blocker_.reset();
772  peripheral_battery_observer_.reset();
773  power_prefs_.reset();
774
775  // The XInput2 event listener needs to be shut down earlier than when
776  // Singletons are finally destroyed in AtExitManager.
777  XInputHierarchyChangedEventListener::GetInstance()->Stop();
778
779#if defined(USE_X11)
780  DeviceUMA::GetInstance()->Stop();
781#endif
782
783  // SystemKeyEventListener::Shutdown() is always safe to call,
784  // even if Initialize() wasn't called.
785  SystemKeyEventListener::Shutdown();
786  imageburner::BurnManager::Shutdown();
787  if (ash::switches::UseNewAudioHandler()) {
788    CrasAudioHandler::Shutdown();
789  } else {
790    AudioHandler::Shutdown();
791  }
792
793  WebSocketProxyController::Shutdown();
794
795  // Let classes unregister themselves as observers of the ash::Shell singleton
796  // before the shell is destroyed.
797  user_activity_notifier_.reset();
798  video_activity_notifier_.reset();
799  display_configuration_observer_.reset();
800
801  // Detach D-Bus clients before DBusThreadManager is shut down.
802  power_button_observer_.reset();
803  screensaver_controller_.reset();
804  idle_action_warning_observer_.reset();
805
806  // Delete ContactManager while |g_browser_process| is still alive.
807  contact_manager_.reset();
808
809  MagnificationManager::Shutdown();
810  AccessibilityManager::Shutdown();
811
812  // Let the UserManager and WallpaperManager unregister itself as an observer
813  // of the CrosSettings singleton before it is destroyed.
814  UserManager::Get()->Shutdown();
815  WallpaperManager::Get()->Shutdown();
816
817  // Let the AutomaticRebootManager unregister itself as an observer of several
818  // subsystems.
819  g_browser_process->platform_part()->ShutdownAutomaticRebootManager();
820
821  // Clean up dependency on CrosSettings and stop pending data fetches.
822  KioskAppManager::Shutdown();
823
824  ChromeBrowserMainPartsLinux::PostMainMessageLoopRun();
825
826  // Destroy the UserManager after ash has been destroyed and
827  // ChromeBrowserMainPartsLinux::PostMainMessageLoopRun run.  The latter might
828  // trigger MergeSessionThrottle::ShouldShowMergeSessionPage, which requires
829  // the UserManager to exist.
830  UserManager::Destroy();
831}
832
833void ChromeBrowserMainPartsChromeos::PostDestroyThreads() {
834  // Destroy DBus services immediately after threads are stopped.
835  dbus_services_.reset();
836
837  ChromeBrowserMainPartsLinux::PostDestroyThreads();
838
839  // Destroy DeviceSettingsService after g_browser_process.
840  DeviceSettingsService::Shutdown();
841}
842
843void ChromeBrowserMainPartsChromeos::SetupPlatformFieldTrials() {
844  default_pinned_apps_field_trial::SetupTrial();
845}
846
847}  //  namespace chromeos
848