1// Copyright 2014 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/ui/settings_window_manager.h"
6
7#include "base/command_line.h"
8#include "base/files/file_util.h"
9#include "base/files/scoped_temp_dir.h"
10#include "chrome/browser/browser_process.h"
11#include "chrome/browser/chrome_notification_types.h"
12#include "chrome/browser/profiles/profile_manager.h"
13#include "chrome/browser/ui/browser.h"
14#include "chrome/browser/ui/browser_finder.h"
15#include "chrome/browser/ui/browser_iterator.h"
16#include "chrome/browser/ui/browser_window.h"
17#include "chrome/browser/ui/chrome_pages.h"
18#include "chrome/browser/ui/settings_window_manager_observer.h"
19#include "chrome/common/chrome_switches.h"
20#include "chrome/common/url_constants.h"
21#include "chrome/test/base/in_process_browser_test.h"
22#include "content/public/browser/notification_service.h"
23#include "content/public/test/test_utils.h"
24#include "url/gurl.h"
25
26namespace {
27
28class SettingsWindowTestObserver
29    : public chrome::SettingsWindowManagerObserver {
30 public:
31  SettingsWindowTestObserver() : browser_(NULL), new_settings_count_(0) {}
32  virtual ~SettingsWindowTestObserver() {}
33
34  virtual void OnNewSettingsWindow(Browser* settings_browser) OVERRIDE {
35    browser_ = settings_browser;
36    ++new_settings_count_;
37  }
38
39  Browser* browser() { return browser_; }
40  size_t new_settings_count() const { return new_settings_count_; }
41
42 private:
43  Browser* browser_;
44  size_t new_settings_count_;
45
46  DISALLOW_COPY_AND_ASSIGN(SettingsWindowTestObserver);
47};
48
49}  // namespace
50
51class SettingsWindowManagerTest : public InProcessBrowserTest {
52 public:
53  SettingsWindowManagerTest()
54      : settings_manager_(chrome::SettingsWindowManager::GetInstance()),
55        test_profile_(NULL) {
56    settings_manager_->AddObserver(&observer_);
57  }
58  virtual ~SettingsWindowManagerTest() {
59    settings_manager_->RemoveObserver(&observer_);
60  }
61
62  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
63    command_line->AppendSwitch(::switches::kEnableSettingsWindow);
64  }
65
66  Profile* CreateTestProfile() {
67    CHECK(!test_profile_);
68
69    ProfileManager* profile_manager = g_browser_process->profile_manager();
70    base::RunLoop run_loop;
71    profile_manager->CreateProfileAsync(
72        profile_manager->GenerateNextProfileDirectoryPath(),
73        base::Bind(&SettingsWindowManagerTest::ProfileInitialized,
74                   base::Unretained(this),
75                   run_loop.QuitClosure()),
76        base::string16(),
77        base::string16(),
78        std::string());
79    run_loop.Run();
80
81    return test_profile_;
82  }
83
84  void ProfileInitialized(const base::Closure& closure,
85                          Profile* profile,
86                          Profile::CreateStatus status) {
87    if (status == Profile::CREATE_STATUS_INITIALIZED) {
88      test_profile_ = profile;
89      closure.Run();
90    }
91  }
92
93  void ShowSettingsForProfile(Profile* profile) {
94    settings_manager_->ShowChromePageForProfile(
95        profile, GURL(chrome::kChromeUISettingsURL));
96  }
97
98  void CloseBrowserSynchronously(Browser* browser) {
99    content::WindowedNotificationObserver observer(
100        chrome::NOTIFICATION_BROWSER_CLOSED,
101        content::NotificationService::AllSources());
102    browser->window()->Close();
103    observer.Wait();
104  }
105
106  void CloseNonDefaultBrowsers() {
107    std::list<Browser*> browsers_to_close;
108    for (chrome::BrowserIterator it; !it.done(); it.Next()) {
109      if (*it != browser())
110        browsers_to_close.push_back(*it);
111    }
112    for (std::list<Browser*>::iterator iter = browsers_to_close.begin();
113         iter != browsers_to_close.end(); ++iter) {
114      CloseBrowserSynchronously(*iter);
115    }
116  }
117
118 protected:
119  chrome::SettingsWindowManager* settings_manager_;
120  SettingsWindowTestObserver observer_;
121  base::ScopedTempDir temp_profile_dir_;
122  Profile* test_profile_;  // Owned by g_browser_process->profile_manager()
123
124  DISALLOW_COPY_AND_ASSIGN(SettingsWindowManagerTest);
125};
126
127
128IN_PROC_BROWSER_TEST_F(SettingsWindowManagerTest, OpenSettingsWindow) {
129  // Open a settings window.
130  ShowSettingsForProfile(browser()->profile());
131  Browser* settings_browser =
132      settings_manager_->FindBrowserForProfile(browser()->profile());
133  ASSERT_TRUE(settings_browser);
134  // Ensure the observer fired correctly.
135  EXPECT_EQ(1u, observer_.new_settings_count());
136  EXPECT_EQ(settings_browser, observer_.browser());
137
138  // Open the settings again: no new window.
139  ShowSettingsForProfile(browser()->profile());
140  EXPECT_EQ(settings_browser,
141            settings_manager_->FindBrowserForProfile(browser()->profile()));
142  EXPECT_EQ(1u, observer_.new_settings_count());
143
144  // Close the settings window.
145  CloseBrowserSynchronously(settings_browser);
146  EXPECT_FALSE(settings_manager_->FindBrowserForProfile(browser()->profile()));
147
148  // Open a new settings window.
149  ShowSettingsForProfile(browser()->profile());
150  Browser* settings_browser2 =
151      settings_manager_->FindBrowserForProfile(browser()->profile());
152  ASSERT_TRUE(settings_browser2);
153  EXPECT_EQ(2u, observer_.new_settings_count());
154
155  CloseBrowserSynchronously(settings_browser2);
156}
157
158#if !defined(OS_CHROMEOS)
159IN_PROC_BROWSER_TEST_F(SettingsWindowManagerTest, SettingsWindowMultiProfile) {
160  Profile* test_profile = CreateTestProfile();
161  ASSERT_TRUE(test_profile);
162
163  // Open a settings window.
164  ShowSettingsForProfile(browser()->profile());
165  Browser* settings_browser =
166      settings_manager_->FindBrowserForProfile(browser()->profile());
167  ASSERT_TRUE(settings_browser);
168  // Ensure the observer fired correctly.
169  EXPECT_EQ(1u, observer_.new_settings_count());
170  EXPECT_EQ(settings_browser, observer_.browser());
171
172  // Open a settings window for a new profile.
173  ShowSettingsForProfile(test_profile);
174  Browser* settings_browser2 =
175      settings_manager_->FindBrowserForProfile(test_profile);
176  ASSERT_TRUE(settings_browser2);
177  // Ensure the observer fired correctly.
178  EXPECT_EQ(2u, observer_.new_settings_count());
179  EXPECT_EQ(settings_browser2, observer_.browser());
180
181  CloseBrowserSynchronously(settings_browser);
182  CloseBrowserSynchronously(settings_browser2);
183}
184#endif
185
186IN_PROC_BROWSER_TEST_F(SettingsWindowManagerTest, OpenChromePages) {
187  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
188
189  // History should open in the existing browser window.
190  chrome::ShowHistory(browser());
191  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
192
193  // Settings should open a new browser window.
194  chrome::ShowSettings(browser());
195  EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
196
197  // About should reuse the existing Settings window.
198  chrome::ShowAboutChrome(browser());
199  EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
200
201  // Extensions should open in an existing browser window.
202  CloseNonDefaultBrowsers();
203  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
204  std::string extension_to_highlight;  // none
205  chrome::ShowExtensions(browser(), extension_to_highlight);
206  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
207
208  // Downloads should open in an existing browser window.
209  chrome::ShowDownloads(browser());
210  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
211
212  // About should open a new browser window.
213  chrome::ShowAboutChrome(browser());
214  EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
215}
216