Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / test / remoting / remote_desktop_browsertest.cc
blobc8049cd40502c77451d3a818f8ff1fe988530a21
1 // Copyright 2013 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/test/remoting/remote_desktop_browsertest.h"
7 #include "base/command_line.h"
8 #include "chrome/browser/extensions/extension_service.h"
9 #include "chrome/browser/extensions/unpacked_installer.h"
10 #include "chrome/browser/ui/extensions/application_launch.h"
11 #include "chrome/common/chrome_switches.h"
12 #include "chrome/common/extensions/extension_file_util.h"
13 #include "chrome/test/remoting/key_code_conv.h"
14 #include "chrome/test/remoting/page_load_notification_observer.h"
15 #include "chrome/test/remoting/waiter.h"
16 #include "content/public/browser/native_web_keyboard_event.h"
17 #include "content/public/browser/render_view_host.h"
18 #include "content/public/test/test_utils.h"
19 #include "extensions/common/constants.h"
20 #include "extensions/common/extension.h"
21 #include "extensions/common/extension_set.h"
22 #include "extensions/common/switches.h"
23 #include "ui/base/window_open_disposition.h"
25 namespace remoting {
27 RemoteDesktopBrowserTest::RemoteDesktopBrowserTest()
28 : extension_(NULL) {
31 RemoteDesktopBrowserTest::~RemoteDesktopBrowserTest() {}
33 void RemoteDesktopBrowserTest::SetUp() {
34 ParseCommandLine();
35 PlatformAppBrowserTest::SetUp();
38 void RemoteDesktopBrowserTest::SetUpOnMainThread() {
39 PlatformAppBrowserTest::SetUpOnMainThread();
41 // Pushing the initial WebContents instance onto the stack before
42 // RunTestOnMainThread() and after |InProcessBrowserTest::browser_|
43 // is initialized in InProcessBrowserTest::RunTestOnMainThreadLoop()
44 web_contents_stack_.push_back(
45 browser()->tab_strip_model()->GetActiveWebContents());
48 // Change behavior of the default host resolver to avoid DNS lookup errors,
49 // so we can make network calls.
50 void RemoteDesktopBrowserTest::SetUpInProcessBrowserTestFixture() {
51 // The resolver object lifetime is managed by sync_test_setup, not here.
52 EnableDNSLookupForThisTest(
53 new net::RuleBasedHostResolverProc(host_resolver()));
56 void RemoteDesktopBrowserTest::TearDownInProcessBrowserTestFixture() {
57 DisableDNSLookupForThisTest();
60 void RemoteDesktopBrowserTest::VerifyInternetAccess() {
61 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
62 browser(), GURL("http://www.google.com"), 1);
64 EXPECT_EQ(GetCurrentURL().host(), "www.google.com");
67 bool RemoteDesktopBrowserTest::HtmlElementVisible(const std::string& name) {
68 _ASSERT_TRUE(HtmlElementExists(name));
70 ExecuteScript(
71 "function isElementVisible(name) {"
72 " var element = document.getElementById(name);"
73 " /* The existence of the element has already been ASSERTed. */"
74 " do {"
75 " if (element.hidden) {"
76 " return false;"
77 " }"
78 " element = element.parentNode;"
79 " } while (element != null);"
80 " return true;"
81 "};");
83 return ExecuteScriptAndExtractBool(
84 "isElementVisible(\"" + name + "\")");
87 void RemoteDesktopBrowserTest::InstallChromotingAppCrx() {
88 ASSERT_TRUE(!is_unpacked());
90 base::FilePath install_dir(WebAppCrxPath());
91 scoped_refptr<const Extension> extension(InstallExtensionWithUIAutoConfirm(
92 install_dir, 1, browser()));
94 EXPECT_FALSE(extension.get() == NULL);
96 extension_ = extension.get();
99 void RemoteDesktopBrowserTest::InstallChromotingAppUnpacked() {
100 ASSERT_TRUE(is_unpacked());
102 scoped_refptr<extensions::UnpackedInstaller> installer =
103 extensions::UnpackedInstaller::Create(extension_service());
104 installer->set_prompt_for_plugins(false);
106 content::WindowedNotificationObserver observer(
107 chrome::NOTIFICATION_EXTENSION_LOADED,
108 content::NotificationService::AllSources());
110 installer->Load(webapp_unpacked_);
112 observer.Wait();
115 void RemoteDesktopBrowserTest::UninstallChromotingApp() {
116 UninstallExtension(ChromotingID());
117 extension_ = NULL;
120 void RemoteDesktopBrowserTest::VerifyChromotingLoaded(bool expected) {
121 const extensions::ExtensionSet* extensions =
122 extension_service()->extensions();
123 scoped_refptr<const extensions::Extension> extension;
124 bool installed = false;
126 for (extensions::ExtensionSet::const_iterator iter = extensions->begin();
127 iter != extensions->end(); ++iter) {
128 extension = *iter;
129 // Is there a better way to recognize the chromoting extension
130 // than name comparison?
131 if (extension->name() == extension_name_) {
132 installed = true;
133 break;
137 if (installed) {
138 if (extension_)
139 EXPECT_EQ(extension, extension_);
140 else
141 extension_ = extension.get();
143 // Either a V1 (TYPE_LEGACY_PACKAGED_APP) or a V2 (TYPE_PLATFORM_APP ) app.
144 extensions::Manifest::Type type = extension->GetType();
145 EXPECT_TRUE(type == extensions::Manifest::TYPE_PLATFORM_APP ||
146 type == extensions::Manifest::TYPE_LEGACY_PACKAGED_APP);
148 EXPECT_TRUE(extension->ShouldDisplayInAppLauncher());
151 ASSERT_EQ(installed, expected);
154 void RemoteDesktopBrowserTest::LaunchChromotingApp() {
155 ASSERT_TRUE(extension_);
157 GURL chromoting_main = Chromoting_Main_URL();
158 // We cannot simply wait for any page load because the first page
159 // loaded could be the generated background page. We need to wait
160 // till the chromoting main page is loaded.
161 PageLoadNotificationObserver observer(chromoting_main);
163 OpenApplication(AppLaunchParams(
164 browser()->profile(),
165 extension_,
166 is_platform_app() ? extensions::LAUNCH_CONTAINER_NONE :
167 extensions::LAUNCH_CONTAINER_TAB,
168 is_platform_app() ? NEW_WINDOW : CURRENT_TAB));
170 observer.Wait();
173 // The active WebContents instance should be the source of the LOAD_STOP
174 // notification.
175 content::NavigationController* controller =
176 content::Source<content::NavigationController>(observer.source()).ptr();
178 content::WebContents* web_contents = controller->GetWebContents();
179 if (web_contents != active_web_contents())
180 web_contents_stack_.push_back(web_contents);
182 if (is_platform_app()) {
183 EXPECT_EQ(GetFirstShellWindowWebContents(), active_web_contents());
184 } else {
185 // For apps v1 only, the DOMOperationObserver is not ready at the LOAD_STOP
186 // event. A half second wait is necessary for the subsequent javascript
187 // injection to work.
188 // TODO(weitaosu): Find out whether there is a more appropriate notification
189 // to wait for so we can get rid of this wait.
190 ASSERT_TRUE(TimeoutWaiter(base::TimeDelta::FromMilliseconds(500)).Wait());
193 EXPECT_EQ(Chromoting_Main_URL(), GetCurrentURL());
196 void RemoteDesktopBrowserTest::Authorize() {
197 // The chromoting extension should be installed.
198 ASSERT_TRUE(extension_);
200 // The chromoting main page should be loaded in the current tab
201 // and isAuthenticated() should be false (auth dialog visible).
202 ASSERT_EQ(Chromoting_Main_URL(), GetCurrentURL());
203 ASSERT_FALSE(IsAuthenticated());
205 // The second observer monitors the loading of the Google login page.
206 // Unfortunately we cannot specify a source in this observer because
207 // we can't get a handle of the new window until the first observer
208 // has finished waiting. But we will assert that the source of the
209 // load stop event is indeed the newly created browser window.
210 content::WindowedNotificationObserver observer(
211 content::NOTIFICATION_LOAD_STOP,
212 content::NotificationService::AllSources());
214 ClickOnControl("auth-button");
216 observer.Wait();
218 content::NavigationController* controller =
219 content::Source<content::NavigationController>(observer.source()).ptr();
221 web_contents_stack_.push_back(controller->GetWebContents());
223 // Verify the active tab is at the "Google Accounts" login page.
224 EXPECT_EQ("accounts.google.com", GetCurrentURL().host());
225 EXPECT_TRUE(HtmlElementExists("Email"));
226 EXPECT_TRUE(HtmlElementExists("Passwd"));
229 void RemoteDesktopBrowserTest::Authenticate() {
230 // The chromoting extension should be installed.
231 ASSERT_TRUE(extension_);
233 // The active tab should have the "Google Accounts" login page loaded.
234 ASSERT_EQ("accounts.google.com", GetCurrentURL().host());
235 ASSERT_TRUE(HtmlElementExists("Email"));
236 ASSERT_TRUE(HtmlElementExists("Passwd"));
238 // Now log in using the username and password passed in from the command line.
239 ExecuteScriptAndWaitForAnyPageLoad(
240 "document.getElementById(\"Email\").value = \"" + username_ + "\";" +
241 "document.getElementById(\"Passwd\").value = \"" + password_ +"\";" +
242 "document.forms[\"gaia_loginform\"].submit();");
244 // TODO(weitaosu): Is there a better way to verify we are on the
245 // "Request for Permission" page?
246 // V2 app won't ask for approval here because the chromoting test account
247 // has already been granted permissions.
248 if (!is_platform_app()) {
249 EXPECT_EQ(GetCurrentURL().host(), "accounts.google.com");
250 EXPECT_TRUE(HtmlElementExists("submit_approve_access"));
254 void RemoteDesktopBrowserTest::Approve() {
255 // The chromoting extension should be installed.
256 ASSERT_TRUE(extension_);
258 if (is_platform_app()) {
259 // Popping the login window off the stack to return to the chromoting
260 // window.
261 web_contents_stack_.pop_back();
263 // There is nothing for the V2 app to approve because the chromoting test
264 // account has already been granted permissions.
265 // TODO(weitaosu): Revoke the permission at the beginning of the test so
266 // that we can test first-time experience here.
267 ConditionalTimeoutWaiter waiter(
268 base::TimeDelta::FromSeconds(3),
269 base::TimeDelta::FromSeconds(1),
270 base::Bind(
271 &RemoteDesktopBrowserTest::IsAuthenticatedInWindow,
272 active_web_contents()));
274 ASSERT_TRUE(waiter.Wait());
275 } else {
276 ASSERT_EQ("accounts.google.com", GetCurrentURL().host());
278 // Is there a better way to verify we are on the "Request for Permission"
279 // page?
280 ASSERT_TRUE(HtmlElementExists("submit_approve_access"));
282 const GURL chromoting_main = Chromoting_Main_URL();
284 // active_web_contents() is still the login window but the observer
285 // should be set up to observe the chromoting window because that is
286 // where we'll receive the message from the login window and reload the
287 // chromoting app.
288 content::WindowedNotificationObserver observer(
289 content::NOTIFICATION_LOAD_STOP,
290 base::Bind(
291 &RemoteDesktopBrowserTest::IsAuthenticatedInWindow,
292 browser()->tab_strip_model()->GetActiveWebContents()));
294 ExecuteScript(
295 "lso.approveButtonAction();"
296 "document.forms[\"connect-approve\"].submit();");
298 observer.Wait();
300 // Popping the login window off the stack to return to the chromoting
301 // window.
302 web_contents_stack_.pop_back();
305 ASSERT_TRUE(GetCurrentURL() == Chromoting_Main_URL());
307 EXPECT_TRUE(IsAuthenticated());
310 void RemoteDesktopBrowserTest::ExpandMe2Me() {
311 // The chromoting extension should be installed.
312 ASSERT_TRUE(extension_);
314 // The active tab should have the chromoting app loaded.
315 ASSERT_EQ(Chromoting_Main_URL(), GetCurrentURL());
316 EXPECT_TRUE(IsAuthenticated());
318 // The Me2Me host list should be hidden.
319 ASSERT_FALSE(HtmlElementVisible("me2me-content"));
320 // The Me2Me "Get Start" button should be visible.
321 ASSERT_TRUE(HtmlElementVisible("get-started-me2me"));
323 // Starting Me2Me.
324 ExecuteScript("remoting.showMe2MeUiAndSave();");
326 EXPECT_TRUE(HtmlElementVisible("me2me-content"));
327 EXPECT_FALSE(HtmlElementVisible("me2me-first-run"));
329 // Wait until localHost is initialized. This can take a while.
330 ConditionalTimeoutWaiter waiter(
331 base::TimeDelta::FromSeconds(3),
332 base::TimeDelta::FromSeconds(1),
333 base::Bind(&RemoteDesktopBrowserTest::IsLocalHostReady, this));
334 EXPECT_TRUE(waiter.Wait());
336 EXPECT_TRUE(ExecuteScriptAndExtractBool(
337 "remoting.hostList.localHost_.hostName && "
338 "remoting.hostList.localHost_.hostId && "
339 "remoting.hostList.localHost_.status && "
340 "remoting.hostList.localHost_.status == 'ONLINE'"));
343 void RemoteDesktopBrowserTest::DisconnectMe2Me() {
344 // The chromoting extension should be installed.
345 ASSERT_TRUE(extension_);
347 // The active tab should have the chromoting app loaded.
348 ASSERT_EQ(Chromoting_Main_URL(), GetCurrentURL());
349 ASSERT_TRUE(RemoteDesktopBrowserTest::IsSessionConnected());
351 ClickOnControl("toolbar-stub");
353 EXPECT_TRUE(HtmlElementVisible("session-toolbar"));
355 ClickOnControl("toolbar-disconnect");
357 EXPECT_TRUE(HtmlElementVisible("client-dialog"));
358 EXPECT_TRUE(HtmlElementVisible("client-reconnect-button"));
359 EXPECT_TRUE(HtmlElementVisible("client-finished-me2me-button"));
361 ClickOnControl("client-finished-me2me-button");
363 EXPECT_FALSE(HtmlElementVisible("client-dialog"));
366 void RemoteDesktopBrowserTest::SimulateKeyPressWithCode(
367 ui::KeyboardCode keyCode,
368 const char* code) {
369 SimulateKeyPressWithCode(keyCode, code, false, false, false, false);
372 void RemoteDesktopBrowserTest::SimulateKeyPressWithCode(
373 ui::KeyboardCode keyCode,
374 const char* code,
375 bool control,
376 bool shift,
377 bool alt,
378 bool command) {
379 content::SimulateKeyPressWithCode(
380 active_web_contents(),
381 keyCode,
382 code,
383 control,
384 shift,
385 alt,
386 command);
389 void RemoteDesktopBrowserTest::SimulateCharInput(char c) {
390 const char* code;
391 ui::KeyboardCode keyboard_code;
392 bool shift;
393 GetKeyValuesFromChar(c, &code, &keyboard_code, &shift);
394 ASSERT_TRUE(code != NULL);
395 SimulateKeyPressWithCode(keyboard_code, code, false, shift, false, false);
398 void RemoteDesktopBrowserTest::SimulateStringInput(const std::string& input) {
399 for (size_t i = 0; i < input.length(); ++i)
400 SimulateCharInput(input[i]);
403 void RemoteDesktopBrowserTest::SimulateMouseLeftClickAt(int x, int y) {
404 SimulateMouseClickAt(0, blink::WebMouseEvent::ButtonLeft, x, y);
407 void RemoteDesktopBrowserTest::SimulateMouseClickAt(
408 int modifiers, blink::WebMouseEvent::Button button, int x, int y) {
409 // TODO(weitaosu): The coordinate translation doesn't work correctly for
410 // apps v2.
411 ExecuteScript(
412 "var clientPluginElement = "
413 "document.getElementById('session-client-plugin');"
414 "var clientPluginRect = clientPluginElement.getBoundingClientRect();");
416 int top = ExecuteScriptAndExtractInt("clientPluginRect.top");
417 int left = ExecuteScriptAndExtractInt("clientPluginRect.left");
418 int width = ExecuteScriptAndExtractInt("clientPluginRect.width");
419 int height = ExecuteScriptAndExtractInt("clientPluginRect.height");
421 ASSERT_GT(x, 0);
422 ASSERT_LT(x, width);
423 ASSERT_GT(y, 0);
424 ASSERT_LT(y, height);
426 content::SimulateMouseClickAt(
427 browser()->tab_strip_model()->GetActiveWebContents(),
428 modifiers,
429 button,
430 gfx::Point(left + x, top + y));
433 void RemoteDesktopBrowserTest::Install() {
434 if (!NoInstall()) {
435 VerifyChromotingLoaded(false);
436 if (is_unpacked())
437 InstallChromotingAppUnpacked();
438 else
439 InstallChromotingAppCrx();
442 VerifyChromotingLoaded(true);
445 void RemoteDesktopBrowserTest::Cleanup() {
446 // TODO(weitaosu): Remove this hack by blocking on the appropriate
447 // notification.
448 // The browser may still be loading images embedded in the webapp. If we
449 // uinstall it now those load will fail.
450 ASSERT_TRUE(TimeoutWaiter(base::TimeDelta::FromSeconds(2)).Wait());
452 if (!NoCleanup()) {
453 UninstallChromotingApp();
454 VerifyChromotingLoaded(false);
458 void RemoteDesktopBrowserTest::Auth() {
459 Authorize();
460 Authenticate();
461 Approve();
464 void RemoteDesktopBrowserTest::ConnectToLocalHost(bool remember_pin) {
465 // Verify that the local host is online.
466 ASSERT_TRUE(ExecuteScriptAndExtractBool(
467 "remoting.hostList.localHost_.hostName && "
468 "remoting.hostList.localHost_.hostId && "
469 "remoting.hostList.localHost_.status && "
470 "remoting.hostList.localHost_.status == 'ONLINE'"));
472 // Connect.
473 ClickOnControl("this-host-connect");
475 // Enter the pin # passed in from the command line.
476 EnterPin(me2me_pin(), remember_pin);
478 WaitForConnection();
481 void RemoteDesktopBrowserTest::ConnectToRemoteHost(
482 const std::string& host_name, bool remember_pin) {
483 std::string host_id = ExecuteScriptAndExtractString(
484 "remoting.hostList.getHostIdForName('" + host_name + "')");
486 EXPECT_FALSE(host_id.empty());
487 std::string element_id = "host_" + host_id;
489 // Verify the host is online.
490 std::string host_div_class = ExecuteScriptAndExtractString(
491 "document.getElementById('" + element_id + "').parentNode.className");
492 EXPECT_NE(std::string::npos, host_div_class.find("host-online"));
494 ClickOnControl(element_id);
496 // Enter the pin # passed in from the command line.
497 EnterPin(me2me_pin(), remember_pin);
499 WaitForConnection();
502 void RemoteDesktopBrowserTest::EnableDNSLookupForThisTest(
503 net::RuleBasedHostResolverProc* host_resolver) {
504 // mock_host_resolver_override_ takes ownership of the resolver.
505 scoped_refptr<net::RuleBasedHostResolverProc> resolver =
506 new net::RuleBasedHostResolverProc(host_resolver);
507 resolver->AllowDirectLookup("*.google.com");
508 // On Linux, we use Chromium's NSS implementation which uses the following
509 // hosts for certificate verification. Without these overrides, running the
510 // integration tests on Linux causes errors as we make external DNS lookups.
511 resolver->AllowDirectLookup("*.thawte.com");
512 resolver->AllowDirectLookup("*.geotrust.com");
513 resolver->AllowDirectLookup("*.gstatic.com");
514 resolver->AllowDirectLookup("*.googleapis.com");
515 mock_host_resolver_override_.reset(
516 new net::ScopedDefaultHostResolverProc(resolver.get()));
519 void RemoteDesktopBrowserTest::DisableDNSLookupForThisTest() {
520 mock_host_resolver_override_.reset();
523 void RemoteDesktopBrowserTest::ParseCommandLine() {
524 CommandLine* command_line = CommandLine::ForCurrentProcess();
526 // The test framework overrides any command line user-data-dir
527 // argument with a /tmp/.org.chromium.Chromium.XXXXXX directory.
528 // That happens in the ChromeTestLauncherDelegate, and affects
529 // all unit tests (no opt out available). It intentionally erases
530 // any --user-data-dir switch if present and appends a new one.
531 // Re-override the default data dir if override-user-data-dir
532 // is specified.
533 if (command_line->HasSwitch(kOverrideUserDataDir)) {
534 const base::FilePath& override_user_data_dir =
535 command_line->GetSwitchValuePath(kOverrideUserDataDir);
537 ASSERT_FALSE(override_user_data_dir.empty());
539 command_line->AppendSwitchPath(switches::kUserDataDir,
540 override_user_data_dir);
543 username_ = command_line->GetSwitchValueASCII(kUsername);
544 password_ = command_line->GetSwitchValueASCII(kkPassword);
545 me2me_pin_ = command_line->GetSwitchValueASCII(kMe2MePin);
546 remote_host_name_ = command_line->GetSwitchValueASCII(kRemoteHostName);
547 extension_name_ = command_line->GetSwitchValueASCII(kExtensionName);
549 no_cleanup_ = command_line->HasSwitch(kNoCleanup);
550 no_install_ = command_line->HasSwitch(kNoInstall);
552 if (!no_install_) {
553 webapp_crx_ = command_line->GetSwitchValuePath(kWebAppCrx);
554 webapp_unpacked_ = command_line->GetSwitchValuePath(kWebAppUnpacked);
555 // One and only one of these two arguments should be provided.
556 ASSERT_NE(webapp_crx_.empty(), webapp_unpacked_.empty());
559 // Run with "enable-web-based-signin" flag to enforce web-based sign-in,
560 // rather than inline signin. This ensures we use the same authentication
561 // page, regardless of whether we are testing the v1 or v2 web-app.
562 command_line->AppendSwitch(switches::kEnableWebBasedSignin);
564 // Enable experimental extensions; this is to allow adding the LG extensions
565 command_line->AppendSwitch(
566 extensions::switches::kEnableExperimentalExtensionApis);
569 void RemoteDesktopBrowserTest::ExecuteScript(const std::string& script) {
570 ASSERT_TRUE(content::ExecuteScript(active_web_contents(), script));
573 void RemoteDesktopBrowserTest::ExecuteScriptAndWaitForAnyPageLoad(
574 const std::string& script) {
575 content::WindowedNotificationObserver observer(
576 content::NOTIFICATION_LOAD_STOP,
577 content::Source<content::NavigationController>(
578 &active_web_contents()->
579 GetController()));
581 ExecuteScript(script);
583 observer.Wait();
586 // static
587 bool RemoteDesktopBrowserTest::ExecuteScriptAndExtractBool(
588 content::WebContents* web_contents, const std::string& script) {
589 bool result;
590 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
591 web_contents,
592 "window.domAutomationController.send(" + script + ");",
593 &result));
595 return result;
598 // static
599 int RemoteDesktopBrowserTest::ExecuteScriptAndExtractInt(
600 content::WebContents* web_contents, const std::string& script) {
601 int result;
602 _ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
603 web_contents,
604 "window.domAutomationController.send(" + script + ");",
605 &result));
607 return result;
610 // static
611 std::string RemoteDesktopBrowserTest::ExecuteScriptAndExtractString(
612 content::WebContents* web_contents, const std::string& script) {
613 std::string result;
614 _ASSERT_TRUE(content::ExecuteScriptAndExtractString(
615 web_contents,
616 "window.domAutomationController.send(" + script + ");",
617 &result));
619 return result;
622 void RemoteDesktopBrowserTest::ClickOnControl(const std::string& name) {
623 ASSERT_TRUE(HtmlElementVisible(name));
625 ExecuteScript("document.getElementById(\"" + name + "\").click();");
628 void RemoteDesktopBrowserTest::EnterPin(const std::string& pin,
629 bool remember_pin) {
630 // Wait for the pin-form to be displayed. This can take a while.
631 // We also need to dismiss the host-needs-update dialog if it comes up.
632 // TODO(weitaosu) 1: Instead of polling, can we register a callback to be
633 // called when the pin-form is ready?
634 // TODO(weitaosu) 2: Instead of blindly dismiss the host-needs-update dialog,
635 // we should verify that it only pops up at the right circumstance. That
636 // probably belongs in a separate test case though.
637 ConditionalTimeoutWaiter waiter(
638 base::TimeDelta::FromSeconds(5),
639 base::TimeDelta::FromSeconds(1),
640 base::Bind(&RemoteDesktopBrowserTest::IsPinFormVisible, this));
641 EXPECT_TRUE(waiter.Wait());
643 ExecuteScript(
644 "document.getElementById(\"pin-entry\").value = \"" + pin + "\";");
646 if (remember_pin) {
647 EXPECT_TRUE(HtmlElementVisible("remember-pin"));
648 EXPECT_FALSE(ExecuteScriptAndExtractBool(
649 "document.getElementById('remember-pin-checkbox').checked"));
650 ClickOnControl("remember-pin");
651 EXPECT_TRUE(ExecuteScriptAndExtractBool(
652 "document.getElementById('remember-pin-checkbox').checked"));
655 ClickOnControl("pin-connect-button");
658 void RemoteDesktopBrowserTest::WaitForConnection() {
659 // Wait until the client has connected to the server.
660 // This can take a while.
661 // TODO(weitaosu): Instead of polling, can we register a callback to
662 // remoting.clientSession.onStageChange_?
663 ConditionalTimeoutWaiter waiter(
664 base::TimeDelta::FromSeconds(4),
665 base::TimeDelta::FromSeconds(1),
666 base::Bind(&RemoteDesktopBrowserTest::IsSessionConnected, this));
667 EXPECT_TRUE(waiter.Wait());
669 // The client is not yet ready to take input when the session state becomes
670 // CONNECTED. Wait for 2 seconds for the client to become ready.
671 // TODO(weitaosu): Find a way to detect when the client is truly ready.
672 TimeoutWaiter(base::TimeDelta::FromSeconds(2)).Wait();
675 bool RemoteDesktopBrowserTest::IsLocalHostReady() {
676 // TODO(weitaosu): Instead of polling, can we register a callback to
677 // remoting.hostList.setLocalHost_?
678 return ExecuteScriptAndExtractBool("remoting.hostList.localHost_ != null");
681 bool RemoteDesktopBrowserTest::IsSessionConnected() {
682 // If some form of PINless authentication is enabled, the host version
683 // warning may appear while waiting for the session to connect.
684 DismissHostVersionWarningIfVisible();
686 return ExecuteScriptAndExtractBool(
687 "remoting.clientSession != null && "
688 "remoting.clientSession.getState() == "
689 "remoting.ClientSession.State.CONNECTED");
692 bool RemoteDesktopBrowserTest::IsPinFormVisible() {
693 DismissHostVersionWarningIfVisible();
694 return HtmlElementVisible("pin-form");
697 void RemoteDesktopBrowserTest::DismissHostVersionWarningIfVisible() {
698 if (HtmlElementVisible("host-needs-update-connect-button"))
699 ClickOnControl("host-needs-update-connect-button");
702 // static
703 bool RemoteDesktopBrowserTest::IsAuthenticatedInWindow(
704 content::WebContents* web_contents) {
705 return ExecuteScriptAndExtractBool(
706 web_contents, "remoting.identity.isAuthenticated()");
709 } // namespace remoting