1 // Copyright (c) 2012 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.
5 #include "chrome/browser/chromeos/chrome_browser_main_chromeos.h"
10 #include "ash/shell.h"
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/chromeos/chromeos_version.h"
14 #include "base/command_line.h"
15 #include "base/lazy_instance.h"
16 #include "base/message_loop.h"
17 #include "base/string_number_conversions.h"
18 #include "base/string_split.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/chromeos/audio/audio_handler.h"
21 #include "chrome/browser/chromeos/boot_times_loader.h"
22 #include "chrome/browser/chromeos/contacts/contact_manager.h"
23 #include "chrome/browser/chromeos/cros/cros_library.h"
24 #include "chrome/browser/chromeos/dbus/cros_dbus_service.h"
25 #include "chrome/browser/chromeos/display/display_preferences.h"
26 #include "chrome/browser/chromeos/display/primary_display_switch_observer.h"
27 #include "chrome/browser/chromeos/external_metrics.h"
28 #include "chrome/browser/chromeos/extensions/default_app_order.h"
29 #include "chrome/browser/chromeos/imageburner/burn_manager.h"
30 #include "chrome/browser/chromeos/input_method/input_method_manager.h"
31 #include "chrome/browser/chromeos/input_method/xkeyboard.h"
32 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_idle_logout.h"
33 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_screensaver.h"
34 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
35 #include "chrome/browser/chromeos/login/authenticator.h"
36 #include "chrome/browser/chromeos/login/login_utils.h"
37 #include "chrome/browser/chromeos/login/login_wizard.h"
38 #include "chrome/browser/chromeos/login/screen_locker.h"
39 #include "chrome/browser/chromeos/login/user_manager.h"
40 #include "chrome/browser/chromeos/login/wallpaper_manager.h"
41 #include "chrome/browser/chromeos/login/wizard_controller.h"
42 #include "chrome/browser/chromeos/memory/low_memory_observer.h"
43 #include "chrome/browser/chromeos/memory/oom_priority_manager.h"
44 #include "chrome/browser/chromeos/net/cros_network_change_notifier_factory.h"
45 #include "chrome/browser/chromeos/net/network_change_notifier_chromeos.h"
46 #include "chrome/browser/chromeos/net/network_portal_detector.h"
47 #include "chrome/browser/chromeos/power/brightness_observer.h"
48 #include "chrome/browser/chromeos/power/output_observer.h"
49 #include "chrome/browser/chromeos/power/power_button_observer.h"
50 #include "chrome/browser/chromeos/power/resume_observer.h"
51 #include "chrome/browser/chromeos/power/screen_dimming_observer.h"
52 #include "chrome/browser/chromeos/power/screen_lock_observer.h"
53 #include "chrome/browser/chromeos/power/user_activity_notifier.h"
54 #include "chrome/browser/chromeos/power/video_activity_notifier.h"
55 #include "chrome/browser/chromeos/settings/device_settings_service.h"
56 #include "chrome/browser/chromeos/settings/owner_key_util.h"
57 #include "chrome/browser/chromeos/system/statistics_provider.h"
58 #include "chrome/browser/chromeos/system_key_event_listener.h"
59 #include "chrome/browser/chromeos/upgrade_detector_chromeos.h"
60 #include "chrome/browser/chromeos/web_socket_proxy_controller.h"
61 #include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h"
62 #include "chrome/browser/defaults.h"
63 #include "chrome/browser/metrics/metrics_service.h"
64 #include "chrome/browser/net/chrome_network_delegate.h"
65 #include "chrome/browser/policy/browser_policy_connector.h"
66 #include "chrome/browser/prefs/pref_service.h"
67 #include "chrome/browser/profiles/profile.h"
68 #include "chrome/browser/profiles/profile_manager.h"
69 #include "chrome/browser/signin/token_service_factory.h"
70 #include "chrome/browser/system_monitor/removable_device_notifications_chromeos.h"
71 #include "chrome/common/chrome_notification_types.h"
72 #include "chrome/common/chrome_switches.h"
73 #include "chrome/common/chrome_version_info.h"
74 #include "chrome/common/logging_chrome.h"
75 #include "chrome/common/pref_names.h"
76 #include "chromeos/chromeos_switches.h"
77 #include "chromeos/cryptohome/async_method_caller.h"
78 #include "chromeos/dbus/dbus_thread_manager.h"
79 #include "chromeos/dbus/power_manager_client.h"
80 #include "chromeos/dbus/session_manager_client.h"
81 #include "chromeos/disks/disk_mount_manager.h"
82 #include "chromeos/display/output_configurator.h"
83 #include "chromeos/network/network_state_handler.h"
84 #include "chromeos/power/power_state_override.h"
85 #include "content/public/browser/notification_service.h"
86 #include "content/public/common/main_function_params.h"
87 #include "grit/platform_locale_settings.h"
88 #include "net/base/network_change_notifier.h"
89 #include "net/url_request/url_request.h"
95 class MessageLoopObserver
: public MessageLoopForUI::Observer
{
96 virtual base::EventStatus
WillProcessEvent(
97 const base::NativeEvent
& event
) OVERRIDE
{
98 return base::EVENT_CONTINUE
;
101 virtual void DidProcessEvent(
102 const base::NativeEvent
& event
) OVERRIDE
{
106 static base::LazyInstance
<MessageLoopObserver
> g_message_loop_observer
=
107 LAZY_INSTANCE_INITIALIZER
;
109 // Login -----------------------------------------------------------------------
111 // Class is used to login using passed username and password.
112 // The instance will be deleted upon success or failure.
113 class StubLogin
: public LoginStatusConsumer
,
114 public LoginUtils::Delegate
{
116 StubLogin(std::string username
, std::string password
)
117 : pending_requests_(false),
118 profile_prepared_(false) {
119 authenticator_
= LoginUtils::Get()->CreateAuthenticator(this);
120 authenticator_
.get()->AuthenticateToLogin(
121 g_browser_process
->profile_manager()->GetDefaultProfile(),
129 LoginUtils::Get()->DelegateDeleted(this);
132 void OnLoginFailure(const LoginFailure
& error
) {
133 LOG(ERROR
) << "Login Failure: " << error
.GetErrorString();
137 void OnLoginSuccess(const std::string
& username
,
138 const std::string
& password
,
139 bool pending_requests
,
141 pending_requests_
= pending_requests
;
142 if (!profile_prepared_
) {
143 // Will call OnProfilePrepared in the end.
144 LoginUtils::Get()->PrepareProfile(username
,
151 } else if (!pending_requests
) {
156 // LoginUtils::Delegate implementation:
157 virtual void OnProfilePrepared(Profile
* profile
) {
158 profile_prepared_
= true;
159 LoginUtils::Get()->DoBrowserLaunch(profile
, NULL
);
160 if (!pending_requests_
)
164 scoped_refptr
<Authenticator
> authenticator_
;
165 bool pending_requests_
;
166 bool profile_prepared_
;
169 void OptionallyRunChromeOSLoginManager(const CommandLine
& parsed_command_line
,
171 if (parsed_command_line
.HasSwitch(::switches::kLoginManager
)) {
172 std::string first_screen
=
173 parsed_command_line
.GetSwitchValueASCII(::switches::kLoginScreen
);
174 std::string size_arg
=
175 parsed_command_line
.GetSwitchValueASCII(
176 ::switches::kLoginScreenSize
);
177 gfx::Size
size(0, 0);
178 // Allow the size of the login window to be set explicitly. If not set,
179 // default to the entire screen. This is mostly useful for testing.
180 if (size_arg
.size()) {
181 std::vector
<std::string
> dimensions
;
182 base::SplitString(size_arg
, ',', &dimensions
);
183 if (dimensions
.size() == 2) {
185 if (base::StringToInt(dimensions
[0], &width
) &&
186 base::StringToInt(dimensions
[1], &height
))
187 size
.SetSize(width
, height
);
191 ShowLoginWizard(first_screen
, size
);
193 if (KioskModeSettings::Get()->IsKioskModeEnabled())
194 InitializeKioskModeScreensaver();
195 } else if (parsed_command_line
.HasSwitch(::switches::kLoginUser
) &&
196 parsed_command_line
.HasSwitch(::switches::kLoginPassword
)) {
197 BootTimesLoader::Get()->RecordLoginAttempted();
199 parsed_command_line
.GetSwitchValueASCII(::switches::kLoginUser
),
200 parsed_command_line
.GetSwitchValueASCII(::switches::kLoginPassword
));
202 if (!parsed_command_line
.HasSwitch(::switches::kTestName
)) {
203 // We did not log in (we crashed or are debugging), so we need to
205 LoginUtils::Get()->RestoreAuthenticationSession(profile
);
214 // Wrapper class for initializing dbus related services and shutting them
215 // down. This gets instantiated in a scoped_ptr so that shutdown methods in the
216 // destructor will get called if and only if this has been instantiated.
219 explicit DBusServices(const content::MainFunctionParams
& parameters
)
220 : cros_initialized_(false),
221 network_handlers_initialized_(false) {
222 // Initialize CrosLibrary only for the browser, unless running tests
223 // (which do their own CrosLibrary setup).
224 if (!parameters
.ui_task
) {
225 const bool use_stub
= !base::chromeos::IsRunningOnChromeOS();
226 CrosLibrary::Initialize(use_stub
);
227 cros_initialized_
= true;
230 // Initialize DBusThreadManager for the browser. This must be done after
231 // the main message loop is started, as it uses the message loop.
232 DBusThreadManager::Initialize();
233 CrosDBusService::Initialize();
235 // This function and SystemKeyEventListener use InputMethodManager.
236 input_method::InputMethodManager::Initialize();
237 disks::DiskMountManager::Initialize();
238 cryptohome::AsyncMethodCaller::Initialize();
240 // Initialize the network change notifier for Chrome OS. The network
241 // change notifier starts to monitor changes from the power manager and
242 // the network manager.
243 CrosNetworkChangeNotifierFactory::GetInstance()->Init();
245 // Likewise, initialize the upgrade detector for Chrome OS. The upgrade
246 // detector starts to monitor changes from the update engine.
247 UpgradeDetectorChromeos::GetInstance()->Init();
249 if (base::chromeos::IsRunningOnChromeOS()) {
250 // Disable Num Lock on X start up for http://crosbug.com/29169.
251 input_method::InputMethodManager::GetInstance()->
252 GetXKeyboard()->SetNumLockEnabled(false);
255 // Initialize the device settings service so that we'll take actions per
256 // signals sent from the session manager.
257 DeviceSettingsService::Get()->Initialize(
258 DBusThreadManager::Get()->GetSessionManagerClient(),
259 OwnerKeyUtil::Create());
261 // Add observers for WallpaperManager. This depends on PowerManagerClient().
262 WallpaperManager::Get()->AddObservers();
265 // TODO(stevenjb): Move this into DBusServices() once the switch is no
266 // longer required. (Switch is set in about_flags.cc and not applied until
267 // after DBusServices() is called).
268 void InitializeNetworkHandlers() {
269 if (!CommandLine::ForCurrentProcess()->HasSwitch(
270 chromeos::switches::kEnableNewNetworkHandlers
))
272 chromeos::NetworkStateHandler::Initialize();
273 network_handlers_initialized_
= true;
277 // CrosLibrary is shut down before DBusThreadManager even though it
278 // is initialized first becuase some of its libraries depend on DBus
280 // TODO(hashimoto): Resolve this situation by removing CrosLibrary.
281 // (crosbug.com/26160)
282 if (cros_initialized_
&& CrosLibrary::Get())
283 CrosLibrary::Shutdown();
285 if (network_handlers_initialized_
)
286 chromeos::NetworkStateHandler::Shutdown();
288 cryptohome::AsyncMethodCaller::Shutdown();
289 disks::DiskMountManager::Shutdown();
290 input_method::InputMethodManager::Shutdown();
291 CrosDBusService::Shutdown();
292 // NOTE: This must only be called if Initialize() was called.
293 DBusThreadManager::Shutdown();
297 bool cros_initialized_
;
298 bool network_handlers_initialized_
;
300 DISALLOW_COPY_AND_ASSIGN(DBusServices
);
303 } // namespace internal
305 // ChromeBrowserMainPartsChromeos ----------------------------------------------
307 ChromeBrowserMainPartsChromeos::ChromeBrowserMainPartsChromeos(
308 const content::MainFunctionParams
& parameters
)
309 : ChromeBrowserMainPartsLinux(parameters
) {
312 ChromeBrowserMainPartsChromeos::~ChromeBrowserMainPartsChromeos() {
313 if (KioskModeSettings::Get()->IsKioskModeEnabled())
314 ShutdownKioskModeScreensaver();
316 dbus_services_
.reset();
318 // To be precise, logout (browser shutdown) is not yet done, but the
319 // remaining work is negligible, hence we say LogoutDone here.
320 BootTimesLoader::Get()->AddLogoutTimeMarker("LogoutDone", false);
321 BootTimesLoader::Get()->WriteLogoutTimes();
324 // content::BrowserMainParts and ChromeBrowserMainExtraParts overrides ---------
326 void ChromeBrowserMainPartsChromeos::PreEarlyInitialization() {
327 CommandLine
* singleton_command_line
= CommandLine::ForCurrentProcess();
329 if (parsed_command_line().HasSwitch(::switches::kGuestSession
)) {
330 // Disable sync and extensions if we're in "browse without sign-in" mode.
331 singleton_command_line
->AppendSwitch(::switches::kDisableSync
);
332 singleton_command_line
->AppendSwitch(::switches::kDisableExtensions
);
333 browser_defaults::bookmarks_enabled
= false;
336 // If we're not running on real ChromeOS hardware (or under VM), and are not
337 // showing the login manager or attempting a command line login, login with a
339 if (!base::chromeos::IsRunningOnChromeOS() &&
340 !parsed_command_line().HasSwitch(::switches::kLoginManager
) &&
341 !parsed_command_line().HasSwitch(::switches::kLoginUser
) &&
342 !parsed_command_line().HasSwitch(::switches::kGuestSession
)) {
343 singleton_command_line
->AppendSwitchASCII(
344 ::switches::kLoginUser
, UserManager::kStubUser
);
345 if (!parsed_command_line().HasSwitch(::switches::kLoginProfile
)) {
346 // This must be kept in sync with TestingProfile::kTestUserProfileDir.
347 singleton_command_line
->AppendSwitchASCII(
348 ::switches::kLoginProfile
, "test-user");
350 LOG(INFO
) << "Running as stub user with profile dir: "
351 << singleton_command_line
->GetSwitchValuePath(
352 ::switches::kLoginProfile
).value();
355 ChromeBrowserMainPartsLinux::PreEarlyInitialization();
358 void ChromeBrowserMainPartsChromeos::PreMainMessageLoopStart() {
359 // Replace the default NetworkChangeNotifierFactory with ChromeOS specific
360 // implementation. This must be done before BrowserMainLoop calls
361 // net::NetworkChangeNotifier::Create() in MainMessageLoopStart().
362 net::NetworkChangeNotifier::SetFactory(
363 new CrosNetworkChangeNotifierFactory());
365 ChromeBrowserMainPartsLinux::PreMainMessageLoopStart();
368 void ChromeBrowserMainPartsChromeos::PostMainMessageLoopStart() {
369 MessageLoopForUI
* message_loop
= MessageLoopForUI::current();
370 message_loop
->AddObserver(g_message_loop_observer
.Pointer());
372 dbus_services_
.reset(new internal::DBusServices(parameters()));
374 ChromeBrowserMainPartsLinux::PostMainMessageLoopStart();
377 // Threads are initialized between MainMessageLoopStart and MainMessageLoopRun.
378 // about_flags settings are applied in ChromeBrowserMainParts::PreCreateThreads.
380 void ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun() {
381 // Must be called after about_flags settings are applied (see note above).
382 dbus_services_
->InitializeNetworkHandlers();
384 AudioHandler::Initialize();
385 imageburner::BurnManager::Initialize();
387 // Listen for system key events so that the user will be able to adjust the
388 // volume on the login screen, if Chrome is running on Chrome OS
389 // (i.e. not Linux desktop), and in non-test mode.
390 // Note: SystemKeyEventListener depends on the DBus thread.
391 if (base::chromeos::IsRunningOnChromeOS() &&
392 !parameters().ui_task
) { // ui_task is non-NULL when running tests.
393 SystemKeyEventListener::Initialize();
396 ChromeBrowserMainPartsLinux::PreMainMessageLoopRun();
399 void ChromeBrowserMainPartsChromeos::PreProfileInit() {
400 // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
401 // -- immediately before Profile creation().
403 // Now that the file thread exists we can record our stats.
404 BootTimesLoader::Get()->RecordChromeMainStats();
406 // Trigger prefetching of ownership status.
407 DeviceSettingsService::Get()->Load();
409 // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
410 // -- just before CreateProfile().
412 // Initialize the screen locker now so that it can receive
413 // LOGIN_USER_CHANGED notification from UserManager.
414 if (KioskModeSettings::Get()->IsKioskModeEnabled()) {
415 KioskModeIdleLogout::Initialize();
417 ScreenLocker::InitClass();
420 // This forces the ProfileManager to be created and register for the
421 // notification it needs to track the logged in user.
422 g_browser_process
->profile_manager();
424 // TODO(abarth): Should this move to InitializeNetworkOptions()?
425 // Allow access to file:// on ChromeOS for tests.
426 if (parsed_command_line().HasSwitch(::switches::kAllowFileAccess
))
427 ChromeNetworkDelegate::AllowAccessToAllFiles();
429 if (parsed_command_line().HasSwitch(::switches::kEnableContacts
)) {
430 contact_manager_
.reset(new contacts::ContactManager());
431 contact_manager_
->Init();
434 // There are two use cases for kLoginUser:
435 // 1) if passed in tandem with kLoginPassword, to drive a "StubLogin"
436 // 2) if passed alone, to signal that the indicated user has already
437 // logged in and we should behave accordingly.
438 // This handles case 2.
439 if (parsed_command_line().HasSwitch(::switches::kLoginUser
) &&
440 !parsed_command_line().HasSwitch(::switches::kLoginPassword
)) {
441 std::string username
=
442 parsed_command_line().GetSwitchValueASCII(::switches::kLoginUser
);
443 VLOG(1) << "Relaunching browser for user: " << username
;
444 UserManager::Get()->UserLoggedIn(username
, true);
446 // Redirects Chrome logging to the user data dir.
447 logging::RedirectChromeLogging(parsed_command_line());
449 // Initialize user policy before creating the profile so the profile
450 // initialization code sees policy settings.
451 // Guest accounts are not subject to user policy.
452 if (!UserManager::Get()->IsLoggedInAsGuest()) {
453 g_browser_process
->browser_policy_connector()->InitializeUserPolicy(
454 username
, false /* wait_for_policy_fetch */);
457 // Load the default app order synchronously for restarting case.
458 app_order_loader_
.reset(
459 new default_app_order::ExternalLoader(false /* async */));
461 UserManager::Get()->SessionStarted();
464 if (!app_order_loader_
) {
465 app_order_loader_
.reset(
466 new default_app_order::ExternalLoader(true /* async */));
469 // In Aura builds this will initialize ash::Shell.
470 ChromeBrowserMainPartsLinux::PreProfileInit();
473 void ChromeBrowserMainPartsChromeos::PostProfileInit() {
474 // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
475 // -- just after CreateProfile().
477 policy::BrowserPolicyConnector
* connector
=
478 g_browser_process
->browser_policy_connector();
480 if (parsed_command_line().HasSwitch(::switches::kLoginUser
) &&
481 !parsed_command_line().HasSwitch(::switches::kLoginPassword
)) {
482 // Pass the TokenService pointer to the policy connector so user policy can
483 // grab a token and register with the policy server.
484 // TODO(mnissler): Remove once OAuth is the only authentication mechanism.
485 connector
->SetUserPolicyTokenService(
486 TokenServiceFactory::GetForProfile(profile()));
488 // Make sure we flip every profile to not share proxies if the user hasn't
489 // specified so explicitly.
490 const PrefService::Preference
* use_shared_proxies_pref
=
491 profile()->GetPrefs()->FindPreference(prefs::kUseSharedProxies
);
492 if (use_shared_proxies_pref
->IsDefaultValue())
493 profile()->GetPrefs()->SetBoolean(prefs::kUseSharedProxies
, false);
496 // Make sure the NetworkConfigurationUpdater is ready so that it pushes ONC
497 // configuration before login.
498 connector
->GetNetworkConfigurationUpdater();
500 // Make sure that wallpaper boot transition and other delays in OOBE
501 // are disabled for tests by default.
502 // Individual tests may enable them if they want.
503 if (parsed_command_line().HasSwitch(::switches::kTestType
))
504 WizardController::SetZeroDelays();
506 // Tests should be able to tune login manager before showing it.
507 // Thus only show login manager in normal (non-testing) mode.
508 if (!parameters().ui_task
)
509 OptionallyRunChromeOSLoginManager(parsed_command_line(), profile());
511 // These observers must be initialized after the profile because
512 // they use the profile to dispatch extension events.
514 // Initialize the brightness observer so that we'll display an onscreen
515 // indication of brightness changes during login.
516 brightness_observer_
.reset(new BrightnessObserver());
517 output_observer_
.reset(new OutputObserver());
518 resume_observer_
.reset(new ResumeObserver());
519 screen_lock_observer_
.reset(new ScreenLockObserver());
520 if (KioskModeSettings::Get()->IsKioskModeEnabled()) {
521 power_state_override_
.reset(new PowerStateOverride(
522 PowerStateOverride::BLOCK_DISPLAY_SLEEP
));
525 primary_display_switch_observer_
.reset(
526 new PrimaryDisplaySwitchObserver());
528 removable_device_notifications_
=
529 new RemovableDeviceNotificationsCros();
531 // Initialize the network portal detector for Chrome OS. The network
532 // portal detector starts to listen for notifications from
533 // NetworkLibrary about changes in the NetworkManager and initiates
534 // captive portal detection for active networks.
535 if (NetworkPortalDetector::IsEnabled() &&
536 NetworkPortalDetector::GetInstance()) {
537 NetworkPortalDetector::GetInstance()->Init();
540 NotifyDisplayLocalStatePrefChanged();
542 ChromeBrowserMainPartsLinux::PostProfileInit();
545 void ChromeBrowserMainPartsChromeos::PreBrowserStart() {
546 // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
547 // -- just before MetricsService::LogNeedForCleanShutdown().
549 g_browser_process
->metrics_service()->StartExternalMetrics();
551 // Listen for XI_HierarchyChanged events. Note: if this is moved to
552 // PreMainMessageLoopRun() then desktopui_PageCyclerTests fail for unknown
553 // reasons, see http://crosbug.com/24833.
554 XInputHierarchyChangedEventListener::GetInstance();
556 // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
557 // -- immediately after ChildProcess::WaitForDebugger().
559 // Start the out-of-memory priority manager here so that we give the most
560 // amount of time for the other services to start up before we start
561 // adjusting the oom priority.
562 g_browser_process
->oom_priority_manager()->Start();
564 ChromeBrowserMainPartsLinux::PreBrowserStart();
567 void ChromeBrowserMainPartsChromeos::PostBrowserStart() {
568 // FILE thread is created in ChromeBrowserMainParts::PreMainMessageLoopRun().
570 // Get the statistics provider instance here to start loading statistcs
571 // on the background FILE thread.
572 system::StatisticsProvider::GetInstance();
574 // These are dependent on the ash::Shell singleton already having been
576 power_button_observer_
.reset(new PowerButtonObserver
);
577 user_activity_notifier_
.reset(new UserActivityNotifier
);
578 video_activity_notifier_
.reset(new VideoActivityNotifier
);
579 screen_dimming_observer_
.reset(new ScreenDimmingObserver
);
581 ChromeBrowserMainPartsLinux::PostBrowserStart();
584 // Shut down services before the browser process, etc are destroyed.
585 void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
586 BootTimesLoader::Get()->AddLogoutTimeMarker("UIMessageLoopEnded",
589 g_browser_process
->oom_priority_manager()->Stop();
591 // Stops LoginUtils background fetchers. This is needed because IO thread is
592 // going to stop soon after this function. The pending background jobs could
593 // cause it to crash during shutdown.
594 LoginUtils::Get()->StopBackgroundFetchers();
596 // Shutdown the upgrade detector for Chrome OS. The upgrade detector
597 // stops monitoring changes from the update engine.
598 if (UpgradeDetectorChromeos::GetInstance())
599 UpgradeDetectorChromeos::GetInstance()->Shutdown();
601 // Shutdown the network change notifier for Chrome OS. The network
602 // change notifier stops monitoring changes from the power manager and
603 // the network manager.
604 if (CrosNetworkChangeNotifierFactory::GetInstance())
605 CrosNetworkChangeNotifierFactory::GetInstance()->Shutdown();
607 if (chromeos::NetworkPortalDetector::IsEnabled() &&
608 chromeos::NetworkPortalDetector::GetInstance()) {
609 chromeos::NetworkPortalDetector::GetInstance()->Shutdown();
612 // Tell DeviceSettingsService to stop talking to session_manager.
613 DeviceSettingsService::Get()->Shutdown();
615 // We should remove observers attached to D-Bus clients before
616 // DBusThreadManager is shut down.
617 screen_lock_observer_
.reset();
618 resume_observer_
.reset();
619 brightness_observer_
.reset();
620 output_observer_
.reset();
621 power_state_override_
.reset();
623 // The XInput2 event listener needs to be shut down earlier than when
624 // Singletons are finally destroyed in AtExitManager.
625 XInputHierarchyChangedEventListener::GetInstance()->Stop();
627 // chromeos::SystemKeyEventListener::Shutdown() is always safe to call,
628 // even if Initialize() wasn't called.
629 SystemKeyEventListener::Shutdown();
630 imageburner::BurnManager::Shutdown();
631 AudioHandler::Shutdown();
633 WebSocketProxyController::Shutdown();
635 // Let classes unregister themselves as observers of the ash::Shell singleton
636 // before the shell is destroyed.
637 user_activity_notifier_
.reset();
638 video_activity_notifier_
.reset();
639 primary_display_switch_observer_
.reset();
641 // Detach D-Bus clients before DBusThreadManager is shut down.
642 power_button_observer_
.reset();
643 screen_dimming_observer_
.reset();
645 // Delete ContactManager while |g_browser_process| is still alive.
646 contact_manager_
.reset();
648 ChromeBrowserMainPartsLinux::PostMainMessageLoopRun();
651 void ChromeBrowserMainPartsChromeos::SetupPlatformFieldTrials() {
652 SetupLowMemoryHeadroomFieldTrial();
655 void ChromeBrowserMainPartsChromeos::SetupLowMemoryHeadroomFieldTrial() {
656 chrome::VersionInfo::Channel channel
= chrome::VersionInfo::GetChannel();
657 // Only enable this experiment on Canary and Dev, since it's possible
658 // that this will make the machine unstable.
659 // Note that to have this code execute in a developer build,
660 // then chrome::VersionInfo::CHANNEL_UNKNOWN needs to be added here.
661 if (channel
== chrome::VersionInfo::CHANNEL_CANARY
||
662 channel
== chrome::VersionInfo::CHANNEL_DEV
) {
663 const base::FieldTrial::Probability kDivisor
= 7;
664 // 1 in 7 probability of being in each group. If the default value for the
665 // kernel matches one of the experiment groups, then they will have
666 // identical results.
667 const base::FieldTrial::Probability kEnableProbability
= 1;
668 scoped_refptr
<base::FieldTrial
> trial
=
669 base::FieldTrialList::FactoryGetFieldTrial(
670 "LowMemoryMargin", kDivisor
, "default", 2012, 7, 30, NULL
);
671 int disable
= trial
->AppendGroup("off", kEnableProbability
);
672 int margin_0mb
= trial
->AppendGroup("0mb", kEnableProbability
);
673 int margin_25mb
= trial
->AppendGroup("25mb", kEnableProbability
);
674 int margin_50mb
= trial
->AppendGroup("50mb", kEnableProbability
);
675 int margin_100mb
= trial
->AppendGroup("100mb", kEnableProbability
);
676 int margin_200mb
= trial
->AppendGroup("200mb", kEnableProbability
);
677 if (trial
->group() == disable
) {
678 LOG(WARNING
) << "low_mem: Part of 'off' experiment";
679 LowMemoryObserver::SetLowMemoryMargin(-1);
680 } else if (trial
->group() == margin_0mb
) {
681 LOG(WARNING
) << "low_mem: Part of '0MB' experiment";
682 LowMemoryObserver::SetLowMemoryMargin(0);
683 } else if (trial
->group() == margin_25mb
) {
684 LOG(WARNING
) << "low_mem: Part of '25MB' experiment";
685 LowMemoryObserver::SetLowMemoryMargin(25);
686 } else if (trial
->group() == margin_50mb
) {
687 LOG(WARNING
) << "low_mem: Part of '50MB' experiment";
688 LowMemoryObserver::SetLowMemoryMargin(50);
689 } else if (trial
->group() == margin_100mb
) {
690 LOG(WARNING
) << "low_mem: Part of '100MB' experiment";
691 LowMemoryObserver::SetLowMemoryMargin(100);
692 } else if (trial
->group() == margin_200mb
) {
693 LOG(WARNING
) << "low_mem: Part of '200MB' experiment";
694 LowMemoryObserver::SetLowMemoryMargin(200);
696 LOG(WARNING
) << "low_mem: Part of 'default' experiment";
701 } // namespace chromeos