summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/test/remoting/pin_browsertest.cc52
-rw-r--r--chrome/test/remoting/remote_desktop_browsertest.cc9
-rw-r--r--chrome/test/remoting/remote_desktop_browsertest.h7
-rw-r--r--remoting/remoting_webapp_files.gypi3
-rw-r--r--remoting/webapp/base.js18
-rw-r--r--remoting/webapp/browser_test/browser_test.js134
-rw-r--r--remoting/webapp/browser_test/cancel_pin_browser_test.js46
-rw-r--r--remoting/webapp/browser_test/invalid_pin_browser_test.js44
-rw-r--r--remoting/webapp/browser_test/update_pin_browser_test.js109
-rw-r--r--remoting/webapp/js_proto/dom_proto.js43
11 files changed, 425 insertions, 41 deletions
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index b7d430f..884a708 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1552,6 +1552,7 @@
'test/remoting/me2me_browsertest.cc',
'test/remoting/page_load_notification_observer.cc',
'test/remoting/page_load_notification_observer.h',
+ 'test/remoting/pin_browsertest.cc',
'test/remoting/remote_desktop_browsertest.cc',
'test/remoting/remote_desktop_browsertest.h',
'test/remoting/waiter.cc',
diff --git a/chrome/test/remoting/pin_browsertest.cc b/chrome/test/remoting/pin_browsertest.cc
new file mode 100644
index 0000000..eac2a3f
--- /dev/null
+++ b/chrome/test/remoting/pin_browsertest.cc
@@ -0,0 +1,52 @@
+// Copyright 2014 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.
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "chrome/test/remoting/remote_desktop_browsertest.h"
+#include "chrome/test/remoting/waiter.h"
+
+namespace remoting {
+
+IN_PROC_BROWSER_TEST_F(RemoteDesktopBrowserTest, MANUAL_Cancel_PIN) {
+ SetUpTestForMe2Me();
+
+ content::WebContents* content = app_web_content();
+ LoadScript(content, FILE_PATH_LITERAL("cancel_pin_browser_test.js"));
+
+ RunJavaScriptTest(content, "Cancel_PIN", "{"
+ "pin: '" + me2me_pin() + "'"
+ "}");
+
+ Cleanup();
+}
+
+IN_PROC_BROWSER_TEST_F(RemoteDesktopBrowserTest, MANUAL_Invalid_PIN) {
+ SetUpTestForMe2Me();
+
+ content::WebContents* content = app_web_content();
+ LoadScript(content, FILE_PATH_LITERAL("invalid_pin_browser_test.js"));
+
+ RunJavaScriptTest(content, "Invalid_PIN", "{"
+ "pin: '" + me2me_pin() + "'"
+ "}");
+
+ Cleanup();
+}
+
+IN_PROC_BROWSER_TEST_F(RemoteDesktopBrowserTest, MANUAL_Update_PIN) {
+ SetUpTestForMe2Me();
+
+ content::WebContents* content = app_web_content();
+ LoadScript(content, FILE_PATH_LITERAL("update_pin_browser_test.js"));
+
+ RunJavaScriptTest(content, "Update_PIN", "{"
+ "old_pin: '" + me2me_pin() + "',"
+ "new_pin: '314159'"
+ "}");
+
+ Cleanup();
+}
+
+} // namespace remoting
diff --git a/chrome/test/remoting/remote_desktop_browsertest.cc b/chrome/test/remoting/remote_desktop_browsertest.cc
index 3d9f4a7..8cd1e50 100644
--- a/chrome/test/remoting/remote_desktop_browsertest.cc
+++ b/chrome/test/remoting/remote_desktop_browsertest.cc
@@ -479,6 +479,15 @@ void RemoteDesktopBrowserTest::Cleanup() {
ASSERT_TRUE(TimeoutWaiter(base::TimeDelta::FromSeconds(2)).Wait());
}
+void RemoteDesktopBrowserTest::SetUpTestForMe2Me() {
+ VerifyInternetAccess();
+ Install();
+ LaunchChromotingApp();
+ Auth();
+ ExpandMe2Me();
+ LoadScript(app_web_content(), FILE_PATH_LITERAL("browser_test.js"));
+}
+
void RemoteDesktopBrowserTest::Auth() {
Authorize();
Authenticate();
diff --git a/chrome/test/remoting/remote_desktop_browsertest.h b/chrome/test/remoting/remote_desktop_browsertest.h
index fbccea67..579c2f21 100644
--- a/chrome/test/remoting/remote_desktop_browsertest.h
+++ b/chrome/test/remoting/remote_desktop_browsertest.h
@@ -122,10 +122,15 @@ class RemoteDesktopBrowserTest : public extensions::PlatformAppBrowserTest {
// 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, authenticattion, etc.
+ // 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();
diff --git a/remoting/remoting_webapp_files.gypi b/remoting/remoting_webapp_files.gypi
index c862a13..fca8cbe 100644
--- a/remoting/remoting_webapp_files.gypi
+++ b/remoting/remoting_webapp_files.gypi
@@ -123,6 +123,9 @@
# browser test JavaScript files.
'remoting_webapp_js_browser_test_files': [
'webapp/browser_test/browser_test.js',
+ 'webapp/browser_test/cancel_pin_browser_test.js',
+ 'webapp/browser_test/invalid_pin_browser_test.js',
+ 'webapp/browser_test/update_pin_browser_test.js',
],
# The JavaScript files required by main.html.
'remoting_webapp_main_html_js_files': [
diff --git a/remoting/webapp/base.js b/remoting/webapp/base.js
index f010d73..88c3faa 100644
--- a/remoting/webapp/base.js
+++ b/remoting/webapp/base.js
@@ -12,7 +12,7 @@
'use strict';
var base = {};
-base.debug = function () {};
+base.debug = function() {};
/**
* Whether to break in debugger and alert when an assertion fails.
@@ -104,7 +104,7 @@ base.doNothing = function() {};
* @param {!Object} dict
* @return {Array}
*/
-base.values = function (dict) {
+base.values = function(dict) {
return Object.keys(dict).map(
/** @param {string} key */
function(key) {
@@ -112,6 +112,20 @@ base.values = function (dict) {
});
};
+base.Promise = function() {};
+
+/**
+ * @param {number} delay
+ * @return {Promise} a Promise that will be fulfilled after |delay| ms.
+ */
+base.Promise.sleep = function(delay) {
+ return new Promise(
+ /** @param {function():void} fulfill */
+ function(fulfill) {
+ window.setTimeout(fulfill, delay);
+ });
+};
+
/**
* A mixin for classes with events.
*
diff --git a/remoting/webapp/browser_test/browser_test.js b/remoting/webapp/browser_test/browser_test.js
index 85985aa..7860002 100644
--- a/remoting/webapp/browser_test/browser_test.js
+++ b/remoting/webapp/browser_test/browser_test.js
@@ -17,17 +17,17 @@
* method.
* For example:
*
- * browserTest.My_Test = function(myObjectLiteral) {};
- * browserTest.My_Test.prototype.run() = function() { ... };
+ * browserTest.My_Test = function() {};
+ * browserTest.My_Test.prototype.run(myObjectLiteral) = function() { ... };
*
* The browser test is async in nature. It will keep running until
* browserTest.fail("My error message.") or browserTest.pass() is called.
*
* For example:
*
- * browserTest.My_Test.prototype.run() = function() {
+ * browserTest.My_Test.prototype.run(myObjectLiteral) = function() {
* window.setTimeout(function() {
- * if (doSomething()) {
+ * if (doSomething(myObjectLiteral)) {
* browserTest.pass();
* } else {
* browserTest.fail('My error message.');
@@ -38,7 +38,7 @@
* You will then invoke the test in C++ by calling:
*
* RunJavaScriptTest(web_content, "My_Test", "{"
- * "pin: 123123"
+ * "pin: '123123'"
* "}");
*/
@@ -57,21 +57,28 @@ browserTest.init = function() {
if (result.succeeded) {
console.log('Test Passed.');
} else {
- console.error(result.error_message);
+ console.error('Test Failed.\n' +
+ result.error_message + '\n' + result.stack_trace);
}
}
};
};
-browserTest.assert = function(expr, message) {
+browserTest.expect = function(expr, message) {
if (!expr) {
message = (message) ? '<' + message + '>' : '';
- browserTest.fail('Assertion failed.' + message);
+ browserTest.fail('Expectation failed.' + message);
}
};
-browserTest.fail = function(error_message, opt_stack_trace) {
- var stack_trace = opt_stack_trace || base.debug.callstack();
+browserTest.fail = function(error) {
+ var error_message = error;
+ var stack_trace = base.debug.callstack();
+
+ if (error instanceof Error) {
+ error_message = error.toString();
+ stack_trace = error.stack;
+ }
// To run browserTest locally:
// 1. Go to |remoting_webapp_files| and look for
@@ -100,7 +107,7 @@ browserTest.pass = function() {
browserTest.clickOnControl = function(id) {
var element = document.getElementById(id);
- browserTest.assert(element);
+ browserTest.expect(element);
element.click();
};
@@ -110,45 +117,96 @@ browserTest.Timeout = {
DEFAULT: 5000
};
-browserTest.waitForUIMode = function(expectedMode, callback, opt_timeout) {
- var uiModeChanged = remoting.testEvents.Names.uiModeChanged;
- var timerId = null;
-
- if (opt_timeout === undefined) {
- opt_timeout = browserTest.Timeout.DEFAULT;
+browserTest.onUIMode = function(expectedMode, opt_timeout) {
+ if (expectedMode == remoting.currentMode) {
+ // If the current mode is the same as the expected mode, return a fulfilled
+ // promise. For some reason, if we fulfill the promise in the same
+ // callstack, V8 will assert at V8RecursionScope.h(66) with
+ // ASSERT(!ScriptForbiddenScope::isScriptForbidden()).
+ // To avoid the assert, execute the callback in a different callstack.
+ return base.Promise.sleep(0);
}
- function onTimeout() {
- remoting.testEvents.removeEventListener(uiModeChanged, onUIModeChanged);
- browserTest.fail('Timeout waiting for ' + expectedMode);
- }
+ return new Promise (function(fulfill, reject) {
+ var uiModeChanged = remoting.testEvents.Names.uiModeChanged;
+ var timerId = null;
+
+ if (opt_timeout === undefined) {
+ opt_timeout = browserTest.Timeout.DEFAULT;
+ }
- function onUIModeChanged (mode) {
- if (mode == expectedMode) {
+ function onTimeout() {
remoting.testEvents.removeEventListener(uiModeChanged, onUIModeChanged);
- window.clearTimeout(timerId);
- timerId = null;
- try {
- callback();
- } catch (e) {
- browserTest.fail(e.toString(), e.stack);
+ reject('Timeout waiting for ' + expectedMode);
+ }
+
+ function onUIModeChanged(mode) {
+ if (mode == expectedMode) {
+ remoting.testEvents.removeEventListener(uiModeChanged, onUIModeChanged);
+ window.clearTimeout(timerId);
+ timerId = null;
+ fulfill();
}
}
- }
- if (opt_timeout != browserTest.Timeout.NONE) {
- timerId = window.setTimeout(onTimeout.bind(window, timerId), opt_timeout);
- }
- remoting.testEvents.addEventListener(uiModeChanged, onUIModeChanged);
+ if (opt_timeout != browserTest.Timeout.NONE) {
+ timerId = window.setTimeout(onTimeout, opt_timeout);
+ }
+ remoting.testEvents.addEventListener(uiModeChanged, onUIModeChanged);
+ });
+};
+
+browserTest.expectMe2MeError = function(errorTag) {
+ var AppMode = remoting.AppMode;
+ var Timeout = browserTest.Timeout;
+
+ var onConnected = browserTest.onUIMode(AppMode.IN_SESSION, Timeout.None);
+ var onFailure = browserTest.onUIMode(AppMode.CLIENT_CONNECT_FAILED_ME2ME);
+
+ onConnected = onConnected.then(function() {
+ return Promise.reject(
+ 'Expected the Me2Me connection to fail.');
+ });
+
+ onFailure = onFailure.then(function() {
+ var errorDiv = document.getElementById('connect-error-message');
+ var actual = errorDiv.innerText;
+ var expected = l10n.getTranslationOrError(errorTag);
+
+ browserTest.clickOnControl('client-finished-me2me-button');
+
+ if (actual != expected) {
+ return Promise.reject('Unexpected failure. actual:' + actual +
+ ' expected:' + expected);
+ }
+ });
+
+ return Promise.race([onConnected, onFailure]);
+};
+
+browserTest.expectMe2MeConnected = function() {
+ var AppMode = remoting.AppMode;
+ // Timeout if the session is not connected within 30 seconds.
+ var SESSION_CONNECTION_TIMEOUT = 30000;
+ var onConnected = browserTest.onUIMode(AppMode.IN_SESSION,
+ SESSION_CONNECTION_TIMEOUT);
+ var onFailure = browserTest.onUIMode(AppMode.CLIENT_CONNECT_FAILED_ME2ME,
+ browserTest.Timeout.NONE);
+ onFailure = onFailure.then(function() {
+ var errorDiv = document.getElementById('connect-error-message');
+ var errorMsg = errorDiv.innerText;
+ return Promise.reject('Unexpected error - ' + errorMsg);
+ });
+ return Promise.race([onConnected, onFailure]);
};
browserTest.runTest = function(testClass, data) {
try {
- var test = new testClass(data);
- browserTest.assert(typeof test.run == 'function');
- test.run();
+ var test = new testClass();
+ browserTest.expect(typeof test.run == 'function');
+ test.run(data);
} catch (e) {
- browserTest.fail(e.toString(), e.stack);
+ browserTest.fail(e);
}
};
diff --git a/remoting/webapp/browser_test/cancel_pin_browser_test.js b/remoting/webapp/browser_test/cancel_pin_browser_test.js
new file mode 100644
index 0000000..7ba01c7
--- /dev/null
+++ b/remoting/webapp/browser_test/cancel_pin_browser_test.js
@@ -0,0 +1,46 @@
+// Copyright 2014 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.
+
+/**
+ * @fileoverview
+ * @suppress {checkTypes}
+ * Browser test for the scenario below:
+ * 1. Attempt to connect.
+ * 2. Hit cancel at the PIN prompt.
+ * 3. Reconnect with the PIN.
+ * 4. Verify that the session is connected.
+ */
+
+'use strict';
+
+/** @constructor */
+browserTest.Cancel_PIN = function() {};
+
+browserTest.Cancel_PIN.prototype.run = function(data) {
+ browserTest.expect(typeof data.pin == 'string');
+
+ var AppMode = remoting.AppMode;
+ browserTest.clickOnControl('this-host-connect');
+ browserTest.onUIMode(AppMode.CLIENT_PIN_PROMPT).then(function() {
+ browserTest.clickOnControl('cancel-pin-entry-button');
+ return browserTest.onUIMode(AppMode.HOME);
+ }).then(function() {
+ browserTest.clickOnControl('this-host-connect');
+ return browserTest.onUIMode(AppMode.CLIENT_PIN_PROMPT);
+ }).then(
+ this.enterPin_.bind(this, data.pin)
+ ).then(function() {
+ // On fulfilled.
+ browserTest.pass();
+ }, function(reason) {
+ // On rejected.
+ browserTest.fail(reason);
+ });
+};
+
+browserTest.Cancel_PIN.prototype.enterPin_ = function(pin) {
+ document.getElementById('pin-entry').value = pin;
+ browserTest.clickOnControl('pin-connect-button');
+ return browserTest.expectMe2MeConnected();
+};
diff --git a/remoting/webapp/browser_test/invalid_pin_browser_test.js b/remoting/webapp/browser_test/invalid_pin_browser_test.js
new file mode 100644
index 0000000..5cdea3e1
--- /dev/null
+++ b/remoting/webapp/browser_test/invalid_pin_browser_test.js
@@ -0,0 +1,44 @@
+// Copyright 2014 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.
+
+/**
+ * @fileoverview
+ * @suppress {checkTypes}
+ * Browser test for the scenario below:
+ * 1. Attempt to connect.
+ * 2. Enter |data.pin| at the PIN prompt.
+ * 3. Verify that there is connection error due to invalid access code.
+ */
+
+'use strict';
+
+/** @constructor */
+browserTest.Invalid_PIN = function() {};
+
+browserTest.Invalid_PIN.prototype.run = function(data) {
+ // Input validation.
+ browserTest.expect(typeof data.pin == 'string');
+
+ // Connect to me2me Host.
+ browserTest.clickOnControl('this-host-connect');
+
+ browserTest.onUIMode(remoting.AppMode.CLIENT_PIN_PROMPT).then(
+ this.enterPIN_.bind(this, data.pin)
+ ).then(
+ // Sleep for two seconds to allow the host backoff timer to reset.
+ base.Promise.sleep.bind(window, 2000)
+ ).then(function() {
+ // On fulfilled.
+ browserTest.pass();
+ }, function(reason) {
+ // On rejected.
+ browserTest.fail(reason);
+ });
+};
+
+browserTest.Invalid_PIN.prototype.enterPIN_ = function(pin) {
+ document.getElementById('pin-entry').value = pin;
+ browserTest.clickOnControl('pin-connect-button');
+ return browserTest.expectMe2MeError(remoting.Error.INVALID_ACCESS_CODE);
+};
diff --git a/remoting/webapp/browser_test/update_pin_browser_test.js b/remoting/webapp/browser_test/update_pin_browser_test.js
new file mode 100644
index 0000000..0d0eba5
--- /dev/null
+++ b/remoting/webapp/browser_test/update_pin_browser_test.js
@@ -0,0 +1,109 @@
+// Copyright 2014 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.
+
+/**
+ * @fileoverview
+ * @suppress {checkTypes}
+ * Browser test for the scenario below:
+ * 1. Change the PIN.
+ * 2. Connect with the new PIN.
+ * 3. Verify the connection succeeded.
+ * 4. Disconnect and reconnect with the old PIN.
+ * 5. Verify the connection failed.
+ */
+
+'use strict';
+
+/** @constructor */
+browserTest.Update_PIN = function() {};
+
+browserTest.Update_PIN.prototype.run = function(data) {
+ var LOGIN_BACKOFF_WAIT = 2000;
+ // Input validation
+ browserTest.expect(typeof data.new_pin == 'string');
+ browserTest.expect(typeof data.old_pin == 'string');
+ browserTest.expect(data.new_pin != data.old_pin,
+ 'The new PIN and the old PIN cannot be the same');
+
+ this.changePIN_(data.new_pin).then(
+ this.connect_.bind(this)
+ ).then(
+ this.enterPIN_.bind(this, data.old_pin, true /* expectError*/)
+ ).then(
+ // Sleep for two seconds to allow for the login backoff logic to reset.
+ base.Promise.sleep.bind(null, LOGIN_BACKOFF_WAIT)
+ ).then(
+ this.connect_.bind(this)
+ ).then(
+ this.enterPIN_.bind(this, data.new_pin, false /* expectError*/)
+ ).then(
+ // Clean up the test by disconnecting and changing the PIN back
+ this.disconnect_.bind(this)
+ ).then(
+ // The PIN must be restored regardless of success or failure.
+ this.changePIN_.bind(this, data.old_pin),
+ this.changePIN_.bind(this, data.old_pin)
+ ).then(
+ // On fulfilled.
+ browserTest.pass,
+ // On rejected.
+ browserTest.fail
+ );
+};
+
+browserTest.Update_PIN.prototype.changePIN_ = function(newPin) {
+ var AppMode = remoting.AppMode;
+ var HOST_RESTART_WAIT = 10000;
+
+ browserTest.clickOnControl('change-daemon-pin');
+
+ return browserTest.onUIMode(AppMode.HOST_SETUP_ASK_PIN).then(function() {
+ var onSetupDone = browserTest.onUIMode(AppMode.HOST_SETUP_DONE);
+ document.getElementById('daemon-pin-entry').value = newPin;
+ document.getElementById('daemon-pin-confirm').value = newPin;
+ browserTest.clickOnControl('daemon-pin-ok');
+ return onSetupDone;
+ }).then(function() {
+ browserTest.clickOnControl('host-config-done-dismiss');
+ // On Linux, we restart the host after changing the PIN, need to sleep
+ // for ten seconds before the host is ready for connection.
+ return base.Promise.sleep(HOST_RESTART_WAIT);
+ });
+};
+
+browserTest.Update_PIN.prototype.connect_ = function() {
+ browserTest.clickOnControl('this-host-connect');
+ return browserTest.onUIMode(remoting.AppMode.CLIENT_PIN_PROMPT);
+};
+
+browserTest.Update_PIN.prototype.disconnect_ = function() {
+ var AppMode = remoting.AppMode;
+
+ remoting.disconnect();
+
+ return browserTest.onUIMode(AppMode.CLIENT_SESSION_FINISHED_ME2ME)
+ .then(function() {
+ var onHome = browserTest.onUIMode(AppMode.HOME);
+ browserTest.clickOnControl('client-finished-me2me-button');
+ return onHome;
+ });
+};
+
+browserTest.Update_PIN.prototype.enterPIN_ = function(pin, expectError) {
+ // Wait for 500ms before hitting the PIN button. From experiment, sometimes
+ // the PIN prompt does not dismiss without the timeout.
+ var CONNECT_PIN_WAIT = 500;
+
+ document.getElementById('pin-entry').value = pin;
+
+ return base.Promise.sleep(CONNECT_PIN_WAIT).then(function() {
+ browserTest.clickOnControl('pin-connect-button');
+ }).then(function() {
+ if (expectError) {
+ return browserTest.expectMe2MeError(remoting.Error.INVALID_ACCESS_CODE);
+ } else {
+ return browserTest.expectMe2MeConnected();
+ }
+ });
+};
diff --git a/remoting/webapp/js_proto/dom_proto.js b/remoting/webapp/js_proto/dom_proto.js
index 64f330f..1e392cb 100644
--- a/remoting/webapp/js_proto/dom_proto.js
+++ b/remoting/webapp/js_proto/dom_proto.js
@@ -167,3 +167,46 @@ var MediaSource = function() {}
* @return {SourceBuffer}
*/
MediaSource.prototype.addSourceBuffer = function(format) {}
+
+/**
+ * @constructor
+ * @param {function(function(*), function(*)) : void} init
+ */
+var Promise = function (init) {};
+
+/**
+ * @param {function(*) : void} onFulfill
+ * @param {function(*) : void} onReject
+ * @return {Promise}
+ */
+Promise.prototype.then = function (onFulfill, onReject) {};
+
+/**
+ * @param {function(*) : void} onReject
+ * @return {Promise}
+ */
+Promise.prototype['catch'] = function (onReject) {};
+
+/**
+ * @param {Array.<Promise>} promises
+ * @return {Promise}
+ */
+Promise.prototype.race = function (promises) {}
+
+/**
+ * @param {Array.<Promise>} promises
+ * @return {Promise}
+ */
+Promise.prototype.all = function (promises) {};
+
+/**
+ * @param {*} reason
+ * @return {Promise}
+ */
+Promise.reject = function (reason) {};
+
+/**
+ * @param {*} value
+ * @return {Promise}
+ */
+Promise.resolve = function (value) {};