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/display/display_preferences.h" 6 7#include <string> 8#include <vector> 9 10#include "ash/display/display_controller.h" 11#include "ash/display/display_layout_store.h" 12#include "ash/display/display_manager.h" 13#include "ash/display/resolution_notification_controller.h" 14#include "ash/screen_util.h" 15#include "ash/shell.h" 16#include "ash/test/ash_test_base.h" 17#include "ash/test/display_manager_test_api.h" 18#include "ash/wm/maximize_mode/maximize_mode_controller.h" 19#include "base/prefs/scoped_user_pref_update.h" 20#include "base/prefs/testing_pref_service.h" 21#include "base/strings/string_number_conversions.h" 22#include "base/values.h" 23#include "chrome/browser/chromeos/display/display_configuration_observer.h" 24#include "chrome/browser/chromeos/login/users/mock_user_manager.h" 25#include "chrome/browser/chromeos/login/users/user_manager.h" 26#include "chrome/common/pref_names.h" 27#include "chrome/test/base/testing_browser_process.h" 28#include "ui/display/chromeos/display_configurator.h" 29#include "ui/gfx/vector3d_f.h" 30#include "ui/message_center/message_center.h" 31 32using ash::ResolutionNotificationController; 33 34namespace chromeos { 35namespace { 36const char kPrimaryIdKey[] = "primary-id"; 37const char kMirroredKey[] = "mirrored"; 38const char kPositionKey[] = "position"; 39const char kOffsetKey[] = "offset"; 40 41class DisplayPreferencesTest : public ash::test::AshTestBase { 42 protected: 43 DisplayPreferencesTest() 44 : mock_user_manager_(new MockUserManager), 45 user_manager_enabler_(mock_user_manager_) { 46 } 47 48 virtual ~DisplayPreferencesTest() {} 49 50 virtual void SetUp() OVERRIDE { 51 EXPECT_CALL(*mock_user_manager_, IsUserLoggedIn()) 52 .WillRepeatedly(testing::Return(false)); 53 EXPECT_CALL(*mock_user_manager_, Shutdown()); 54 ash::test::AshTestBase::SetUp(); 55 RegisterDisplayLocalStatePrefs(local_state_.registry()); 56 TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_); 57 observer_.reset(new DisplayConfigurationObserver()); 58 } 59 60 virtual void TearDown() OVERRIDE { 61 observer_.reset(); 62 TestingBrowserProcess::GetGlobal()->SetLocalState(NULL); 63 ash::test::AshTestBase::TearDown(); 64 } 65 66 void LoggedInAsUser() { 67 EXPECT_CALL(*mock_user_manager_, IsUserLoggedIn()) 68 .WillRepeatedly(testing::Return(true)); 69 EXPECT_CALL(*mock_user_manager_, IsLoggedInAsRegularUser()) 70 .WillRepeatedly(testing::Return(true)); 71 } 72 73 void LoggedInAsGuest() { 74 EXPECT_CALL(*mock_user_manager_, IsUserLoggedIn()) 75 .WillRepeatedly(testing::Return(true)); 76 EXPECT_CALL(*mock_user_manager_, IsLoggedInAsRegularUser()) 77 .WillRepeatedly(testing::Return(false)); 78 EXPECT_CALL(*mock_user_manager_, IsLoggedInAsLocallyManagedUser()) 79 .WillRepeatedly(testing::Return(false)); 80 } 81 82 // Do not use the implementation of display_preferences.cc directly to avoid 83 // notifying the update to the system. 84 void StoreDisplayLayoutPrefForName(const std::string& name, 85 ash::DisplayLayout::Position layout, 86 int offset, 87 int64 primary_id) { 88 DictionaryPrefUpdate update(&local_state_, prefs::kSecondaryDisplays); 89 ash::DisplayLayout display_layout(layout, offset); 90 display_layout.primary_id = primary_id; 91 92 DCHECK(!name.empty()); 93 94 base::DictionaryValue* pref_data = update.Get(); 95 scoped_ptr<base::Value>layout_value(new base::DictionaryValue()); 96 if (pref_data->HasKey(name)) { 97 base::Value* value = NULL; 98 if (pref_data->Get(name, &value) && value != NULL) 99 layout_value.reset(value->DeepCopy()); 100 } 101 if (ash::DisplayLayout::ConvertToValue(display_layout, layout_value.get())) 102 pref_data->Set(name, layout_value.release()); 103 } 104 105 void StoreDisplayLayoutPrefForPair(int64 id1, 106 int64 id2, 107 ash::DisplayLayout::Position layout, 108 int offset) { 109 StoreDisplayLayoutPrefForName( 110 base::Int64ToString(id1) + "," + base::Int64ToString(id2), 111 layout, offset, id1); 112 } 113 114 void StoreDisplayLayoutPrefForSecondary(int64 id, 115 ash::DisplayLayout::Position layout, 116 int offset, 117 int64 primary_id) { 118 StoreDisplayLayoutPrefForName( 119 base::Int64ToString(id), layout, offset, primary_id); 120 } 121 122 void StoreDisplayOverscan(int64 id, const gfx::Insets& insets) { 123 DictionaryPrefUpdate update(&local_state_, prefs::kDisplayProperties); 124 const std::string name = base::Int64ToString(id); 125 126 base::DictionaryValue* pref_data = update.Get(); 127 base::DictionaryValue* insets_value = new base::DictionaryValue(); 128 insets_value->SetInteger("insets_top", insets.top()); 129 insets_value->SetInteger("insets_left", insets.left()); 130 insets_value->SetInteger("insets_bottom", insets.bottom()); 131 insets_value->SetInteger("insets_right", insets.right()); 132 pref_data->Set(name, insets_value); 133 } 134 135 void StoreColorProfile(int64 id, const std::string& profile) { 136 DictionaryPrefUpdate update(&local_state_, prefs::kDisplayProperties); 137 const std::string name = base::Int64ToString(id); 138 139 base::DictionaryValue* pref_data = update.Get(); 140 base::DictionaryValue* property = new base::DictionaryValue(); 141 property->SetString("color_profile_name", profile); 142 pref_data->Set(name, property); 143 } 144 145 std::string GetRegisteredDisplayLayoutStr(int64 id1, int64 id2) { 146 ash::DisplayIdPair pair; 147 pair.first = id1; 148 pair.second = id2; 149 return ash::Shell::GetInstance()->display_manager()->layout_store()-> 150 GetRegisteredDisplayLayout(pair).ToString(); 151 } 152 153 PrefService* local_state() { return &local_state_; } 154 155 private: 156 MockUserManager* mock_user_manager_; // Not owned. 157 ScopedUserManagerEnabler user_manager_enabler_; 158 TestingPrefServiceSimple local_state_; 159 scoped_ptr<DisplayConfigurationObserver> observer_; 160 161 DISALLOW_COPY_AND_ASSIGN(DisplayPreferencesTest); 162}; 163 164} // namespace 165 166TEST_F(DisplayPreferencesTest, PairedLayoutOverrides) { 167 UpdateDisplay("100x100,200x200"); 168 int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id(); 169 int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id(); 170 int64 dummy_id = id2 + 1; 171 ASSERT_NE(id1, dummy_id); 172 173 StoreDisplayLayoutPrefForPair(id1, id2, ash::DisplayLayout::TOP, 20); 174 StoreDisplayLayoutPrefForPair(id1, dummy_id, ash::DisplayLayout::LEFT, 30); 175 StoreDisplayPowerStateForTest( 176 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON); 177 178 ash::Shell* shell = ash::Shell::GetInstance(); 179 180 LoadDisplayPreferences(true); 181 // DisplayPowerState should be ignored at boot. 182 EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, 183 shell->display_configurator()->power_state()); 184 185 shell->display_manager()->UpdateDisplays(); 186 // Check if the layout settings are notified to the system properly. 187 // The paired layout overrides old layout. 188 // Inverted one of for specified pair (id1, id2). Not used for the pair 189 // (id1, dummy_id) since dummy_id is not connected right now. 190 EXPECT_EQ("top, 20", 191 shell->display_manager()->GetCurrentDisplayLayout().ToString()); 192 EXPECT_EQ("top, 20", GetRegisteredDisplayLayoutStr(id1, id2)); 193 EXPECT_EQ("left, 30", GetRegisteredDisplayLayoutStr(id1, dummy_id)); 194} 195 196TEST_F(DisplayPreferencesTest, BasicStores) { 197 ash::DisplayController* display_controller = 198 ash::Shell::GetInstance()->display_controller(); 199 ash::DisplayManager* display_manager = 200 ash::Shell::GetInstance()->display_manager(); 201 202 UpdateDisplay("200x200*2, 400x300#400x400|300x200"); 203 int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id(); 204 gfx::Display::SetInternalDisplayId(id1); 205 int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id(); 206 int64 dummy_id = id2 + 1; 207 ASSERT_NE(id1, dummy_id); 208 std::vector<ui::ColorCalibrationProfile> profiles; 209 profiles.push_back(ui::COLOR_PROFILE_STANDARD); 210 profiles.push_back(ui::COLOR_PROFILE_DYNAMIC); 211 profiles.push_back(ui::COLOR_PROFILE_MOVIE); 212 profiles.push_back(ui::COLOR_PROFILE_READING); 213 ash::test::DisplayManagerTestApi test_api(display_manager); 214 // Allows only |id1|. 215 test_api.SetAvailableColorProfiles(id1, profiles); 216 display_manager->SetColorCalibrationProfile(id1, ui::COLOR_PROFILE_DYNAMIC); 217 display_manager->SetColorCalibrationProfile(id2, ui::COLOR_PROFILE_DYNAMIC); 218 219 LoggedInAsUser(); 220 ash::DisplayLayout layout(ash::DisplayLayout::TOP, 10); 221 SetCurrentDisplayLayout(layout); 222 StoreDisplayLayoutPrefForTest( 223 id1, dummy_id, ash::DisplayLayout(ash::DisplayLayout::LEFT, 20)); 224 // Can't switch to a display that does not exist. 225 display_controller->SetPrimaryDisplayId(dummy_id); 226 EXPECT_NE(dummy_id, ash::Shell::GetScreen()->GetPrimaryDisplay().id()); 227 228 display_controller->SetOverscanInsets(id1, gfx::Insets(10, 11, 12, 13)); 229 display_manager->SetDisplayRotation(id1, gfx::Display::ROTATE_90); 230 display_manager->SetDisplayUIScale(id1, 1.25f); 231 display_manager->SetDisplayUIScale(id2, 1.25f); 232 233 const base::DictionaryValue* displays = 234 local_state()->GetDictionary(prefs::kSecondaryDisplays); 235 const base::DictionaryValue* layout_value = NULL; 236 std::string key = base::Int64ToString(id1) + "," + base::Int64ToString(id2); 237 EXPECT_TRUE(displays->GetDictionary(key, &layout_value)); 238 239 ash::DisplayLayout stored_layout; 240 EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*layout_value, 241 &stored_layout)); 242 EXPECT_EQ(layout.position, stored_layout.position); 243 EXPECT_EQ(layout.offset, stored_layout.offset); 244 245 bool mirrored = true; 246 EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored)); 247 EXPECT_FALSE(mirrored); 248 249 const base::DictionaryValue* properties = 250 local_state()->GetDictionary(prefs::kDisplayProperties); 251 const base::DictionaryValue* property = NULL; 252 EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id1), &property)); 253 int ui_scale = 0; 254 int rotation = 0; 255 EXPECT_TRUE(property->GetInteger("rotation", &rotation)); 256 EXPECT_TRUE(property->GetInteger("ui-scale", &ui_scale)); 257 EXPECT_EQ(1, rotation); 258 EXPECT_EQ(1250, ui_scale); 259 260 // Internal display never registered the resolution. 261 int width = 0, height = 0; 262 EXPECT_FALSE(property->GetInteger("width", &width)); 263 EXPECT_FALSE(property->GetInteger("height", &height)); 264 265 int top = 0, left = 0, bottom = 0, right = 0; 266 EXPECT_TRUE(property->GetInteger("insets_top", &top)); 267 EXPECT_TRUE(property->GetInteger("insets_left", &left)); 268 EXPECT_TRUE(property->GetInteger("insets_bottom", &bottom)); 269 EXPECT_TRUE(property->GetInteger("insets_right", &right)); 270 EXPECT_EQ(10, top); 271 EXPECT_EQ(11, left); 272 EXPECT_EQ(12, bottom); 273 EXPECT_EQ(13, right); 274 275 std::string color_profile; 276 EXPECT_TRUE(property->GetString("color_profile_name", &color_profile)); 277 EXPECT_EQ("dynamic", color_profile); 278 279 EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property)); 280 EXPECT_TRUE(property->GetInteger("rotation", &rotation)); 281 EXPECT_TRUE(property->GetInteger("ui-scale", &ui_scale)); 282 EXPECT_EQ(0, rotation); 283 // ui_scale works only on 2x scale factor/1st display. 284 EXPECT_EQ(1000, ui_scale); 285 EXPECT_FALSE(property->GetInteger("insets_top", &top)); 286 EXPECT_FALSE(property->GetInteger("insets_left", &left)); 287 EXPECT_FALSE(property->GetInteger("insets_bottom", &bottom)); 288 EXPECT_FALSE(property->GetInteger("insets_right", &right)); 289 290 // |id2| doesn't have the color_profile because it doesn't have 'dynamic' in 291 // its available list. 292 EXPECT_FALSE(property->GetString("color_profile_name", &color_profile)); 293 294 // Resolution is saved only when the resolution is set 295 // by DisplayManager::SetDisplayResolution 296 width = 0; 297 height = 0; 298 EXPECT_FALSE(property->GetInteger("width", &width)); 299 EXPECT_FALSE(property->GetInteger("height", &height)); 300 301 display_manager->SetDisplayResolution(id2, gfx::Size(300, 200)); 302 303 display_controller->SetPrimaryDisplayId(id2); 304 305 EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id1), &property)); 306 width = 0; 307 height = 0; 308 // Internal display shouldn't store its resolution. 309 EXPECT_FALSE(property->GetInteger("width", &width)); 310 EXPECT_FALSE(property->GetInteger("height", &height)); 311 312 // External display's resolution must be stored this time because 313 // it's not best. 314 EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property)); 315 EXPECT_TRUE(property->GetInteger("width", &width)); 316 EXPECT_TRUE(property->GetInteger("height", &height)); 317 EXPECT_EQ(300, width); 318 EXPECT_EQ(200, height); 319 320 // The layout remains the same. 321 EXPECT_TRUE(displays->GetDictionary(key, &layout_value)); 322 EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*layout_value, 323 &stored_layout)); 324 EXPECT_EQ(layout.position, stored_layout.position); 325 EXPECT_EQ(layout.offset, stored_layout.offset); 326 EXPECT_EQ(id2, stored_layout.primary_id); 327 328 mirrored = true; 329 EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored)); 330 EXPECT_FALSE(mirrored); 331 std::string primary_id_str; 332 EXPECT_TRUE(layout_value->GetString(kPrimaryIdKey, &primary_id_str)); 333 EXPECT_EQ(base::Int64ToString(id2), primary_id_str); 334 335 SetCurrentDisplayLayout( 336 ash::DisplayLayout(ash::DisplayLayout::BOTTOM, 20)); 337 338 UpdateDisplay("1+0-200x200*2,1+0-200x200"); 339 // Mirrored. 340 int offset = 0; 341 std::string position; 342 EXPECT_TRUE(displays->GetDictionary(key, &layout_value)); 343 EXPECT_TRUE(layout_value->GetString(kPositionKey, &position)); 344 EXPECT_EQ("top", position); 345 EXPECT_TRUE(layout_value->GetInteger(kOffsetKey, &offset)); 346 EXPECT_EQ(-20, offset); 347 mirrored = false; 348 EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored)); 349 EXPECT_TRUE(mirrored); 350 EXPECT_TRUE(layout_value->GetString(kPrimaryIdKey, &primary_id_str)); 351 EXPECT_EQ(base::Int64ToString(id2), primary_id_str); 352 353 EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id1), &property)); 354 EXPECT_FALSE(property->GetInteger("width", &width)); 355 EXPECT_FALSE(property->GetInteger("height", &height)); 356 357 // External display's selected resolution must not change 358 // by mirroring. 359 EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property)); 360 EXPECT_TRUE(property->GetInteger("width", &width)); 361 EXPECT_TRUE(property->GetInteger("height", &height)); 362 EXPECT_EQ(300, width); 363 EXPECT_EQ(200, height); 364 365 // Set new display's selected resolution. 366 display_manager->RegisterDisplayProperty( 367 id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400), 368 ui::COLOR_PROFILE_STANDARD); 369 370 UpdateDisplay("200x200*2, 600x500#600x500|500x400"); 371 372 // Update key as the 2nd display gets new id. 373 id2 = ash::ScreenUtil::GetSecondaryDisplay().id(); 374 key = base::Int64ToString(id1) + "," + base::Int64ToString(id2); 375 EXPECT_TRUE(displays->GetDictionary(key, &layout_value)); 376 EXPECT_TRUE(layout_value->GetString(kPositionKey, &position)); 377 EXPECT_EQ("right", position); 378 EXPECT_TRUE(layout_value->GetInteger(kOffsetKey, &offset)); 379 EXPECT_EQ(0, offset); 380 mirrored = true; 381 EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored)); 382 EXPECT_FALSE(mirrored); 383 EXPECT_TRUE(layout_value->GetString(kPrimaryIdKey, &primary_id_str)); 384 EXPECT_EQ(base::Int64ToString(id1), primary_id_str); 385 386 // Best resolution should not be saved. 387 EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property)); 388 EXPECT_FALSE(property->GetInteger("width", &width)); 389 EXPECT_FALSE(property->GetInteger("height", &height)); 390 391 // Set yet another new display's selected resolution. 392 display_manager->RegisterDisplayProperty( 393 id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400), 394 ui::COLOR_PROFILE_STANDARD); 395 // Disconnect 2nd display first to generate new id for external display. 396 UpdateDisplay("200x200*2"); 397 UpdateDisplay("200x200*2, 500x400#600x500|500x400%60.0f"); 398 // Update key as the 2nd display gets new id. 399 id2 = ash::ScreenUtil::GetSecondaryDisplay().id(); 400 key = base::Int64ToString(id1) + "," + base::Int64ToString(id2); 401 EXPECT_TRUE(displays->GetDictionary(key, &layout_value)); 402 EXPECT_TRUE(layout_value->GetString(kPositionKey, &position)); 403 EXPECT_EQ("right", position); 404 EXPECT_TRUE(layout_value->GetInteger(kOffsetKey, &offset)); 405 EXPECT_EQ(0, offset); 406 mirrored = true; 407 EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored)); 408 EXPECT_FALSE(mirrored); 409 EXPECT_TRUE(layout_value->GetString(kPrimaryIdKey, &primary_id_str)); 410 EXPECT_EQ(base::Int64ToString(id1), primary_id_str); 411 412 // External display's selected resolution must be updated. 413 EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property)); 414 EXPECT_TRUE(property->GetInteger("width", &width)); 415 EXPECT_TRUE(property->GetInteger("height", &height)); 416 EXPECT_EQ(500, width); 417 EXPECT_EQ(400, height); 418} 419 420TEST_F(DisplayPreferencesTest, PreventStore) { 421 ResolutionNotificationController::SuppressTimerForTest(); 422 LoggedInAsUser(); 423 UpdateDisplay("400x300#500x400|400x300|300x200"); 424 int64 id = ash::Shell::GetScreen()->GetPrimaryDisplay().id(); 425 // Set display's resolution in single display. It creates the notification and 426 // display preferences should not stored meanwhile. 427 ash::Shell::GetInstance()->resolution_notification_controller()-> 428 SetDisplayResolutionAndNotify( 429 id, gfx::Size(400, 300), gfx::Size(500, 400), base::Closure()); 430 UpdateDisplay("500x400#500x400|400x300|300x200"); 431 432 const base::DictionaryValue* properties = 433 local_state()->GetDictionary(prefs::kDisplayProperties); 434 const base::DictionaryValue* property = NULL; 435 EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id), &property)); 436 int width = 0, height = 0; 437 EXPECT_FALSE(property->GetInteger("width", &width)); 438 EXPECT_FALSE(property->GetInteger("height", &height)); 439 440 // Revert the change. When timeout, 2nd button is revert. 441 message_center::MessageCenter::Get()->ClickOnNotificationButton( 442 ResolutionNotificationController::kNotificationId, 1); 443 RunAllPendingInMessageLoop(); 444 EXPECT_FALSE( 445 message_center::MessageCenter::Get()->FindVisibleNotificationById( 446 ResolutionNotificationController::kNotificationId)); 447 448 // Once the notification is removed, the specified resolution will be stored 449 // by SetDisplayResolution. 450 ash::Shell::GetInstance()->display_manager()->SetDisplayResolution( 451 id, gfx::Size(300, 200)); 452 UpdateDisplay("300x200#500x400|400x300|300x200"); 453 454 property = NULL; 455 EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id), &property)); 456 EXPECT_TRUE(property->GetInteger("width", &width)); 457 EXPECT_TRUE(property->GetInteger("height", &height)); 458 EXPECT_EQ(300, width); 459 EXPECT_EQ(200, height); 460} 461 462TEST_F(DisplayPreferencesTest, StoreForSwappedDisplay) { 463 UpdateDisplay("100x100,200x200"); 464 int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id(); 465 int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id(); 466 467 ash::DisplayController* display_controller = 468 ash::Shell::GetInstance()->display_controller(); 469 display_controller->SwapPrimaryDisplay(); 470 ASSERT_EQ(id1, ash::ScreenUtil::GetSecondaryDisplay().id()); 471 472 LoggedInAsUser(); 473 ash::DisplayLayout layout(ash::DisplayLayout::TOP, 10); 474 SetCurrentDisplayLayout(layout); 475 layout = layout.Invert(); 476 477 const base::DictionaryValue* displays = 478 local_state()->GetDictionary(prefs::kSecondaryDisplays); 479 const base::DictionaryValue* new_value = NULL; 480 std::string key = base::Int64ToString(id1) + "," + base::Int64ToString(id2); 481 EXPECT_TRUE(displays->GetDictionary(key, &new_value)); 482 483 ash::DisplayLayout stored_layout; 484 EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*new_value, &stored_layout)); 485 EXPECT_EQ(layout.position, stored_layout.position); 486 EXPECT_EQ(layout.offset, stored_layout.offset); 487 EXPECT_EQ(id2, stored_layout.primary_id); 488 489 display_controller->SwapPrimaryDisplay(); 490 EXPECT_TRUE(displays->GetDictionary(key, &new_value)); 491 EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*new_value, &stored_layout)); 492 EXPECT_EQ(layout.position, stored_layout.position); 493 EXPECT_EQ(layout.offset, stored_layout.offset); 494 EXPECT_EQ(id1, stored_layout.primary_id); 495} 496 497TEST_F(DisplayPreferencesTest, RestoreColorProfiles) { 498 ash::DisplayManager* display_manager = 499 ash::Shell::GetInstance()->display_manager(); 500 501 int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id(); 502 503 StoreColorProfile(id1, "dynamic"); 504 505 LoggedInAsUser(); 506 LoadDisplayPreferences(false); 507 508 // id1's available color profiles list is empty, means somehow the color 509 // profile suport is temporary in trouble. 510 EXPECT_NE(ui::COLOR_PROFILE_DYNAMIC, 511 display_manager->GetDisplayInfo(id1).color_profile()); 512 513 // Once the profile is supported, the color profile should be restored. 514 std::vector<ui::ColorCalibrationProfile> profiles; 515 profiles.push_back(ui::COLOR_PROFILE_STANDARD); 516 profiles.push_back(ui::COLOR_PROFILE_DYNAMIC); 517 profiles.push_back(ui::COLOR_PROFILE_MOVIE); 518 profiles.push_back(ui::COLOR_PROFILE_READING); 519 ash::test::DisplayManagerTestApi test_api(display_manager); 520 test_api.SetAvailableColorProfiles(id1, profiles); 521 522 LoadDisplayPreferences(false); 523 EXPECT_EQ(ui::COLOR_PROFILE_DYNAMIC, 524 display_manager->GetDisplayInfo(id1).color_profile()); 525} 526 527TEST_F(DisplayPreferencesTest, DontStoreInGuestMode) { 528 ash::DisplayController* display_controller = 529 ash::Shell::GetInstance()->display_controller(); 530 ash::DisplayManager* display_manager = 531 ash::Shell::GetInstance()->display_manager(); 532 533 UpdateDisplay("200x200*2,200x200"); 534 535 LoggedInAsGuest(); 536 int64 id1 = ash::Shell::GetScreen()->GetPrimaryDisplay().id(); 537 gfx::Display::SetInternalDisplayId(id1); 538 int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id(); 539 ash::DisplayLayout layout(ash::DisplayLayout::TOP, 10); 540 SetCurrentDisplayLayout(layout); 541 display_manager->SetDisplayUIScale(id1, 1.25f); 542 display_controller->SetPrimaryDisplayId(id2); 543 int64 new_primary = ash::Shell::GetScreen()->GetPrimaryDisplay().id(); 544 display_controller->SetOverscanInsets( 545 new_primary, 546 gfx::Insets(10, 11, 12, 13)); 547 display_manager->SetDisplayRotation(new_primary, gfx::Display::ROTATE_90); 548 549 // Does not store the preferences locally. 550 EXPECT_FALSE(local_state()->FindPreference( 551 prefs::kSecondaryDisplays)->HasUserSetting()); 552 EXPECT_FALSE(local_state()->FindPreference( 553 prefs::kDisplayProperties)->HasUserSetting()); 554 555 // Settings are still notified to the system. 556 gfx::Screen* screen = gfx::Screen::GetNativeScreen(); 557 EXPECT_EQ(id2, screen->GetPrimaryDisplay().id()); 558 EXPECT_EQ(ash::DisplayLayout::BOTTOM, 559 display_manager->GetCurrentDisplayLayout().position); 560 EXPECT_EQ(-10, display_manager->GetCurrentDisplayLayout().offset); 561 const gfx::Display& primary_display = screen->GetPrimaryDisplay(); 562 EXPECT_EQ("178x176", primary_display.bounds().size().ToString()); 563 EXPECT_EQ(gfx::Display::ROTATE_90, primary_display.rotation()); 564 565 const ash::DisplayInfo& info1 = display_manager->GetDisplayInfo(id1); 566 EXPECT_EQ(1.25f, info1.configured_ui_scale()); 567 568 const ash::DisplayInfo& info_primary = 569 display_manager->GetDisplayInfo(new_primary); 570 EXPECT_EQ(gfx::Display::ROTATE_90, info_primary.rotation()); 571 EXPECT_EQ(1.0f, info_primary.configured_ui_scale()); 572} 573 574TEST_F(DisplayPreferencesTest, StorePowerStateNoLogin) { 575 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayPowerState)); 576 577 // Stores display prefs without login, which still stores the power state. 578 StoreDisplayPrefs(); 579 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayPowerState)); 580} 581 582TEST_F(DisplayPreferencesTest, StorePowerStateGuest) { 583 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayPowerState)); 584 585 LoggedInAsGuest(); 586 StoreDisplayPrefs(); 587 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayPowerState)); 588} 589 590TEST_F(DisplayPreferencesTest, StorePowerStateNormalUser) { 591 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayPowerState)); 592 593 LoggedInAsUser(); 594 StoreDisplayPrefs(); 595 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayPowerState)); 596} 597 598TEST_F(DisplayPreferencesTest, DisplayPowerStateAfterRestart) { 599 StoreDisplayPowerStateForTest( 600 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON); 601 LoadDisplayPreferences(false); 602 EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, 603 ash::Shell::GetInstance()->display_configurator()->power_state()); 604} 605 606TEST_F(DisplayPreferencesTest, DontSaveAndRestoreAllOff) { 607 ash::Shell* shell = ash::Shell::GetInstance(); 608 StoreDisplayPowerStateForTest( 609 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON); 610 LoadDisplayPreferences(false); 611 // DisplayPowerState should be ignored at boot. 612 EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, 613 shell->display_configurator()->power_state()); 614 615 StoreDisplayPowerStateForTest( 616 chromeos::DISPLAY_POWER_ALL_OFF); 617 EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, 618 shell->display_configurator()->power_state()); 619 EXPECT_EQ("internal_off_external_on", 620 local_state()->GetString(prefs::kDisplayPowerState)); 621 622 // Don't try to load 623 local_state()->SetString(prefs::kDisplayPowerState, "all_off"); 624 LoadDisplayPreferences(false); 625 EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, 626 shell->display_configurator()->power_state()); 627} 628 629// Tests that display configuration changes caused by MaximizeModeController 630// are not saved. 631TEST_F(DisplayPreferencesTest, DontSaveMaximizeModeControllerRotations) { 632 ash::Shell* shell = ash::Shell::GetInstance(); 633 ash::MaximizeModeController* controller = shell->maximize_mode_controller(); 634 gfx::Display::SetInternalDisplayId( 635 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id()); 636 ash::DisplayManager* display_manager = shell->display_manager(); 637 LoggedInAsUser(); 638 // Populate the properties. 639 display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(), 640 gfx::Display::ROTATE_180); 641 // Reset property to avoid rotation lock 642 display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(), 643 gfx::Display::ROTATE_0); 644 645 // Open up 270 degrees to trigger maximize mode 646 controller->OnAccelerometerUpdated(gfx::Vector3dF(0.0f, 0.0f, -1.0f), 647 gfx::Vector3dF(-1.0f, 0.0f, 0.0f)); 648 EXPECT_TRUE(controller->IsMaximizeModeWindowManagerEnabled()); 649 650 // Trigger 90 degree rotation 651 controller->OnAccelerometerUpdated(gfx::Vector3dF(0.0f, 1.0f, 0.0f), 652 gfx::Vector3dF(0.0f, 1.0f, 0.0f)); 653 EXPECT_EQ(gfx::Display::ROTATE_90, display_manager-> 654 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation()); 655 656 const base::DictionaryValue* properties = 657 local_state()->GetDictionary(prefs::kDisplayProperties); 658 const base::DictionaryValue* property = NULL; 659 EXPECT_TRUE(properties->GetDictionary( 660 base::Int64ToString(gfx::Display::InternalDisplayId()), &property)); 661 int rotation = -1; 662 EXPECT_TRUE(property->GetInteger("rotation", &rotation)); 663 EXPECT_EQ(gfx::Display::ROTATE_0, rotation); 664} 665 666} // namespace chromeos 667