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

Side by Side Diff: chrome/browser/chromeos/login/ui/login_display_host_impl.cc

Issue 542623002: Minimal support for OOBE/login for chrome-athena (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: one more nit Created 6 years, 3 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" 5 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "ash/audio/sounds.h" 9 #include "ash/audio/sounds.h"
10 #include "ash/desktop_background/desktop_background_controller.h" 10 #include "ash/desktop_background/desktop_background_controller.h"
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 #include "ui/gfx/size.h" 89 #include "ui/gfx/size.h"
90 #include "ui/gfx/transform.h" 90 #include "ui/gfx/transform.h"
91 #include "ui/keyboard/keyboard_controller.h" 91 #include "ui/keyboard/keyboard_controller.h"
92 #include "ui/keyboard/keyboard_util.h" 92 #include "ui/keyboard/keyboard_util.h"
93 #include "ui/views/focus/focus_manager.h" 93 #include "ui/views/focus/focus_manager.h"
94 #include "ui/views/widget/widget.h" 94 #include "ui/views/widget/widget.h"
95 #include "ui/views/widget/widget_delegate.h" 95 #include "ui/views/widget/widget_delegate.h"
96 #include "ui/wm/core/window_animations.h" 96 #include "ui/wm/core/window_animations.h"
97 #include "url/gurl.h" 97 #include "url/gurl.h"
98 98
99 #if defined(USE_ATHENA)
100 #include "athena/common/container_priorities.h"
101 #include "athena/screen/public/screen_manager.h"
102 #endif
103
99 namespace { 104 namespace {
100 105
101 // Maximum delay for startup sound after 'loginPromptVisible' signal. 106 // Maximum delay for startup sound after 'loginPromptVisible' signal.
102 const int kStartupSoundMaxDelayMs = 2000; 107 const int kStartupSoundMaxDelayMs = 2000;
103 108
104 // URL which corresponds to the login WebUI. 109 // URL which corresponds to the login WebUI.
105 const char kLoginURL[] = "chrome://oobe/login"; 110 const char kLoginURL[] = "chrome://oobe/login";
106 111
107 // URL which corresponds to the OOBE WebUI. 112 // URL which corresponds to the OOBE WebUI.
108 const char kOobeURL[] = "chrome://oobe/oobe"; 113 const char kOobeURL[] = "chrome://oobe/oobe";
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 startup_sound_played_(false), 287 startup_sound_played_(false),
283 startup_sound_honors_spoken_feedback_(false), 288 startup_sound_honors_spoken_feedback_(false),
284 is_observing_keyboard_(false) { 289 is_observing_keyboard_(false) {
285 DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this); 290 DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this);
286 CrasAudioHandler::Get()->AddAudioObserver(this); 291 CrasAudioHandler::Get()->AddAudioObserver(this);
287 if (keyboard::KeyboardController::GetInstance()) { 292 if (keyboard::KeyboardController::GetInstance()) {
288 keyboard::KeyboardController::GetInstance()->AddObserver(this); 293 keyboard::KeyboardController::GetInstance()->AddObserver(this);
289 is_observing_keyboard_ = true; 294 is_observing_keyboard_ = true;
290 } 295 }
291 296
292 ash::Shell::GetInstance()->delegate()->AddVirtualKeyboardStateObserver(this); 297 if (ash::Shell::HasInstance()) {
293 ash::Shell::GetScreen()->AddObserver(this); 298 ash::Shell::GetInstance()->delegate()->
299 AddVirtualKeyboardStateObserver(this);
300 ash::Shell::GetScreen()->AddObserver(this);
301 }
294 302
295 // We need to listen to CLOSE_ALL_BROWSERS_REQUEST but not APP_TERMINATING 303 // We need to listen to CLOSE_ALL_BROWSERS_REQUEST but not APP_TERMINATING
296 // because/ APP_TERMINATING will never be fired as long as this keeps 304 // because/ APP_TERMINATING will never be fired as long as this keeps
297 // ref-count. CLOSE_ALL_BROWSERS_REQUEST is safe here because there will be no 305 // ref-count. CLOSE_ALL_BROWSERS_REQUEST is safe here because there will be no
298 // browser instance that will block the shutdown. 306 // browser instance that will block the shutdown.
299 registrar_.Add(this, 307 registrar_.Add(this,
300 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST, 308 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
301 content::NotificationService::AllSources()); 309 content::NotificationService::AllSources());
302 310
303 // NOTIFICATION_BROWSER_OPENED is issued after browser is created, but 311 // NOTIFICATION_BROWSER_OPENED is issued after browser is created, but
(...skipping 15 matching lines...) Expand all
319 chrome::IncrementKeepAliveCount(); 327 chrome::IncrementKeepAliveCount();
320 328
321 bool is_registered = StartupUtils::IsDeviceRegistered(); 329 bool is_registered = StartupUtils::IsDeviceRegistered();
322 bool zero_delay_enabled = WizardController::IsZeroDelayEnabled(); 330 bool zero_delay_enabled = WizardController::IsZeroDelayEnabled();
323 bool disable_boot_animation = CommandLine::ForCurrentProcess()->HasSwitch( 331 bool disable_boot_animation = CommandLine::ForCurrentProcess()->HasSwitch(
324 switches::kDisableBootAnimation); 332 switches::kDisableBootAnimation);
325 333
326 waiting_for_wallpaper_load_ = !zero_delay_enabled && 334 waiting_for_wallpaper_load_ = !zero_delay_enabled &&
327 (!is_registered || !disable_boot_animation); 335 (!is_registered || !disable_boot_animation);
328 336
337 #if defined(USE_ATHENA)
338 // Athena doesn't use wallpaper manager so don't wait for wallpaper loading.
oshima 2014/09/04 16:14:28 I believe we want to use it, and if so, we should
bshe 2014/09/04 18:36:53 Right. I think eventually we want to support chang
Dmitry Polukhin 2014/09/05 15:05:00 Done.
339 waiting_for_wallpaper_load_ = false;
340 #endif
341
329 // For slower hardware we have boot animation disabled so 342 // For slower hardware we have boot animation disabled so
330 // we'll be initializing WebUI hidden, waiting for user pods to load and then 343 // we'll be initializing WebUI hidden, waiting for user pods to load and then
331 // show WebUI at once. 344 // show WebUI at once.
332 waiting_for_user_pods_ = !zero_delay_enabled && !waiting_for_wallpaper_load_; 345 waiting_for_user_pods_ = !zero_delay_enabled && !waiting_for_wallpaper_load_;
333 346
334 initialize_webui_hidden_ = 347 initialize_webui_hidden_ =
335 kHiddenWebUIInitializationDefault && !zero_delay_enabled; 348 kHiddenWebUIInitializationDefault && !zero_delay_enabled;
336 349
337 // Check if WebUI init type is overriden. 350 // Check if WebUI init type is overriden.
338 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshWebUIInit)) { 351 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshWebUIInit)) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 } 397 }
385 398
386 LoginDisplayHostImpl::~LoginDisplayHostImpl() { 399 LoginDisplayHostImpl::~LoginDisplayHostImpl() {
387 DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this); 400 DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this);
388 CrasAudioHandler::Get()->RemoveAudioObserver(this); 401 CrasAudioHandler::Get()->RemoveAudioObserver(this);
389 if (keyboard::KeyboardController::GetInstance() && is_observing_keyboard_) { 402 if (keyboard::KeyboardController::GetInstance() && is_observing_keyboard_) {
390 keyboard::KeyboardController::GetInstance()->RemoveObserver(this); 403 keyboard::KeyboardController::GetInstance()->RemoveObserver(this);
391 is_observing_keyboard_ = false; 404 is_observing_keyboard_ = false;
392 } 405 }
393 406
394 ash::Shell::GetInstance()->delegate()-> 407 if (ash::Shell::HasInstance()) {
395 RemoveVirtualKeyboardStateObserver(this); 408 ash::Shell::GetInstance()->delegate()->
396 ash::Shell::GetScreen()->RemoveObserver(this); 409 RemoveVirtualKeyboardStateObserver(this);
410 ash::Shell::GetScreen()->RemoveObserver(this);
411 }
397 412
398 if (login_view_ && login_window_) 413 if (login_view_ && login_window_)
399 login_window_->RemoveRemovalsObserver(this); 414 login_window_->RemoveRemovalsObserver(this);
400 415
401 if (login::LoginScrollIntoViewEnabled()) 416 if (login::LoginScrollIntoViewEnabled())
402 ResetKeyboardOverscrollOverride(); 417 ResetKeyboardOverscrollOverride();
403 418
404 views::FocusManager::set_arrow_key_traversal_enabled(false); 419 views::FocusManager::set_arrow_key_traversal_enabled(false);
405 ResetLoginWindowAndView(); 420 ResetLoginWindowAndView();
406 421
422 #if !defined(USE_ATHENA)
407 // Let chrome process exit after login/oobe screen if needed. 423 // Let chrome process exit after login/oobe screen if needed.
408 chrome::DecrementKeepAliveCount(); 424 chrome::DecrementKeepAliveCount();
425 #endif
409 426
410 default_host_ = NULL; 427 default_host_ = NULL;
411 // TODO(tengs): This should be refactored. See crbug.com/314934. 428 // TODO(tengs): This should be refactored. See crbug.com/314934.
412 if (user_manager::UserManager::Get()->IsCurrentUserNew()) { 429 if (user_manager::UserManager::Get()->IsCurrentUserNew()) {
413 // DriveOptInController will delete itself when finished. 430 // DriveOptInController will delete itself when finished.
414 (new DriveFirstRunController( 431 (new DriveFirstRunController(
415 ProfileManager::GetActiveUserProfile()))->EnableOfflineMode(); 432 ProfileManager::GetActiveUserProfile()))->EnableOfflineMode();
416 } 433 }
417 } 434 }
418 435
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 // example) are ignored. 789 // example) are ignored.
773 OnBrowserCreated(); 790 OnBrowserCreated();
774 registrar_.Remove(this, 791 registrar_.Remove(this,
775 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST, 792 chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
776 content::NotificationService::AllSources()); 793 content::NotificationService::AllSources());
777 registrar_.Remove(this, 794 registrar_.Remove(this,
778 chrome::NOTIFICATION_BROWSER_OPENED, 795 chrome::NOTIFICATION_BROWSER_OPENED,
779 content::NotificationService::AllSources()); 796 content::NotificationService::AllSources());
780 } else if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED && 797 } else if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED &&
781 user_manager::UserManager::Get()->IsCurrentUserNew()) { 798 user_manager::UserManager::Get()->IsCurrentUserNew()) {
782 // For new user, move desktop to locker container so that windows created 799 if (ash::Shell::HasInstance()) {
783 // during the user image picker step are below it. 800 // For new user, move desktop to locker container so that windows created
784 ash::Shell::GetInstance()-> 801 // during the user image picker step are below it.
785 desktop_background_controller()->MoveDesktopToLockedContainer(); 802 ash::Shell::GetInstance()->
803 desktop_background_controller()->MoveDesktopToLockedContainer();
804 }
786 registrar_.Remove(this, 805 registrar_.Remove(this,
787 chrome::NOTIFICATION_LOGIN_USER_CHANGED, 806 chrome::NOTIFICATION_LOGIN_USER_CHANGED,
788 content::NotificationService::AllSources()); 807 content::NotificationService::AllSources());
789 } 808 }
790 } 809 }
791 810
792 //////////////////////////////////////////////////////////////////////////////// 811 ////////////////////////////////////////////////////////////////////////////////
793 // LoginDisplayHostImpl, WebContentsObserver implementation: 812 // LoginDisplayHostImpl, WebContentsObserver implementation:
794 813
795 void LoginDisplayHostImpl::RenderProcessGone(base::TerminationStatus status) { 814 void LoginDisplayHostImpl::RenderProcessGone(base::TerminationStatus status) {
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 focus_ring_controller_->SetVisible(true); 1052 focus_ring_controller_->SetVisible(true);
1034 1053
1035 keyboard_driven_oobe_key_handler_.reset(new KeyboardDrivenOobeKeyHandler); 1054 keyboard_driven_oobe_key_handler_.reset(new KeyboardDrivenOobeKeyHandler);
1036 } 1055 }
1037 1056
1038 views::Widget::InitParams params( 1057 views::Widget::InitParams params(
1039 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); 1058 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1040 params.bounds = background_bounds(); 1059 params.bounds = background_bounds();
1041 params.show_state = ui::SHOW_STATE_FULLSCREEN; 1060 params.show_state = ui::SHOW_STATE_FULLSCREEN;
1042 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 1061 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
1062 #if defined(USE_ATHENA)
1063 // TODO(dpolukhin): find right place for login/lock screen container,
1064 // perhaps inside athena::SystemUI.
1065 athena::ScreenManager::ContainerParams container_params(
1066 "LoginScreen", athena::CP_LOGIN_SCREEN);
1067 container_params.can_activate_children = true;
1068 params.parent = athena::ScreenManager::Get()->CreateContainer(
1069 container_params);
oshima 2014/09/04 16:14:28 this container should be deleted when exiting logi
Dmitry Polukhin 2014/09/08 09:10:45 Done.
Nikita (slow) 2014/09/08 09:53:17 Are there plans to have single place (like RootWin
1070 #else
1043 params.parent = 1071 params.parent =
1044 ash::Shell::GetContainer(ash::Shell::GetPrimaryRootWindow(), 1072 ash::Shell::GetContainer(ash::Shell::GetPrimaryRootWindow(),
1045 ash::kShellWindowId_LockScreenContainer); 1073 ash::kShellWindowId_LockScreenContainer);
1046 1074 #endif
1047 login_window_ = new views::Widget; 1075 login_window_ = new views::Widget;
1048 params.delegate = new LoginWidgetDelegate(login_window_); 1076 params.delegate = new LoginWidgetDelegate(login_window_);
1049 login_window_->Init(params); 1077 login_window_->Init(params);
1050 1078
1051 login_view_ = new WebUILoginView(); 1079 login_view_ = new WebUILoginView();
1052 login_view_->Init(); 1080 login_view_->Init();
1053 if (login_view_->webui_visible()) 1081 if (login_view_->webui_visible())
1054 OnLoginPromptVisible(); 1082 OnLoginPromptVisible();
1055 1083
1056 wm::SetWindowVisibilityAnimationDuration( 1084 wm::SetWindowVisibilityAnimationDuration(
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 // external 1166 // external
1139 1167
1140 // Declared in login_wizard.h so that others don't need to depend on our .h. 1168 // Declared in login_wizard.h so that others don't need to depend on our .h.
1141 // TODO(nkostylev): Split this into a smaller functions. 1169 // TODO(nkostylev): Split this into a smaller functions.
1142 void ShowLoginWizard(const std::string& first_screen_name) { 1170 void ShowLoginWizard(const std::string& first_screen_name) {
1143 if (browser_shutdown::IsTryingToQuit()) 1171 if (browser_shutdown::IsTryingToQuit())
1144 return; 1172 return;
1145 1173
1146 VLOG(1) << "Showing OOBE screen: " << first_screen_name; 1174 VLOG(1) << "Showing OOBE screen: " << first_screen_name;
1147 1175
1176 #if !defined(USE_ATHENA)
1148 chromeos::input_method::InputMethodManager* manager = 1177 chromeos::input_method::InputMethodManager* manager =
1149 chromeos::input_method::InputMethodManager::Get(); 1178 chromeos::input_method::InputMethodManager::Get();
1150 1179
1151 // Set up keyboards. For example, when |locale| is "en-US", enable US qwerty 1180 // Set up keyboards. For example, when |locale| is "en-US", enable US qwerty
1152 // and US dvorak keyboard layouts. 1181 // and US dvorak keyboard layouts.
1153 if (g_browser_process && g_browser_process->local_state()) { 1182 if (g_browser_process && g_browser_process->local_state()) {
1154 manager->GetActiveIMEState()->SetInputMethodLoginDefault(); 1183 manager->GetActiveIMEState()->SetInputMethodLoginDefault();
1155 1184
1156 PrefService* prefs = g_browser_process->local_state(); 1185 PrefService* prefs = g_browser_process->local_state();
1157 // Apply owner preferences for tap-to-click and mouse buttons swap for 1186 // Apply owner preferences for tap-to-click and mouse buttons swap for
1158 // login screen. 1187 // login screen.
1159 system::InputDeviceSettings::Get()->SetPrimaryButtonRight( 1188 system::InputDeviceSettings::Get()->SetPrimaryButtonRight(
1160 prefs->GetBoolean(prefs::kOwnerPrimaryMouseButtonRight)); 1189 prefs->GetBoolean(prefs::kOwnerPrimaryMouseButtonRight));
1161 system::InputDeviceSettings::Get()->SetTapToClick( 1190 system::InputDeviceSettings::Get()->SetTapToClick(
1162 prefs->GetBoolean(prefs::kOwnerTapToClickEnabled)); 1191 prefs->GetBoolean(prefs::kOwnerTapToClickEnabled));
1163 } 1192 }
1164 system::InputDeviceSettings::Get()->SetNaturalScroll( 1193 system::InputDeviceSettings::Get()->SetNaturalScroll(
1165 CommandLine::ForCurrentProcess()->HasSwitch( 1194 CommandLine::ForCurrentProcess()->HasSwitch(
1166 switches::kNaturalScrollDefault)); 1195 switches::kNaturalScrollDefault));
1196 #endif
1167 1197
1168 gfx::Rect screen_bounds(chromeos::CalculateScreenBounds(gfx::Size())); 1198 gfx::Rect screen_bounds(chromeos::CalculateScreenBounds(gfx::Size()));
1169 1199
1170 g_browser_process->platform_part()->SessionManager()->SetSessionState( 1200 g_browser_process->platform_part()->SessionManager()->SetSessionState(
1171 StartupUtils::IsOobeCompleted() 1201 StartupUtils::IsOobeCompleted()
1172 ? session_manager::SESSION_STATE_LOGIN_PRIMARY 1202 ? session_manager::SESSION_STATE_LOGIN_PRIMARY
1173 : session_manager::SESSION_STATE_OOBE); 1203 : session_manager::SESSION_STATE_OOBE);
1174 1204
1175 LoginDisplayHost* display_host = new LoginDisplayHostImpl(screen_bounds); 1205 LoginDisplayHost* display_host = new LoginDisplayHostImpl(screen_bounds);
1176 1206
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1227 // EmitLoginPromptReady. 1257 // EmitLoginPromptReady.
1228 PrefService* prefs = g_browser_process->local_state(); 1258 PrefService* prefs = g_browser_process->local_state();
1229 const std::string& current_locale = 1259 const std::string& current_locale =
1230 prefs->GetString(prefs::kApplicationLocale); 1260 prefs->GetString(prefs::kApplicationLocale);
1231 VLOG(1) << "Current locale: " << current_locale; 1261 VLOG(1) << "Current locale: " << current_locale;
1232 const std::string& locale = startup_manifest->initial_locale_default(); 1262 const std::string& locale = startup_manifest->initial_locale_default();
1233 1263
1234 const std::string& layout = startup_manifest->keyboard_layout(); 1264 const std::string& layout = startup_manifest->keyboard_layout();
1235 VLOG(1) << "Initial locale: " << locale << "keyboard layout " << layout; 1265 VLOG(1) << "Initial locale: " << locale << "keyboard layout " << layout;
1236 1266
1267 #if !defined(USE_ATHENA)
1237 // Determine keyboard layout from OEM customization (if provided) or 1268 // Determine keyboard layout from OEM customization (if provided) or
1238 // initial locale and save it in preferences. 1269 // initial locale and save it in preferences.
1239 manager->GetActiveIMEState()->SetInputMethodLoginDefaultFromVPD(locale, 1270 manager->GetActiveIMEState()->SetInputMethodLoginDefaultFromVPD(locale,
1240 layout); 1271 layout);
1272 #endif
1241 1273
1242 if (!current_locale.empty() || locale.empty()) { 1274 if (!current_locale.empty() || locale.empty()) {
1243 ShowLoginWizardFinish(first_screen_name, startup_manifest, display_host); 1275 ShowLoginWizardFinish(first_screen_name, startup_manifest, display_host);
1244 return; 1276 return;
1245 } 1277 }
1246 1278
1247 // Save initial locale from VPD/customization manifest as current 1279 // Save initial locale from VPD/customization manifest as current
1248 // Chrome locale. Otherwise it will be lost if Chrome restarts. 1280 // Chrome locale. Otherwise it will be lost if Chrome restarts.
1249 // Don't need to schedule pref save because setting initial local 1281 // Don't need to schedule pref save because setting initial local
1250 // will enforce preference saving. 1282 // will enforce preference saving.
1251 prefs->SetString(prefs::kApplicationLocale, locale); 1283 prefs->SetString(prefs::kApplicationLocale, locale);
1252 StartupUtils::SetInitialLocale(locale); 1284 StartupUtils::SetInitialLocale(locale);
1253 1285
1254 scoped_ptr<ShowLoginWizardSwitchLanguageCallbackData> data( 1286 scoped_ptr<ShowLoginWizardSwitchLanguageCallbackData> data(
1255 new ShowLoginWizardSwitchLanguageCallbackData( 1287 new ShowLoginWizardSwitchLanguageCallbackData(
1256 first_screen_name, startup_manifest, display_host)); 1288 first_screen_name, startup_manifest, display_host));
1257 1289
1258 scoped_ptr<locale_util::SwitchLanguageCallback> callback( 1290 scoped_ptr<locale_util::SwitchLanguageCallback> callback(
1259 new locale_util::SwitchLanguageCallback( 1291 new locale_util::SwitchLanguageCallback(
1260 base::Bind(&OnLanguageSwitchedCallback, base::Passed(data.Pass())))); 1292 base::Bind(&OnLanguageSwitchedCallback, base::Passed(data.Pass()))));
1261 1293
1262 // Load locale keyboards here. Hardware layout would be automatically enabled. 1294 // Load locale keyboards here. Hardware layout would be automatically enabled.
1263 locale_util::SwitchLanguage( 1295 locale_util::SwitchLanguage(
1264 locale, true, true /* login_layouts_only */, callback.Pass()); 1296 locale, true, true /* login_layouts_only */, callback.Pass());
1265 } 1297 }
1266 1298
1267 } // namespace chromeos 1299 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698