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
22class PreferenceServiceTest : public UITest {
23 public:
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
63  bool LaunchAppWithProfile() {
64    if (!file_util::PathExists(tmp_pref_file_))
65      return false;
66    UITest::SetUp();
67    return true;
68  }
69
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.
88TEST_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)
146TEST_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