Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / options / options_ui_browsertest.cc
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 "chrome/browser/ui/webui/options/options_ui_browsertest.h"
6
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/signin_manager_factory.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chrome/browser/ui/webui/options/options_ui.h"
16 #include "chrome/browser/ui/webui/uber/uber_ui.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/common/url_constants.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "components/signin/core/browser/signin_manager.h"
21 #include "content/public/browser/notification_service.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/test/browser_test_utils.h"
24 #include "content/public/test/test_utils.h"
25 #include "grit/generated_resources.h"
26 #include "ui/base/l10n/l10n_util.h"
27
28 #if !defined(OS_CHROMEOS)
29 #include <string>
30
31 #include "base/basictypes.h"
32 #include "base/bind.h"
33 #include "base/callback.h"
34 #include "base/files/file_path.h"
35 #include "base/run_loop.h"
36 #include "chrome/browser/browser_process.h"
37 #include "chrome/browser/profiles/profile.h"
38 #include "chrome/browser/profiles/profile_manager.h"
39 #include "chrome/browser/ui/browser_commands.h"
40 #include "content/public/test/test_navigation_observer.h"
41 #include "ui/base/window_open_disposition.h"
42 #include "url/gurl.h"
43 #endif
44
45 using content::MessageLoopRunner;
46
47 namespace options {
48
49 namespace {
50
51 class SignOutWaiter : public SigninManagerBase::Observer {
52  public:
53   SignOutWaiter(SigninManagerBase* signin_manager)
54       : seen_(false), running_(false), scoped_observer_(this) {
55     scoped_observer_.Add(signin_manager);
56   }
57   virtual ~SignOutWaiter() {}
58
59   void Wait() {
60     if (seen_)
61       return;
62
63     running_ = true;
64     message_loop_runner_ = new MessageLoopRunner;
65     message_loop_runner_->Run();
66     EXPECT_TRUE(seen_);
67   }
68
69   virtual void GoogleSignedOut(const std::string& username) OVERRIDE {
70     seen_ = true;
71     if (!running_)
72       return;
73
74     message_loop_runner_->Quit();
75     running_ = false;
76   }
77
78  private:
79   bool seen_;
80   bool running_;
81   ScopedObserver<SigninManagerBase, SignOutWaiter> scoped_observer_;
82   scoped_refptr<MessageLoopRunner> message_loop_runner_;
83 };
84
85 #if !defined(OS_CHROMEOS)
86 void RunClosureWhenProfileInitialized(const base::Closure& closure,
87                                       Profile* profile,
88                                       Profile::CreateStatus status) {
89   if (status == Profile::CREATE_STATUS_INITIALIZED)
90     closure.Run();
91 }
92 #endif
93
94 }  // namespace
95
96 OptionsUIBrowserTest::OptionsUIBrowserTest() {
97 }
98
99 void OptionsUIBrowserTest::NavigateToSettings() {
100   const GURL& url = GURL(chrome::kChromeUISettingsURL);
101   ui_test_utils::NavigateToURLWithDisposition(browser(), url, CURRENT_TAB, 0);
102
103   content::WebContents* web_contents =
104       browser()->tab_strip_model()->GetActiveWebContents();
105   ASSERT_TRUE(web_contents);
106   ASSERT_TRUE(web_contents->GetWebUI());
107   UberUI* uber_ui = static_cast<UberUI*>(
108       web_contents->GetWebUI()->GetController());
109   OptionsUI* options_ui = static_cast<OptionsUI*>(
110       uber_ui->GetSubpage(chrome::kChromeUISettingsFrameURL)->GetController());
111
112   // It is not possible to subscribe to the OnFinishedLoading event before the
113   // call to NavigateToURL(), because the WebUI does not yet exist at that time.
114   // However, it is safe to subscribe afterwards, because the event will always
115   // be posted asynchronously to the message loop.
116   scoped_refptr<MessageLoopRunner> message_loop_runner(new MessageLoopRunner);
117   scoped_ptr<OptionsUI::OnFinishedLoadingCallbackList::Subscription>
118       subscription = options_ui->RegisterOnFinishedLoadingCallback(
119           message_loop_runner->QuitClosure());
120   message_loop_runner->Run();
121 }
122
123 void OptionsUIBrowserTest::NavigateToSettingsFrame() {
124   const GURL& url = GURL(chrome::kChromeUISettingsFrameURL);
125   ui_test_utils::NavigateToURL(browser(), url);
126 }
127
128 void OptionsUIBrowserTest::VerifyNavbar() {
129   bool navbar_exist = false;
130   EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
131       browser()->tab_strip_model()->GetActiveWebContents(),
132       "domAutomationController.send("
133       "    !!document.getElementById('navigation'))",
134       &navbar_exist));
135   EXPECT_EQ(true, navbar_exist);
136 }
137
138 void OptionsUIBrowserTest::VerifyTitle() {
139   base::string16 title =
140       browser()->tab_strip_model()->GetActiveWebContents()->GetTitle();
141   base::string16 expected_title = l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE);
142   EXPECT_NE(title.find(expected_title), base::string16::npos);
143 }
144
145 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, LoadOptionsByURL) {
146   NavigateToSettings();
147   VerifyTitle();
148   VerifyNavbar();
149 }
150
151 // Flaky on win_rel when the profile is deleted crbug.com/103355
152 // Also related to crbug.com/104851
153 #if defined(OS_WIN)
154 #define MAYBE_VerifyManagedSignout DISABLED_VerifyManagedSignout
155 #else
156 #define MAYBE_VerifyManagedSignout VerifyManagedSignout
157 #endif
158
159 #if !defined(OS_CHROMEOS)
160 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, MAYBE_VerifyManagedSignout) {
161   SigninManager* signin =
162       SigninManagerFactory::GetForProfile(browser()->profile());
163   signin->OnExternalSigninCompleted("test@example.com");
164   signin->ProhibitSignout(true);
165
166   NavigateToSettingsFrame();
167
168   // This script simulates a click on the "Disconnect your Google Account"
169   // button and returns true if the hidden flag of the appropriate dialog gets
170   // flipped.
171   bool result = false;
172   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
173       browser()->tab_strip_model()->GetActiveWebContents(),
174       "var dialog = $('manage-profile-overlay-disconnect-managed');"
175       "var original_status = dialog.hidden;"
176       "$('start-stop-sync').click();"
177       "domAutomationController.send(original_status && !dialog.hidden);",
178       &result));
179
180   EXPECT_TRUE(result);
181
182   base::FilePath profile_dir = browser()->profile()->GetPath();
183   ProfileInfoCache& profile_info_cache =
184       g_browser_process->profile_manager()->GetProfileInfoCache();
185
186   EXPECT_TRUE(DirectoryExists(profile_dir));
187   EXPECT_TRUE(profile_info_cache.GetIndexOfProfileWithPath(profile_dir) !=
188               std::string::npos);
189
190   content::WindowedNotificationObserver wait_for_profile_deletion(
191       chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
192       content::NotificationService::AllSources());
193
194   // TODO(kaliamoorthi): Get the macos problem fixed and remove this code.
195   // Deleting the Profile also destroys all browser windows of that Profile.
196   // Wait for the current browser to close before resuming, otherwise
197   // the browser_tests shutdown code will be confused on the Mac.
198   content::WindowedNotificationObserver wait_for_browser_closed(
199       chrome::NOTIFICATION_BROWSER_CLOSED,
200       content::NotificationService::AllSources());
201
202   ASSERT_TRUE(content::ExecuteScript(
203       browser()->tab_strip_model()->GetActiveWebContents(),
204       "$('disconnect-managed-profile-ok').click();"));
205
206   wait_for_profile_deletion.Wait();
207
208   EXPECT_TRUE(profile_info_cache.GetIndexOfProfileWithPath(profile_dir) ==
209               std::string::npos);
210
211   wait_for_browser_closed.Wait();
212 }
213
214 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, VerifyUnmanagedSignout) {
215   SigninManager* signin =
216       SigninManagerFactory::GetForProfile(browser()->profile());
217   const std::string user = "test@example.com";
218   signin->OnExternalSigninCompleted(user);
219
220   NavigateToSettingsFrame();
221
222   // This script simulates a click on the "Disconnect your Google Account"
223   // button and returns true if the hidden flag of the appropriate dialog gets
224   // flipped.
225   bool result = false;
226   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
227       browser()->tab_strip_model()->GetActiveWebContents(),
228       "var dialog = $('sync-setup-stop-syncing');"
229       "var original_status = dialog.hidden;"
230       "$('start-stop-sync').click();"
231       "domAutomationController.send(original_status && !dialog.hidden);",
232       &result));
233
234   EXPECT_TRUE(result);
235
236   SignOutWaiter sign_out_waiter(signin);
237
238   ASSERT_TRUE(content::ExecuteScript(
239       browser()->tab_strip_model()->GetActiveWebContents(),
240       "$('stop-syncing-ok').click();"));
241
242   sign_out_waiter.Wait();
243
244   EXPECT_TRUE(browser()->profile()->GetProfileName() != user);
245   EXPECT_TRUE(signin->GetAuthenticatedUsername().empty());
246 }
247
248 // Regression test for http://crbug.com/301436, excluded on Chrome OS because
249 // profile management in the settings UI exists on desktop platforms only.
250 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, NavigateBackFromOverlayDialog) {
251   NavigateToSettingsFrame();
252
253   // Click a button that opens an overlay dialog.
254   content::WebContents* contents =
255       browser()->tab_strip_model()->GetActiveWebContents();
256   ASSERT_TRUE(content::ExecuteScript(
257       contents, "$('manage-default-search-engines').click();"));
258
259   // Go back to the settings page.
260   content::TestNavigationObserver observer(contents);
261   chrome::GoBack(browser(), CURRENT_TAB);
262   observer.Wait();
263
264   // Verify that the settings page lists one profile.
265   const char javascript[] =
266       "domAutomationController.send("
267       "    document.querySelectorAll('list#profiles-list > div[role=listitem]')"
268       "        .length);";
269   int profiles;
270   ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
271       contents, javascript, &profiles));
272   EXPECT_EQ(1, profiles);
273
274   // Create a second profile.
275   ProfileManager* profile_manager = g_browser_process->profile_manager();
276   const base::FilePath profile_path =
277       profile_manager->GenerateNextProfileDirectoryPath();
278
279   base::RunLoop run_loop;
280   profile_manager->CreateProfileAsync(
281       profile_manager->GenerateNextProfileDirectoryPath(),
282       base::Bind(&RunClosureWhenProfileInitialized,
283                  run_loop.QuitClosure()),
284                  base::string16(),
285                  base::string16(),
286                  std::string());
287   run_loop.Run();
288
289   // Verify that the settings page has updated and lists two profiles.
290   ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
291       contents, javascript, &profiles));
292   EXPECT_EQ(2, profiles);
293 }
294 #endif
295
296 }  // namespace options