Home | History | Annotate | Download | only in display
      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 
     32 using ash::ResolutionNotificationController;
     33 
     34 namespace chromeos {
     35 namespace {
     36 const char kPrimaryIdKey[] = "primary-id";
     37 const char kMirroredKey[] = "mirrored";
     38 const char kPositionKey[] = "position";
     39 const char kOffsetKey[] = "offset";
     40 
     41 class 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 
    166 TEST_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 
    196 TEST_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 
    420 TEST_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 
    462 TEST_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 
    497 TEST_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 
    527 TEST_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 
    574 TEST_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 
    582 TEST_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 
    590 TEST_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 
    598 TEST_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 
    606 TEST_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.
    631 TEST_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