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 <string> 6 7 #include "base/command_line.h" 8 #include "base/file_util.h" 9 #include "base/files/scoped_temp_dir.h" 10 #include "base/json/json_file_value_serializer.h" 11 #include "base/path_service.h" 12 #include "base/test/test_file_util.h" 13 #include "base/values.h" 14 #include "build/build_config.h" 15 #include "chrome/browser/ui/browser.h" 16 #include "chrome/browser/ui/browser_window.h" 17 #include "chrome/browser/ui/browser_window_state.h" 18 #include "chrome/common/chrome_constants.h" 19 #include "chrome/common/chrome_paths.h" 20 #include "chrome/common/pref_names.h" 21 #include "chrome/test/base/in_process_browser_test.h" 22 #include "chrome/test/base/test_switches.h" 23 #include "chrome/test/base/testing_profile.h" 24 #include "chrome/test/base/ui_test_utils.h" 25 #include "ui/gfx/rect.h" 26 27 // On GTK, resizing happens asynchronously and we currently don't have a way to 28 // get called back (it's probably possible, but we don't have that code). Since 29 // the GTK code is going away, not spending more time on this. 30 #if !defined(TOOLKIT_GTK) 31 32 typedef InProcessBrowserTest PreservedWindowPlacement; 33 34 IN_PROC_BROWSER_TEST_F(PreservedWindowPlacement, PRE_Test) { 35 browser()->window()->SetBounds(gfx::Rect(20, 30, 400, 500)); 36 } 37 38 // Fails on Chrome OS as the browser thinks it is restarting after a crash, see 39 // http://crbug.com/168044 40 #if defined(OS_CHROMEOS) 41 #define MAYBE_Test DISABLED_Test 42 #else 43 #define MAYBE_Test Test 44 #endif 45 IN_PROC_BROWSER_TEST_F(PreservedWindowPlacement, MAYBE_Test) { 46 #if defined(OS_WIN) && defined(USE_ASH) 47 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 48 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 49 return; 50 #endif 51 52 gfx::Rect bounds = browser()->window()->GetBounds(); 53 gfx::Rect expected_bounds(gfx::Rect(20, 30, 400, 500)); 54 ASSERT_EQ(expected_bounds.ToString(), bounds.ToString()); 55 } 56 57 #endif // defined(TOOLKIT_GTK) 58 59 class PreferenceServiceTest : public InProcessBrowserTest { 60 public: 61 explicit PreferenceServiceTest(bool new_profile) : new_profile_(new_profile) { 62 } 63 64 virtual bool SetUpUserDataDirectory() OVERRIDE { 65 base::FilePath user_data_directory; 66 PathService::Get(chrome::DIR_USER_DATA, &user_data_directory); 67 68 base::FilePath reference_pref_file; 69 if (new_profile_) { 70 reference_pref_file = ui_test_utils::GetTestFilePath( 71 base::FilePath().AppendASCII("profiles"). 72 AppendASCII("window_placement"). 73 AppendASCII("Default"), 74 base::FilePath().Append(chrome::kPreferencesFilename)); 75 tmp_pref_file_ = 76 user_data_directory.AppendASCII(TestingProfile::kTestUserProfileDir); 77 CHECK(file_util::CreateDirectory(tmp_pref_file_)); 78 tmp_pref_file_ = tmp_pref_file_.Append(chrome::kPreferencesFilename); 79 } else { 80 reference_pref_file = ui_test_utils::GetTestFilePath( 81 base::FilePath().AppendASCII("profiles"). 82 AppendASCII("window_placement"), 83 base::FilePath().Append(chrome::kLocalStateFilename)); 84 tmp_pref_file_ = user_data_directory.Append(chrome::kLocalStateFilename); 85 } 86 87 CHECK(base::PathExists(reference_pref_file)); 88 // Copy only the Preferences file if |new_profile_|, or Local State if not, 89 // and the rest will be automatically created. 90 CHECK(base::CopyFile(reference_pref_file, tmp_pref_file_)); 91 92 #if defined(OS_WIN) 93 // Make the copy writable. On POSIX we assume the umask allows files 94 // we create to be writable. 95 CHECK(::SetFileAttributesW(tmp_pref_file_.value().c_str(), 96 FILE_ATTRIBUTE_NORMAL)); 97 #endif 98 return true; 99 } 100 101 protected: 102 base::FilePath tmp_pref_file_; 103 104 private: 105 bool new_profile_; 106 }; 107 108 #if defined(OS_WIN) || defined(OS_MACOSX) 109 // This test verifies that the window position from the prefs file is restored 110 // when the app restores. This doesn't really make sense on Linux, where 111 // the window manager might fight with you over positioning. However, we 112 // might be able to make this work on buildbots. 113 // TODO(port): revisit this. 114 115 class PreservedWindowPlacementIsLoaded : public PreferenceServiceTest { 116 public: 117 PreservedWindowPlacementIsLoaded() : PreferenceServiceTest(true) { 118 } 119 }; 120 121 IN_PROC_BROWSER_TEST_F(PreservedWindowPlacementIsLoaded, Test) { 122 #if defined(OS_WIN) && defined(USE_ASH) 123 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 124 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 125 return; 126 #endif 127 128 // The window should open with the new reference profile, with window 129 // placement values stored in the user data directory. 130 JSONFileValueSerializer deserializer(tmp_pref_file_); 131 scoped_ptr<Value> root(deserializer.Deserialize(NULL, NULL)); 132 133 ASSERT_TRUE(root.get()); 134 ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY)); 135 136 DictionaryValue* root_dict = static_cast<DictionaryValue*>(root.get()); 137 138 // Retrieve the screen rect for the launched window 139 gfx::Rect bounds = browser()->window()->GetRestoredBounds(); 140 141 // Retrieve the expected rect values from "Preferences" 142 int bottom = 0; 143 std::string kBrowserWindowPlacement(prefs::kBrowserWindowPlacement); 144 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".bottom", 145 &bottom)); 146 EXPECT_EQ(bottom, bounds.y() + bounds.height()); 147 148 int top = 0; 149 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".top", 150 &top)); 151 EXPECT_EQ(top, bounds.y()); 152 153 int left = 0; 154 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".left", 155 &left)); 156 EXPECT_EQ(left, bounds.x()); 157 158 int right = 0; 159 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".right", 160 &right)); 161 EXPECT_EQ(right, bounds.x() + bounds.width()); 162 163 // Find if launched window is maximized. 164 bool is_window_maximized = browser()->window()->IsMaximized(); 165 bool is_maximized = false; 166 EXPECT_TRUE(root_dict->GetBoolean(kBrowserWindowPlacement + ".maximized", 167 &is_maximized)); 168 EXPECT_EQ(is_maximized, is_window_maximized); 169 } 170 #endif 171 172 #if defined(OS_WIN) || defined(OS_MACOSX) 173 174 class PreservedWindowPlacementIsMigrated : public PreferenceServiceTest { 175 public: 176 PreservedWindowPlacementIsMigrated() : PreferenceServiceTest(false) { 177 } 178 }; 179 180 IN_PROC_BROWSER_TEST_F(PreservedWindowPlacementIsMigrated, Test) { 181 #if defined(OS_WIN) && defined(USE_ASH) 182 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 183 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 184 return; 185 #endif 186 187 // The window should open with the old reference profile, with window 188 // placement values stored in Local State. 189 190 JSONFileValueSerializer deserializer(tmp_pref_file_); 191 scoped_ptr<Value> root(deserializer.Deserialize(NULL, NULL)); 192 193 ASSERT_TRUE(root.get()); 194 ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY)); 195 196 // Retrieve the screen rect for the launched window 197 gfx::Rect bounds = browser()->window()->GetRestoredBounds(); 198 199 // Values from old reference profile in Local State should have been 200 // correctly migrated to the user's Preferences -- if so, the window 201 // should be set to values taken from the user's Local State. 202 DictionaryValue* root_dict = static_cast<DictionaryValue*>(root.get()); 203 204 // Retrieve the expected rect values from User Preferences, where they 205 // should have been migrated from Local State. 206 int bottom = 0; 207 std::string kBrowserWindowPlacement(prefs::kBrowserWindowPlacement); 208 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".bottom", 209 &bottom)); 210 EXPECT_EQ(bottom, bounds.y() + bounds.height()); 211 212 int top = 0; 213 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".top", 214 &top)); 215 EXPECT_EQ(top, bounds.y()); 216 217 int left = 0; 218 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".left", 219 &left)); 220 EXPECT_EQ(left, bounds.x()); 221 222 int right = 0; 223 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".right", 224 &right)); 225 EXPECT_EQ(right, bounds.x() + bounds.width()); 226 227 // Find if launched window is maximized. 228 bool is_window_maximized = browser()->window()->IsMaximized(); 229 bool is_maximized = false; 230 EXPECT_TRUE(root_dict->GetBoolean(kBrowserWindowPlacement + ".maximized", 231 &is_maximized)); 232 EXPECT_EQ(is_maximized, is_window_maximized); 233 } 234 #endif 235