• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
_ASSERT_TRUE(bool condition)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.
me2me_pin()160   std::string me2me_pin() { return me2me_pin_; }
161 
162   // Helper to get the name of the remote host to connect to.
remote_host_name()163   std::string remote_host_name() { return remote_host_name_; }
164 
165   // Helper to get the test controller URL.
http_server()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.
WebAppCrxPath()181   base::FilePath WebAppCrxPath() { return webapp_crx_; }
182 
183   // Helper to get the extension ID of the installed chromoting webapp.
ChromotingID()184   std::string ChromotingID() { return extension_->id(); }
185 
186   // Is this a appsv2 web app?
is_platform_app()187   bool is_platform_app() {
188     return extension_->GetType() == extensions::Manifest::TYPE_PLATFORM_APP;
189   }
190 
191   // Are we testing an unpacked extension?
is_unpacked()192   bool is_unpacked() {
193     return !webapp_unpacked_.empty();
194   }
195 
196   // The "active" WebContents instance the test needs to interact with.
active_web_contents()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.
client_web_content()203   content::WebContents* client_web_content() {
204     return client_web_content_;
205   }
206 
app_web_content()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.
NoCleanup()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.
NoInstall()217   bool NoInstall() { return no_install_; }
218 
219   // Helper to construct the starting URL of the installed chromoting webapp.
Chromoting_Main_URL()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.
GetCurrentURL()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.
ExecuteScriptAndExtractBool(const std::string & script)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.
ExecuteScriptAndExtractInt(const std::string & script)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.
ExecuteScriptAndExtractString(const std::string & script)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.
HtmlElementExists(const std::string & name)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.
IsAuthenticated()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