Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / ui / webui / options / options_ui_browsertest.cc
blob284c38a15a66f724f92951bfdc9772f17df7acde
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.
5 #include "chrome/browser/ui/webui/options/options_ui_browsertest.h"
7 #include "base/prefs/pref_service.h"
8 #include "base/scoped_observer.h"
9 #include "base/strings/string16.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/signin/account_tracker_service_factory.h"
13 #include "chrome/browser/signin/signin_manager_factory.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/chrome_pages.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/browser/ui/webui/options/options_ui.h"
18 #include "chrome/browser/ui/webui/uber/uber_ui.h"
19 #include "chrome/common/url_constants.h"
20 #include "chrome/grit/generated_resources.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "components/signin/core/browser/account_tracker_service.h"
23 #include "components/signin/core/browser/signin_manager.h"
24 #include "content/public/browser/notification_service.h"
25 #include "content/public/browser/render_frame_host.h"
26 #include "content/public/browser/web_contents.h"
27 #include "content/public/test/browser_test_utils.h"
28 #include "content/public/test/test_utils.h"
29 #include "ui/base/l10n/l10n_util.h"
31 #if !defined(OS_CHROMEOS)
32 #include <string>
34 #include "base/basictypes.h"
35 #include "base/bind.h"
36 #include "base/callback.h"
37 #include "base/files/file_path.h"
38 #include "base/run_loop.h"
39 #include "chrome/browser/browser_process.h"
40 #include "chrome/browser/profiles/profile.h"
41 #include "chrome/browser/profiles/profile_manager.h"
42 #include "chrome/browser/ui/browser_commands.h"
43 #include "content/public/test/test_navigation_observer.h"
44 #include "ui/base/window_open_disposition.h"
45 #include "url/gurl.h"
46 #endif
48 using content::MessageLoopRunner;
50 namespace options {
52 namespace {
54 class SignOutWaiter : public SigninManagerBase::Observer {
55 public:
56 explicit SignOutWaiter(SigninManagerBase* signin_manager)
57 : seen_(false), running_(false), scoped_observer_(this) {
58 scoped_observer_.Add(signin_manager);
60 ~SignOutWaiter() override {}
62 void Wait() {
63 if (seen_)
64 return;
66 running_ = true;
67 message_loop_runner_ = new MessageLoopRunner;
68 message_loop_runner_->Run();
69 EXPECT_TRUE(seen_);
72 void GoogleSignedOut(const std::string& account_id,
73 const std::string& username) override {
74 seen_ = true;
75 if (!running_)
76 return;
78 message_loop_runner_->Quit();
79 running_ = false;
82 private:
83 bool seen_;
84 bool running_;
85 ScopedObserver<SigninManagerBase, SignOutWaiter> scoped_observer_;
86 scoped_refptr<MessageLoopRunner> message_loop_runner_;
89 #if !defined(OS_CHROMEOS)
90 void RunClosureWhenProfileInitialized(const base::Closure& closure,
91 Profile* profile,
92 Profile::CreateStatus status) {
93 if (status == Profile::CREATE_STATUS_INITIALIZED)
94 closure.Run();
96 #endif
98 bool FrameHasSettingsSourceHost(content::RenderFrameHost* frame) {
99 return frame->GetLastCommittedURL().DomainIs(
100 chrome::kChromeUISettingsFrameHost);
103 } // namespace
105 OptionsUIBrowserTest::OptionsUIBrowserTest() {
108 void OptionsUIBrowserTest::NavigateToSettings() {
109 NavigateToSettingsSubpage("");
112 void OptionsUIBrowserTest::NavigateToSettingsSubpage(
113 const std::string& sub_page) {
114 const GURL& url = chrome::GetSettingsUrl(sub_page);
115 ui_test_utils::NavigateToURLWithDisposition(browser(), url, CURRENT_TAB, 0);
117 content::WebContents* web_contents =
118 browser()->tab_strip_model()->GetActiveWebContents();
119 ASSERT_TRUE(web_contents);
120 ASSERT_TRUE(web_contents->GetWebUI());
122 content::WebUIController* controller =
123 web_contents->GetWebUI()->GetController();
124 #if !defined(OS_CHROMEOS)
125 controller = static_cast<UberUI*>(controller)->
126 GetSubpage(chrome::kChromeUISettingsFrameURL)->GetController();
127 #endif
128 OptionsUI* options_ui = static_cast<OptionsUI*>(controller);
130 // It is not possible to subscribe to the OnFinishedLoading event before the
131 // call to NavigateToURL(), because the WebUI does not yet exist at that time.
132 // However, it is safe to subscribe afterwards, because the event will always
133 // be posted asynchronously to the message loop.
134 scoped_refptr<MessageLoopRunner> message_loop_runner(new MessageLoopRunner);
135 scoped_ptr<OptionsUI::OnFinishedLoadingCallbackList::Subscription>
136 subscription = options_ui->RegisterOnFinishedLoadingCallback(
137 message_loop_runner->QuitClosure());
138 message_loop_runner->Run();
140 // The OnFinishedLoading event, which indicates that all WebUI initialization
141 // methods have been called on the JS side, is temporally unrelated to whether
142 // or not the WebContents considers itself to have finished loading. We want
143 // to wait for this too, however, because, e.g. this is a sufficient condition
144 // to get the focus properly placed on a form element.
145 content::WaitForLoadStop(web_contents);
148 void OptionsUIBrowserTest::NavigateToSettingsFrame() {
149 const GURL& url = GURL(chrome::kChromeUISettingsFrameURL);
150 ui_test_utils::NavigateToURL(browser(), url);
153 void OptionsUIBrowserTest::VerifyNavbar() {
154 bool navbar_exist = false;
155 #if defined(OS_CHROMEOS)
156 bool should_navbar_exist = false;
157 #else
158 bool should_navbar_exist = true;
159 #endif
160 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
161 browser()->tab_strip_model()->GetActiveWebContents(),
162 "domAutomationController.send("
163 " !!document.getElementById('navigation'))",
164 &navbar_exist));
165 EXPECT_EQ(should_navbar_exist, navbar_exist);
168 void OptionsUIBrowserTest::VerifyTitle() {
169 base::string16 title =
170 browser()->tab_strip_model()->GetActiveWebContents()->GetTitle();
171 base::string16 expected_title = l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE);
172 EXPECT_NE(title.find(expected_title), base::string16::npos);
175 content::RenderFrameHost* OptionsUIBrowserTest::GetSettingsFrame() {
176 // NB: The utility function content::FrameHasSourceUrl can't be used because
177 // the settings frame navigates itself to chrome://settings-frame/settings
178 // to indicate that it's showing the top-level settings. Therefore, just
179 // match the host.
180 return content::FrameMatchingPredicate(
181 browser()->tab_strip_model()->GetActiveWebContents(),
182 base::Bind(&FrameHasSettingsSourceHost));
185 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, LoadOptionsByURL) {
186 NavigateToSettings();
187 VerifyTitle();
188 VerifyNavbar();
191 // Flaky on Linux, Mac and Win: http://crbug.com/469113
192 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
193 #define MAYBE_VerifyManagedSignout DISABLED_VerifyManagedSignout
194 #else
195 #define MAYBE_VerifyManagedSignout VerifyManagedSignout
196 #endif
198 #if !defined(OS_CHROMEOS)
199 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, MAYBE_VerifyManagedSignout) {
200 SigninManager* signin =
201 SigninManagerFactory::GetForProfile(browser()->profile());
202 signin->OnExternalSigninCompleted("test@example.com");
203 signin->ProhibitSignout(true);
205 NavigateToSettingsFrame();
207 // This script simulates a click on the "Disconnect your Google Account"
208 // button and returns true if the hidden flag of the appropriate dialog gets
209 // flipped.
210 bool result = false;
211 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
212 browser()->tab_strip_model()->GetActiveWebContents(),
213 "var dialog = $('manage-profile-overlay-disconnect-managed');"
214 "var original_status = dialog.hidden;"
215 "var original = ManageProfileOverlay.showDisconnectManagedProfileDialog;"
216 "var teststub = function(event) {"
217 " original(event);"
218 " domAutomationController.send(original_status && !dialog.hidden);"
219 "};"
220 "ManageProfileOverlay.showDisconnectManagedProfileDialog = teststub;"
221 "$('start-stop-sync').click();",
222 &result));
224 EXPECT_TRUE(result);
226 base::FilePath profile_dir = browser()->profile()->GetPath();
227 ProfileInfoCache& profile_info_cache =
228 g_browser_process->profile_manager()->GetProfileInfoCache();
230 EXPECT_TRUE(DirectoryExists(profile_dir));
231 EXPECT_TRUE(profile_info_cache.GetIndexOfProfileWithPath(profile_dir) !=
232 std::string::npos);
234 // TODO(kaliamoorthi): Get the macos problem fixed and remove this code.
235 // Deleting the Profile also destroys all browser windows of that Profile.
236 // Wait for the current browser to close before resuming, otherwise
237 // the browser_tests shutdown code will be confused on the Mac.
238 content::WindowedNotificationObserver wait_for_browser_closed(
239 chrome::NOTIFICATION_BROWSER_CLOSED,
240 content::NotificationService::AllSources());
242 ASSERT_TRUE(content::ExecuteScript(
243 browser()->tab_strip_model()->GetActiveWebContents(),
244 "$('disconnect-managed-profile-ok').click();"));
246 EXPECT_TRUE(profile_info_cache.GetIndexOfProfileWithPath(profile_dir) ==
247 std::string::npos);
249 wait_for_browser_closed.Wait();
252 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, VerifyUnmanagedSignout) {
253 const std::string user = "test@example.com";
254 std::string account_id =
255 AccountTrackerServiceFactory::GetForProfile(browser()->profile())
256 ->SeedAccountInfo("12345", user);
257 SigninManager* signin =
258 SigninManagerFactory::GetForProfile(browser()->profile());
259 signin->OnExternalSigninCompleted(account_id);
261 NavigateToSettingsFrame();
263 // This script simulates a click on the "Disconnect your Google Account"
264 // button and returns true if the hidden flag of the appropriate dialog gets
265 // flipped.
266 bool result = false;
267 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
268 browser()->tab_strip_model()->GetActiveWebContents(),
269 "var dialog = $('sync-setup-stop-syncing');"
270 "var original_status = dialog.hidden;"
271 "$('start-stop-sync').click();"
272 "domAutomationController.send(original_status && !dialog.hidden);",
273 &result));
275 EXPECT_TRUE(result);
277 SignOutWaiter sign_out_waiter(signin);
279 ASSERT_TRUE(content::ExecuteScript(
280 browser()->tab_strip_model()->GetActiveWebContents(),
281 "$('stop-syncing-ok').click();"));
283 sign_out_waiter.Wait();
285 EXPECT_TRUE(browser()->profile()->GetProfileUserName() != user);
286 EXPECT_FALSE(signin->IsAuthenticated());
289 // Regression test for http://crbug.com/301436, excluded on Chrome OS because
290 // profile management in the settings UI exists on desktop platforms only.
291 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, NavigateBackFromOverlayDialog) {
292 NavigateToSettingsFrame();
294 // Click a button that opens an overlay dialog.
295 content::WebContents* contents =
296 browser()->tab_strip_model()->GetActiveWebContents();
297 ASSERT_TRUE(content::ExecuteScript(
298 contents, "$('manage-default-search-engines').click();"));
300 // Go back to the settings page.
301 content::TestNavigationObserver observer(contents);
302 chrome::GoBack(browser(), CURRENT_TAB);
303 observer.Wait();
305 // Verify that the settings page lists one profile.
306 const char javascript[] =
307 "domAutomationController.send("
308 " document.querySelectorAll('list#profiles-list > div[role=listitem]')"
309 " .length);";
310 int profiles;
311 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
312 contents, javascript, &profiles));
313 EXPECT_EQ(1, profiles);
315 // Create a second profile.
316 ProfileManager* profile_manager = g_browser_process->profile_manager();
317 const base::FilePath profile_path =
318 profile_manager->GenerateNextProfileDirectoryPath();
320 base::RunLoop run_loop;
321 profile_manager->CreateProfileAsync(
322 profile_manager->GenerateNextProfileDirectoryPath(),
323 base::Bind(&RunClosureWhenProfileInitialized,
324 run_loop.QuitClosure()),
325 base::string16(),
326 base::string16(),
327 std::string());
328 run_loop.Run();
330 // Verify that the settings page has updated and lists two profiles.
331 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
332 contents, javascript, &profiles));
333 EXPECT_EQ(2, profiles);
335 #endif
337 } // namespace options