1 // Copyright (c) 2011 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/test/test_file_util.h"
10 #include "base/values.h"
11 #include "base/memory/scoped_temp_dir.h"
12 #include "build/build_config.h"
13 #include "chrome/common/chrome_constants.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/pref_names.h"
16 #include "chrome/test/automation/browser_proxy.h"
17 #include "chrome/test/automation/window_proxy.h"
18 #include "chrome/test/ui/ui_test.h"
19 #include "content/common/json_value_serializer.h"
20 #include "ui/gfx/rect.h"
21
22 class PreferenceServiceTest : public UITest {
23 public:
SetUp()24 void SetUp() {
25 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
26 FilePath tmp_profile = temp_dir_.path().AppendASCII("tmp_profile");
27
28 ASSERT_TRUE(file_util::CreateDirectory(tmp_profile));
29
30 FilePath reference_pref_file;
31 if (new_profile_) {
32 reference_pref_file = test_data_directory_
33 .AppendASCII("profiles")
34 .AppendASCII("window_placement")
35 .AppendASCII("Default")
36 .Append(chrome::kPreferencesFilename);
37 tmp_pref_file_ = tmp_profile.AppendASCII("Default");
38 ASSERT_TRUE(file_util::CreateDirectory(tmp_pref_file_));
39 tmp_pref_file_ = tmp_pref_file_.Append(chrome::kPreferencesFilename);
40 } else {
41 reference_pref_file = test_data_directory_
42 .AppendASCII("profiles")
43 .AppendASCII("window_placement")
44 .Append(chrome::kLocalStateFilename);
45 tmp_pref_file_ = tmp_profile.Append(chrome::kLocalStateFilename);
46 }
47
48 ASSERT_TRUE(file_util::PathExists(reference_pref_file));
49 // Copy only the Preferences file if |new_profile_|, or Local State if not,
50 // and the rest will be automatically created.
51 ASSERT_TRUE(file_util::CopyFile(reference_pref_file, tmp_pref_file_));
52
53 #if defined(OS_WIN)
54 // Make the copy writable. On POSIX we assume the umask allows files
55 // we create to be writable.
56 ASSERT_TRUE(::SetFileAttributesW(tmp_pref_file_.value().c_str(),
57 FILE_ATTRIBUTE_NORMAL));
58 #endif
59
60 launch_arguments_.AppendSwitchPath(switches::kUserDataDir, tmp_profile);
61 }
62
LaunchAppWithProfile()63 bool LaunchAppWithProfile() {
64 if (!file_util::PathExists(tmp_pref_file_))
65 return false;
66 UITest::SetUp();
67 return true;
68 }
69
TearDown()70 void TearDown() {
71 UITest::TearDown();
72 }
73
74 public:
75 bool new_profile_;
76 FilePath tmp_pref_file_;
77
78 private:
79 ScopedTempDir temp_dir_;
80 };
81
82 #if !defined(OS_LINUX)
83 // This test verifies that the window position from the prefs file is restored
84 // when the app restores. This doesn't really make sense on Linux, where
85 // the window manager might fight with you over positioning. However, we
86 // might be able to make this work on buildbots.
87 // TODO(port): revisit this.
TEST_F(PreferenceServiceTest,PreservedWindowPlacementIsLoaded)88 TEST_F(PreferenceServiceTest, PreservedWindowPlacementIsLoaded) {
89 // The window should open with the new reference profile, with window
90 // placement values stored in the user data directory.
91 new_profile_ = true;
92 ASSERT_TRUE(LaunchAppWithProfile());
93
94 ASSERT_TRUE(file_util::PathExists(tmp_pref_file_));
95
96 JSONFileValueSerializer deserializer(tmp_pref_file_);
97 scoped_ptr<Value> root(deserializer.Deserialize(NULL, NULL));
98
99 ASSERT_TRUE(root.get());
100 ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
101
102 DictionaryValue* root_dict = static_cast<DictionaryValue*>(root.get());
103
104 // Retrieve the screen rect for the launched window
105 scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
106 ASSERT_TRUE(browser.get());
107 scoped_refptr<WindowProxy> window(browser->GetWindow());
108 ASSERT_TRUE(window.get());
109
110 gfx::Rect bounds;
111 ASSERT_TRUE(window->GetBounds(&bounds));
112
113 // Retrieve the expected rect values from "Preferences"
114 int bottom = 0;
115 std::string kBrowserWindowPlacement(prefs::kBrowserWindowPlacement);
116 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".bottom",
117 &bottom));
118 EXPECT_EQ(bottom, bounds.y() + bounds.height());
119
120 int top = 0;
121 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".top",
122 &top));
123 EXPECT_EQ(top, bounds.y());
124
125 int left = 0;
126 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".left",
127 &left));
128 EXPECT_EQ(left, bounds.x());
129
130 int right = 0;
131 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".right",
132 &right));
133 EXPECT_EQ(right, bounds.x() + bounds.width());
134
135 // Find if launched window is maximized.
136 bool is_window_maximized = false;
137 ASSERT_TRUE(window->IsMaximized(&is_window_maximized));
138 bool is_maximized = false;
139 EXPECT_TRUE(root_dict->GetBoolean(kBrowserWindowPlacement + ".maximized",
140 &is_maximized));
141 EXPECT_EQ(is_maximized, is_window_maximized);
142 }
143 #endif
144
145 #if !defined(OS_LINUX)
TEST_F(PreferenceServiceTest,PreservedWindowPlacementIsMigrated)146 TEST_F(PreferenceServiceTest, PreservedWindowPlacementIsMigrated) {
147 // The window should open with the old reference profile, with window
148 // placement values stored in Local State.
149 new_profile_ = false;
150 ASSERT_TRUE(LaunchAppWithProfile());
151
152 ASSERT_TRUE(file_util::PathExists(tmp_pref_file_));
153
154 JSONFileValueSerializer deserializer(tmp_pref_file_);
155 scoped_ptr<Value> root(deserializer.Deserialize(NULL, NULL));
156
157 ASSERT_TRUE(root.get());
158 ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
159
160 // Retrieve the screen rect for the launched window
161 scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
162 ASSERT_TRUE(browser.get());
163 scoped_refptr<WindowProxy> window(browser->GetWindow());
164 ASSERT_TRUE(window.get());
165
166 gfx::Rect bounds;
167 ASSERT_TRUE(window->GetBounds(&bounds));
168
169 // Values from old reference profile in Local State should have been
170 // correctly migrated to the user's Preferences -- if so, the window
171 // should be set to values taken from the user's Local State.
172 DictionaryValue* root_dict = static_cast<DictionaryValue*>(root.get());
173
174 // Retrieve the expected rect values from User Preferences, where they
175 // should have been migrated from Local State.
176 int bottom = 0;
177 std::string kBrowserWindowPlacement(prefs::kBrowserWindowPlacement);
178 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".bottom",
179 &bottom));
180 EXPECT_EQ(bottom, bounds.y() + bounds.height());
181
182 int top = 0;
183 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".top",
184 &top));
185 EXPECT_EQ(top, bounds.y());
186
187 int left = 0;
188 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".left",
189 &left));
190 EXPECT_EQ(left, bounds.x());
191
192 int right = 0;
193 EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".right",
194 &right));
195 EXPECT_EQ(right, bounds.x() + bounds.width());
196
197 // Find if launched window is maximized.
198 bool is_window_maximized = false;
199 ASSERT_TRUE(window->IsMaximized(&is_window_maximized));
200 bool is_maximized = false;
201 EXPECT_TRUE(root_dict->GetBoolean(kBrowserWindowPlacement + ".maximized",
202 &is_maximized));
203 EXPECT_EQ(is_maximized, is_window_maximized);
204 }
205 #endif
206
207