Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(721)

Side by Side Diff: chrome/browser/chromeos/login/base_login_display_host.cc

Issue 14200033: [cros] Rename BaseLoginDisplayHost to LoginDisplayHostImpl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/chromeos/login/base_login_display_host.h"
6
7 #include "ash/desktop_background/desktop_background_controller.h"
8 #include "ash/shell.h"
9 #include "ash/shell_window_ids.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/debug/trace_event.h"
13 #include "base/file_util.h"
14 #include "base/logging.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/threading/thread_restrictions.h"
17 #include "base/utf_string_conversions.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/browser_shutdown.h"
20 #include "chrome/browser/chromeos/cros/cros_library.h"
21 #include "chrome/browser/chromeos/customization_document.h"
22 #include "chrome/browser/chromeos/input_method/input_method_configuration.h"
23 #include "chrome/browser/chromeos/input_method/input_method_manager.h"
24 #include "chrome/browser/chromeos/input_method/input_method_util.h"
25 #include "chrome/browser/chromeos/language_preferences.h"
26 #include "chrome/browser/chromeos/login/existing_user_controller.h"
27 #include "chrome/browser/chromeos/login/helper.h"
28 #include "chrome/browser/chromeos/login/language_switch_menu.h"
29 #include "chrome/browser/chromeos/login/login_utils.h"
30 #include "chrome/browser/chromeos/login/login_wizard.h"
31 #include "chrome/browser/chromeos/login/user_manager.h"
32 #include "chrome/browser/chromeos/login/webui_login_display_host.h"
33 #include "chrome/browser/chromeos/login/wizard_controller.h"
34 #include "chrome/browser/chromeos/mobile_config.h"
35 #include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
36 #include "chrome/browser/chromeos/system/input_device_settings.h"
37 #include "chrome/browser/chromeos/system/timezone_settings.h"
38 #include "chrome/browser/lifetime/application_lifetime.h"
39 #include "chrome/browser/managed_mode/managed_mode.h"
40 #include "chrome/browser/policy/browser_policy_connector.h"
41 #include "chrome/common/chrome_notification_types.h"
42 #include "chrome/common/chrome_switches.h"
43 #include "chrome/common/pref_names.h"
44 #include "chromeos/dbus/dbus_thread_manager.h"
45 #include "chromeos/dbus/session_manager_client.h"
46 #include "content/public/browser/notification_service.h"
47 #include "content/public/browser/notification_types.h"
48 #include "googleurl/src/gurl.h"
49 #include "ui/aura/window.h"
50 #include "ui/base/events/event_utils.h"
51 #include "ui/base/resource/resource_bundle.h"
52 #include "ui/compositor/layer.h"
53 #include "ui/compositor/layer_animation_element.h"
54 #include "ui/compositor/layer_animation_sequence.h"
55 #include "ui/compositor/layer_animator.h"
56 #include "ui/compositor/scoped_layer_animation_settings.h"
57 #include "ui/gfx/rect.h"
58 #include "ui/gfx/transform.h"
59 #include "ui/views/widget/widget.h"
60
61 namespace {
62
63 // The delay of triggering initialization of the device policy subsystem
64 // after the login screen is initialized. This makes sure that device policy
65 // network requests are made while the system is idle waiting for user input.
66 const int64 kPolicyServiceInitializationDelayMilliseconds = 100;
67
68 // Determines the hardware keyboard from the given locale code
69 // and the OEM layout information, and saves it to "Locale State".
70 // The information will be used in InputMethodUtil::GetHardwareInputMethodId().
71 void DetermineAndSaveHardwareKeyboard(const std::string& locale,
72 const std::string& oem_layout) {
73 std::string layout;
74 if (!oem_layout.empty()) {
75 // If the OEM layout information is provided, use it.
76 layout = oem_layout;
77 } else {
78 chromeos::input_method::InputMethodManager* manager =
79 chromeos::input_method::GetInputMethodManager();
80 // Otherwise, determine the hardware keyboard from the locale.
81 std::vector<std::string> input_method_ids;
82 if (manager->GetInputMethodUtil()->GetInputMethodIdsFromLanguageCode(
83 locale,
84 chromeos::input_method::kKeyboardLayoutsOnly,
85 &input_method_ids)) {
86 // The output list |input_method_ids| is sorted by popularity, hence
87 // input_method_ids[0] now contains the most popular keyboard layout
88 // for the given locale.
89 layout = input_method_ids[0];
90 }
91 }
92
93 if (!layout.empty()) {
94 PrefService* prefs = g_browser_process->local_state();
95 prefs->SetString(prefs::kHardwareKeyboardLayout, layout);
96 // This asks the file thread to save the prefs (i.e. doesn't block).
97 // The latest values of Local State reside in memory so we can safely
98 // get the value of kHardwareKeyboardLayout even if the data is not
99 // yet saved to disk.
100 prefs->CommitPendingWrite();
101 }
102 }
103
104 ui::Layer* GetLayer(views::Widget* widget) {
105 return widget->GetNativeView()->layer();
106 }
107
108 } // namespace
109
110 namespace chromeos {
111
112 // static
113 LoginDisplayHost* BaseLoginDisplayHost::default_host_ = NULL;
114
115 ////////////////////////////////////////////////////////////////////////////////
116 // BaseLoginDisplayHost, public
117
118 BaseLoginDisplayHost::BaseLoginDisplayHost(const gfx::Rect& background_bounds)
119 : background_bounds_(background_bounds),
120 ALLOW_THIS_IN_INITIALIZER_LIST(pointer_factory_(this)),
121 shutting_down_(false),
122 oobe_progress_bar_visible_(false),
123 session_starting_(false) {
124 // We need to listen to CLOSE_ALL_BROWSERS_REQUEST but not APP_TERMINATIN
125 // because/ APP_TERMINATING will never be fired as long as this keeps
126 // ref-count. CLOSE_ALL_BROWSERS_REQUEST is safe here because there will be no
127 // browser instance that will block the shutdown.
128 registrar_.Add(this,
129 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
130 content::NotificationService::AllSources());
131
132 // NOTIFICATION_BROWSER_OPENED is issued after browser is created, but
133 // not shown yet. Lock window has to be closed at this point so that
134 // a browser window exists and the window can acquire input focus.
135 registrar_.Add(this,
136 chrome::NOTIFICATION_BROWSER_OPENED,
137 content::NotificationService::AllSources());
138
139 // Login screen is moved to lock screen container when user logs in.
140 registrar_.Add(this,
141 chrome::NOTIFICATION_LOGIN_USER_CHANGED,
142 content::NotificationService::AllSources());
143
144 DCHECK(default_host_ == NULL);
145 default_host_ = this;
146
147 // Make sure chrome won't exit while we are at login/oobe screen.
148 chrome::StartKeepAlive();
149 }
150
151 BaseLoginDisplayHost::~BaseLoginDisplayHost() {
152 // Let chrome process exit after login/oobe screen if needed.
153 chrome::EndKeepAlive();
154
155 default_host_ = NULL;
156 }
157
158 ////////////////////////////////////////////////////////////////////////////////
159 // BaseLoginDisplayHost, LoginDisplayHost implementation:
160
161 void BaseLoginDisplayHost::BeforeSessionStart() {
162 session_starting_ = true;
163 }
164
165 void BaseLoginDisplayHost::OnSessionStart() {
166 DVLOG(1) << "Session starting";
167 ash::Shell::GetInstance()->
168 desktop_background_controller()->MoveDesktopToUnlockedContainer();
169 if (wizard_controller_.get())
170 wizard_controller_->OnSessionStart();
171 // Display host is deleted once animation is completed
172 // since sign in screen widget has to stay alive.
173 StartAnimation();
174 ShutdownDisplayHost(false);
175 }
176
177 void BaseLoginDisplayHost::OnCompleteLogin() {
178 // Cancelling the |auto_enrollment_client_| now allows it to determine whether
179 // its protocol finished before login was complete.
180 if (auto_enrollment_client_.get())
181 auto_enrollment_client_.release()->CancelAndDeleteSoon();
182 }
183
184 void BaseLoginDisplayHost::StartWizard(
185 const std::string& first_screen_name,
186 DictionaryValue* screen_parameters) {
187 DVLOG(1) << "Starting wizard, first_screen_name: " << first_screen_name;
188 // Create and show the wizard.
189 // Note, dtor of the old WizardController should be called before ctor of the
190 // new one, because "default_controller()" is updated there. So pure "reset()"
191 // is done before new controller creation.
192 wizard_controller_.reset();
193 wizard_controller_.reset(CreateWizardController());
194
195 oobe_progress_bar_visible_ = !WizardController::IsDeviceRegistered();
196 SetOobeProgressBarVisible(oobe_progress_bar_visible_);
197 wizard_controller_->Init(first_screen_name, screen_parameters);
198 }
199
200 void BaseLoginDisplayHost::StartSignInScreen() {
201 DVLOG(1) << "Starting sign in screen";
202 const chromeos::UserList& users = chromeos::UserManager::Get()->GetUsers();
203
204 // Fix for users who updated device and thus never passed register screen.
205 // If we already have users, we assume that it is not a second part of
206 // OOBE. See http://crosbug.com/6289
207 if (!WizardController::IsDeviceRegistered() && !users.empty()) {
208 VLOG(1) << "Mark device registered because there are remembered users: "
209 << users.size();
210 WizardController::MarkDeviceRegistered();
211 }
212
213 sign_in_controller_.reset(); // Only one controller in a time.
214 sign_in_controller_.reset(new chromeos::ExistingUserController(this));
215 oobe_progress_bar_visible_ = !WizardController::IsDeviceRegistered();
216 SetOobeProgressBarVisible(oobe_progress_bar_visible_);
217 SetStatusAreaVisible(true);
218 SetShutdownButtonEnabled(true);
219 sign_in_controller_->Init(users);
220
221 // We might be here after a reboot that was triggered after OOBE was complete,
222 // so check for auto-enrollment again. This might catch a cached decision from
223 // a previous oobe flow, or might start a new check with the server.
224 CheckForAutoEnrollment();
225
226 // Initiate services customization manifest fetching.
227 ServicesCustomizationDocument::GetInstance()->StartFetching();
228
229 // Initiate mobile config load.
230 MobileConfig::GetInstance();
231
232 // Initiate device policy fetching.
233 g_browser_process->browser_policy_connector()->ScheduleServiceInitialization(
234 kPolicyServiceInitializationDelayMilliseconds);
235 }
236
237 WizardController* BaseLoginDisplayHost::GetWizardController() {
238 return wizard_controller_.get();
239 }
240
241 void BaseLoginDisplayHost::ResumeSignInScreen() {
242 // We only get here after a previous call the StartSignInScreen. That sign-in
243 // was successful but was interrupted by an auto-enrollment execution; once
244 // auto-enrollment is complete we resume the normal login flow from here.
245 DVLOG(1) << "Resuming sign in screen";
246 CHECK(sign_in_controller_.get());
247 SetOobeProgressBarVisible(oobe_progress_bar_visible_);
248 SetStatusAreaVisible(true);
249 SetShutdownButtonEnabled(true);
250 sign_in_controller_->ResumeLogin();
251 }
252
253 void BaseLoginDisplayHost::CheckForAutoEnrollment() {
254 // This method is called when the controller determines that the
255 // auto-enrollment check can start. This happens either after the EULA is
256 // accepted, or right after a reboot if the EULA has already been accepted.
257
258 if (policy::AutoEnrollmentClient::IsDisabled()) {
259 VLOG(1) << "CheckForAutoEnrollment: auto-enrollment disabled";
260 return;
261 }
262
263 // Start by checking if the device has already been owned.
264 pointer_factory_.InvalidateWeakPtrs();
265 DeviceSettingsService::Get()->GetOwnershipStatusAsync(
266 base::Bind(&BaseLoginDisplayHost::OnOwnershipStatusCheckDone,
267 pointer_factory_.GetWeakPtr()));
268 }
269
270 ////////////////////////////////////////////////////////////////////////////////
271 // BaseLoginDisplayHost, content:NotificationObserver implementation:
272
273 void BaseLoginDisplayHost::Observe(
274 int type,
275 const content::NotificationSource& source,
276 const content::NotificationDetails& details) {
277 if (type == chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST) {
278 ShutdownDisplayHost(true);
279 } else if (type == chrome::NOTIFICATION_BROWSER_OPENED && session_starting_) {
280 // Browsers created before session start (windows opened by extensions, for
281 // example) are ignored.
282 OnBrowserCreated();
283 registrar_.Remove(this,
284 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
285 content::NotificationService::AllSources());
286 registrar_.Remove(this,
287 chrome::NOTIFICATION_BROWSER_OPENED,
288 content::NotificationService::AllSources());
289 } else if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED &&
290 chromeos::UserManager::Get()->IsCurrentUserNew()) {
291 // For new user, move desktop to locker container so that windows created
292 // during the user image picker step are below it.
293 ash::Shell::GetInstance()->
294 desktop_background_controller()->MoveDesktopToLockedContainer();
295 registrar_.Remove(this,
296 chrome::NOTIFICATION_LOGIN_USER_CHANGED,
297 content::NotificationService::AllSources());
298 }
299 }
300
301 void BaseLoginDisplayHost::ShutdownDisplayHost(bool post_quit_task) {
302 if (shutting_down_)
303 return;
304
305 shutting_down_ = true;
306 registrar_.RemoveAll();
307 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
308 if (post_quit_task)
309 MessageLoop::current()->Quit();
310 }
311
312 void BaseLoginDisplayHost::StartAnimation() {
313 if (ash::Shell::GetContainer(
314 ash::Shell::GetPrimaryRootWindow(),
315 ash::internal::kShellWindowId_DesktopBackgroundContainer)->
316 children().empty()) {
317 // If there is no background window, don't perform any animation on the
318 // default and background layer because there is nothing behind it.
319 return;
320 }
321
322 if (!CommandLine::ForCurrentProcess()->HasSwitch(
323 switches::kDisableLoginAnimations))
324 ash::Shell::GetInstance()->DoInitialWorkspaceAnimation();
325 }
326
327 void BaseLoginDisplayHost::OnOwnershipStatusCheckDone(
328 DeviceSettingsService::OwnershipStatus status,
329 bool current_user_is_owner) {
330 if (status != DeviceSettingsService::OWNERSHIP_NONE) {
331 // The device is already owned. No need for auto-enrollment checks.
332 VLOG(1) << "CheckForAutoEnrollment: device already owned";
333 return;
334 }
335
336 // Kick off the auto-enrollment client.
337 if (auto_enrollment_client_.get()) {
338 // They client might have been started after the EULA screen, but we made
339 // it to the login screen before it finished. In that case let the current
340 // client proceed.
341 //
342 // CheckForAutoEnrollment() is also called when we reach the sign-in screen,
343 // because that's what happens after an auto-update.
344 VLOG(1) << "CheckForAutoEnrollment: client already started";
345
346 // If the client already started and already finished too, pass the decision
347 // to the |sign_in_controller_| now.
348 if (auto_enrollment_client_->should_auto_enroll())
349 ForceAutoEnrollment();
350 } else {
351 VLOG(1) << "CheckForAutoEnrollment: starting auto-enrollment client";
352 auto_enrollment_client_.reset(policy::AutoEnrollmentClient::Create(
353 base::Bind(&BaseLoginDisplayHost::OnAutoEnrollmentClientDone,
354 base::Unretained(this))));
355 auto_enrollment_client_->Start();
356 }
357 }
358
359 void BaseLoginDisplayHost::OnAutoEnrollmentClientDone() {
360 bool auto_enroll = auto_enrollment_client_->should_auto_enroll();
361 VLOG(1) << "OnAutoEnrollmentClientDone, decision is " << auto_enroll;
362
363 if (auto_enroll)
364 ForceAutoEnrollment();
365 }
366
367 void BaseLoginDisplayHost::ForceAutoEnrollment() {
368 if (sign_in_controller_.get())
369 sign_in_controller_->DoAutoEnrollment();
370 }
371
372 // Declared in login_wizard.h so that others don't need to depend on our .h.
373 // TODO(nkostylev): Split this into a smaller functions.
374 void ShowLoginWizard(const std::string& first_screen_name,
375 const gfx::Size& size) {
376 if (browser_shutdown::IsTryingToQuit())
377 return;
378
379 // Managed mode is defined as a machine-level setting so we have to reset it
380 // each time login screen is shown. See also http://crbug.com/167642
381 // TODO(nkostylev): Remove this call when managed mode scope is
382 // limited to user session.
383 if (ManagedMode::IsInManagedMode())
384 ManagedMode::LeaveManagedMode();
385
386 VLOG(1) << "Showing OOBE screen: " << first_screen_name;
387
388 chromeos::input_method::InputMethodManager* manager =
389 chromeos::input_method::GetInputMethodManager();
390
391 // Set up keyboards. For example, when |locale| is "en-US", enable US qwerty
392 // and US dvorak keyboard layouts.
393 if (g_browser_process && g_browser_process->local_state()) {
394 const std::string locale = g_browser_process->GetApplicationLocale();
395 // If the preferred keyboard for the login screen has been saved, use it.
396 PrefService* prefs = g_browser_process->local_state();
397 std::string initial_input_method_id =
398 prefs->GetString(chromeos::language_prefs::kPreferredKeyboardLayout);
399 if (initial_input_method_id.empty()) {
400 // If kPreferredKeyboardLayout is not specified, use the hardware layout.
401 initial_input_method_id =
402 manager->GetInputMethodUtil()->GetHardwareInputMethodId();
403 }
404 manager->EnableLayouts(locale, initial_input_method_id);
405
406 // Apply owner preferences for tap-to-click and mouse buttons swap for
407 // login screen.
408 system::mouse_settings::SetPrimaryButtonRight(
409 prefs->GetBoolean(prefs::kOwnerPrimaryMouseButtonRight));
410 system::touchpad_settings::SetTapToClick(
411 prefs->GetBoolean(prefs::kOwnerTapToClickEnabled));
412 }
413
414 ui::SetNaturalScroll(CommandLine::ForCurrentProcess()->HasSwitch(
415 switches::kNaturalScrollDefault));
416
417 gfx::Rect screen_bounds(chromeos::CalculateScreenBounds(size));
418
419 // Check whether we need to execute OOBE process.
420 bool oobe_complete = chromeos::WizardController::IsOobeCompleted();
421 bool show_login_screen =
422 (first_screen_name.empty() && oobe_complete) ||
423 first_screen_name == chromeos::WizardController::kLoginScreenName;
424
425 chromeos::LoginDisplayHost* display_host;
426 display_host = new chromeos::WebUILoginDisplayHost(screen_bounds);
427
428 if (show_login_screen) {
429 // R11 > R12 migration fix. See http://crosbug.com/p/4898.
430 // If user has manually changed locale during R11 OOBE, locale will be set.
431 // On R12 > R12|R13 etc. this fix won't get activated since
432 // OOBE process has set kApplicationLocale to non-default value.
433 PrefService* prefs = g_browser_process->local_state();
434 if (!prefs->HasPrefPath(prefs::kApplicationLocale)) {
435 std::string locale = chromeos::WizardController::GetInitialLocale();
436 prefs->SetString(prefs::kApplicationLocale, locale);
437 manager->EnableLayouts(
438 locale,
439 manager->GetInputMethodUtil()->GetHardwareInputMethodId());
440 base::ThreadRestrictions::ScopedAllowIO allow_io;
441 const std::string loaded_locale =
442 ResourceBundle::GetSharedInstance().ReloadLocaleResources(locale);
443 g_browser_process->SetApplicationLocale(loaded_locale);
444 }
445 display_host->StartSignInScreen();
446 return;
447 }
448
449 // Load startup manifest.
450 const chromeos::StartupCustomizationDocument* startup_manifest =
451 chromeos::StartupCustomizationDocument::GetInstance();
452
453 // Switch to initial locale if specified by customization
454 // and has not been set yet. We cannot call
455 // chromeos::LanguageSwitchMenu::SwitchLanguage here before
456 // EmitLoginPromptReady.
457 PrefService* prefs = g_browser_process->local_state();
458 const std::string current_locale =
459 prefs->GetString(prefs::kApplicationLocale);
460 VLOG(1) << "Current locale: " << current_locale;
461 std::string locale;
462 if (current_locale.empty()) {
463 locale = startup_manifest->initial_locale();
464 std::string layout = startup_manifest->keyboard_layout();
465 VLOG(1) << "Initial locale: " << locale
466 << "keyboard layout " << layout;
467 if (!locale.empty()) {
468 // Save initial locale from VPD/customization manifest as current
469 // Chrome locale. Otherwise it will be lost if Chrome restarts.
470 // Don't need to schedule pref save because setting initial local
471 // will enforce preference saving.
472 prefs->SetString(prefs::kApplicationLocale, locale);
473 chromeos::WizardController::SetInitialLocale(locale);
474 // Determine keyboard layout from OEM customization (if provided) or
475 // initial locale and save it in preferences.
476 DetermineAndSaveHardwareKeyboard(locale, layout);
477 // Then, enable the hardware keyboard.
478 manager->EnableLayouts(
479 locale,
480 manager->GetInputMethodUtil()->GetHardwareInputMethodId());
481 // Reloading resource bundle causes us to do blocking IO on UI thread.
482 // Temporarily allow it until we fix http://crosbug.com/11102
483 base::ThreadRestrictions::ScopedAllowIO allow_io;
484 const std::string loaded_locale =
485 ResourceBundle::GetSharedInstance().ReloadLocaleResources(locale);
486 CHECK(!loaded_locale.empty()) << "Locale could not be found for "
487 << locale;
488 // Set the application locale here so that the language switch
489 // menu works properly with the newly loaded locale.
490 g_browser_process->SetApplicationLocale(loaded_locale);
491 }
492 }
493
494 display_host->StartWizard(first_screen_name, NULL);
495
496 chromeos::LoginUtils::Get()->PrewarmAuthentication();
497 chromeos::DBusThreadManager::Get()->GetSessionManagerClient()
498 ->EmitLoginPromptReady();
499 TRACE_EVENT0("chromeos", "ShowLoginWizard::EmitLoginPromptReady");
500
501 // Set initial timezone if specified by customization.
502 const std::string timezone_name = startup_manifest->initial_timezone();
503 VLOG(1) << "Initial time zone: " << timezone_name;
504 // Apply locale customizations only once to preserve whatever locale
505 // user has changed to during OOBE.
506 if (!timezone_name.empty()) {
507 chromeos::system::TimezoneSettings::GetInstance()->SetTimezoneFromID(
508 UTF8ToUTF16(timezone_name));
509 }
510 }
511
512 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/login/base_login_display_host.h ('k') | chrome/browser/chromeos/login/login_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698