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/scoped_user_manager_enabler.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 // The mean acceleration due to gravity on Earth in m/s^2.
     42 const float kMeanGravity = 9.80665f;
     43 
     44 class DisplayPreferencesTest : public ash::test::AshTestBase {
     45  protected:
     46   DisplayPreferencesTest()
     47       : mock_user_manager_(new MockUserManager),
     48         user_manager_enabler_(mock_user_manager_) {
     49   }
     50 
     51   virtual ~DisplayPreferencesTest() {}
     52 
     53   virtual void SetUp() OVERRIDE {
     54     EXPECT_CALL(*mock_user_manager_, IsUserLoggedIn())
     55         .WillRepeatedly(testing::Return(false));
     56     EXPECT_CALL(*mock_user_manager_, Shutdown());
     57     ash::test::AshTestBase::SetUp();
     58     RegisterDisplayLocalStatePrefs(local_state_.registry());
     59     TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
     60     observer_.reset(new DisplayConfigurationObserver());
     61   }
     62 
     63   virtual void TearDown() OVERRIDE {
     64     observer_.reset();
     65     TestingBrowserProcess::GetGlobal()->SetLocalState(NULL);
     66     ash::test::AshTestBase::TearDown();
     67   }
     68 
     69   void LoggedInAsUser() {
     70     EXPECT_CALL(*mock_user_manager_, IsUserLoggedIn())
     71         .WillRepeatedly(testing::Return(true));
     72     EXPECT_CALL(*mock_user_manager_, IsLoggedInAsRegularUser())
     73         .WillRepeatedly(testing::Return(true));
     74   }
     75 
     76   void LoggedInAsGuest() {
     77     EXPECT_CALL(*mock_user_manager_, IsUserLoggedIn())
     78         .WillRepeatedly(testing::Return(true));
     79     EXPECT_CALL(*mock_user_manager_, IsLoggedInAsRegularUser())
     80         .WillRepeatedly(testing::Return(false));
     81     EXPECT_CALL(*mock_user_manager_, IsLoggedInAsSupervisedUser())
     82         .WillRepeatedly(testing::Return(false));
     83   }
     84 
     85   // Do not use the implementation of display_preferences.cc directly to avoid
     86   // notifying the update to the system.
     87   void StoreDisplayLayoutPrefForName(const std::string& name,
     88                                      ash::DisplayLayout::Position layout,
     89                                      int offset,
     90                                      int64 primary_id) {
     91     DictionaryPrefUpdate update(&local_state_, prefs::kSecondaryDisplays);
     92     ash::DisplayLayout display_layout(layout, offset);
     93     display_layout.primary_id = primary_id;
     94 
     95     DCHECK(!name.empty());
     96 
     97     base::DictionaryValue* pref_data = update.Get();
     98     scoped_ptr<base::Value>layout_value(new base::DictionaryValue());
     99     if (pref_data->HasKey(name)) {
    100       base::Value* value = NULL;
    101       if (pref_data->Get(name, &value) && value != NULL)
    102         layout_value.reset(value->DeepCopy());
    103     }
    104     if (ash::DisplayLayout::ConvertToValue(display_layout, layout_value.get()))
    105       pref_data->Set(name, layout_value.release());
    106   }
    107 
    108   void StoreDisplayLayoutPrefForPair(int64 id1,
    109                                      int64 id2,
    110                                      ash::DisplayLayout::Position layout,
    111                                      int offset) {
    112     StoreDisplayLayoutPrefForName(
    113         base::Int64ToString(id1) + "," + base::Int64ToString(id2),
    114         layout, offset, id1);
    115   }
    116 
    117   void StoreDisplayLayoutPrefForSecondary(int64 id,
    118                                           ash::DisplayLayout::Position layout,
    119                                           int offset,
    120                                           int64 primary_id) {
    121     StoreDisplayLayoutPrefForName(
    122         base::Int64ToString(id), layout, offset, primary_id);
    123   }
    124 
    125   void StoreDisplayOverscan(int64 id, const gfx::Insets& insets) {
    126     DictionaryPrefUpdate update(&local_state_, prefs::kDisplayProperties);
    127     const std::string name = base::Int64ToString(id);
    128 
    129     base::DictionaryValue* pref_data = update.Get();
    130     base::DictionaryValue* insets_value = new base::DictionaryValue();
    131     insets_value->SetInteger("insets_top", insets.top());
    132     insets_value->SetInteger("insets_left", insets.left());
    133     insets_value->SetInteger("insets_bottom", insets.bottom());
    134     insets_value->SetInteger("insets_right", insets.right());
    135     pref_data->Set(name, insets_value);
    136   }
    137 
    138   void StoreColorProfile(int64 id, const std::string& profile) {
    139     DictionaryPrefUpdate update(&local_state_, prefs::kDisplayProperties);
    140     const std::string name = base::Int64ToString(id);
    141 
    142     base::DictionaryValue* pref_data = update.Get();
    143     base::DictionaryValue* property = new base::DictionaryValue();
    144     property->SetString("color_profile_name", profile);
    145     pref_data->Set(name, property);
    146   }
    147 
    148   void StoreDisplayRotationPrefsForTest(bool rotation_lock,
    149                                         gfx::Display::Rotation rotation) {
    150     DictionaryPrefUpdate update(local_state(), prefs::kDisplayRotationLock);
    151     base::DictionaryValue* pref_data = update.Get();
    152     pref_data->SetBoolean("lock", rotation_lock);
    153     pref_data->SetInteger("orientation", static_cast<int>(rotation));
    154   }
    155 
    156   std::string GetRegisteredDisplayLayoutStr(int64 id1, int64 id2) {
    157     ash::DisplayIdPair pair;
    158     pair.first = id1;
    159     pair.second = id2;
    160     return ash::Shell::GetInstance()->display_manager()->layout_store()->
    161         GetRegisteredDisplayLayout(pair).ToString();
    162   }
    163 
    164   PrefService* local_state() { return &local_state_; }
    165 
    166  private:
    167   MockUserManager* mock_user_manager_;  // Not owned.
    168   ScopedUserManagerEnabler user_manager_enabler_;
    169   TestingPrefServiceSimple local_state_;
    170   scoped_ptr<DisplayConfigurationObserver> observer_;
    171 
    172   DISALLOW_COPY_AND_ASSIGN(DisplayPreferencesTest);
    173 };
    174 
    175 }  // namespace
    176 
    177 TEST_F(DisplayPreferencesTest, PairedLayoutOverrides) {
    178   UpdateDisplay("100x100,200x200");
    179   int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
    180   int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
    181   int64 dummy_id = id2 + 1;
    182   ASSERT_NE(id1, dummy_id);
    183 
    184   StoreDisplayLayoutPrefForPair(id1, id2, ash::DisplayLayout::TOP, 20);
    185   StoreDisplayLayoutPrefForPair(id1, dummy_id, ash::DisplayLayout::LEFT, 30);
    186   StoreDisplayPowerStateForTest(
    187       chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON);
    188 
    189   ash::Shell* shell = ash::Shell::GetInstance();
    190 
    191   LoadDisplayPreferences(true);
    192   // DisplayPowerState should be ignored at boot.
    193   EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON,
    194             shell->display_configurator()->requested_power_state());
    195 
    196   shell->display_manager()->UpdateDisplays();
    197   // Check if the layout settings are notified to the system properly.
    198   // The paired layout overrides old layout.
    199   // Inverted one of for specified pair (id1, id2).  Not used for the pair
    200   // (id1, dummy_id) since dummy_id is not connected right now.
    201   EXPECT_EQ("top, 20",
    202             shell->display_manager()->GetCurrentDisplayLayout().ToString());
    203   EXPECT_EQ("top, 20", GetRegisteredDisplayLayoutStr(id1, id2));
    204   EXPECT_EQ("left, 30", GetRegisteredDisplayLayoutStr(id1, dummy_id));
    205 }
    206 
    207 TEST_F(DisplayPreferencesTest, BasicStores) {
    208   ash::DisplayController* display_controller =
    209       ash::Shell::GetInstance()->display_controller();
    210   ash::DisplayManager* display_manager =
    211       ash::Shell::GetInstance()->display_manager();
    212 
    213   UpdateDisplay("200x200*2, 400x300#400x400|300x200*1.25");
    214   int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
    215   gfx::Display::SetInternalDisplayId(id1);
    216   int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
    217   int64 dummy_id = id2 + 1;
    218   ASSERT_NE(id1, dummy_id);
    219   std::vector<ui::ColorCalibrationProfile> profiles;
    220   profiles.push_back(ui::COLOR_PROFILE_STANDARD);
    221   profiles.push_back(ui::COLOR_PROFILE_DYNAMIC);
    222   profiles.push_back(ui::COLOR_PROFILE_MOVIE);
    223   profiles.push_back(ui::COLOR_PROFILE_READING);
    224   ash::test::DisplayManagerTestApi test_api(display_manager);
    225   // Allows only |id1|.
    226   test_api.SetAvailableColorProfiles(id1, profiles);
    227   display_manager->SetColorCalibrationProfile(id1, ui::COLOR_PROFILE_DYNAMIC);
    228   display_manager->SetColorCalibrationProfile(id2, ui::COLOR_PROFILE_DYNAMIC);
    229 
    230   LoggedInAsUser();
    231   ash::DisplayLayout layout(ash::DisplayLayout::TOP, 10);
    232   SetCurrentDisplayLayout(layout);
    233   StoreDisplayLayoutPrefForTest(
    234       id1, dummy_id, ash::DisplayLayout(ash::DisplayLayout::LEFT, 20));
    235   // Can't switch to a display that does not exist.
    236   display_controller->SetPrimaryDisplayId(dummy_id);
    237   EXPECT_NE(dummy_id, ash::Shell::GetScreen()->GetPrimaryDisplay().id());
    238 
    239   display_controller->SetOverscanInsets(id1, gfx::Insets(10, 11, 12, 13));
    240   display_manager->SetDisplayRotation(id1, gfx::Display::ROTATE_90);
    241   display_manager->SetDisplayUIScale(id1, 1.25f);
    242   display_manager->SetDisplayUIScale(id2, 1.25f);
    243 
    244   const base::DictionaryValue* displays =
    245       local_state()->GetDictionary(prefs::kSecondaryDisplays);
    246   const base::DictionaryValue* layout_value = NULL;
    247   std::string key = base::Int64ToString(id1) + "," + base::Int64ToString(id2);
    248   EXPECT_TRUE(displays->GetDictionary(key, &layout_value));
    249 
    250   ash::DisplayLayout stored_layout;
    251   EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*layout_value,
    252                                                    &stored_layout));
    253   EXPECT_EQ(layout.position, stored_layout.position);
    254   EXPECT_EQ(layout.offset, stored_layout.offset);
    255 
    256   bool mirrored = true;
    257   EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored));
    258   EXPECT_FALSE(mirrored);
    259 
    260   const base::DictionaryValue* properties =
    261       local_state()->GetDictionary(prefs::kDisplayProperties);
    262   const base::DictionaryValue* property = NULL;
    263   EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id1), &property));
    264   int ui_scale = 0;
    265   int rotation = 0;
    266   EXPECT_TRUE(property->GetInteger("rotation", &rotation));
    267   EXPECT_TRUE(property->GetInteger("ui-scale", &ui_scale));
    268   EXPECT_EQ(1, rotation);
    269   EXPECT_EQ(1250, ui_scale);
    270 
    271   // Internal display never registered the resolution.
    272   int width = 0, height = 0;
    273   EXPECT_FALSE(property->GetInteger("width", &width));
    274   EXPECT_FALSE(property->GetInteger("height", &height));
    275 
    276   int top = 0, left = 0, bottom = 0, right = 0;
    277   EXPECT_TRUE(property->GetInteger("insets_top", &top));
    278   EXPECT_TRUE(property->GetInteger("insets_left", &left));
    279   EXPECT_TRUE(property->GetInteger("insets_bottom", &bottom));
    280   EXPECT_TRUE(property->GetInteger("insets_right", &right));
    281   EXPECT_EQ(10, top);
    282   EXPECT_EQ(11, left);
    283   EXPECT_EQ(12, bottom);
    284   EXPECT_EQ(13, right);
    285 
    286   std::string color_profile;
    287   EXPECT_TRUE(property->GetString("color_profile_name", &color_profile));
    288   EXPECT_EQ("dynamic", color_profile);
    289 
    290   EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property));
    291   EXPECT_TRUE(property->GetInteger("rotation", &rotation));
    292   EXPECT_TRUE(property->GetInteger("ui-scale", &ui_scale));
    293   EXPECT_EQ(0, rotation);
    294   // ui_scale works only on 2x scale factor/1st display.
    295   EXPECT_EQ(1000, ui_scale);
    296   EXPECT_FALSE(property->GetInteger("insets_top", &top));
    297   EXPECT_FALSE(property->GetInteger("insets_left", &left));
    298   EXPECT_FALSE(property->GetInteger("insets_bottom", &bottom));
    299   EXPECT_FALSE(property->GetInteger("insets_right", &right));
    300 
    301   // |id2| doesn't have the color_profile because it doesn't have 'dynamic' in
    302   // its available list.
    303   EXPECT_FALSE(property->GetString("color_profile_name", &color_profile));
    304 
    305   // Resolution is saved only when the resolution is set
    306   // by DisplayManager::SetDisplayMode
    307   width = 0;
    308   height = 0;
    309   EXPECT_FALSE(property->GetInteger("width", &width));
    310   EXPECT_FALSE(property->GetInteger("height", &height));
    311 
    312   ash::DisplayMode mode(gfx::Size(300, 200), 60.0f, false, true);
    313   mode.device_scale_factor = 1.25f;
    314   display_manager->SetDisplayMode(id2, mode);
    315 
    316   display_controller->SetPrimaryDisplayId(id2);
    317 
    318   EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id1), &property));
    319   width = 0;
    320   height = 0;
    321   // Internal display shouldn't store its resolution.
    322   EXPECT_FALSE(property->GetInteger("width", &width));
    323   EXPECT_FALSE(property->GetInteger("height", &height));
    324 
    325   // External display's resolution must be stored this time because
    326   // it's not best.
    327   int device_scale_factor = 0;
    328   EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property));
    329   EXPECT_TRUE(property->GetInteger("width", &width));
    330   EXPECT_TRUE(property->GetInteger("height", &height));
    331   EXPECT_TRUE(property->GetInteger(
    332       "device-scale-factor", &device_scale_factor));
    333   EXPECT_EQ(300, width);
    334   EXPECT_EQ(200, height);
    335   EXPECT_EQ(1250, device_scale_factor);
    336 
    337   // The layout remains the same.
    338   EXPECT_TRUE(displays->GetDictionary(key, &layout_value));
    339   EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*layout_value,
    340                                                    &stored_layout));
    341   EXPECT_EQ(layout.position, stored_layout.position);
    342   EXPECT_EQ(layout.offset, stored_layout.offset);
    343   EXPECT_EQ(id2, stored_layout.primary_id);
    344 
    345   mirrored = true;
    346   EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored));
    347   EXPECT_FALSE(mirrored);
    348   std::string primary_id_str;
    349   EXPECT_TRUE(layout_value->GetString(kPrimaryIdKey, &primary_id_str));
    350   EXPECT_EQ(base::Int64ToString(id2), primary_id_str);
    351 
    352   SetCurrentDisplayLayout(
    353       ash::DisplayLayout(ash::DisplayLayout::BOTTOM, 20));
    354 
    355   UpdateDisplay("1+0-200x200*2,1+0-200x200");
    356   // Mirrored.
    357   int offset = 0;
    358   std::string position;
    359   EXPECT_TRUE(displays->GetDictionary(key, &layout_value));
    360   EXPECT_TRUE(layout_value->GetString(kPositionKey, &position));
    361   EXPECT_EQ("top", position);
    362   EXPECT_TRUE(layout_value->GetInteger(kOffsetKey, &offset));
    363   EXPECT_EQ(-20, offset);
    364   mirrored = false;
    365   EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored));
    366   EXPECT_TRUE(mirrored);
    367   EXPECT_TRUE(layout_value->GetString(kPrimaryIdKey, &primary_id_str));
    368   EXPECT_EQ(base::Int64ToString(id2), primary_id_str);
    369 
    370   EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id1), &property));
    371   EXPECT_FALSE(property->GetInteger("width", &width));
    372   EXPECT_FALSE(property->GetInteger("height", &height));
    373 
    374   // External display's selected resolution must not change
    375   // by mirroring.
    376   EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property));
    377   EXPECT_TRUE(property->GetInteger("width", &width));
    378   EXPECT_TRUE(property->GetInteger("height", &height));
    379   EXPECT_EQ(300, width);
    380   EXPECT_EQ(200, height);
    381 
    382   // Set new display's selected resolution.
    383   display_manager->RegisterDisplayProperty(
    384       id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400), 1.0f,
    385       ui::COLOR_PROFILE_STANDARD);
    386 
    387   UpdateDisplay("200x200*2, 600x500#600x500|500x400");
    388 
    389   // Update key as the 2nd display gets new id.
    390   id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
    391   key = base::Int64ToString(id1) + "," + base::Int64ToString(id2);
    392   EXPECT_TRUE(displays->GetDictionary(key, &layout_value));
    393   EXPECT_TRUE(layout_value->GetString(kPositionKey, &position));
    394   EXPECT_EQ("right", position);
    395   EXPECT_TRUE(layout_value->GetInteger(kOffsetKey, &offset));
    396   EXPECT_EQ(0, offset);
    397   mirrored = true;
    398   EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored));
    399   EXPECT_FALSE(mirrored);
    400   EXPECT_TRUE(layout_value->GetString(kPrimaryIdKey, &primary_id_str));
    401   EXPECT_EQ(base::Int64ToString(id1), primary_id_str);
    402 
    403   // Best resolution should not be saved.
    404   EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property));
    405   EXPECT_FALSE(property->GetInteger("width", &width));
    406   EXPECT_FALSE(property->GetInteger("height", &height));
    407 
    408   // Set yet another new display's selected resolution.
    409   display_manager->RegisterDisplayProperty(
    410       id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400), 1.0f,
    411       ui::COLOR_PROFILE_STANDARD);
    412   // Disconnect 2nd display first to generate new id for external display.
    413   UpdateDisplay("200x200*2");
    414   UpdateDisplay("200x200*2, 500x400#600x500|500x400%60.0f");
    415   // Update key as the 2nd display gets new id.
    416   id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
    417   key = base::Int64ToString(id1) + "," + base::Int64ToString(id2);
    418   EXPECT_TRUE(displays->GetDictionary(key, &layout_value));
    419   EXPECT_TRUE(layout_value->GetString(kPositionKey, &position));
    420   EXPECT_EQ("right", position);
    421   EXPECT_TRUE(layout_value->GetInteger(kOffsetKey, &offset));
    422   EXPECT_EQ(0, offset);
    423   mirrored = true;
    424   EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored));
    425   EXPECT_FALSE(mirrored);
    426   EXPECT_TRUE(layout_value->GetString(kPrimaryIdKey, &primary_id_str));
    427   EXPECT_EQ(base::Int64ToString(id1), primary_id_str);
    428 
    429   // External display's selected resolution must be updated.
    430   EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property));
    431   EXPECT_TRUE(property->GetInteger("width", &width));
    432   EXPECT_TRUE(property->GetInteger("height", &height));
    433   EXPECT_EQ(500, width);
    434   EXPECT_EQ(400, height);
    435 }
    436 
    437 TEST_F(DisplayPreferencesTest, PreventStore) {
    438   ResolutionNotificationController::SuppressTimerForTest();
    439   LoggedInAsUser();
    440   UpdateDisplay("400x300#500x400|400x300|300x200");
    441   int64 id = ash::Shell::GetScreen()->GetPrimaryDisplay().id();
    442   // Set display's resolution in single display. It creates the notification and
    443   // display preferences should not stored meanwhile.
    444   ash::Shell* shell = ash::Shell::GetInstance();
    445   ash::DisplayMode old_mode;
    446   ash::DisplayMode new_mode;
    447   old_mode.size = gfx::Size(400, 300);
    448   new_mode.size = gfx::Size(500, 400);
    449   if (shell->display_manager()->SetDisplayMode(id, new_mode)) {
    450     shell->resolution_notification_controller()->PrepareNotification(
    451         id, old_mode, new_mode, base::Closure());
    452   }
    453   UpdateDisplay("500x400#500x400|400x300|300x200");
    454 
    455   const base::DictionaryValue* properties =
    456       local_state()->GetDictionary(prefs::kDisplayProperties);
    457   const base::DictionaryValue* property = NULL;
    458   EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id), &property));
    459   int width = 0, height = 0;
    460   EXPECT_FALSE(property->GetInteger("width", &width));
    461   EXPECT_FALSE(property->GetInteger("height", &height));
    462 
    463   // Revert the change. When timeout, 2nd button is revert.
    464   message_center::MessageCenter::Get()->ClickOnNotificationButton(
    465       ResolutionNotificationController::kNotificationId, 1);
    466   RunAllPendingInMessageLoop();
    467   EXPECT_FALSE(
    468       message_center::MessageCenter::Get()->FindVisibleNotificationById(
    469           ResolutionNotificationController::kNotificationId));
    470 
    471   // Once the notification is removed, the specified resolution will be stored
    472   // by SetDisplayMode.
    473   ash::Shell::GetInstance()->display_manager()->SetDisplayMode(
    474       id, ash::DisplayMode(gfx::Size(300, 200), 60.0f, false, true));
    475   UpdateDisplay("300x200#500x400|400x300|300x200");
    476 
    477   property = NULL;
    478   EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id), &property));
    479   EXPECT_TRUE(property->GetInteger("width", &width));
    480   EXPECT_TRUE(property->GetInteger("height", &height));
    481   EXPECT_EQ(300, width);
    482   EXPECT_EQ(200, height);
    483 }
    484 
    485 TEST_F(DisplayPreferencesTest, StoreForSwappedDisplay) {
    486   UpdateDisplay("100x100,200x200");
    487   int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
    488   int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
    489 
    490   ash::DisplayController* display_controller =
    491       ash::Shell::GetInstance()->display_controller();
    492   display_controller->SwapPrimaryDisplay();
    493   ASSERT_EQ(id1, ash::ScreenUtil::GetSecondaryDisplay().id());
    494 
    495   LoggedInAsUser();
    496   ash::DisplayLayout layout(ash::DisplayLayout::TOP, 10);
    497   SetCurrentDisplayLayout(layout);
    498   layout = layout.Invert();
    499 
    500   const base::DictionaryValue* displays =
    501       local_state()->GetDictionary(prefs::kSecondaryDisplays);
    502   const base::DictionaryValue* new_value = NULL;
    503   std::string key = base::Int64ToString(id1) + "," + base::Int64ToString(id2);
    504   EXPECT_TRUE(displays->GetDictionary(key, &new_value));
    505 
    506   ash::DisplayLayout stored_layout;
    507   EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*new_value, &stored_layout));
    508   EXPECT_EQ(layout.position, stored_layout.position);
    509   EXPECT_EQ(layout.offset, stored_layout.offset);
    510   EXPECT_EQ(id2, stored_layout.primary_id);
    511 
    512   display_controller->SwapPrimaryDisplay();
    513   EXPECT_TRUE(displays->GetDictionary(key, &new_value));
    514   EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*new_value, &stored_layout));
    515   EXPECT_EQ(layout.position, stored_layout.position);
    516   EXPECT_EQ(layout.offset, stored_layout.offset);
    517   EXPECT_EQ(id1, stored_layout.primary_id);
    518 }
    519 
    520 TEST_F(DisplayPreferencesTest, RestoreColorProfiles) {
    521   ash::DisplayManager* display_manager =
    522       ash::Shell::GetInstance()->display_manager();
    523 
    524   int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
    525 
    526   StoreColorProfile(id1, "dynamic");
    527 
    528   LoggedInAsUser();
    529   LoadDisplayPreferences(false);
    530 
    531   // id1's available color profiles list is empty, means somehow the color
    532   // profile suport is temporary in trouble.
    533   EXPECT_NE(ui::COLOR_PROFILE_DYNAMIC,
    534             display_manager->GetDisplayInfo(id1).color_profile());
    535 
    536   // Once the profile is supported, the color profile should be restored.
    537   std::vector<ui::ColorCalibrationProfile> profiles;
    538   profiles.push_back(ui::COLOR_PROFILE_STANDARD);
    539   profiles.push_back(ui::COLOR_PROFILE_DYNAMIC);
    540   profiles.push_back(ui::COLOR_PROFILE_MOVIE);
    541   profiles.push_back(ui::COLOR_PROFILE_READING);
    542   ash::test::DisplayManagerTestApi test_api(display_manager);
    543   test_api.SetAvailableColorProfiles(id1, profiles);
    544 
    545   LoadDisplayPreferences(false);
    546   EXPECT_EQ(ui::COLOR_PROFILE_DYNAMIC,
    547             display_manager->GetDisplayInfo(id1).color_profile());
    548 }
    549 
    550 TEST_F(DisplayPreferencesTest, DontStoreInGuestMode) {
    551   ash::DisplayController* display_controller =
    552       ash::Shell::GetInstance()->display_controller();
    553   ash::DisplayManager* display_manager =
    554       ash::Shell::GetInstance()->display_manager();
    555 
    556   UpdateDisplay("200x200*2,200x200");
    557 
    558   LoggedInAsGuest();
    559   int64 id1 = ash::Shell::GetScreen()->GetPrimaryDisplay().id();
    560   gfx::Display::SetInternalDisplayId(id1);
    561   int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
    562   ash::DisplayLayout layout(ash::DisplayLayout::TOP, 10);
    563   SetCurrentDisplayLayout(layout);
    564   display_manager->SetDisplayUIScale(id1, 1.25f);
    565   display_controller->SetPrimaryDisplayId(id2);
    566   int64 new_primary = ash::Shell::GetScreen()->GetPrimaryDisplay().id();
    567   display_controller->SetOverscanInsets(
    568       new_primary,
    569       gfx::Insets(10, 11, 12, 13));
    570   display_manager->SetDisplayRotation(new_primary, gfx::Display::ROTATE_90);
    571 
    572   // Does not store the preferences locally.
    573   EXPECT_FALSE(local_state()->FindPreference(
    574       prefs::kSecondaryDisplays)->HasUserSetting());
    575   EXPECT_FALSE(local_state()->FindPreference(
    576       prefs::kDisplayProperties)->HasUserSetting());
    577 
    578   // Settings are still notified to the system.
    579   gfx::Screen* screen = gfx::Screen::GetNativeScreen();
    580   EXPECT_EQ(id2, screen->GetPrimaryDisplay().id());
    581   EXPECT_EQ(ash::DisplayLayout::BOTTOM,
    582             display_manager->GetCurrentDisplayLayout().position);
    583   EXPECT_EQ(-10, display_manager->GetCurrentDisplayLayout().offset);
    584   const gfx::Display& primary_display = screen->GetPrimaryDisplay();
    585   EXPECT_EQ("178x176", primary_display.bounds().size().ToString());
    586   EXPECT_EQ(gfx::Display::ROTATE_90, primary_display.rotation());
    587 
    588   const ash::DisplayInfo& info1 = display_manager->GetDisplayInfo(id1);
    589   EXPECT_EQ(1.25f, info1.configured_ui_scale());
    590 
    591   const ash::DisplayInfo& info_primary =
    592       display_manager->GetDisplayInfo(new_primary);
    593   EXPECT_EQ(gfx::Display::ROTATE_90, info_primary.rotation());
    594   EXPECT_EQ(1.0f, info_primary.configured_ui_scale());
    595 }
    596 
    597 TEST_F(DisplayPreferencesTest, StorePowerStateNoLogin) {
    598   EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayPowerState));
    599 
    600   // Stores display prefs without login, which still stores the power state.
    601   StoreDisplayPrefs();
    602   EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayPowerState));
    603 }
    604 
    605 TEST_F(DisplayPreferencesTest, StorePowerStateGuest) {
    606   EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayPowerState));
    607 
    608   LoggedInAsGuest();
    609   StoreDisplayPrefs();
    610   EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayPowerState));
    611 }
    612 
    613 TEST_F(DisplayPreferencesTest, StorePowerStateNormalUser) {
    614   EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayPowerState));
    615 
    616   LoggedInAsUser();
    617   StoreDisplayPrefs();
    618   EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayPowerState));
    619 }
    620 
    621 TEST_F(DisplayPreferencesTest, DisplayPowerStateAfterRestart) {
    622   StoreDisplayPowerStateForTest(
    623       chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON);
    624   LoadDisplayPreferences(false);
    625   EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
    626             ash::Shell::GetInstance()->display_configurator()->
    627                 requested_power_state());
    628 }
    629 
    630 TEST_F(DisplayPreferencesTest, DontSaveAndRestoreAllOff) {
    631   ash::Shell* shell = ash::Shell::GetInstance();
    632   StoreDisplayPowerStateForTest(
    633       chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON);
    634   LoadDisplayPreferences(false);
    635   // DisplayPowerState should be ignored at boot.
    636   EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
    637             shell->display_configurator()->requested_power_state());
    638 
    639   StoreDisplayPowerStateForTest(
    640       chromeos::DISPLAY_POWER_ALL_OFF);
    641   EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
    642             shell->display_configurator()->requested_power_state());
    643   EXPECT_EQ("internal_off_external_on",
    644             local_state()->GetString(prefs::kDisplayPowerState));
    645 
    646   // Don't try to load
    647   local_state()->SetString(prefs::kDisplayPowerState, "all_off");
    648   LoadDisplayPreferences(false);
    649   EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
    650             shell->display_configurator()->requested_power_state());
    651 }
    652 
    653 // Tests that display configuration changes caused by MaximizeModeController
    654 // are not saved.
    655 TEST_F(DisplayPreferencesTest, DontSaveMaximizeModeControllerRotations) {
    656   ash::Shell* shell = ash::Shell::GetInstance();
    657   ash::MaximizeModeController* controller = shell->maximize_mode_controller();
    658   gfx::Display::SetInternalDisplayId(
    659       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
    660   ash::DisplayManager* display_manager = shell->display_manager();
    661   LoggedInAsUser();
    662   // Populate the properties.
    663   display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(),
    664                                       gfx::Display::ROTATE_180);
    665   // Reset property to avoid rotation lock
    666   display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(),
    667                                       gfx::Display::ROTATE_0);
    668 
    669   // Open up 270 degrees to trigger maximize mode
    670   ui::AccelerometerUpdate update;
    671   update.Set(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD,
    672              0.0f, 0.0f, kMeanGravity);
    673   update.Set(ui::ACCELEROMETER_SOURCE_SCREEN,
    674              0.0f, -kMeanGravity, 0.0f);
    675   controller->OnAccelerometerUpdated(update);
    676   EXPECT_TRUE(controller->IsMaximizeModeWindowManagerEnabled());
    677 
    678   // Trigger 90 degree rotation
    679   update.Set(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD,
    680              -kMeanGravity, 0.0f, 0.0f);
    681   update.Set(ui::ACCELEROMETER_SOURCE_SCREEN,
    682              -kMeanGravity, 0.0f, 0.0f);
    683   controller->OnAccelerometerUpdated(update);
    684   EXPECT_EQ(gfx::Display::ROTATE_90, display_manager->
    685                 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation());
    686 
    687   const base::DictionaryValue* properties =
    688       local_state()->GetDictionary(prefs::kDisplayProperties);
    689   const base::DictionaryValue* property = NULL;
    690   EXPECT_TRUE(properties->GetDictionary(
    691       base::Int64ToString(gfx::Display::InternalDisplayId()), &property));
    692   int rotation = -1;
    693   EXPECT_TRUE(property->GetInteger("rotation", &rotation));
    694   EXPECT_EQ(gfx::Display::ROTATE_0, rotation);
    695 }
    696 
    697 // Tests that the rotation state is saved without a user being logged in.
    698 TEST_F(DisplayPreferencesTest, StoreRotationStateNoLogin) {
    699   gfx::Display::SetInternalDisplayId(
    700             gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
    701   EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock));
    702 
    703   bool current_rotation_lock =
    704       ash::Shell::GetInstance()->maximize_mode_controller()->rotation_locked();
    705   StoreDisplayRotationPrefs(current_rotation_lock);
    706   EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock));
    707 
    708   const base::DictionaryValue* properties =
    709       local_state()->GetDictionary(prefs::kDisplayRotationLock);
    710   bool rotation_lock;
    711   EXPECT_TRUE(properties->GetBoolean("lock", &rotation_lock));
    712   EXPECT_EQ(current_rotation_lock, rotation_lock);
    713 
    714   int orientation;
    715   gfx::Display::Rotation current_rotation = ash::Shell::GetInstance()->
    716       display_manager()->
    717           GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
    718   EXPECT_TRUE(properties->GetInteger("orientation", &orientation));
    719   EXPECT_EQ(current_rotation, orientation);
    720 }
    721 
    722 // Tests that the rotation state is saved when a guest is logged in.
    723 TEST_F(DisplayPreferencesTest, StoreRotationStateGuest) {
    724   gfx::Display::SetInternalDisplayId(
    725       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
    726   EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock));
    727   LoggedInAsGuest();
    728 
    729   bool current_rotation_lock =
    730       ash::Shell::GetInstance()->maximize_mode_controller()->rotation_locked();
    731   StoreDisplayRotationPrefs(current_rotation_lock);
    732   EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock));
    733 
    734   const base::DictionaryValue* properties =
    735       local_state()->GetDictionary(prefs::kDisplayRotationLock);
    736   bool rotation_lock;
    737   EXPECT_TRUE(properties->GetBoolean("lock", &rotation_lock));
    738   EXPECT_EQ(current_rotation_lock, rotation_lock);
    739 
    740   int orientation;
    741   gfx::Display::Rotation current_rotation = ash::Shell::GetInstance()->
    742       display_manager()->
    743           GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
    744   EXPECT_TRUE(properties->GetInteger("orientation", &orientation));
    745   EXPECT_EQ(current_rotation, orientation);
    746 }
    747 
    748 // Tests that the rotation state is saved when a normal user is logged in.
    749 TEST_F(DisplayPreferencesTest, StoreRotationStateNormalUser) {
    750   gfx::Display::SetInternalDisplayId(
    751       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
    752   EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock));
    753   LoggedInAsGuest();
    754 
    755   bool current_rotation_lock =
    756       ash::Shell::GetInstance()->maximize_mode_controller()->rotation_locked();
    757   StoreDisplayRotationPrefs(current_rotation_lock);
    758   EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock));
    759 
    760   const base::DictionaryValue* properties =
    761       local_state()->GetDictionary(prefs::kDisplayRotationLock);
    762   bool rotation_lock;
    763   EXPECT_TRUE(properties->GetBoolean("lock", &rotation_lock));
    764   EXPECT_EQ(current_rotation_lock, rotation_lock);
    765 
    766   int orientation;
    767   gfx::Display::Rotation current_rotation = ash::Shell::GetInstance()->
    768       display_manager()->
    769           GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
    770   EXPECT_TRUE(properties->GetInteger("orientation", &orientation));
    771   EXPECT_EQ(current_rotation, orientation);
    772 }
    773 
    774 // Tests that rotation state is loaded without a user being logged in, and that
    775 // entering maximize mode applies the state.
    776 TEST_F(DisplayPreferencesTest, LoadRotationNoLogin) {
    777   gfx::Display::SetInternalDisplayId(
    778       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
    779   ASSERT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock));
    780 
    781   ash::Shell* shell = ash::Shell::GetInstance();
    782   ash::MaximizeModeController* maximize_mode_controller =
    783       shell->maximize_mode_controller();
    784   bool initial_rotation_lock = maximize_mode_controller->rotation_locked();
    785   ASSERT_FALSE(initial_rotation_lock);
    786   ash::DisplayManager* display_manager = shell->display_manager();
    787   gfx::Display::Rotation initial_rotation = display_manager->
    788       GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
    789   ASSERT_EQ(gfx::Display::ROTATE_0, initial_rotation);
    790 
    791   StoreDisplayRotationPrefs(initial_rotation_lock);
    792   ASSERT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock));
    793 
    794   StoreDisplayRotationPrefsForTest(true, gfx::Display::ROTATE_90);
    795   LoadDisplayPreferences(false);
    796 
    797   bool display_rotation_lock =
    798       display_manager->registered_internal_display_rotation_lock();
    799   bool display_rotation =
    800       display_manager->registered_internal_display_rotation();
    801   EXPECT_TRUE(display_rotation_lock);
    802   EXPECT_EQ(gfx::Display::ROTATE_90, display_rotation);
    803 
    804   bool rotation_lock = maximize_mode_controller->rotation_locked();
    805   gfx::Display::Rotation before_maximize_mode_rotation = display_manager->
    806       GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
    807 
    808   // Settings should not be applied until maximize mode activates
    809   EXPECT_FALSE(rotation_lock);
    810   EXPECT_EQ(gfx::Display::ROTATE_0, before_maximize_mode_rotation);
    811 
    812   // Open up 270 degrees to trigger maximize mode
    813   ui::AccelerometerUpdate update;
    814   update.Set(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD,
    815              0.0f, 0.0f, kMeanGravity);
    816   update.Set(ui::ACCELEROMETER_SOURCE_SCREEN,
    817              0.0f, -kMeanGravity, 0.0f);
    818   maximize_mode_controller->OnAccelerometerUpdated(update);
    819   EXPECT_TRUE(maximize_mode_controller->IsMaximizeModeWindowManagerEnabled());
    820   bool maximize_mode_rotation_lock =
    821       maximize_mode_controller->rotation_locked();
    822   gfx::Display::Rotation maximize_mode_rotation = display_manager->
    823       GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
    824   EXPECT_TRUE(maximize_mode_rotation_lock);
    825   EXPECT_EQ(gfx::Display::ROTATE_90, maximize_mode_rotation);
    826 }
    827 
    828 // Tests that loaded rotation state is ignored if the device starts in normal
    829 // mode, and that they are not applied upon first entering maximize mode.
    830 TEST_F(DisplayPreferencesTest, LoadRotationIgnoredInNormalMode) {
    831   gfx::Display::SetInternalDisplayId(
    832       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
    833   ASSERT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock));
    834   StoreDisplayRotationPrefs(false /* rotation_lock*/);
    835   ASSERT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock));
    836 
    837   StoreDisplayRotationPrefsForTest(true, gfx::Display::ROTATE_90);
    838   LoadDisplayPreferences(false);
    839 
    840   ash::MaximizeModeController* maximize_mode_controller =
    841       ash::Shell::GetInstance()->maximize_mode_controller();
    842   // Lid open to 90 degrees
    843   ui::AccelerometerUpdate update;
    844   update.Set(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD,
    845              -kMeanGravity, 0.0f, 0.0f);
    846   update.Set(ui::ACCELEROMETER_SOURCE_SCREEN,
    847              -kMeanGravity, 0.0f, 0.0f);
    848   maximize_mode_controller->OnAccelerometerUpdated(update);
    849   EXPECT_FALSE(maximize_mode_controller->IsMaximizeModeWindowManagerEnabled());
    850   EXPECT_FALSE(maximize_mode_controller->rotation_locked());
    851 
    852   // Open up 270 degrees to trigger maximize mode
    853   update.Set(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD,
    854              0.0f, 0.0f, kMeanGravity);
    855   update.Set(ui::ACCELEROMETER_SOURCE_SCREEN,
    856              0.0f, -kMeanGravity, 0.0f);
    857   maximize_mode_controller->OnAccelerometerUpdated(update);
    858   EXPECT_TRUE(maximize_mode_controller->IsMaximizeModeWindowManagerEnabled());
    859   EXPECT_FALSE(maximize_mode_controller->rotation_locked());
    860 }
    861 
    862 // Tests that rotation lock being set causes the rotation state to be saved.
    863 TEST_F(DisplayPreferencesTest, RotationLockTriggersStore) {
    864   gfx::Display::SetInternalDisplayId(
    865     gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
    866   ASSERT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock));
    867 
    868   ash::MaximizeModeController* maximize_mode_controller =
    869       ash::Shell::GetInstance()->maximize_mode_controller();
    870   maximize_mode_controller->SetRotationLocked(true);
    871 
    872   EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock));
    873 
    874   const base::DictionaryValue* properties =
    875       local_state()->GetDictionary(prefs::kDisplayRotationLock);
    876   bool rotation_lock;
    877   EXPECT_TRUE(properties->GetBoolean("lock", &rotation_lock));
    878 }
    879 
    880 }  // namespace chromeos
    881