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