// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_TEST_REMOTING_REMOTE_DESKTOP_BROWSERTEST_H_ #define CHROME_TEST_REMOTING_REMOTE_DESKTOP_BROWSERTEST_H_ #include "chrome/browser/apps/app_browsertest_util.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/notification_service.h" #include "content/public/test/browser_test_utils.h" #include "net/dns/mock_host_resolver.h" namespace { // Command line arguments specific to the chromoting browser tests. const char kOverrideUserDataDir[] = "override-user-data-dir"; const char kNoCleanup[] = "no-cleanup"; const char kNoInstall[] = "no-install"; const char kWebAppCrx[] = "webapp-crx"; const char kWebAppUnpacked[] = "webapp-unpacked"; const char kUsername[] = "username"; const char kkPassword[] = "password"; const char kMe2MePin[] = "me2me-pin"; const char kRemoteHostName[] = "remote-host-name"; const char kExtensionName[] = "extension-name"; const char kHttpServer[] = "http-server"; // ASSERT_TRUE can only be used in void returning functions. This version // should be used in non-void-returning functions. inline void _ASSERT_TRUE(bool condition) { ASSERT_TRUE(condition); return; } } // namespace using extensions::Extension; namespace remoting { class RemoteDesktopBrowserTest : public extensions::PlatformAppBrowserTest { public: RemoteDesktopBrowserTest(); virtual ~RemoteDesktopBrowserTest(); // InProcessBrowserTest Overrides virtual void SetUp() OVERRIDE; virtual void SetUpOnMainThread() OVERRIDE; protected: // InProcessBrowserTest Overrides virtual void SetUpInProcessBrowserTestFixture() OVERRIDE; // InProcessBrowserTest Overrides virtual void TearDownInProcessBrowserTestFixture() OVERRIDE; // The following helpers each perform a simple task. // Verify the test has access to the internet (specifically google.com) void VerifyInternetAccess(); // Open the client page for the browser test to get status of host actions void OpenClientBrowserPage(); // Install the chromoting extension from a crx file. void InstallChromotingAppCrx(); // Install the unpacked chromoting extension. void InstallChromotingAppUnpacked(); // Uninstall the chromoting extension. void UninstallChromotingApp(); // Test whether the chromoting extension is installed. void VerifyChromotingLoaded(bool expected); // Launch the chromoting app. void LaunchChromotingApp(); // Authorize: grant extended access permission to the user's computer. void Authorize(); // Authenticate: sign in to google using the credentials provided. void Authenticate(); // Approve: grant the chromoting app necessary permissions. void Approve(); // Click on "Get Started" in the Me2Me section and show the host list. void ExpandMe2Me(); // Disconnect the active Me2Me session. void DisconnectMe2Me(); // Simulate a key event. void SimulateKeyPressWithCode(ui::KeyboardCode keyCode, const char* code); void SimulateKeyPressWithCode(ui::KeyboardCode keyCode, const char* code, bool control, bool shift, bool alt, bool command); // Simulate typing a character void SimulateCharInput(char c); // Simulate typing a string void SimulateStringInput(const std::string& input); // Helper to simulate a left button mouse click. void SimulateMouseLeftClickAt(int x, int y); // Helper to simulate a mouse click. void SimulateMouseClickAt( int modifiers, blink::WebMouseEvent::Button button, int x, int y); // The following helpers each perform a composite task. // Install the chromoting extension void Install(); // Perform all necessary steps (installation, authorization, authentication, // expanding the me2me section) so that the app is ready for a me2me // connection. void SetUpTestForMe2Me(); // Clean up after the test. void Cleanup(); // Perform all the auth steps: authorization, authentication, etc. // It starts from the chromoting main page unauthenticated and ends up back // on the chromoting main page authenticated and ready to go. void Auth(); // Connect to the local host through Me2Me. void ConnectToLocalHost(bool remember_pin); // Connect to a remote host through Me2Me. void ConnectToRemoteHost(const std::string& host_name, bool remember_pin); // Enter the pin number and connect. void EnterPin(const std::string& name, bool remember_pin); // Helper to get the pin number used for me2me authentication. std::string me2me_pin() { return me2me_pin_; } // Helper to get the name of the remote host to connect to. std::string remote_host_name() { return remote_host_name_; } // Helper to get the test controller URL. std::string http_server() { return http_server_; } // Change behavior of the default host resolver to allow DNS lookup // to proceed instead of being blocked by the test infrastructure. void EnableDNSLookupForThisTest( net::RuleBasedHostResolverProc* host_resolver); // We need to reset the DNS lookup when we finish, or the test will fail. void DisableDNSLookupForThisTest(); void ParseCommandLine(); // Accessor methods. // Helper to get the path to the crx file of the webapp to be tested. base::FilePath WebAppCrxPath() { return webapp_crx_; } // Helper to get the extension ID of the installed chromoting webapp. std::string ChromotingID() { return extension_->id(); } // Is this a appsv2 web app? bool is_platform_app() { return extension_->GetType() == extensions::Manifest::TYPE_PLATFORM_APP; } // Are we testing an unpacked extension? bool is_unpacked() { return !webapp_unpacked_.empty(); } // The "active" WebContents instance the test needs to interact with. content::WebContents* active_web_contents() { DCHECK(!web_contents_stack_.empty()); return web_contents_stack_.back(); } // The client WebContents instance the test needs to interact with. content::WebContents* client_web_content() { return client_web_content_; } content::WebContents* app_web_content() { return app_web_content_; } // Whether to perform the cleanup tasks (uninstalling chromoting, etc). // This is useful for diagnostic purposes. bool NoCleanup() { return no_cleanup_; } // Whether to install the chromoting extension before running the test cases. // This is useful for diagnostic purposes. bool NoInstall() { return no_install_; } // Helper to construct the starting URL of the installed chromoting webapp. GURL Chromoting_Main_URL() { return GURL("chrome-extension://" + ChromotingID() + "/main.html"); } // Helper to retrieve the current URL in the active WebContents. GURL GetCurrentURL() { return active_web_contents()->GetURL(); } // Helpers to execute JavaScript code on a web page. // Helper to execute a JavaScript code snippet in the active WebContents. void ExecuteScript(const std::string& script); // Helper to execute a JavaScript code snippet in the active WebContents // and wait for page load to complete. void ExecuteScriptAndWaitForAnyPageLoad(const std::string& script); // Helper to execute a JavaScript code snippet in the active WebContents // and extract the boolean result. bool ExecuteScriptAndExtractBool(const std::string& script) { return ExecuteScriptAndExtractBool(active_web_contents(), script); } // Helper to execute a JavaScript code snippet and extract the boolean result. static bool ExecuteScriptAndExtractBool(content::WebContents* web_contents, const std::string& script); // Helper to execute a JavaScript code snippet in the active WebContents // and extract the int result. int ExecuteScriptAndExtractInt(const std::string& script) { return ExecuteScriptAndExtractInt(active_web_contents(), script); } // Helper to execute a JavaScript code snippet and extract the int result. static int ExecuteScriptAndExtractInt(content::WebContents* web_contents, const std::string& script); // Helper to execute a JavaScript code snippet in the active WebContents // and extract the string result. std::string ExecuteScriptAndExtractString(const std::string& script) { return ExecuteScriptAndExtractString(active_web_contents(), script); } // Helper to execute a JavaScript code snippet and extract the string result. static std::string ExecuteScriptAndExtractString( content::WebContents* web_contents, const std::string& script); // Helper to load a JavaScript file from |path| and inject it to // current web_content. The variable |path| is relative to the directory of // the |browsertest| executable. static bool LoadScript(content::WebContents* web_contents, const base::FilePath::StringType& path); // Helper to execute a JavaScript browser test. It creates an object using // the |browserTest.testName| ctor and calls |run| on the created object with // |testData|, which can be any arbitrary object literal. The script // browser_test.js must be loaded (using LoadScript) before calling this // function. void RunJavaScriptTest(content::WebContents* web_contents, const std::string& testName, const std::string& testData); // Helper to check whether an html element with the given name exists in // the active WebContents. bool HtmlElementExists(const std::string& name) { return ExecuteScriptAndExtractBool( "document.getElementById(\"" + name + "\") != null"); } // Helper to check whether a html element with the given name is visible in // the active WebContents. bool HtmlElementVisible(const std::string& name); // Click on the named HTML control in the active WebContents. void ClickOnControl(const std::string& name); // Wait for the me2me connection to be established. void WaitForConnection(); // Checking whether the localHost has been initialized. bool IsLocalHostReady(); // Callback used by EnterPin to check whether the pin form is visible // and to dismiss the host-needs-update dialog. bool IsPinFormVisible(); // Callback used by WaitForConnection to check whether the connection // has been established. bool IsSessionConnected(); // Callback used by Approve to check whether the chromoting app has // successfully authenticated with the Google services. bool IsAuthenticated() { return IsAuthenticatedInWindow(active_web_contents()); } // If the "Host version out-of-date" form is visible, dismiss it. void DismissHostVersionWarningIfVisible(); // Callback used by Approve to check whether the chromoting app has // successfully authenticated with the Google services. static bool IsAuthenticatedInWindow(content::WebContents* web_contents); // Callback used to check whether a host action is completed. // Used by browser tests while conditionally waiting for host actions. static bool IsHostActionComplete( content::WebContents* client_web_content, std::string host_action_var); private: // Fields // This test needs to make live DNS requests for access to // GAIA and sync server URLs under google.com. We use a scoped version // to override the default resolver while the test is active. scoped_ptr<net::ScopedDefaultHostResolverProc> mock_host_resolver_override_; // Stores all the WebContents instance in a stack so that we can easily // return to the previous instance. // The active WebContents instance is always stored at the top of the stack. // Initially the stack contains the WebContents instance created by // InProcessBrowserTest as the initial context to run test in. // Whenever a WebContents instance is spawned and needs attention we // push it onto the stack and that becomes the active instance. // And once we are done with the current WebContents instance // we pop it off the stack, returning to the previous instance. std::vector<content::WebContents*> web_contents_stack_; // WebContent of the client page that facilitates communication with // the HTTP server. This is how the remoting browser tests // will get acknowledgments of actions completed on the host. content::WebContents* client_web_content_; // WebContent of the landing page in the chromoting app. content::WebContents* app_web_content_; bool no_cleanup_; bool no_install_; const Extension* extension_; base::FilePath webapp_crx_; base::FilePath webapp_unpacked_; std::string username_; std::string password_; std::string me2me_pin_; std::string remote_host_name_; std::string extension_name_; std::string http_server_; }; } // namespace remoting #endif // CHROME_TEST_REMOTING_REMOTE_DESKTOP_BROWSERTEST_H_