Upstream version 10.39.225.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/chrome_pages.h"
15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
16 #include "chrome/browser/ui/webui/options/options_ui.h"
17 #include "chrome/browser/ui/webui/uber/uber_ui.h"
18 #include "chrome/common/pref_names.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/signin_manager.h"
23 #include "content/public/browser/notification_service.h"
24 #include "content/public/browser/render_frame_host.h"
25 #include "content/public/browser/web_contents.h"
26 #include "content/public/test/browser_test_utils.h"
27 #include "content/public/test/test_utils.h"
28 #include "ui/base/l10n/l10n_util.h"
29
30 #if !defined(OS_CHROMEOS)
31 #include <string>
32
33 #include "base/basictypes.h"
34 #include "base/bind.h"
35 #include "base/callback.h"
36 #include "base/files/file_path.h"
37 #include "base/run_loop.h"
38 #include "chrome/browser/browser_process.h"
39 #include "chrome/browser/profiles/profile.h"
40 #include "chrome/browser/profiles/profile_manager.h"
41 #include "chrome/browser/ui/browser_commands.h"
42 #include "content/public/test/test_navigation_observer.h"
43 #include "ui/base/window_open_disposition.h"
44 #include "url/gurl.h"
45 #endif
46
47 using content::MessageLoopRunner;
48
49 namespace options {
50
51 namespace {
52
53 class SignOutWaiter : public SigninManagerBase::Observer {
54  public:
55   explicit SignOutWaiter(SigninManagerBase* signin_manager)
56       : seen_(false), running_(false), scoped_observer_(this) {
57     scoped_observer_.Add(signin_manager);
58   }
59   virtual ~SignOutWaiter() {}
60
61   void Wait() {
62     if (seen_)
63       return;
64
65     running_ = true;
66     message_loop_runner_ = new MessageLoopRunner;
67     message_loop_runner_->Run();
68     EXPECT_TRUE(seen_);
69   }
70
71   virtual void GoogleSignedOut(const std::string& account_id,
72                                const std::string& username) OVERRIDE {
73     seen_ = true;
74     if (!running_)
75       return;
76
77     message_loop_runner_->Quit();
78     running_ = false;
79   }
80
81  private:
82   bool seen_;
83   bool running_;
84   ScopedObserver<SigninManagerBase, SignOutWaiter> scoped_observer_;
85   scoped_refptr<MessageLoopRunner> message_loop_runner_;
86 };
87
88 #if !defined(OS_CHROMEOS)
89 void RunClosureWhenProfileInitialized(const base::Closure& closure,
90                                       Profile* profile,
91                                       Profile::CreateStatus status) {
92   if (status == Profile::CREATE_STATUS_INITIALIZED)
93     closure.Run();
94 }
95 #endif
96
97 bool FrameHasSettingsSourceHost(content::RenderFrameHost* frame) {
98   return frame->GetLastCommittedURL().DomainIs(
99       chrome::kChromeUISettingsFrameHost);
100 }
101
102 }  // namespace
103
104 OptionsUIBrowserTest::OptionsUIBrowserTest() {
105 }
106
107 void OptionsUIBrowserTest::NavigateToSettings() {
108   NavigateToSettingsSubpage("");
109 }
110
111 void OptionsUIBrowserTest::NavigateToSettingsSubpage(
112     const std::string& sub_page) {
113   const GURL& url = chrome::GetSettingsUrl(sub_page);
114   ui_test_utils::NavigateToURLWithDisposition(browser(), url, CURRENT_TAB, 0);
115
116   content::WebContents* web_contents =
117       browser()->tab_strip_model()->GetActiveWebContents();
118   ASSERT_TRUE(web_contents);
119   ASSERT_TRUE(web_contents->GetWebUI());
120
121   content::WebUIController* controller =
122       web_contents->GetWebUI()->GetController();
123 #if !defined(OS_CHROMEOS)
124   controller = static_cast<UberUI*>(controller)->
125       GetSubpage(chrome::kChromeUISettingsFrameURL)->GetController();
126 #endif
127   OptionsUI* options_ui = static_cast<OptionsUI*>(controller);
128
129   // It is not possible to subscribe to the OnFinishedLoading event before the
130   // call to NavigateToURL(), because the WebUI does not yet exist at that time.
131   // However, it is safe to subscribe afterwards, because the event will always
132   // be posted asynchronously to the message loop.
133   scoped_refptr<MessageLoopRunner> message_loop_runner(new MessageLoopRunner);
134   scoped_ptr<OptionsUI::OnFinishedLoadingCallbackList::Subscription>
135       subscription = options_ui->RegisterOnFinishedLoadingCallback(
136           message_loop_runner->QuitClosure());
137   message_loop_runner->Run();
138
139   // The OnFinishedLoading event, which indicates that all WebUI initialization
140   // methods have been called on the JS side, is temporally unrelated to whether
141   // or not the WebContents considers itself to have finished loading. We want
142   // to wait for this too, however, because, e.g. this is a sufficient condition
143   // to get the focus properly placed on a form element.
144   content::WaitForLoadStop(web_contents);
145 }
146
147 void OptionsUIBrowserTest::NavigateToSettingsFrame() {
148   const GURL& url = GURL(chrome::kChromeUISettingsFrameURL);
149   ui_test_utils::NavigateToURL(browser(), url);
150 }
151
152 void OptionsUIBrowserTest::VerifyNavbar() {
153   bool navbar_exist = false;
154 #if defined(OS_CHROMEOS)
155   bool should_navbar_exist = false;
156 #else
157   bool should_navbar_exist = true;
158 #endif
159   EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
160       browser()->tab_strip_model()->GetActiveWebContents(),
161       "domAutomationController.send("
162       "    !!document.getElementById('navigation'))",
163       &navbar_exist));
164   EXPECT_EQ(should_navbar_exist, navbar_exist);
165 }
166
167 void OptionsUIBrowserTest::VerifyTitle() {
168   base::string16 title =
169       browser()->tab_strip_model()->GetActiveWebContents()->GetTitle();
170   base::string16 expected_title = l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE);
171   EXPECT_NE(title.find(expected_title), base::string16::npos);
172 }
173
174 content::RenderFrameHost* OptionsUIBrowserTest::GetSettingsFrame() {
175   // NB: The utility function content::FrameHasSourceUrl can't be used because
176   // the settings frame navigates itself to chrome://settings-frame/settings
177   // to indicate that it's showing the top-level settings. Therefore, just
178   // match the host.
179   return content::FrameMatchingPredicate(
180       browser()->tab_strip_model()->GetActiveWebContents(),
181       base::Bind(&FrameHasSettingsSourceHost));
182 }
183
184 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, LoadOptionsByURL) {
185   NavigateToSettings();
186   VerifyTitle();
187   VerifyNavbar();
188 }
189
190 // Flaky on win_rel when the profile is deleted crbug.com/103355
191 // Also related to crbug.com/104851
192 #if defined(OS_WIN)
193 #define MAYBE_VerifyManagedSignout DISABLED_VerifyManagedSignout
194 #else
195 #define MAYBE_VerifyManagedSignout VerifyManagedSignout
196 #endif
197
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);
204
205   NavigateToSettingsFrame();
206
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));
223
224   EXPECT_TRUE(result);
225
226   base::FilePath profile_dir = browser()->profile()->GetPath();
227   ProfileInfoCache& profile_info_cache =
228       g_browser_process->profile_manager()->GetProfileInfoCache();
229
230   EXPECT_TRUE(DirectoryExists(profile_dir));
231   EXPECT_TRUE(profile_info_cache.GetIndexOfProfileWithPath(profile_dir) !=
232               std::string::npos);
233
234   content::WindowedNotificationObserver wait_for_profile_deletion(
235       chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
236       content::NotificationService::AllSources());
237
238   // TODO(kaliamoorthi): Get the macos problem fixed and remove this code.
239   // Deleting the Profile also destroys all browser windows of that Profile.
240   // Wait for the current browser to close before resuming, otherwise
241   // the browser_tests shutdown code will be confused on the Mac.
242   content::WindowedNotificationObserver wait_for_browser_closed(
243       chrome::NOTIFICATION_BROWSER_CLOSED,
244       content::NotificationService::AllSources());
245
246   ASSERT_TRUE(content::ExecuteScript(
247       browser()->tab_strip_model()->GetActiveWebContents(),
248       "$('disconnect-managed-profile-ok').click();"));
249
250   wait_for_profile_deletion.Wait();
251
252   EXPECT_TRUE(profile_info_cache.GetIndexOfProfileWithPath(profile_dir) ==
253               std::string::npos);
254
255   wait_for_browser_closed.Wait();
256 }
257
258 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, VerifyUnmanagedSignout) {
259   SigninManager* signin =
260       SigninManagerFactory::GetForProfile(browser()->profile());
261   const std::string user = "test@example.com";
262   signin->OnExternalSigninCompleted(user);
263
264   NavigateToSettingsFrame();
265
266   // This script simulates a click on the "Disconnect your Google Account"
267   // button and returns true if the hidden flag of the appropriate dialog gets
268   // flipped.
269   bool result = false;
270   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
271       browser()->tab_strip_model()->GetActiveWebContents(),
272       "var dialog = $('sync-setup-stop-syncing');"
273       "var original_status = dialog.hidden;"
274       "$('start-stop-sync').click();"
275       "domAutomationController.send(original_status && !dialog.hidden);",
276       &result));
277
278   EXPECT_TRUE(result);
279
280   SignOutWaiter sign_out_waiter(signin);
281
282   ASSERT_TRUE(content::ExecuteScript(
283       browser()->tab_strip_model()->GetActiveWebContents(),
284       "$('stop-syncing-ok').click();"));
285
286   sign_out_waiter.Wait();
287
288   EXPECT_TRUE(browser()->profile()->GetProfileName() != user);
289   EXPECT_FALSE(signin->IsAuthenticated());
290 }
291
292 // Regression test for http://crbug.com/301436, excluded on Chrome OS because
293 // profile management in the settings UI exists on desktop platforms only.
294 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, NavigateBackFromOverlayDialog) {
295   NavigateToSettingsFrame();
296
297   // Click a button that opens an overlay dialog.
298   content::WebContents* contents =
299       browser()->tab_strip_model()->GetActiveWebContents();
300   ASSERT_TRUE(content::ExecuteScript(
301       contents, "$('manage-default-search-engines').click();"));
302
303   // Go back to the settings page.
304   content::TestNavigationObserver observer(contents);
305   chrome::GoBack(browser(), CURRENT_TAB);
306   observer.Wait();
307
308   // Verify that the settings page lists one profile.
309   const char javascript[] =
310       "domAutomationController.send("
311       "    document.querySelectorAll('list#profiles-list > div[role=listitem]')"
312       "        .length);";
313   int profiles;
314   ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
315       contents, javascript, &profiles));
316   EXPECT_EQ(1, profiles);
317
318   // Create a second profile.
319   ProfileManager* profile_manager = g_browser_process->profile_manager();
320   const base::FilePath profile_path =
321       profile_manager->GenerateNextProfileDirectoryPath();
322
323   base::RunLoop run_loop;
324   profile_manager->CreateProfileAsync(
325       profile_manager->GenerateNextProfileDirectoryPath(),
326       base::Bind(&RunClosureWhenProfileInitialized,
327                  run_loop.QuitClosure()),
328                  base::string16(),
329                  base::string16(),
330                  std::string());
331   run_loop.Run();
332
333   // Verify that the settings page has updated and lists two profiles.
334   ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
335       contents, javascript, &profiles));
336   EXPECT_EQ(2, profiles);
337 }
338 #endif
339
340 }  // namespace options