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. 4 5 #ifndef CHROME_TEST_REMOTING_REMOTE_DESKTOP_BROWSERTEST_H_ 6 #define CHROME_TEST_REMOTING_REMOTE_DESKTOP_BROWSERTEST_H_ 7 8 #include "base/debug/stack_trace.h" 9 #include "chrome/browser/apps/app_browsertest_util.h" 10 #include "chrome/browser/chrome_notification_types.h" 11 #include "chrome/browser/ui/tabs/tab_strip_model.h" 12 #include "chrome/test/base/ui_test_utils.h" 13 #include "content/public/browser/notification_service.h" 14 #include "content/public/test/browser_test_utils.h" 15 #include "net/dns/mock_host_resolver.h" 16 17 namespace { 18 // Command line arguments specific to the chromoting browser tests. 19 const char kOverrideUserDataDir[] = "override-user-data-dir"; 20 const char kNoCleanup[] = "no-cleanup"; 21 const char kNoInstall[] = "no-install"; 22 const char kWebAppCrx[] = "webapp-crx"; 23 const char kWebAppUnpacked[] = "webapp-unpacked"; 24 const char kUsername[] = "username"; 25 const char kkPassword[] = "password"; 26 const char kMe2MePin[] = "me2me-pin"; 27 const char kRemoteHostName[] = "remote-host-name"; 28 const char kExtensionName[] = "extension-name"; 29 const char kHttpServer[] = "http-server"; 30 31 // ASSERT_TRUE can only be used in void returning functions. This version 32 // should be used in non-void-returning functions. 33 inline void _ASSERT_TRUE(bool condition) { 34 if (!condition) { 35 // ASSERT_TRUE only prints the first call frame in the error message. 36 // In our case, this is the _ASSERT_TRUE wrapper function, which is not 37 // useful. To help with debugging, we will dump the full callstack. 38 LOG(ERROR) << "Assertion failed."; 39 LOG(ERROR) << base::debug::StackTrace().ToString(); 40 } 41 ASSERT_TRUE(condition); 42 return; 43 } 44 45 } // namespace 46 47 using extensions::Extension; 48 49 namespace remoting { 50 51 class RemoteDesktopBrowserTest : public extensions::PlatformAppBrowserTest { 52 public: 53 RemoteDesktopBrowserTest(); 54 virtual ~RemoteDesktopBrowserTest(); 55 56 // InProcessBrowserTest Overrides 57 virtual void SetUp() OVERRIDE; 58 virtual void SetUpOnMainThread() OVERRIDE; 59 60 protected: 61 // InProcessBrowserTest Overrides 62 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE; 63 64 // InProcessBrowserTest Overrides 65 virtual void TearDownInProcessBrowserTestFixture() OVERRIDE; 66 67 // The following helpers each perform a simple task. 68 69 // Verify the test has access to the internet (specifically google.com) 70 void VerifyInternetAccess(); 71 72 // Open the client page for the browser test to get status of host actions 73 void OpenClientBrowserPage(); 74 75 // Install the chromoting extension from a crx file. 76 void InstallChromotingAppCrx(); 77 78 // Install the unpacked chromoting extension. 79 void InstallChromotingAppUnpacked(); 80 81 // Uninstall the chromoting extension. 82 void UninstallChromotingApp(); 83 84 // Test whether the chromoting extension is installed. 85 void VerifyChromotingLoaded(bool expected); 86 87 // Launch the chromoting app. 88 void LaunchChromotingApp(); 89 90 // Authorize: grant extended access permission to the user's computer. 91 void Authorize(); 92 93 // Authenticate: sign in to google using the credentials provided. 94 void Authenticate(); 95 96 // Approve: grant the chromoting app necessary permissions. 97 void Approve(); 98 99 // Click on "Get Started" in the Me2Me section and show the host list. 100 void ExpandMe2Me(); 101 102 // Disconnect the active Me2Me session. 103 void DisconnectMe2Me(); 104 105 // Simulate a key event. 106 void SimulateKeyPressWithCode(ui::KeyboardCode keyCode, const char* code); 107 108 void SimulateKeyPressWithCode(ui::KeyboardCode keyCode, 109 const char* code, 110 bool control, 111 bool shift, 112 bool alt, 113 bool command); 114 115 // Simulate typing a character 116 void SimulateCharInput(char c); 117 118 // Simulate typing a string 119 void SimulateStringInput(const std::string& input); 120 121 // Helper to simulate a left button mouse click. 122 void SimulateMouseLeftClickAt(int x, int y); 123 124 // Helper to simulate a mouse click. 125 void SimulateMouseClickAt( 126 int modifiers, blink::WebMouseEvent::Button button, int x, int y); 127 128 // The following helpers each perform a composite task. 129 130 // Install the chromoting extension 131 void Install(); 132 133 // Perform all necessary steps (installation, authorization, authentication, 134 // expanding the me2me section) so that the app is ready for a me2me 135 // connection. 136 void SetUpTestForMe2Me(); 137 138 // Clean up after the test. 139 void Cleanup(); 140 141 // Perform all the auth steps: authorization, authentication, etc. 142 // It starts from the chromoting main page unauthenticated and ends up back 143 // on the chromoting main page authenticated and ready to go. 144 void Auth(); 145 146 // Ensures that the host is started locally with |me2me_pin()|. 147 // Browser_test.js must be loaded before calling this function. 148 void EnsureRemoteConnectionEnabled(); 149 150 // Connect to the local host through Me2Me. 151 void ConnectToLocalHost(bool remember_pin); 152 153 // Connect to a remote host through Me2Me. 154 void ConnectToRemoteHost(const std::string& host_name, bool remember_pin); 155 156 // Enter the pin number and connect. 157 void EnterPin(const std::string& name, bool remember_pin); 158 159 // Helper to get the pin number used for me2me authentication. 160 std::string me2me_pin() { return me2me_pin_; } 161 162 // Helper to get the name of the remote host to connect to. 163 std::string remote_host_name() { return remote_host_name_; } 164 165 // Helper to get the test controller URL. 166 std::string http_server() { return http_server_; } 167 168 // Change behavior of the default host resolver to allow DNS lookup 169 // to proceed instead of being blocked by the test infrastructure. 170 void EnableDNSLookupForThisTest( 171 net::RuleBasedHostResolverProc* host_resolver); 172 173 // We need to reset the DNS lookup when we finish, or the test will fail. 174 void DisableDNSLookupForThisTest(); 175 176 void ParseCommandLine(); 177 178 // Accessor methods. 179 180 // Helper to get the path to the crx file of the webapp to be tested. 181 base::FilePath WebAppCrxPath() { return webapp_crx_; } 182 183 // Helper to get the extension ID of the installed chromoting webapp. 184 std::string ChromotingID() { return extension_->id(); } 185 186 // Is this a appsv2 web app? 187 bool is_platform_app() { 188 return extension_->GetType() == extensions::Manifest::TYPE_PLATFORM_APP; 189 } 190 191 // Are we testing an unpacked extension? 192 bool is_unpacked() { 193 return !webapp_unpacked_.empty(); 194 } 195 196 // The "active" WebContents instance the test needs to interact with. 197 content::WebContents* active_web_contents() { 198 DCHECK(!web_contents_stack_.empty()); 199 return web_contents_stack_.back(); 200 } 201 202 // The client WebContents instance the test needs to interact with. 203 content::WebContents* client_web_content() { 204 return client_web_content_; 205 } 206 207 content::WebContents* app_web_content() { 208 return app_web_content_; 209 } 210 211 // Whether to perform the cleanup tasks (uninstalling chromoting, etc). 212 // This is useful for diagnostic purposes. 213 bool NoCleanup() { return no_cleanup_; } 214 215 // Whether to install the chromoting extension before running the test cases. 216 // This is useful for diagnostic purposes. 217 bool NoInstall() { return no_install_; } 218 219 // Helper to construct the starting URL of the installed chromoting webapp. 220 GURL Chromoting_Main_URL() { 221 return GURL("chrome-extension://" + ChromotingID() + "/main.html"); 222 } 223 224 // Helper to retrieve the current URL in the active WebContents. 225 GURL GetCurrentURL() { 226 return active_web_contents()->GetURL(); 227 } 228 229 // Helpers to execute JavaScript code on a web page. 230 231 // Helper to execute a JavaScript code snippet in the active WebContents. 232 void ExecuteScript(const std::string& script); 233 234 // Helper to execute a JavaScript code snippet in the active WebContents 235 // and wait for page load to complete. 236 void ExecuteScriptAndWaitForAnyPageLoad(const std::string& script); 237 238 // Helper to execute a JavaScript code snippet in the active WebContents 239 // and extract the boolean result. 240 bool ExecuteScriptAndExtractBool(const std::string& script) { 241 return ExecuteScriptAndExtractBool(active_web_contents(), script); 242 } 243 244 // Helper to execute a JavaScript code snippet and extract the boolean result. 245 static bool ExecuteScriptAndExtractBool(content::WebContents* web_contents, 246 const std::string& script); 247 248 // Helper to execute a JavaScript code snippet in the active WebContents 249 // and extract the int result. 250 int ExecuteScriptAndExtractInt(const std::string& script) { 251 return ExecuteScriptAndExtractInt(active_web_contents(), script); 252 } 253 254 // Helper to execute a JavaScript code snippet and extract the int result. 255 static int ExecuteScriptAndExtractInt(content::WebContents* web_contents, 256 const std::string& script); 257 258 // Helper to execute a JavaScript code snippet in the active WebContents 259 // and extract the string result. 260 std::string ExecuteScriptAndExtractString(const std::string& script) { 261 return ExecuteScriptAndExtractString(active_web_contents(), script); 262 } 263 264 // Helper to execute a JavaScript code snippet and extract the string result. 265 static std::string ExecuteScriptAndExtractString( 266 content::WebContents* web_contents, const std::string& script); 267 268 // Helper to load a JavaScript file from |path| and inject it to 269 // current web_content. The variable |path| is relative to the directory of 270 // the |browsertest| executable. 271 static bool LoadScript(content::WebContents* web_contents, 272 const base::FilePath::StringType& path); 273 274 // Helper to execute a JavaScript browser test. It creates an object using 275 // the |browserTest.testName| ctor and calls |run| on the created object with 276 // |testData|, which can be any arbitrary object literal. The script 277 // browser_test.js must be loaded (using LoadScript) before calling this 278 // function. 279 void RunJavaScriptTest(content::WebContents* web_contents, 280 const std::string& testName, 281 const std::string& testData); 282 283 // Helper to check whether an html element with the given name exists in 284 // the active WebContents. 285 bool HtmlElementExists(const std::string& name) { 286 return ExecuteScriptAndExtractBool( 287 "document.getElementById(\"" + name + "\") != null"); 288 } 289 290 // Helper to check whether a html element with the given name is visible in 291 // the active WebContents. 292 bool HtmlElementVisible(const std::string& name); 293 294 // Click on the named HTML control in the active WebContents. 295 void ClickOnControl(const std::string& name); 296 297 // Wait for the me2me connection to be established. 298 void WaitForConnection(); 299 300 // Checking whether the localHost has been initialized. 301 bool IsLocalHostReady(); 302 303 // Callback used by EnterPin to check whether the pin form is visible 304 // and to dismiss the host-needs-update dialog. 305 bool IsPinFormVisible(); 306 307 // Callback used by WaitForConnection to check whether the connection 308 // has been established. 309 bool IsSessionConnected(); 310 311 // Callback used by Approve to check whether the chromoting app has 312 // successfully authenticated with the Google services. 313 bool IsAuthenticated() { 314 return IsAuthenticatedInWindow(active_web_contents()); 315 } 316 317 // Callback used by Approve to check whether the Accept button is enabled 318 // and ready to receive a click. 319 static bool IsEnabled( 320 content::WebContents* web_contents, const std::string& name); 321 322 // If the "Host version out-of-date" form is visible, dismiss it. 323 void DismissHostVersionWarningIfVisible(); 324 325 // Callback used by Approve to check whether the chromoting app has 326 // successfully authenticated with the Google services. 327 static bool IsAuthenticatedInWindow(content::WebContents* web_contents); 328 329 // Callback used to check whether a host action is completed. 330 // Used by browser tests while conditionally waiting for host actions. 331 static bool IsHostActionComplete( 332 content::WebContents* client_web_content, std::string host_action_var); 333 334 private: 335 // Fields 336 337 // This test needs to make live DNS requests for access to 338 // GAIA and sync server URLs under google.com. We use a scoped version 339 // to override the default resolver while the test is active. 340 scoped_ptr<net::ScopedDefaultHostResolverProc> mock_host_resolver_override_; 341 342 // Stores all the WebContents instance in a stack so that we can easily 343 // return to the previous instance. 344 // The active WebContents instance is always stored at the top of the stack. 345 // Initially the stack contains the WebContents instance created by 346 // InProcessBrowserTest as the initial context to run test in. 347 // Whenever a WebContents instance is spawned and needs attention we 348 // push it onto the stack and that becomes the active instance. 349 // And once we are done with the current WebContents instance 350 // we pop it off the stack, returning to the previous instance. 351 std::vector<content::WebContents*> web_contents_stack_; 352 353 // WebContent of the client page that facilitates communication with 354 // the HTTP server. This is how the remoting browser tests 355 // will get acknowledgments of actions completed on the host. 356 content::WebContents* client_web_content_; 357 358 // WebContent of the landing page in the chromoting app. 359 content::WebContents* app_web_content_; 360 361 bool no_cleanup_; 362 bool no_install_; 363 const Extension* extension_; 364 base::FilePath webapp_crx_; 365 base::FilePath webapp_unpacked_; 366 std::string username_; 367 std::string password_; 368 std::string me2me_pin_; 369 std::string remote_host_name_; 370 std::string extension_name_; 371 std::string http_server_; 372 }; 373 374 } // namespace remoting 375 376 #endif // CHROME_TEST_REMOTING_REMOTE_DESKTOP_BROWSERTEST_H_ 377