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