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