Home | History | Annotate | Download | only in remoting
      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