From 2aa4a82499d4becd2284cdb482213d541b8804dd Mon Sep 17 00:00:00 2001
From: Daniel Baumann
Date: Sun, 28 Apr 2024 16:29:10 +0200
Subject: Adding upstream version 86.0.1.
Signed-off-by: Daniel Baumann
---
widget/tests/.eslintrc.js | 5 +
widget/tests/TestChromeMargin.cpp | 130 +
widget/tests/browser/browser.ini | 2 +
.../tests/browser/browser_test_clipboardcache.js | 145 +
widget/tests/bug586713_window.xhtml | 50 +
widget/tests/chrome.ini | 107 +
widget/tests/empty_window.xhtml | 4 +
widget/tests/file_bug596600.html | 4 +
.../file_input_events_on_deactive_window.html | 5 +
widget/tests/file_secure_input.html | 1 +
widget/tests/gtest/TestTimeConverter.cpp | 265 +
widget/tests/gtest/TestTouchResampler.cpp | 941 ++
widget/tests/gtest/moz.build | 16 +
widget/tests/mochitest.ini | 18 +
widget/tests/moz.build | 125 +
widget/tests/native_menus_window.xhtml | 282 +
widget/tests/native_mouse_mac_window.xhtml | 770 ++
widget/tests/standalone_native_menu_window.xhtml | 332 +
widget/tests/system_font_changes.xhtml | 63 +
widget/tests/taskbar_previews.xhtml | 118 +
...AltGr_key_events_in_web_content_on_windows.html | 106 +
widget/tests/test_actionhint.html | 85 +
widget/tests/test_alwaysontop_focus.xhtml | 39 +
widget/tests/test_assign_event_data.html | 759 ++
widget/tests/test_autocapitalize.html | 65 +
widget/tests/test_bug1123480.xhtml | 147 +
widget/tests/test_bug343416.xhtml | 191 +
widget/tests/test_bug413277.html | 35 +
widget/tests/test_bug428405.xhtml | 167 +
widget/tests/test_bug429954.xhtml | 43 +
widget/tests/test_bug444800.xhtml | 98 +
widget/tests/test_bug466599.xhtml | 103 +
widget/tests/test_bug478536.xhtml | 33 +
widget/tests/test_bug485118.xhtml | 72 +
widget/tests/test_bug517396.xhtml | 54 +
widget/tests/test_bug522217.xhtml | 35 +
widget/tests/test_bug538242.xhtml | 55 +
widget/tests/test_bug565392.html | 64 +
widget/tests/test_bug586713.xhtml | 29 +
widget/tests/test_bug593307.xhtml | 40 +
widget/tests/test_bug596600.xhtml | 168 +
widget/tests/test_bug673301.xhtml | 35 +
widget/tests/test_bug760802.xhtml | 85 +
widget/tests/test_clipboard.xhtml | 72 +
.../tests/test_composition_text_querycontent.xhtml | 35 +
widget/tests/test_imestate.html | 1458 +++
.../test_input_events_on_deactive_window.xhtml | 235 +
widget/tests/test_key_event_counts.xhtml | 90 +
widget/tests/test_keycodes.xhtml | 5628 ++++++++++++
.../tests/test_keypress_event_with_alt_on_mac.html | 109 +
.../test_mouse_event_with_control_on_mac.html | 114 +
widget/tests/test_mouse_scroll.xhtml | 35 +
widget/tests/test_native_key_bindings_mac.html | 336 +
widget/tests/test_native_menus.xhtml | 29 +
widget/tests/test_native_mouse_mac.xhtml | 29 +
widget/tests/test_panel_mouse_coords.xhtml | 78 +
widget/tests/test_picker_no_crash.html | 36 +
widget/tests/test_platform_colors.xhtml | 106 +
widget/tests/test_plugin_scroll_consistency.html | 59 +
widget/tests/test_position_on_resize.xhtml | 90 +
widget/tests/test_scrollbar_colors.html | 120 +
widget/tests/test_secure_input.html | 141 +
widget/tests/test_sizemode_events.xhtml | 105 +
widget/tests/test_standalone_native_menu.xhtml | 29 +
widget/tests/test_system_font_changes.xhtml | 28 +
widget/tests/test_system_status_bar.xhtml | 53 +
widget/tests/test_taskbar_progress.xhtml | 119 +
widget/tests/test_transferable_overflow.xhtml | 152 +
widget/tests/test_wheeltransaction.xhtml | 27 +
widget/tests/unit/test_macsharingservice.js | 29 +
widget/tests/unit/test_macwebapputils.js | 34 +
widget/tests/unit/test_taskbar_jumplistitems.js | 328 +
widget/tests/unit/xpcshell.ini | 9 +
widget/tests/utils.js | 27 +
widget/tests/window_bug429954.xhtml | 44 +
widget/tests/window_bug478536.xhtml | 211 +
widget/tests/window_bug522217.xhtml | 80 +
widget/tests/window_bug538242.xhtml | 3 +
widget/tests/window_bug593307_centerscreen.xhtml | 26 +
widget/tests/window_bug593307_offscreen.xhtml | 33 +
.../window_composition_text_querycontent.xhtml | 9632 ++++++++++++++++++++
widget/tests/window_imestate_iframes.html | 360 +
widget/tests/window_mouse_scroll_win.html | 1518 +++
widget/tests/window_mouse_scroll_win_2.html | 6 +
widget/tests/window_picker_no_crash_child.html | 10 +
widget/tests/window_state_windows.xhtml | 82 +
widget/tests/window_wheeltransaction.xhtml | 1569 ++++
87 files changed, 29205 insertions(+)
create mode 100644 widget/tests/.eslintrc.js
create mode 100644 widget/tests/TestChromeMargin.cpp
create mode 100644 widget/tests/browser/browser.ini
create mode 100644 widget/tests/browser/browser_test_clipboardcache.js
create mode 100644 widget/tests/bug586713_window.xhtml
create mode 100644 widget/tests/chrome.ini
create mode 100644 widget/tests/empty_window.xhtml
create mode 100644 widget/tests/file_bug596600.html
create mode 100644 widget/tests/file_input_events_on_deactive_window.html
create mode 100644 widget/tests/file_secure_input.html
create mode 100644 widget/tests/gtest/TestTimeConverter.cpp
create mode 100644 widget/tests/gtest/TestTouchResampler.cpp
create mode 100644 widget/tests/gtest/moz.build
create mode 100644 widget/tests/mochitest.ini
create mode 100644 widget/tests/moz.build
create mode 100644 widget/tests/native_menus_window.xhtml
create mode 100644 widget/tests/native_mouse_mac_window.xhtml
create mode 100644 widget/tests/standalone_native_menu_window.xhtml
create mode 100644 widget/tests/system_font_changes.xhtml
create mode 100644 widget/tests/taskbar_previews.xhtml
create mode 100644 widget/tests/test_AltGr_key_events_in_web_content_on_windows.html
create mode 100644 widget/tests/test_actionhint.html
create mode 100644 widget/tests/test_alwaysontop_focus.xhtml
create mode 100644 widget/tests/test_assign_event_data.html
create mode 100644 widget/tests/test_autocapitalize.html
create mode 100644 widget/tests/test_bug1123480.xhtml
create mode 100644 widget/tests/test_bug343416.xhtml
create mode 100644 widget/tests/test_bug413277.html
create mode 100644 widget/tests/test_bug428405.xhtml
create mode 100644 widget/tests/test_bug429954.xhtml
create mode 100644 widget/tests/test_bug444800.xhtml
create mode 100644 widget/tests/test_bug466599.xhtml
create mode 100644 widget/tests/test_bug478536.xhtml
create mode 100644 widget/tests/test_bug485118.xhtml
create mode 100644 widget/tests/test_bug517396.xhtml
create mode 100644 widget/tests/test_bug522217.xhtml
create mode 100644 widget/tests/test_bug538242.xhtml
create mode 100644 widget/tests/test_bug565392.html
create mode 100644 widget/tests/test_bug586713.xhtml
create mode 100644 widget/tests/test_bug593307.xhtml
create mode 100644 widget/tests/test_bug596600.xhtml
create mode 100644 widget/tests/test_bug673301.xhtml
create mode 100644 widget/tests/test_bug760802.xhtml
create mode 100644 widget/tests/test_clipboard.xhtml
create mode 100644 widget/tests/test_composition_text_querycontent.xhtml
create mode 100644 widget/tests/test_imestate.html
create mode 100644 widget/tests/test_input_events_on_deactive_window.xhtml
create mode 100644 widget/tests/test_key_event_counts.xhtml
create mode 100644 widget/tests/test_keycodes.xhtml
create mode 100644 widget/tests/test_keypress_event_with_alt_on_mac.html
create mode 100644 widget/tests/test_mouse_event_with_control_on_mac.html
create mode 100644 widget/tests/test_mouse_scroll.xhtml
create mode 100644 widget/tests/test_native_key_bindings_mac.html
create mode 100644 widget/tests/test_native_menus.xhtml
create mode 100644 widget/tests/test_native_mouse_mac.xhtml
create mode 100644 widget/tests/test_panel_mouse_coords.xhtml
create mode 100644 widget/tests/test_picker_no_crash.html
create mode 100644 widget/tests/test_platform_colors.xhtml
create mode 100644 widget/tests/test_plugin_scroll_consistency.html
create mode 100644 widget/tests/test_position_on_resize.xhtml
create mode 100644 widget/tests/test_scrollbar_colors.html
create mode 100644 widget/tests/test_secure_input.html
create mode 100644 widget/tests/test_sizemode_events.xhtml
create mode 100644 widget/tests/test_standalone_native_menu.xhtml
create mode 100644 widget/tests/test_system_font_changes.xhtml
create mode 100644 widget/tests/test_system_status_bar.xhtml
create mode 100644 widget/tests/test_taskbar_progress.xhtml
create mode 100644 widget/tests/test_transferable_overflow.xhtml
create mode 100644 widget/tests/test_wheeltransaction.xhtml
create mode 100644 widget/tests/unit/test_macsharingservice.js
create mode 100644 widget/tests/unit/test_macwebapputils.js
create mode 100644 widget/tests/unit/test_taskbar_jumplistitems.js
create mode 100644 widget/tests/unit/xpcshell.ini
create mode 100644 widget/tests/utils.js
create mode 100644 widget/tests/window_bug429954.xhtml
create mode 100644 widget/tests/window_bug478536.xhtml
create mode 100644 widget/tests/window_bug522217.xhtml
create mode 100644 widget/tests/window_bug538242.xhtml
create mode 100644 widget/tests/window_bug593307_centerscreen.xhtml
create mode 100644 widget/tests/window_bug593307_offscreen.xhtml
create mode 100644 widget/tests/window_composition_text_querycontent.xhtml
create mode 100644 widget/tests/window_imestate_iframes.html
create mode 100644 widget/tests/window_mouse_scroll_win.html
create mode 100644 widget/tests/window_mouse_scroll_win_2.html
create mode 100644 widget/tests/window_picker_no_crash_child.html
create mode 100644 widget/tests/window_state_windows.xhtml
create mode 100644 widget/tests/window_wheeltransaction.xhtml
(limited to 'widget/tests')
diff --git a/widget/tests/.eslintrc.js b/widget/tests/.eslintrc.js
new file mode 100644
index 0000000000..19d9df957a
--- /dev/null
+++ b/widget/tests/.eslintrc.js
@@ -0,0 +1,5 @@
+"use strict";
+
+module.exports = {
+ extends: ["plugin:mozilla/chrome-test", "plugin:mozilla/mochitest-test"],
+};
diff --git a/widget/tests/TestChromeMargin.cpp b/widget/tests/TestChromeMargin.cpp
new file mode 100644
index 0000000000..0eed86b208
--- /dev/null
+++ b/widget/tests/TestChromeMargin.cpp
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* This tests the margin parsing functionality in nsAttrValue.cpp, which
+ * is accessible via nsContentUtils, and is used in setting chromemargins
+ * to widget windows. It's located here due to linking issues in the
+ * content directory.
+ */
+
+/* This test no longer compiles now that we've removed nsIContentUtils (bug
+ * 647273). We need to be internal code in order to include nsContentUtils.h,
+ * but defining MOZILLA_INTERNAL_API is not enough to make us internal.
+ */
+
+#include "TestHarness.h"
+
+#ifndef MOZILLA_INTERNAL_API
+# error This test needs MOZILLA_INTERNAL_API (see bug 652123)
+#endif
+
+#include "nscore.h"
+#include "nsContentUtils.h"
+#include "nsString.h"
+
+struct DATA {
+ bool shouldfail;
+ const char* margins;
+ int top;
+ int right;
+ int bottom;
+ int left;
+};
+
+const bool SHOULD_FAIL = true;
+const int SHOULD_PASS = false;
+
+const DATA Data[] = {
+ {SHOULD_FAIL, "", 1, 2, 3, 4},
+ {SHOULD_FAIL, "1,0,0,0", 1, 2, 3, 4},
+ {SHOULD_FAIL, "1,2,0,0", 1, 2, 3, 4},
+ {SHOULD_FAIL, "1,2,3,0", 1, 2, 3, 4},
+ {SHOULD_FAIL, "4,3,2,1", 1, 2, 3, 4},
+ {SHOULD_FAIL, "azsasdasd", 0, 0, 0, 0},
+ {SHOULD_FAIL, ",azsasdasd", 0, 0, 0, 0},
+ {SHOULD_FAIL, " ", 1, 2, 3, 4},
+ {SHOULD_FAIL,
+ "azsdfsdfsdfsdfsdfsasdasd,asdasdasdasdasdasd,asdadasdasd,asdasdasdasd", 0,
+ 0, 0, 0},
+ {SHOULD_FAIL, "as,as,as,as", 0, 0, 0, 0},
+ {SHOULD_FAIL, "0,0,0", 0, 0, 0, 0},
+ {SHOULD_FAIL, "0,0", 0, 0, 0, 0},
+ {SHOULD_FAIL, "4.6,1,1,1", 0, 0, 0, 0},
+ {SHOULD_FAIL, ",,,,", 0, 0, 0, 0},
+ {SHOULD_FAIL, "1, , , ,", 0, 0, 0, 0},
+ {SHOULD_FAIL, "1, , ,", 0, 0, 0, 0},
+ {SHOULD_FAIL, "@!@%^&^*()", 1, 2, 3, 4},
+ {SHOULD_PASS, "4,3,2,1", 4, 3, 2, 1},
+ {SHOULD_PASS, "-4,-3,-2,-1", -4, -3, -2, -1},
+ {SHOULD_PASS, "10000,3,2,1", 10000, 3, 2, 1},
+ {SHOULD_PASS, "4 , 3 , 2 , 1", 4, 3, 2, 1},
+ {SHOULD_PASS, "4, 3 ,2,1", 4, 3, 2, 1},
+ {SHOULD_FAIL, "4,3,2,10000000000000 --", 4, 3, 2, 10000000000000},
+ {SHOULD_PASS, "4,3,2,1000", 4, 3, 2, 1000},
+ {SHOULD_PASS, "2147483647,3,2,1000", 2147483647, 3, 2, 1000},
+ {SHOULD_PASS, "2147483647,2147483647,2147483647,2147483647", 2147483647,
+ 2147483647, 2147483647, 2147483647},
+ {SHOULD_PASS, "-2147483647,3,2,1000", -2147483647, 3, 2, 1000},
+ {SHOULD_FAIL, "2147483648,3,2,1000", 1, 3, 2, 1000},
+ {0, nullptr, 0, 0, 0, 0}};
+
+void DoAttrValueTest() {
+ int idx = -1;
+ bool didFail = false;
+ while (Data[++idx].margins) {
+ nsAutoString str;
+ str.AssignLiteral(Data[idx].margins);
+ nsIntMargin values(99, 99, 99, 99);
+ bool result = nsContentUtils::ParseIntMarginValue(str, values);
+
+ // if the parse fails
+ if (!result) {
+ if (Data[idx].shouldfail) continue;
+ fail(Data[idx].margins);
+ didFail = true;
+ printf("*1\n");
+ continue;
+ }
+
+ if (Data[idx].shouldfail) {
+ if (Data[idx].top == values.top && Data[idx].right == values.right &&
+ Data[idx].bottom == values.bottom && Data[idx].left == values.left) {
+ // not likely
+ fail(Data[idx].margins);
+ didFail = true;
+ printf("*2\n");
+ continue;
+ }
+ // good failure, parse failed and that's what we expected.
+ continue;
+ }
+#if 0
+ printf("%d==%d %d==%d %d==%d %d==%d\n",
+ Data[idx].top, values.top,
+ Data[idx].right, values.right,
+ Data[idx].bottom, values.bottom,
+ Data[idx].left, values.left);
+#endif
+ if (Data[idx].top == values.top && Data[idx].right == values.right &&
+ Data[idx].bottom == values.bottom && Data[idx].left == values.left) {
+ // good parse results
+ continue;
+ } else {
+ fail(Data[idx].margins);
+ didFail = true;
+ printf("*3\n");
+ continue;
+ }
+ }
+
+ if (!didFail) passed("nsAttrValue margin parsing tests passed.");
+}
+
+int main(int argc, char** argv) {
+ ScopedXPCOM xpcom("");
+ if (xpcom.failed()) return 1;
+ DoAttrValueTest();
+ return 0;
+}
diff --git a/widget/tests/browser/browser.ini b/widget/tests/browser/browser.ini
new file mode 100644
index 0000000000..a50eec47e7
--- /dev/null
+++ b/widget/tests/browser/browser.ini
@@ -0,0 +1,2 @@
+[browser_test_clipboardcache.js]
+skip-if = os == 'android' || (os == 'linux' && ccov) || tsan # Bug 1613516, the test consistently timeouts on Linux coverage builds.
diff --git a/widget/tests/browser/browser_test_clipboardcache.js b/widget/tests/browser/browser_test_clipboardcache.js
new file mode 100644
index 0000000000..8364d48507
--- /dev/null
+++ b/widget/tests/browser/browser_test_clipboardcache.js
@@ -0,0 +1,145 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+const { AppConstants } = ChromeUtils.import(
+ "resource://gre/modules/AppConstants.jsm"
+);
+
+// Note: widget/tests/test_bug1123480.xhtml checks whether nsTransferable behaves
+// as expected with regards to private browsing mode and the clipboard cache,
+// i.e. that the clipboard is not cached to the disk when private browsing mode
+// is enabled.
+//
+// This test tests that the clipboard is not cached to the disk by IPC,
+// as a regression test for bug 1396224.
+// It indirectly uses nsTransferable, via the async navigator.clipboard API.
+
+// Create over 1 MB of sample garbage text. JavaScript strings are represented
+// by UTF16 strings, so the size is twice as much as the actual string length.
+// This value is chosen such that the size of the memory for the string exceeds
+// the kLargeDatasetSize threshold in nsTransferable.h.
+// It is also not a round number to reduce the odds of having an accidental
+// collisions with another file (since the test below looks at the file size
+// to identify the file).
+var Ipsum = "0123456789".repeat(1234321);
+var IpsumByteLength = Ipsum.length * 2;
+var SHORT_STRING_NO_CACHE = "short string that will not be cached to the disk";
+
+// Get a list of open file descriptors that refer to a file with the same size
+// as the expected data (and assume that any mutations in file descriptor counts
+// are caused by our test).
+// TODO: This logic only counts file descriptors that are still open (e.g. when
+// data persists after a copy). It does not detect cache files that exist only
+// temporarily (e.g. after a paste).
+function getClipboardCacheFDCount() {
+ let dir;
+ if (AppConstants.platform === "win") {
+ // On Windows, nsAnonymousTemporaryFile does not immediately delete a file.
+ // Instead, the Windows-specific FILE_FLAG_DELETE_ON_CLOSE flag is used,
+ // which means that the file is deleted when the last handle is closed.
+ // Apparently, this flag is unreliable (e.g. when the application crashes),
+ // so nsAnonymousTemporaryFile stores the temporary files in a subdirectory,
+ // which is cleaned up some time after start-up.
+
+ // This is just a test, and during the test we deterministically close the
+ // handles, so if FILE_FLAG_DELETE_ON_CLOSE does the thing it promises, the
+ // file is actually removed when the handle is closed.
+
+ let { FileUtils } = ChromeUtils.import(
+ "resource://gre/modules/FileUtils.jsm"
+ );
+ // Path from nsAnonymousTemporaryFile.cpp, GetTempDir.
+ dir = FileUtils.getFile("TmpD", ["mozilla-temp-files"]);
+ } else {
+ dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
+ dir.initWithPath("/dev/fd");
+ }
+ let count = 0;
+ for (let fdFile of dir.directoryEntries) {
+ let fileSize;
+ try {
+ fileSize = fdFile.fileSize;
+ } catch (e) {
+ // This can happen on macOS.
+ continue;
+ }
+ if (fileSize === IpsumByteLength) {
+ // Assume that the file was created by us if the size matches.
+ ++count;
+ }
+ }
+ return count;
+}
+
+async function testCopyPaste(isPrivate) {
+ let win = await BrowserTestUtils.openNewBrowserWindow({ private: isPrivate });
+ let tab = await BrowserTestUtils.openNewForegroundTab(win);
+ let browser = tab.linkedBrowser;
+
+ // Sanitize environment
+ await ContentTask.spawn(browser, SHORT_STRING_NO_CACHE, async shortStr => {
+ await content.navigator.clipboard.writeText(shortStr);
+ });
+
+ let initialFdCount = getClipboardCacheFDCount();
+
+ await SpecialPowers.spawn(browser, [Ipsum], async largeString => {
+ await content.navigator.clipboard.writeText(largeString);
+ });
+
+ let fdCountAfterCopy = getClipboardCacheFDCount();
+ if (isPrivate) {
+ is(fdCountAfterCopy, initialFdCount, "Private write");
+ } else {
+ is(fdCountAfterCopy, initialFdCount + 1, "Cached write");
+ }
+
+ let readStr = await SpecialPowers.spawn(browser, [], async () => {
+ let { document } = content;
+ document.body.contentEditable = true;
+ document.body.focus();
+ let pastePromise = new Promise(resolve => {
+ document.addEventListener(
+ "paste",
+ e => {
+ resolve(e.clipboardData.getData("text/plain"));
+ },
+ { once: true }
+ );
+ });
+ document.execCommand("paste");
+ return pastePromise;
+ });
+ ok(readStr === Ipsum, "Read what we pasted");
+
+ if (isPrivate) {
+ is(getClipboardCacheFDCount(), fdCountAfterCopy, "Private read");
+ } else {
+ // Upon reading from the clipboard, a temporary nsTransferable is used, for
+ // which the cache is disabled. The content process does not cache clipboard
+ // data either. So the file descriptor count should be identical.
+ is(getClipboardCacheFDCount(), fdCountAfterCopy, "Read not cached");
+ }
+
+ // Cleanup.
+ await SpecialPowers.spawn(
+ browser,
+ [SHORT_STRING_NO_CACHE],
+ async shortStr => {
+ await content.navigator.clipboard.writeText(shortStr);
+ }
+ );
+ is(getClipboardCacheFDCount(), initialFdCount, "Drop clipboard cache if any");
+
+ BrowserTestUtils.removeTab(tab);
+ await BrowserTestUtils.closeWindow(win);
+}
+
+add_task(async function test_private() {
+ await testCopyPaste(true);
+});
+
+add_task(async function test_non_private() {
+ await testCopyPaste(false);
+});
diff --git a/widget/tests/bug586713_window.xhtml b/widget/tests/bug586713_window.xhtml
new file mode 100644
index 0000000000..c180c00235
--- /dev/null
+++ b/widget/tests/bug586713_window.xhtml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/chrome.ini b/widget/tests/chrome.ini
new file mode 100644
index 0000000000..aa700b25d2
--- /dev/null
+++ b/widget/tests/chrome.ini
@@ -0,0 +1,107 @@
+[DEFAULT]
+prefs =
+ plugin.load_flash_only=false
+skip-if = os == 'android'
+support-files =
+ empty_window.xhtml
+ utils.js
+
+[test_alwaysontop_focus.xhtml]
+[test_bug343416.xhtml]
+skip-if = debug
+[test_bug429954.xhtml]
+support-files = window_bug429954.xhtml
+[test_bug444800.xhtml]
+[test_bug478536.xhtml]
+skip-if = true # Bug 561929
+support-files = window_bug478536.xhtml
+[test_bug517396.xhtml]
+skip-if = (verify && (os == 'win'))
+[test_bug538242.xhtml]
+support-files = window_bug538242.xhtml
+[test_bug565392.html]
+skip-if = toolkit != "windows"
+[test_bug593307.xhtml]
+support-files = window_bug593307_offscreen.xhtml window_bug593307_centerscreen.xhtml
+[test_keycodes.xhtml]
+[test_wheeltransaction.xhtml]
+support-files = window_wheeltransaction.xhtml
+[test_imestate.html]
+support-files = window_imestate_iframes.html
+[test_composition_text_querycontent.xhtml]
+support-files = window_composition_text_querycontent.xhtml
+[test_input_events_on_deactive_window.xhtml]
+support-files = file_input_events_on_deactive_window.html
+[test_position_on_resize.xhtml]
+skip-if =
+ verify && (os == 'win')
+ webrender && (os == "linux" && bits == 64) # Bug 1616760
+[test_sizemode_events.xhtml]
+[test_taskbar_progress.xhtml]
+skip-if = toolkit != "cocoa" && toolkit != "windows" || (os == "win" && os_version == "10.0" && !ccov) # Bug 1456811
+[test_bug760802.xhtml]
+[test_clipboard.xhtml]
+[test_panel_mouse_coords.xhtml]
+skip-if = toolkit == "windows" # bug 1009955
+
+# Cocoa
+[test_native_menus.xhtml]
+skip-if = toolkit != "cocoa"
+support-files = native_menus_window.xhtml
+[test_native_mouse_mac.xhtml]
+skip-if = toolkit != "cocoa" || os_version == '10.14' # macosx1014: bug 1137575
+support-files = native_mouse_mac_window.xhtml
+[test_bug413277.html]
+skip-if = toolkit != "cocoa"
+[test_bug428405.xhtml]
+skip-if = toolkit != "cocoa"
+[test_bug466599.xhtml]
+skip-if = toolkit != "cocoa"
+[test_bug485118.xhtml]
+skip-if = toolkit != "cocoa"
+[test_bug522217.xhtml]
+tags = fullscreen
+skip-if = toolkit != "cocoa"
+support-files = window_bug522217.xhtml
+[test_platform_colors.xhtml]
+#skip-if = toolkit != "cocoa"
+skip-if = true # Bug 1207190
+[test_standalone_native_menu.xhtml]
+skip-if = toolkit != "cocoa"
+support-files = standalone_native_menu_window.xhtml
+[test_bug586713.xhtml]
+skip-if = toolkit != "cocoa"
+support-files = bug586713_window.xhtml
+[test_key_event_counts.xhtml]
+skip-if = toolkit != "cocoa"
+[test_bug596600.xhtml]
+support-files = file_bug596600.html
+skip-if = toolkit != "cocoa" || !debug # Bug 1661132 (disable on opt)
+[test_bug673301.xhtml]
+skip-if = toolkit != "cocoa"
+[test_secure_input.html]
+support-files = file_secure_input.html
+skip-if = toolkit != "cocoa"
+[test_native_key_bindings_mac.html]
+skip-if = toolkit != "cocoa" || verify
+[test_system_status_bar.xhtml]
+skip-if = toolkit != "cocoa"
+
+[test_system_font_changes.xhtml]
+support-files = system_font_changes.xhtml
+run-if = toolkit == 'gtk' # Currently the test works on only gtk3
+
+# Windows
+# taskbar_previews.xhtml
+# window_state_windows.xhtml
+[test_mouse_scroll.xhtml]
+skip-if = toolkit != "windows"
+support-files =
+ window_mouse_scroll_win.html
+ window_mouse_scroll_win_2.html
+
+# Privacy relevant
+[test_bug1123480.xhtml]
+[test_transferable_overflow.xhtml]
+skip-if = (verify && (os == 'mac' || os == 'linux'))
+
diff --git a/widget/tests/empty_window.xhtml b/widget/tests/empty_window.xhtml
new file mode 100644
index 0000000000..f0e01761d2
--- /dev/null
+++ b/widget/tests/empty_window.xhtml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/widget/tests/file_bug596600.html b/widget/tests/file_bug596600.html
new file mode 100644
index 0000000000..1b178a6b68
--- /dev/null
+++ b/widget/tests/file_bug596600.html
@@ -0,0 +1,4 @@
+
+
+Content page
+
diff --git a/widget/tests/file_input_events_on_deactive_window.html b/widget/tests/file_input_events_on_deactive_window.html
new file mode 100644
index 0000000000..e733adbb9d
--- /dev/null
+++ b/widget/tests/file_input_events_on_deactive_window.html
@@ -0,0 +1,5 @@
+
+
+ this is an active window.
+
+
diff --git a/widget/tests/file_secure_input.html b/widget/tests/file_secure_input.html
new file mode 100644
index 0000000000..28fec7b44b
--- /dev/null
+++ b/widget/tests/file_secure_input.html
@@ -0,0 +1 @@
+
diff --git a/widget/tests/gtest/TestTimeConverter.cpp b/widget/tests/gtest/TestTimeConverter.cpp
new file mode 100644
index 0000000000..22cbc3f9e6
--- /dev/null
+++ b/widget/tests/gtest/TestTimeConverter.cpp
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "gtest/gtest.h"
+#include "mozilla/TimeStamp.h"
+#include "SystemTimeConverter.h"
+
+using mozilla::SystemTimeConverter;
+using mozilla::TimeDuration;
+using mozilla::TimeStamp;
+
+namespace {
+
+// This class provides a mock implementation of the CurrentTimeGetter template
+// type used in SystemTimeConverter. It can be constructed with a particular
+// Time and always returns that Time.
+template
+class MockCurrentTimeGetter {
+ public:
+ MockCurrentTimeGetter() : mTime(0) {}
+ explicit MockCurrentTimeGetter(Time aTime) : mTime(aTime) {}
+
+ // Methods needed for CurrentTimeGetter compatibility
+ Time GetCurrentTime() const { return mTime; }
+ void GetTimeAsyncForPossibleBackwardsSkew(const TimeStamp& aNow) {}
+
+ private:
+ Time mTime;
+};
+
+// This is another mock implementation of the CurrentTimeGetter template
+// type used in SystemTimeConverter, except this asserts that it will not be
+// used. i.e. it should only be used in calls to SystemTimeConverter that we
+// know will not invoke it.
+template
+class UnusedCurrentTimeGetter {
+ public:
+ Time GetCurrentTime() const {
+ EXPECT_TRUE(false);
+ return 0;
+ }
+
+ void GetTimeAsyncForPossibleBackwardsSkew(const TimeStamp& aNow) {
+ EXPECT_TRUE(false);
+ }
+};
+
+// This class provides a mock implementation of the TimeStampNowProvider
+// template type used in SystemTimeConverter. It also has other things in it
+// that allow the test to better control time for testing purposes.
+class MockTimeStamp {
+ public:
+ // This should generally be called at the start of every test function, as
+ // it will initialize this class's static fields to sane values. In particular
+ // it will initialize the baseline TimeStamp against which all other
+ // TimeStamps are compared.
+ static void Init() {
+ sBaseline = TimeStamp::Now();
+ sTimeStamp = sBaseline;
+ }
+
+ // Advance the timestamp returned by `MockTimeStamp::Now()`
+ static void Advance(double ms) {
+ sTimeStamp += TimeDuration::FromMilliseconds(ms);
+ }
+
+ // Returns the baseline TimeStamp, that is used as a fixed reference point
+ // in time against which other TimeStamps can be compared. This is needed
+ // because mozilla::TimeStamp itself doesn't provide any conversion to
+ // human-readable strings, and we need to convert it to a TimeDuration in
+ // order to get that. This baseline TimeStamp can be used to turn an
+ // arbitrary TimeStamp into a TimeDuration.
+ static TimeStamp Baseline() { return sBaseline; }
+
+ // This is the method needed for TimeStampNowProvider compatibility, and
+ // simulates `TimeStamp::Now()`
+ static TimeStamp Now() { return sTimeStamp; }
+
+ private:
+ static TimeStamp sTimeStamp;
+ static TimeStamp sBaseline;
+};
+
+TimeStamp MockTimeStamp::sTimeStamp;
+TimeStamp MockTimeStamp::sBaseline;
+
+// Could have platform-specific implementations of this using DWORD, guint32,
+// etc behind ifdefs. But this is sufficient for now.
+using GTestTime = uint32_t;
+using TimeConverter = SystemTimeConverter;
+
+} // namespace
+
+// Checks the expectation that the TimeStamp `ts` is exactly `ms` milliseconds
+// after the baseline timestamp. This is a macro so gtest still gives us useful
+// line numbers for failures.
+#define EXPECT_TS(ts, ms) \
+ EXPECT_EQ((ts)-MockTimeStamp::Baseline(), TimeDuration::FromMilliseconds(ms))
+
+#define EXPECT_TS_FUZZY(ts, ms) \
+ EXPECT_DOUBLE_EQ(((ts)-MockTimeStamp::Baseline()).ToMilliseconds(), ms)
+
+TEST(TimeConverter, SanityCheck)
+{
+ MockTimeStamp::Init();
+
+ MockCurrentTimeGetter timeGetter(10);
+ UnusedCurrentTimeGetter unused;
+ TimeConverter converter;
+
+ // This call sets the reference time and timestamp
+ TimeStamp ts = converter.GetTimeStampFromSystemTime(10, timeGetter);
+ EXPECT_TS(ts, 0);
+
+ // Advance "TimeStamp::Now" by 10ms, use the same event time and OS time.
+ // Since the event time is the same as before, we expect to get back the
+ // same TimeStamp as before too, despite Now() changing.
+ MockTimeStamp::Advance(10);
+ ts = converter.GetTimeStampFromSystemTime(10, unused);
+ EXPECT_TS(ts, 0);
+
+ // Now let's use an event time 20ms after the old event. This will trigger
+ // forward skew detection and resync the TimeStamp for the new event to Now().
+ ts = converter.GetTimeStampFromSystemTime(30, unused);
+ EXPECT_TS(ts, 10);
+}
+
+TEST(TimeConverter, Overflow)
+{
+ // This tests wrapping time around the max value supported in the GTestTime
+ // type and ensuring it is handled properly.
+
+ MockTimeStamp::Init();
+
+ const GTestTime max = std::numeric_limits::max();
+ const GTestTime min = std::numeric_limits::min();
+ double fullRange = (double)max - (double)min;
+ double wrapPeriod = fullRange + 1.0;
+
+ GTestTime almostOverflowed = max - 100;
+ GTestTime overflowed = max + 100;
+ MockCurrentTimeGetter timeGetter(almostOverflowed);
+ UnusedCurrentTimeGetter unused;
+ TimeConverter converter;
+
+ // Set reference time to 100ms before the overflow point
+ TimeStamp ts =
+ converter.GetTimeStampFromSystemTime(almostOverflowed, timeGetter);
+ EXPECT_TS(ts, 0);
+
+ // Advance everything by 200ms and verify we get back a TimeStamp 200ms from
+ // the baseline despite wrapping an overflow.
+ MockTimeStamp::Advance(200);
+ ts = converter.GetTimeStampFromSystemTime(overflowed, unused);
+ EXPECT_TS(ts, 200);
+
+ // Advance by another full wraparound of the time. This loses some precision
+ // so we have to do the FUZZY match
+ MockTimeStamp::Advance(wrapPeriod);
+ ts = converter.GetTimeStampFromSystemTime(overflowed, unused);
+ EXPECT_TS_FUZZY(ts, 200.0 + wrapPeriod);
+}
+
+TEST(TimeConverter, InvertedOverflow)
+{
+ // This tests time going from near the min value of GTestTime to the max
+ // value of GTestTime
+
+ MockTimeStamp::Init();
+
+ const GTestTime max = std::numeric_limits::max();
+ const GTestTime min = std::numeric_limits::min();
+ double fullRange = (double)max - (double)min;
+ double wrapPeriod = fullRange + 1.0;
+
+ GTestTime nearRangeMin = min + 100;
+ GTestTime nearRangeMax = max - 100;
+ double gap = (double)nearRangeMax - (double)nearRangeMin;
+
+ MockCurrentTimeGetter timeGetter(nearRangeMin);
+ UnusedCurrentTimeGetter unused;
+ TimeConverter converter;
+
+ // Set reference time to value near min numeric limit
+ TimeStamp ts = converter.GetTimeStampFromSystemTime(nearRangeMin, timeGetter);
+ EXPECT_TS(ts, 0);
+
+ // Advance to value near max numeric limit
+ MockTimeStamp::Advance(gap);
+ ts = converter.GetTimeStampFromSystemTime(nearRangeMax, unused);
+ EXPECT_TS(ts, gap);
+
+ // Advance by another full wraparound of the time. This loses some precision
+ // so we have to do the FUZZY match
+ MockTimeStamp::Advance(wrapPeriod);
+ ts = converter.GetTimeStampFromSystemTime(nearRangeMax, unused);
+ EXPECT_TS_FUZZY(ts, gap + wrapPeriod);
+}
+
+TEST(TimeConverter, HalfRangeBoundary)
+{
+ MockTimeStamp::Init();
+
+ GTestTime max = std::numeric_limits::max();
+ GTestTime min = std::numeric_limits::min();
+ double fullRange = (double)max - (double)min;
+ double wrapPeriod = fullRange + 1.0;
+ GTestTime halfRange = (GTestTime)(fullRange / 2.0);
+ GTestTime halfWrapPeriod = (GTestTime)(wrapPeriod / 2.0);
+
+ TimeConverter converter;
+
+ GTestTime firstEvent = 10;
+ MockCurrentTimeGetter timeGetter(firstEvent);
+ UnusedCurrentTimeGetter unused;
+
+ // Set reference time
+ TimeStamp ts = converter.GetTimeStampFromSystemTime(firstEvent, timeGetter);
+ EXPECT_TS(ts, 0);
+
+ // Advance event time by just under the half-period, to trigger about as big
+ // a forwards skew as we possibly can.
+ GTestTime secondEvent = firstEvent + (halfWrapPeriod - 1);
+ ts = converter.GetTimeStampFromSystemTime(secondEvent, unused);
+ EXPECT_TS(ts, 0);
+
+ // The above forwards skew will have reset the reference timestamp. Now
+ // advance Now time by just under the half-range, to trigger about as big
+ // a backwards skew as we possibly can.
+ MockTimeStamp::Advance(halfRange - 1);
+ ts = converter.GetTimeStampFromSystemTime(secondEvent, unused);
+ EXPECT_TS(ts, 0);
+}
+
+TEST(TimeConverter, FractionalMillisBug1626734)
+{
+ MockTimeStamp::Init();
+
+ TimeConverter converter;
+
+ GTestTime eventTime = 10;
+ MockCurrentTimeGetter timeGetter(eventTime);
+ UnusedCurrentTimeGetter unused;
+
+ TimeStamp ts = converter.GetTimeStampFromSystemTime(eventTime, timeGetter);
+ EXPECT_TS(ts, 0);
+
+ MockTimeStamp::Advance(0.2);
+ ts = converter.GetTimeStampFromSystemTime(eventTime, unused);
+ EXPECT_TS(ts, 0);
+
+ MockTimeStamp::Advance(0.9);
+ TimeStamp ts2 = converter.GetTimeStampFromSystemTime(eventTime, unused);
+ EXPECT_TS(ts2, 0);
+
+ // Since ts2 came from a "future" call relative to ts, we expect ts2 to not
+ // be "before" ts. (i.e. time shouldn't go backwards, even by fractional
+ // milliseconds). This assertion is technically already implied by the
+ // EXPECT_TS checks above, but fixing this assertion is the end result that
+ // we wanted in bug 1626734 so it feels appropriate to recheck it explicitly.
+ EXPECT_TRUE(ts <= ts2);
+}
diff --git a/widget/tests/gtest/TestTouchResampler.cpp b/widget/tests/gtest/TestTouchResampler.cpp
new file mode 100644
index 0000000000..1a5b8e2430
--- /dev/null
+++ b/widget/tests/gtest/TestTouchResampler.cpp
@@ -0,0 +1,941 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include
+#include "InputData.h"
+#include "Units.h"
+#include "gtest/gtest.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/TimeStamp.h"
+#include "TouchResampler.h"
+
+using namespace mozilla;
+using widget::TouchResampler;
+
+class TouchResamplerTest : public ::testing::Test {
+ protected:
+ virtual void SetUp() { baseTimeStamp = TimeStamp::Now(); }
+
+ TimeStamp Time(double aMilliseconds) {
+ return baseTimeStamp + TimeDuration::FromMilliseconds(aMilliseconds);
+ }
+
+ uint64_t ProcessEvent(
+ MultiTouchInput::MultiTouchType aType,
+ std::initializer_list>
+ aHistoricalData,
+ const TimeStamp& aTimeStamp, const ScreenIntPoint& aPosition) {
+ MultiTouchInput input(aType, 0, aTimeStamp, 0);
+ input.mTouches.AppendElement(SingleTouchData(1, aPosition, {}, 0.0f, 0.0f));
+ for (const auto& histData : aHistoricalData) {
+ input.mTouches[0].mHistoricalData.AppendElement(
+ SingleTouchData::HistoricalTouchData{
+ histData.first, histData.second, {}, {}, 0.0f, 0.0f});
+ }
+ return resampler.ProcessEvent(std::move(input));
+ }
+
+ void CheckTime(const TimeStamp& aTimeStamp,
+ const TimeStamp& aExpectedTimeStamp) {
+ EXPECT_EQ((aTimeStamp - baseTimeStamp).ToMilliseconds(),
+ (aExpectedTimeStamp - baseTimeStamp).ToMilliseconds());
+ }
+
+ void CheckEvent(const MultiTouchInput& aEvent,
+ MultiTouchInput::MultiTouchType aExpectedType,
+ std::initializer_list>
+ aExpectedHistoricalData,
+ const TimeStamp& aExpectedTimeStamp,
+ const ScreenIntPoint& aExpectedPosition) {
+ EXPECT_EQ(aEvent.mType, aExpectedType);
+ EXPECT_EQ(aEvent.mTouches.Length(), size_t(1));
+ EXPECT_EQ(aEvent.mTouches[0].mHistoricalData.Length(),
+ aExpectedHistoricalData.size());
+ for (size_t i = 0; i < aExpectedHistoricalData.size(); i++) {
+ CheckTime(aEvent.mTouches[0].mHistoricalData[i].mTimeStamp,
+ aExpectedHistoricalData.begin()[i].first);
+ EXPECT_EQ(aEvent.mTouches[0].mHistoricalData[i].mScreenPoint,
+ aExpectedHistoricalData.begin()[i].second);
+ }
+ CheckTime(aEvent.mTimeStamp, aExpectedTimeStamp);
+ EXPECT_EQ(aEvent.mTouches[0].mScreenPoint, aExpectedPosition);
+ }
+
+ struct ExpectedOutgoingEvent {
+ Maybe mEventId;
+ MultiTouchInput::MultiTouchType mType = MultiTouchInput::MULTITOUCH_START;
+ std::initializer_list> mHistoricalData;
+ TimeStamp mTimeStamp;
+ ScreenIntPoint mPosition;
+ };
+
+ void CheckOutgoingEvents(
+ std::initializer_list aExpectedEvents) {
+ auto outgoing = resampler.ConsumeOutgoingEvents();
+ EXPECT_EQ(outgoing.size(), aExpectedEvents.size());
+ for (const auto& expectedEvent : aExpectedEvents) {
+ auto outgoingEvent = std::move(outgoing.front());
+ outgoing.pop();
+
+ EXPECT_EQ(outgoingEvent.mEventId, expectedEvent.mEventId);
+ CheckEvent(outgoingEvent.mEvent, expectedEvent.mType,
+ expectedEvent.mHistoricalData, expectedEvent.mTimeStamp,
+ expectedEvent.mPosition);
+ }
+ }
+
+ TimeStamp baseTimeStamp;
+ TouchResampler resampler;
+};
+
+TEST_F(TouchResamplerTest, BasicExtrapolation) {
+ // Execute the following sequence:
+ //
+ // 0----------10-------16-----20---------------32------------
+ // * touchstart at (10, 10)
+ // * touchmove at (20, 20)
+ // * frame
+ // * touchend at (20, 20)
+ // * frame
+ //
+ // And expect the following output:
+ //
+ // 0----------10-------16-----20---------------32------------
+ // * touchstart at (10, 10)
+ // * touchmove at (26, 26)
+ // * touchmove at (20, 20)
+ // * touchend at (20, 20)
+ //
+ // The first frame should emit an extrapolated touchmove from the position
+ // data in the touchstart and touchmove events.
+ // The touchend should force a synthesized touchmove that returns back to a
+ // non-resampled position.
+
+ EXPECT_FALSE(resampler.InTouchingState());
+
+ auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
+ ScreenIntPoint(10, 10));
+ EXPECT_TRUE(resampler.InTouchingState());
+ auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(10.0),
+ ScreenIntPoint(20, 20));
+
+ resampler.NotifyFrame(Time(16.0));
+
+ CheckOutgoingEvents({
+ {Some(idStart0),
+ MultiTouchInput::MULTITOUCH_START,
+ {},
+ Time(0.0),
+ ScreenIntPoint(10, 10)},
+
+ {Some(idMove1),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(20, 20)}},
+ Time(16.0),
+ ScreenIntPoint(26, 26)},
+ });
+
+ auto idEnd2 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(20.0),
+ ScreenIntPoint(20, 20));
+
+ EXPECT_FALSE(resampler.InTouchingState());
+
+ CheckOutgoingEvents({
+ {Nothing(),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {},
+ Time(16.0),
+ ScreenIntPoint(20, 20)},
+
+ {Some(idEnd2),
+ MultiTouchInput::MULTITOUCH_END,
+ {},
+ Time(20.0),
+ ScreenIntPoint(20, 20)},
+ });
+
+ // No more events should be produced from here on out.
+ resampler.NotifyFrame(Time(32.0));
+ auto outgoing = resampler.ConsumeOutgoingEvents();
+ EXPECT_TRUE(outgoing.empty());
+}
+
+TEST_F(TouchResamplerTest, BasicInterpolation) {
+ // Same test as BasicExtrapolation, but with a frame time that's 10ms earlier.
+ //
+ // Execute the following sequence:
+ //
+ // 0------6---10-----------20--22------------30-------------
+ // * touchstart at (10, 10)
+ // * touchmove at (20, 20)
+ // * frame
+ // * touchend at (20, 20)
+ // * frame
+ //
+ // And expect the following output:
+ //
+ // 0------6---10-----------20--22------------30-------------
+ // * touchstart at (10, 10)
+ // * touchmove (16, 16)
+ // * touchmove (20, 20)
+ // * touchend at (20, 20)
+ //
+ // The first frame should emit an interpolated touchmove from the position
+ // data in the touchstart and touchmove events.
+ // The touchend should create a touchmove that returns back to a non-resampled
+ // position.
+
+ auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
+ ScreenIntPoint(10, 10));
+ EXPECT_TRUE(resampler.InTouchingState());
+ auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(10.0),
+ ScreenIntPoint(20, 20));
+
+ resampler.NotifyFrame(Time(6.0));
+
+ CheckOutgoingEvents({
+ {Some(idStart0),
+ MultiTouchInput::MULTITOUCH_START,
+ {},
+ Time(0.0),
+ ScreenIntPoint(10, 10)},
+
+ {Some(idMove1),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {},
+ Time(6.0),
+ ScreenIntPoint(16, 16)},
+ });
+
+ auto idEnd2 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(20.0),
+ ScreenIntPoint(20, 20));
+ EXPECT_FALSE(resampler.InTouchingState());
+
+ CheckOutgoingEvents({
+ {Nothing(),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {},
+ Time(10.0),
+ ScreenIntPoint(20, 20)},
+
+ {Some(idEnd2),
+ MultiTouchInput::MULTITOUCH_END,
+ {},
+ Time(20.0),
+ ScreenIntPoint(20, 20)},
+ });
+
+ // No more events should be produced from here on out.
+ resampler.NotifyFrame(Time(22.0));
+ auto outgoing = resampler.ConsumeOutgoingEvents();
+ EXPECT_TRUE(outgoing.empty());
+}
+
+TEST_F(TouchResamplerTest, InterpolationFromHistoricalData) {
+ // Interpolate from the historical data in a touch move event.
+ //
+ // Execute the following sequence:
+ //
+ // 0----------10-------16-----20-----------30--32------------
+ // * touchstart at (10, 10)
+ // * [hist] at (20, 25) for
+ // `---------------* touchmove at (30, 30)
+ // * frame
+ // * touchend at (30, 30)
+ // * frame
+ //
+ // And expect the following output:
+ //
+ // 0----------10-------16-----20-----------30--32------------
+ // * touchstart at (10, 10)
+ // * [hist] at (20, 25) for
+ // `--------* touchmove at (26, 28)
+ // * touchmove at (30, 30)
+ // * touchend at (30, 30)
+ //
+ // The first frame should emit an interpolated touchmove from the position
+ // data in the touchmove event, and integrate the historical data point into
+ // the resampled event.
+ // The touchend should force a synthesized touchmove that returns back to a
+ // non-resampled position.
+
+ // This also tests that interpolation works for both x and y, by giving the
+ // historical datapoint different values for x and y.
+ // (26, 28) is 60% of the way from (20, 25) to (30, 30).
+
+ auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
+ ScreenIntPoint(10, 10));
+ auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(20, 25)}},
+ Time(20.0), ScreenIntPoint(30, 30));
+ resampler.NotifyFrame(Time(16.0));
+ auto idEnd2 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(30.0),
+ ScreenIntPoint(30, 30));
+ resampler.NotifyFrame(Time(32.0));
+
+ CheckOutgoingEvents({
+ {Some(idStart0),
+ MultiTouchInput::MULTITOUCH_START,
+ {},
+ Time(0.0),
+ ScreenIntPoint(10, 10)},
+
+ {Some(idMove1),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(20, 25)}},
+ Time(16.0),
+ ScreenIntPoint(26, 28)},
+
+ {Nothing(),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {},
+ Time(20.0),
+ ScreenIntPoint(30, 30)},
+
+ {Some(idEnd2),
+ MultiTouchInput::MULTITOUCH_END,
+ {},
+ Time(30.0),
+ ScreenIntPoint(30, 30)},
+ });
+}
+
+TEST_F(TouchResamplerTest, MultipleTouches) {
+ EXPECT_FALSE(resampler.InTouchingState());
+
+ // Touch start
+ MultiTouchInput inputStart0(MultiTouchInput::MULTITOUCH_START, 0, Time(0.0),
+ 0);
+ inputStart0.mTouches.AppendElement(
+ SingleTouchData(1, ScreenIntPoint(10, 10), {}, 0.0f, 0.0f));
+ auto idStart0 = resampler.ProcessEvent(std::move(inputStart0));
+ EXPECT_TRUE(resampler.InTouchingState());
+
+ // Touch move
+ MultiTouchInput inputMove1(MultiTouchInput::MULTITOUCH_MOVE, 0, Time(20.0),
+ 0);
+ inputMove1.mTouches.AppendElement(
+ SingleTouchData(1, ScreenIntPoint(30, 30), {}, 0.0f, 0.0f));
+ inputMove1.mTouches[0].mHistoricalData.AppendElement(
+ SingleTouchData::HistoricalTouchData{
+ Time(10.0), ScreenIntPoint(20, 25), {}, {}, 0.0f, 0.0f});
+ auto idMove1 = resampler.ProcessEvent(std::move(inputMove1));
+ EXPECT_TRUE(resampler.InTouchingState());
+
+ // Frame
+ resampler.NotifyFrame(Time(16.0));
+
+ // Touch move
+ MultiTouchInput inputMove2(MultiTouchInput::MULTITOUCH_MOVE, 0, Time(30.0),
+ 0);
+ inputMove2.mTouches.AppendElement(
+ SingleTouchData(1, ScreenIntPoint(30, 40), {}, 0.0f, 0.0f));
+ auto idMove2 = resampler.ProcessEvent(std::move(inputMove2));
+ EXPECT_TRUE(resampler.InTouchingState());
+
+ // Touch start
+ MultiTouchInput inputStart3(MultiTouchInput::MULTITOUCH_START, 0, Time(30.0),
+ 0);
+ inputStart3.mTouches.AppendElement(
+ SingleTouchData(2, ScreenIntPoint(100, 10), {}, 0.0f, 0.0f));
+ inputStart3.mTouches.AppendElement(
+ SingleTouchData(1, ScreenIntPoint(30, 40), {}, 0.0f, 0.0f));
+ auto idStart3 = resampler.ProcessEvent(std::move(inputStart3));
+ EXPECT_TRUE(resampler.InTouchingState());
+
+ // Touch move
+ MultiTouchInput inputMove4(MultiTouchInput::MULTITOUCH_MOVE, 0, Time(40.0),
+ 0);
+ inputMove4.mTouches.AppendElement(
+ SingleTouchData(1, ScreenIntPoint(30, 50), {}, 0.0f, 0.0f));
+ inputMove4.mTouches.AppendElement(
+ SingleTouchData(2, ScreenIntPoint(100, 30), {}, 0.0f, 0.0f));
+ auto idMove4 = resampler.ProcessEvent(std::move(inputMove4));
+ EXPECT_TRUE(resampler.InTouchingState());
+
+ // Frame
+ resampler.NotifyFrame(Time(32.0));
+
+ // Touch move
+ MultiTouchInput inputMove5(MultiTouchInput::MULTITOUCH_MOVE, 0, Time(50.0),
+ 0);
+ inputMove5.mTouches.AppendElement(
+ SingleTouchData(1, ScreenIntPoint(30, 60), {}, 0.0f, 0.0f));
+ inputMove5.mTouches.AppendElement(
+ SingleTouchData(2, ScreenIntPoint(100, 40), {}, 0.0f, 0.0f));
+ auto idMove5 = resampler.ProcessEvent(std::move(inputMove5));
+ EXPECT_TRUE(resampler.InTouchingState());
+
+ // Touch end
+ MultiTouchInput inputEnd6(MultiTouchInput::MULTITOUCH_END, 0, Time(50.0), 0);
+ // Touch point with identifier 1 is lifted
+ inputEnd6.mTouches.AppendElement(
+ SingleTouchData(1, ScreenIntPoint(30, 60), {}, 0.0f, 0.0f));
+ auto idEnd6 = resampler.ProcessEvent(std::move(inputEnd6));
+ EXPECT_TRUE(resampler.InTouchingState());
+
+ // Frame
+ resampler.NotifyFrame(Time(48.0));
+
+ // Touch move
+ MultiTouchInput inputMove7(MultiTouchInput::MULTITOUCH_MOVE, 0, Time(60.0),
+ 0);
+ inputMove7.mTouches.AppendElement(
+ SingleTouchData(2, ScreenIntPoint(100, 60), {}, 0.0f, 0.0f));
+ auto idMove7 = resampler.ProcessEvent(std::move(inputMove7));
+ EXPECT_TRUE(resampler.InTouchingState());
+
+ // Frame
+ resampler.NotifyFrame(Time(64.0));
+
+ // Touch end
+ MultiTouchInput inputEnd8(MultiTouchInput::MULTITOUCH_END, 0, Time(70.0), 0);
+ // Touch point with identifier 2 is lifted
+ inputEnd8.mTouches.AppendElement(
+ SingleTouchData(2, ScreenIntPoint(100, 60), {}, 0.0f, 0.0f));
+ auto idEnd8 = resampler.ProcessEvent(std::move(inputEnd8));
+ EXPECT_FALSE(resampler.InTouchingState());
+
+ // Check outgoing events
+ auto outgoing = resampler.ConsumeOutgoingEvents();
+ EXPECT_EQ(outgoing.size(), size_t(9));
+
+ auto outgoingStart0 = std::move(outgoing.front());
+ outgoing.pop();
+ EXPECT_EQ(outgoingStart0.mEventId, Some(idStart0));
+ CheckEvent(outgoingStart0.mEvent, MultiTouchInput::MULTITOUCH_START, {},
+ Time(0.0), ScreenIntPoint(10, 10));
+
+ auto outgoingMove1 = std::move(outgoing.front());
+ outgoing.pop();
+ EXPECT_EQ(outgoingMove1.mEventId, Some(idMove1));
+ // (26, 28) is 60% of the way from (20, 25) to (30, 30).
+ CheckEvent(outgoingMove1.mEvent, MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(20, 25)}}, Time(16.0),
+ ScreenIntPoint(26, 28));
+
+ auto outgoingMove2 = std::move(outgoing.front());
+ outgoing.pop();
+ EXPECT_EQ(outgoingMove2.mEventId, Some(idMove2));
+ CheckEvent(outgoingMove2.mEvent, MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(20.0), ScreenIntPoint(30, 30)}}, Time(30.0),
+ ScreenIntPoint(30, 40));
+
+ auto outgoingStart3 = std::move(outgoing.front());
+ outgoing.pop();
+ EXPECT_EQ(outgoingStart3.mEventId, Some(idStart3));
+ EXPECT_EQ(outgoingStart3.mEvent.mType, MultiTouchInput::MULTITOUCH_START);
+ CheckTime(outgoingStart3.mEvent.mTimeStamp, Time(30.0));
+ EXPECT_EQ(outgoingStart3.mEvent.mTouches.Length(), size_t(2));
+ // touch order should be taken from the original touch start event
+ EXPECT_EQ(outgoingStart3.mEvent.mTouches[0].mIdentifier, 2);
+ EXPECT_EQ(outgoingStart3.mEvent.mTouches[0].mScreenPoint,
+ ScreenIntPoint(100, 10));
+ EXPECT_EQ(outgoingStart3.mEvent.mTouches[1].mIdentifier, 1);
+ EXPECT_EQ(outgoingStart3.mEvent.mTouches[1].mScreenPoint,
+ ScreenIntPoint(30, 40));
+
+ auto outgoingMove4 = std::move(outgoing.front());
+ outgoing.pop();
+ EXPECT_EQ(outgoingMove4.mEventId, Some(idMove4));
+ EXPECT_EQ(outgoingMove4.mEvent.mType, MultiTouchInput::MULTITOUCH_MOVE);
+ CheckTime(outgoingMove4.mEvent.mTimeStamp, Time(32.0));
+ EXPECT_EQ(outgoingMove4.mEvent.mTouches.Length(), size_t(2));
+ // Touch order should be taken from the original touch move event.
+ // Both touches should be resampled.
+ EXPECT_EQ(outgoingMove4.mEvent.mTouches[0].mIdentifier, 1);
+ EXPECT_EQ(outgoingMove4.mEvent.mTouches[0].mScreenPoint,
+ ScreenIntPoint(30, 42));
+ EXPECT_EQ(outgoingMove4.mEvent.mTouches[1].mIdentifier, 2);
+ EXPECT_EQ(outgoingMove4.mEvent.mTouches[1].mScreenPoint,
+ ScreenIntPoint(100, 14));
+
+ auto outgoingMove5 = std::move(outgoing.front());
+ outgoing.pop();
+ EXPECT_EQ(outgoingMove5.mEventId, Some(idMove5));
+ EXPECT_EQ(outgoingMove5.mEvent.mType, MultiTouchInput::MULTITOUCH_MOVE);
+ CheckTime(outgoingMove5.mEvent.mTimeStamp, Time(50.0));
+ EXPECT_EQ(outgoingMove5.mEvent.mTouches.Length(), size_t(2));
+ // touch order should be taken from the original touch move event
+ EXPECT_EQ(outgoingMove5.mEvent.mTouches[0].mIdentifier, 1);
+ EXPECT_EQ(outgoingMove5.mEvent.mTouches[0].mScreenPoint,
+ ScreenIntPoint(30, 60));
+ EXPECT_EQ(outgoingMove5.mEvent.mTouches[0].mHistoricalData.Length(),
+ size_t(1));
+ CheckTime(outgoingMove5.mEvent.mTouches[0].mHistoricalData[0].mTimeStamp,
+ Time(40.0));
+ EXPECT_EQ(outgoingMove5.mEvent.mTouches[0].mHistoricalData[0].mScreenPoint,
+ ScreenIntPoint(30, 50));
+ EXPECT_EQ(outgoingMove5.mEvent.mTouches[1].mIdentifier, 2);
+ EXPECT_EQ(outgoingMove5.mEvent.mTouches[1].mScreenPoint,
+ ScreenIntPoint(100, 40));
+ EXPECT_EQ(outgoingMove5.mEvent.mTouches[1].mHistoricalData.Length(),
+ size_t(1));
+ CheckTime(outgoingMove5.mEvent.mTouches[1].mHistoricalData[0].mTimeStamp,
+ Time(40.0));
+ EXPECT_EQ(outgoingMove5.mEvent.mTouches[1].mHistoricalData[0].mScreenPoint,
+ ScreenIntPoint(100, 30));
+
+ auto outgoingEnd6 = std::move(outgoing.front());
+ outgoing.pop();
+ EXPECT_EQ(outgoingEnd6.mEventId, Some(idEnd6));
+ CheckEvent(outgoingEnd6.mEvent, MultiTouchInput::MULTITOUCH_END, {},
+ Time(50.0), ScreenIntPoint(30, 60));
+
+ auto outgoingMove7 = std::move(outgoing.front());
+ outgoing.pop();
+ EXPECT_EQ(outgoingMove7.mEventId, Some(idMove7));
+ // No extrapolation because the frame at 64.0 cleared the data points because
+ // there was no pending touch move event at that point
+ CheckEvent(outgoingMove7.mEvent, MultiTouchInput::MULTITOUCH_MOVE, {},
+ Time(60.0), ScreenIntPoint(100, 60));
+ EXPECT_EQ(outgoingMove7.mEvent.mTouches[0].mIdentifier, 2);
+
+ auto outgoingEnd8 = std::move(outgoing.front());
+ outgoing.pop();
+ EXPECT_EQ(outgoingEnd8.mEventId, Some(idEnd8));
+ CheckEvent(outgoingEnd8.mEvent, MultiTouchInput::MULTITOUCH_END, {},
+ Time(70.0), ScreenIntPoint(100, 60));
+}
+
+TEST_F(TouchResamplerTest, MovingPauses) {
+ auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
+ ScreenIntPoint(10, 10));
+ auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(10.0),
+ ScreenIntPoint(20, 20));
+ resampler.NotifyFrame(Time(16.0));
+ auto idMove2 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(30.0),
+ ScreenIntPoint(40, 40));
+ resampler.NotifyFrame(Time(32.0));
+ auto idMove3 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(40.0),
+ ScreenIntPoint(50, 40));
+ resampler.NotifyFrame(Time(48.0));
+ resampler.NotifyFrame(Time(64.0));
+ auto idEnd4 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(70.0),
+ ScreenIntPoint(50, 40));
+
+ CheckOutgoingEvents({
+ {Some(idStart0),
+ MultiTouchInput::MULTITOUCH_START,
+ {},
+ Time(0.0),
+ ScreenIntPoint(10, 10)},
+
+ {Some(idMove1),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(20, 20)}},
+ Time(16.0),
+ ScreenIntPoint(26, 26)},
+
+ {Some(idMove2),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(30.0), ScreenIntPoint(40, 40)}},
+ Time(32.0),
+ ScreenIntPoint(42, 42)},
+
+ {Some(idMove3),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(40.0), ScreenIntPoint(50, 40)}},
+ Time(48.0),
+ ScreenIntPoint(58, 40)},
+
+ // There was no event between two frames here, so we expect a reset event,
+ // so that we pause at a non-resampled position.
+ {Nothing(),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {},
+ Time(48.0),
+ ScreenIntPoint(50, 40)},
+
+ {Some(idEnd4),
+ MultiTouchInput::MULTITOUCH_END,
+ {},
+ Time(70.0),
+ ScreenIntPoint(50, 40)},
+ });
+}
+
+TEST_F(TouchResamplerTest, MixedInterAndExtrapolation) {
+ auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
+ ScreenIntPoint(0, 0));
+ auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(10.0),
+ ScreenIntPoint(0, 10));
+ resampler.NotifyFrame(Time(11.0)); // 16 - 5
+ auto idMove2 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(20.0), ScreenIntPoint(0, 20)}}, Time(30.0),
+ ScreenIntPoint(0, 30));
+ resampler.NotifyFrame(Time(27.0)); // 32 - 5
+ auto idMove3 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(40.0),
+ ScreenIntPoint(0, 40));
+ resampler.NotifyFrame(Time(43.0)); // 48 - 5
+ auto idMove4 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(50.0), ScreenIntPoint(0, 50)}}, Time(60.0),
+ ScreenIntPoint(0, 60));
+ resampler.NotifyFrame(Time(59.0)); // 64 - 5
+ auto idEnd5 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(70.0),
+ ScreenIntPoint(0, 60));
+
+ CheckOutgoingEvents({
+ {Some(idStart0),
+ MultiTouchInput::MULTITOUCH_START,
+ {},
+ Time(0.0),
+ ScreenIntPoint(0, 0)},
+
+ {Some(idMove1),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(0, 10)}},
+ Time(11.0),
+ ScreenIntPoint(0, 11)},
+
+ {Some(idMove2),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(20.0), ScreenIntPoint(0, 20)}},
+ Time(27.0),
+ ScreenIntPoint(0, 27)},
+
+ {Some(idMove3),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(30.0), ScreenIntPoint(0, 30)},
+ {Time(40.0), ScreenIntPoint(0, 40)}},
+ Time(43.0),
+ ScreenIntPoint(0, 43)},
+
+ {Some(idMove4),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(50.0), ScreenIntPoint(0, 50)}},
+ Time(59.0),
+ ScreenIntPoint(0, 59)},
+
+ {Nothing(),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {},
+ Time(60.0),
+ ScreenIntPoint(0, 60)},
+
+ {Some(idEnd5),
+ MultiTouchInput::MULTITOUCH_END,
+ {},
+ Time(70.0),
+ ScreenIntPoint(0, 60)},
+ });
+}
+
+TEST_F(TouchResamplerTest, MultipleMoveEvents) {
+ // Test what happens if multiple touch move events appear between two frames.
+ // This scenario shouldn't occur on Android but we should be able to deal with
+ // it anyway. Check that we don't discard any event IDs.
+ auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
+ ScreenIntPoint(0, 0));
+ auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(10.0),
+ ScreenIntPoint(0, 10));
+ resampler.NotifyFrame(Time(11.0)); // 16 - 5
+ auto idMove2 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(20.0), ScreenIntPoint(0, 20)}}, Time(30.0),
+ ScreenIntPoint(0, 30));
+ auto idMove3 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(40.0),
+ ScreenIntPoint(0, 40));
+ auto idMove4 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(45.0), ScreenIntPoint(0, 45)}}, Time(50.0),
+ ScreenIntPoint(0, 50));
+ auto idMove5 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE, {}, Time(55.0),
+ ScreenIntPoint(0, 55));
+ resampler.NotifyFrame(Time(43.0)); // 48 - 5
+ resampler.NotifyFrame(Time(59.0)); // 64 - 5
+ auto idEnd5 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(70.0),
+ ScreenIntPoint(0, 60));
+
+ CheckOutgoingEvents({
+ {Some(idStart0),
+ MultiTouchInput::MULTITOUCH_START,
+ {},
+ Time(0.0),
+ ScreenIntPoint(0, 0)},
+
+ {Some(idMove1),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(0, 10)}},
+ Time(11.0),
+ ScreenIntPoint(0, 11)},
+
+ {Some(idMove2),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(20.0), ScreenIntPoint(0, 20)}},
+ Time(30.0),
+ ScreenIntPoint(0, 30)},
+
+ {Some(idMove3),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {},
+ Time(40.0),
+ ScreenIntPoint(0, 40)},
+
+ {Some(idMove4),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {},
+ Time(43.0),
+ ScreenIntPoint(0, 43)},
+
+ {Some(idMove5),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(45.0), ScreenIntPoint(0, 45)},
+ {Time(50.0), ScreenIntPoint(0, 50)},
+ {Time(55.0), ScreenIntPoint(0, 55)}},
+ Time(59.0),
+ ScreenIntPoint(0, 59)},
+
+ {Nothing(),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {},
+ Time(59.0),
+ ScreenIntPoint(0, 55)},
+
+ {Some(idEnd5),
+ MultiTouchInput::MULTITOUCH_END,
+ {},
+ Time(70.0),
+ ScreenIntPoint(0, 60)},
+ });
+}
+
+TEST_F(TouchResamplerTest, LimitFuturePrediction) {
+ auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
+ ScreenIntPoint(0, 0));
+ // Fingers move until time 44, then pause. UI thread is occupied until 64.
+ auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(20.0), ScreenIntPoint(0, 20)},
+ {Time(32.0), ScreenIntPoint(0, 32)}},
+ Time(44.0), ScreenIntPoint(0, 44));
+ resampler.NotifyFrame(Time(59.0)); // 64 - 5
+ auto idEnd2 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(70.0),
+ ScreenIntPoint(0, 44));
+
+ CheckOutgoingEvents({
+ {Some(idStart0),
+ MultiTouchInput::MULTITOUCH_START,
+ {},
+ Time(0.0),
+ ScreenIntPoint(0, 0)},
+
+ // kTouchResampleMaxPredictMs == 8
+ // Refuse to predict more than 8ms into the future, the fingers might have
+ // paused. Make an event for time 52 (= 44 + 8) instead of 59.
+ {Some(idMove1),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(20.0), ScreenIntPoint(0, 20)},
+ {Time(32.0), ScreenIntPoint(0, 32)},
+ {Time(44.0), ScreenIntPoint(0, 44)}},
+ Time(52.0),
+ ScreenIntPoint(0, 52)},
+
+ {Nothing(),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {},
+ Time(52.0),
+ ScreenIntPoint(0, 44)},
+
+ {Some(idEnd2),
+ MultiTouchInput::MULTITOUCH_END,
+ {},
+ Time(70.0),
+ ScreenIntPoint(0, 44)},
+ });
+}
+
+TEST_F(TouchResamplerTest, LimitBacksampling) {
+ auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
+ ScreenIntPoint(0, 0));
+ // Fingers move until time 44, then pause. UI thread is occupied until 64.
+ // Then we get a frame callback with a very outdated frametime.
+ auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(20.0), ScreenIntPoint(0, 20)},
+ {Time(32.0), ScreenIntPoint(0, 32)}},
+ Time(44.0), ScreenIntPoint(0, 44));
+ resampler.NotifyFrame(Time(11.0)); // 16 - 5
+ auto idEnd2 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(70.0),
+ ScreenIntPoint(0, 44));
+
+ CheckOutgoingEvents({
+ {Some(idStart0),
+ MultiTouchInput::MULTITOUCH_START,
+ {},
+ Time(0.0),
+ ScreenIntPoint(0, 0)},
+
+ // kTouchResampleMaxBacksampleMs == 20
+ // Refuse to sample further back than 20ms before the last data point.
+ // Make an event for time 24 (= 44 - 20) instead of time 11.
+ {Some(idMove1),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(20.0), ScreenIntPoint(0, 20)}},
+ Time(24.0),
+ ScreenIntPoint(0, 24)},
+
+ {Nothing(),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(32.0), ScreenIntPoint(0, 32)}},
+ Time(44.0),
+ ScreenIntPoint(0, 44)},
+
+ {Some(idEnd2),
+ MultiTouchInput::MULTITOUCH_END,
+ {},
+ Time(70.0),
+ ScreenIntPoint(0, 44)},
+ });
+}
+
+TEST_F(TouchResamplerTest, DontExtrapolateFromOldTouch) {
+ auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
+ ScreenIntPoint(0, 0));
+ // Fingers move until time 40, then pause. UI thread is occupied until 64.
+ auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(20.0), ScreenIntPoint(0, 20)},
+ {Time(30.0), ScreenIntPoint(0, 30)}},
+ Time(40.0), ScreenIntPoint(0, 40));
+ resampler.NotifyFrame(Time(59.0)); // 64 - 5
+ auto idEnd2 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(70.0),
+ ScreenIntPoint(0, 44));
+
+ CheckOutgoingEvents({
+ {Some(idStart0),
+ MultiTouchInput::MULTITOUCH_START,
+ {},
+ Time(0.0),
+ ScreenIntPoint(0, 0)},
+
+ // kTouchResampleOldTouchThresholdMs == 17
+ // Refuse to extrapolate from a data point that's more than 17ms older
+ // than the frame time.
+ {Some(idMove1),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(20.0), ScreenIntPoint(0, 20)},
+ {Time(30.0), ScreenIntPoint(0, 30)}},
+ Time(40.0),
+ ScreenIntPoint(0, 40)},
+
+ {Some(idEnd2),
+ MultiTouchInput::MULTITOUCH_END,
+ {},
+ Time(70.0),
+ ScreenIntPoint(0, 44)},
+ });
+}
+
+TEST_F(TouchResamplerTest, DontExtrapolateIfTooOld) {
+ auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
+ ScreenIntPoint(0, 0));
+ // Fingers move until time 10, pause, and move again at 55.
+ // UI thread is occupied until 64.
+ auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(0, 10)}}, Time(55.0),
+ ScreenIntPoint(0, 55));
+ resampler.NotifyFrame(Time(59.0)); // 64 - 5
+ auto idEnd2 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(70.0),
+ ScreenIntPoint(0, 60));
+
+ CheckOutgoingEvents({
+ {Some(idStart0),
+ MultiTouchInput::MULTITOUCH_START,
+ {},
+ Time(0.0),
+ ScreenIntPoint(0, 0)},
+
+ // kTouchResampleWindowSize == 40
+ // Refuse to resample between two data points that are more than 40ms
+ // apart.
+ {Some(idMove1),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(0, 10)}},
+ Time(55.0),
+ ScreenIntPoint(0, 55)},
+
+ {Some(idEnd2),
+ MultiTouchInput::MULTITOUCH_END,
+ {},
+ Time(70.0),
+ ScreenIntPoint(0, 60)},
+ });
+}
+
+TEST_F(TouchResamplerTest, DontInterpolateIfTooOld) {
+ auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
+ ScreenIntPoint(0, 0));
+ // Fingers move until time 10, pause, and move again at 60.
+ // UI thread is occupied until 64.
+ auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(0, 10)}}, Time(60.0),
+ ScreenIntPoint(0, 60));
+ resampler.NotifyFrame(Time(59.0)); // 64 - 5
+ auto idEnd2 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(70.0),
+ ScreenIntPoint(0, 60));
+
+ CheckOutgoingEvents({
+ {Some(idStart0),
+ MultiTouchInput::MULTITOUCH_START,
+ {},
+ Time(0.0),
+ ScreenIntPoint(0, 0)},
+
+ // kTouchResampleWindowSize == 40
+ // Refuse to resample between two data points that are more than 40ms
+ // apart.
+ {Some(idMove1),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(0, 10)}},
+ Time(60.0),
+ ScreenIntPoint(0, 60)},
+
+ {Some(idEnd2),
+ MultiTouchInput::MULTITOUCH_END,
+ {},
+ Time(70.0),
+ ScreenIntPoint(0, 60)},
+ });
+}
+
+TEST_F(TouchResamplerTest, DiscardOutdatedHistoricalData) {
+ auto idStart0 = ProcessEvent(MultiTouchInput::MULTITOUCH_START, {}, Time(0.0),
+ ScreenIntPoint(0, 0));
+ auto idMove1 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(0, 10)}}, Time(16.0),
+ ScreenIntPoint(0, 16));
+ resampler.NotifyFrame(Time(20.0));
+ auto idMove2 = ProcessEvent(MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(18.0), ScreenIntPoint(0, 18)}}, Time(25.0),
+ ScreenIntPoint(0, 25));
+ auto idEnd3 = ProcessEvent(MultiTouchInput::MULTITOUCH_END, {}, Time(35.0),
+ ScreenIntPoint(0, 25));
+
+ CheckOutgoingEvents({
+ {Some(idStart0),
+ MultiTouchInput::MULTITOUCH_START,
+ {},
+ Time(0.0),
+ ScreenIntPoint(0, 0)},
+
+ {Some(idMove1),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {{Time(10.0), ScreenIntPoint(0, 10)},
+ {Time(16.0), ScreenIntPoint(0, 16)}},
+ Time(20.0),
+ ScreenIntPoint(0, 20)},
+
+ // Discard the historical data point from time 18, because we've already
+ // sent out an event with time 20 and don't want to go back before that.
+ {Some(idMove2),
+ MultiTouchInput::MULTITOUCH_MOVE,
+ {},
+ Time(25.0),
+ ScreenIntPoint(0, 25)},
+
+ {Some(idEnd3),
+ MultiTouchInput::MULTITOUCH_END,
+ {},
+ Time(35.0),
+ ScreenIntPoint(0, 25)},
+ });
+}
diff --git a/widget/tests/gtest/moz.build b/widget/tests/gtest/moz.build
new file mode 100644
index 0000000000..078b454e06
--- /dev/null
+++ b/widget/tests/gtest/moz.build
@@ -0,0 +1,16 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at http://mozilla.org/MPL/2.0/.
+
+UNIFIED_SOURCES = [
+ "TestTimeConverter.cpp",
+ "TestTouchResampler.cpp",
+]
+
+FINAL_LIBRARY = "xul-gtest"
+
+LOCAL_INCLUDES += [
+ "/widget",
+]
diff --git a/widget/tests/mochitest.ini b/widget/tests/mochitest.ini
new file mode 100644
index 0000000000..534310d279
--- /dev/null
+++ b/widget/tests/mochitest.ini
@@ -0,0 +1,18 @@
+[DEFAULT]
+support-files = utils.js
+
+[test_AltGr_key_events_in_web_content_on_windows.html]
+skip-if = toolkit != 'windows' || headless # headless: Bug 1410525
+[test_actionhint.html]
+[test_assign_event_data.html]
+skip-if = toolkit == "cocoa" || (toolkit == 'android' && debug) || android_version == '24' || (headless && os == "win") # Mac: Bug 933303, Android bug 1285414
+[test_autocapitalize.html]
+[test_keypress_event_with_alt_on_mac.html]
+skip-if = toolkit != "cocoa"
+[test_mouse_event_with_control_on_mac.html]
+skip-if = toolkit != "cocoa"
+[test_picker_no_crash.html]
+skip-if = toolkit != "windows" || e10s # Bug 1267491
+support-files = window_picker_no_crash_child.html
+[test_scrollbar_colors.html]
+skip-if = (os == 'linux' && headless) # bug 1460109
diff --git a/widget/tests/moz.build b/widget/tests/moz.build
new file mode 100644
index 0000000000..d3b1073713
--- /dev/null
+++ b/widget/tests/moz.build
@@ -0,0 +1,125 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "Widget")
+
+with Files("unit/*macwebapputils*"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("unit/*taskbar_jumplistitems*"):
+ BUG_COMPONENT = ("Core", "Widget: Win32")
+
+with Files("TestChromeMargin.cpp"):
+ BUG_COMPONENT = ("Core", "Widget: Win32")
+
+with Files("*413277*"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("*428405*"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("*429954*"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("*444800*"):
+ BUG_COMPONENT = ("Core", "Widget: Win32")
+
+with Files("*466599*"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("*478536*"):
+ BUG_COMPONENT = ("Core", "DOM: UI Events & Focus Handling")
+
+with Files("*485118*"):
+ BUG_COMPONENT = ("Toolkit", "XUL Widgets")
+
+with Files("*517396*"):
+ BUG_COMPONENT = ("Toolkit", "XUL Widgets")
+
+with Files("*522217*"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("*538242*"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("*565392*"):
+ BUG_COMPONENT = ("Core", "DOM: Serializers")
+
+with Files("*586713*"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("*593307*"):
+ BUG_COMPONENT = ("Core", "Widget: Win32")
+
+with Files("*596600*"):
+ BUG_COMPONENT = ("Core", "DOM: UI Events & Focus Handling")
+
+with Files("*673301*"):
+ BUG_COMPONENT = ("Firefox", "Bookmarks & History")
+
+with Files("test_assign_event_data.html"):
+ BUG_COMPONENT = ("Core", "DOM: UI Events & Focus Handling")
+
+with Files("test_input_events_on_deactive_window.xhtml"):
+ BUG_COMPONENT = ("Core", "DOM: UI Events & Focus Handling")
+
+with Files("*chrome_context_menus_win*"):
+ BUG_COMPONENT = ("Core", "General")
+
+with Files("*composition_text_querycontent*"):
+ BUG_COMPONENT = ("Core", "DOM: UI Events & Focus Handling")
+
+with Files("*key_event_counts*"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("*imestate*"):
+ BUG_COMPONENT = ("Core", "DOM: UI Events & Focus Handling")
+
+with Files("*mouse_scroll*"):
+ BUG_COMPONENT = ("Core", "Widget: Win32")
+
+with Files("*native*"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("*panel_mouse_coords*"):
+ BUG_COMPONENT = ("Core", "Widget: Gtk")
+
+with Files("*picker_no_crash*"):
+ BUG_COMPONENT = ("Core", "Widget: Win32")
+
+with Files("*platform_colors*"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("*plugin*"):
+ BUG_COMPONENT = ("Core", "Plug-ins")
+
+with Files("*position_on_resize*"):
+ BUG_COMPONENT = ("Core", "Widget: Gtk")
+
+with Files("test_sizemode_events.xhtml"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("*system_status_bar*"):
+ BUG_COMPONENT = ("Core", "Widget: Cocoa")
+
+with Files("*taskbar_progress*"):
+ BUG_COMPONENT = ("Core", "Widget: Win32")
+
+with Files("*wheeltransaction*"):
+ BUG_COMPONENT = ("Core", "DOM: UI Events & Focus Handling")
+
+
+XPCSHELL_TESTS_MANIFESTS += ["unit/xpcshell.ini"]
+MOCHITEST_MANIFESTS += ["mochitest.ini"]
+MOCHITEST_CHROME_MANIFESTS += ["chrome.ini"]
+BROWSER_CHROME_MANIFESTS += ["browser/browser.ini"]
+
+# if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
+#
+# Test disabled because it requires the internal API. Re-enabling this test
+# is bug 652123.
+# CPP_UNIT_TESTS += ['TestChromeMargin']
diff --git a/widget/tests/native_menus_window.xhtml b/widget/tests/native_menus_window.xhtml
new file mode 100644
index 0000000000..2b3d3f2aa3
--- /dev/null
+++ b/widget/tests/native_menus_window.xhtml
@@ -0,0 +1,282 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/native_mouse_mac_window.xhtml b/widget/tests/native_mouse_mac_window.xhtml
new file mode 100644
index 0000000000..514664bc69
--- /dev/null
+++ b/widget/tests/native_mouse_mac_window.xhtml
@@ -0,0 +1,770 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/standalone_native_menu_window.xhtml b/widget/tests/standalone_native_menu_window.xhtml
new file mode 100644
index 0000000000..14a325ff2b
--- /dev/null
+++ b/widget/tests/standalone_native_menu_window.xhtml
@@ -0,0 +1,332 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/system_font_changes.xhtml b/widget/tests/system_font_changes.xhtml
new file mode 100644
index 0000000000..1cef650015
--- /dev/null
+++ b/widget/tests/system_font_changes.xhtml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+Hello world
+
+
+
diff --git a/widget/tests/taskbar_previews.xhtml b/widget/tests/taskbar_previews.xhtml
new file mode 100644
index 0000000000..c3f2f3890c
--- /dev/null
+++ b/widget/tests/taskbar_previews.xhtml
@@ -0,0 +1,118 @@
+
+
+
+
+
+ Previews - yeah!
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/test_AltGr_key_events_in_web_content_on_windows.html b/widget/tests/test_AltGr_key_events_in_web_content_on_windows.html
new file mode 100644
index 0000000000..ff89f8fdad
--- /dev/null
+++ b/widget/tests/test_AltGr_key_events_in_web_content_on_windows.html
@@ -0,0 +1,106 @@
+
+
+
+ Testing if AltGr keydown and keyup events are fired in web content on Windows
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/widget/tests/test_actionhint.html b/widget/tests/test_actionhint.html
new file mode 100644
index 0000000000..d4a2285aab
--- /dev/null
+++ b/widget/tests/test_actionhint.html
@@ -0,0 +1,85 @@
+
+
+
+Tests for action hint that is used by software keyboard
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/test_alwaysontop_focus.xhtml b/widget/tests/test_alwaysontop_focus.xhtml
new file mode 100644
index 0000000000..bf0a61b69d
--- /dev/null
+++ b/widget/tests/test_alwaysontop_focus.xhtml
@@ -0,0 +1,39 @@
+
+
+
+
+ Test that alwaysontop windows do not pull focus when opened.
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html
new file mode 100644
index 0000000000..709e0e647e
--- /dev/null
+++ b/widget/tests/test_assign_event_data.html
@@ -0,0 +1,759 @@
+
+
+
+ Testing ns*Event::Assign*EventData()
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/test_keypress_event_with_alt_on_mac.html b/widget/tests/test_keypress_event_with_alt_on_mac.html
new file mode 100644
index 0000000000..b5bdfcc4fd
--- /dev/null
+++ b/widget/tests/test_keypress_event_with_alt_on_mac.html
@@ -0,0 +1,109 @@
+
+
+
+ Testing if keypress event is fired when alt key is pressed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/widget/tests/test_mouse_event_with_control_on_mac.html b/widget/tests/test_mouse_event_with_control_on_mac.html
new file mode 100644
index 0000000000..85e206ea95
--- /dev/null
+++ b/widget/tests/test_mouse_event_with_control_on_mac.html
@@ -0,0 +1,114 @@
+
+
+ Test control+click on Mac
+
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/test_mouse_scroll.xhtml b/widget/tests/test_mouse_scroll.xhtml
new file mode 100644
index 0000000000..82cb6a3ea3
--- /dev/null
+++ b/widget/tests/test_mouse_scroll.xhtml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/test_native_key_bindings_mac.html b/widget/tests/test_native_key_bindings_mac.html
new file mode 100644
index 0000000000..8767a5a77d
--- /dev/null
+++ b/widget/tests/test_native_key_bindings_mac.html
@@ -0,0 +1,336 @@
+
+
+
+
+ Native Key Bindings for Cocoa Test
+
+
+
+
+
+
+
+
Stretching attack nullam stuck in a tree zzz, suspendisse cras nec
+ suspendisse lick suscipit. Nunc egestas amet litter box, nullam climb the
+ curtains biting I don't like that food tristique biting sleep on your
+ keyboard non. Lay down in your way cras nec tempus chase the red dot cras
+ nec, pharetra pharetra eat the grass leap run orci turpis attack.
+ Consectetur sleep in the sink eat I don't like that food, knock over the
+ lamp catnip in viverra tail flick zzz meow etiam enim. Ac ac hiss shed
+ everywhere kittens rhoncus, attack your ankles zzz iaculis kittens. Nullam
+ pellentesque rip the couch iaculis rhoncus nibh, give me fish orci turpis
+ purr sleep on your face quis nunc bibendum.
+
+
Neque jump on the table bat iaculis, adipiscing sleep on your keyboard
+ jump vel justo shed everywhere suspendisse lick. Zzz enim faucibus
+ hairball faucibus, pharetra sunbathe biting bat leap rip the couch attack.
+ Tortor nibh in viverra quis hairball nam, vulputate adipiscing sleep on
+ your keyboard purr knock over the lamp orci turpis. Vestibulum I don't
+ like that food et chase the red dot, adipiscing neque bibendum rutrum
+ accumsan quis rhoncus claw. Leap accumsan vehicula enim biting sleep on
+ your face, pharetra nam accumsan egestas kittens sunbathe. Pharetra chase
+ the red dot sniff non eat the grass, vulputate fluffy fur aliquam puking
+ judging you.
+
+
Claw purr sollicitudin sollicitudin lay down in your way consectetur,
+ pellentesque vehicula zzz orci turpis consectetur. I don't like that food
+ rhoncus pellentesque sniff attack, rhoncus tortor attack your ankles
+ iaculis scratched hiss vel. Tortor zzz tortor nullam rip the couch rutrum,
+ bat enim ut leap hairball iaculis. Bibendum sunbathe elit suspendisse
+ nibh, puking adipiscing sleep on your face sleep on your face zzz catnip.
+ Judging you rutrum bat sunbathe sleep on your face, jump on the table leap
+ tincidunt a faucibus sleep in the sink. Stuck in a tree tristique zzz hiss
+ in viverra nullam, quis tortor pharetra attack.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/test_taskbar_progress.xhtml b/widget/tests/test_taskbar_progress.xhtml
new file mode 100644
index 0000000000..0b9f49e441
--- /dev/null
+++ b/widget/tests/test_taskbar_progress.xhtml
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/test_transferable_overflow.xhtml b/widget/tests/test_transferable_overflow.xhtml
new file mode 100644
index 0000000000..ad1650f00a
--- /dev/null
+++ b/widget/tests/test_transferable_overflow.xhtml
@@ -0,0 +1,152 @@
+
+
+
+
+ nsTransferable with large string
+
+
+
+
+
+
+ This test checks whether a big string can be copied to the clipboard, and then retrieved in the same form.
+ On non-Windows, the test also checks whether the data of the transferable is really stored in a file.
+
+
diff --git a/widget/tests/test_wheeltransaction.xhtml b/widget/tests/test_wheeltransaction.xhtml
new file mode 100644
index 0000000000..23e855c39b
--- /dev/null
+++ b/widget/tests/test_wheeltransaction.xhtml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/unit/test_macsharingservice.js b/widget/tests/unit/test_macsharingservice.js
new file mode 100644
index 0000000000..d85b9ae737
--- /dev/null
+++ b/widget/tests/unit/test_macsharingservice.js
@@ -0,0 +1,29 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Basic tests to verify that MacSharingService returns expected data
+
+function test_getSharingProviders() {
+ let sharingService = Cc["@mozilla.org/widget/macsharingservice;1"].getService(
+ Ci.nsIMacSharingService
+ );
+ let providers = sharingService.getSharingProviders("http://example.org");
+ Assert.greater(providers.length, 1, "There are providers returned");
+ providers.forEach(provider => {
+ Assert.ok("name" in provider, "Provider has name");
+ Assert.ok("menuItemTitle" in provider, "Provider has menuItemTitle");
+ Assert.ok("image" in provider, "Provider has image");
+
+ Assert.notEqual(
+ provider.title,
+ "Mail",
+ "Known filtered provider not returned"
+ );
+ });
+}
+
+function run_test() {
+ test_getSharingProviders();
+}
diff --git a/widget/tests/unit/test_macwebapputils.js b/widget/tests/unit/test_macwebapputils.js
new file mode 100644
index 0000000000..8967f8a593
--- /dev/null
+++ b/widget/tests/unit/test_macwebapputils.js
@@ -0,0 +1,34 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Basic tests to verify that MacWebAppUtils works
+
+function test_find_app() {
+ var mwaUtils = Cc["@mozilla.org/widget/mac-web-app-utils;1"].createInstance(
+ Ci.nsIMacWebAppUtils
+ );
+ let sig = "com.apple.TextEdit";
+
+ let path;
+ path = mwaUtils.pathForAppWithIdentifier(sig);
+ info("TextEdit path: " + path + "\n");
+ Assert.notEqual(path, "");
+}
+
+function test_dont_find_fake_app() {
+ var mwaUtils = Cc["@mozilla.org/widget/mac-web-app-utils;1"].createInstance(
+ Ci.nsIMacWebAppUtils
+ );
+ let sig = "calliope.penitentiary.dramamine";
+
+ let path;
+ path = mwaUtils.pathForAppWithIdentifier(sig);
+ Assert.equal(path, "");
+}
+
+function run_test() {
+ test_find_app();
+ test_dont_find_fake_app();
+}
diff --git a/widget/tests/unit/test_taskbar_jumplistitems.js b/widget/tests/unit/test_taskbar_jumplistitems.js
new file mode 100644
index 0000000000..fad9680e02
--- /dev/null
+++ b/widget/tests/unit/test_taskbar_jumplistitems.js
@@ -0,0 +1,328 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This tests taskbar jump list functionality available on win7 and up.
+const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+function test_basics() {
+ var item = Cc["@mozilla.org/windows-jumplistitem;1"].createInstance(
+ Ci.nsIJumpListItem
+ );
+
+ var sep = Cc["@mozilla.org/windows-jumplistseparator;1"].createInstance(
+ Ci.nsIJumpListSeparator
+ );
+
+ var shortcut = Cc["@mozilla.org/windows-jumplistshortcut;1"].createInstance(
+ Ci.nsIJumpListShortcut
+ );
+
+ var link = Cc["@mozilla.org/windows-jumplistlink;1"].createInstance(
+ Ci.nsIJumpListLink
+ );
+
+ Assert.ok(!item.equals(sep));
+ Assert.ok(!item.equals(shortcut));
+ Assert.ok(!item.equals(link));
+
+ Assert.ok(!sep.equals(item));
+ Assert.ok(!sep.equals(shortcut));
+ Assert.ok(!sep.equals(link));
+
+ Assert.ok(!shortcut.equals(item));
+ Assert.ok(!shortcut.equals(sep));
+ Assert.ok(!shortcut.equals(link));
+
+ Assert.ok(!link.equals(item));
+ Assert.ok(!link.equals(sep));
+ Assert.ok(!link.equals(shortcut));
+
+ Assert.ok(item.equals(item));
+ Assert.ok(sep.equals(sep));
+ Assert.ok(link.equals(link));
+ Assert.ok(shortcut.equals(shortcut));
+}
+
+function test_separator() {
+ // separators:
+
+ var item = Cc["@mozilla.org/windows-jumplistseparator;1"].createInstance(
+ Ci.nsIJumpListSeparator
+ );
+
+ Assert.ok(item.type == Ci.nsIJumpListItem.JUMPLIST_ITEM_SEPARATOR);
+}
+
+function test_hashes() {
+ var link = Cc["@mozilla.org/windows-jumplistlink;1"].createInstance(
+ Ci.nsIJumpListLink
+ );
+ var uri1 = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+ .createInstance(Ci.nsIURIMutator)
+ .setSpec("http://www.123.com/")
+ .finalize();
+ var uri2 = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+ .createInstance(Ci.nsIURIMutator)
+ .setSpec("http://www.123.com/")
+ .finalize();
+
+ link.uri = uri1;
+
+ Assert.ok(link.compareHash(uri2));
+ uri2 = uri2
+ .mutate()
+ .setSpec("http://www.456.com/")
+ .finalize();
+ Assert.ok(!link.compareHash(uri2));
+ uri2 = uri2
+ .mutate()
+ .setSpec("http://www.123.com/")
+ .finalize();
+ Assert.ok(link.compareHash(uri2));
+ uri2 = uri2
+ .mutate()
+ .setSpec("https://www.123.com/")
+ .finalize();
+ Assert.ok(!link.compareHash(uri2));
+ uri2 = uri2
+ .mutate()
+ .setSpec("http://www.123.com/test/")
+ .finalize();
+ Assert.ok(!link.compareHash(uri2));
+ uri1 = uri1
+ .mutate()
+ .setSpec("http://www.123.com/test/")
+ .finalize();
+ link.uri = uri1;
+ uri2 = uri2
+ .mutate()
+ .setSpec("http://www.123.com/test/")
+ .finalize();
+ Assert.ok(link.compareHash(uri2));
+ uri1 = uri1
+ .mutate()
+ .setSpec("https://www.123.com/test/")
+ .finalize();
+ link.uri = uri1;
+ uri2 = uri2
+ .mutate()
+ .setSpec("https://www.123.com/test/")
+ .finalize();
+ Assert.ok(link.compareHash(uri2));
+ uri2 = uri2
+ .mutate()
+ .setSpec("ftp://www.123.com/test/")
+ .finalize();
+ Assert.ok(!link.compareHash(uri2));
+ uri2 = uri2
+ .mutate()
+ .setSpec("http://123.com/test/")
+ .finalize();
+ Assert.ok(!link.compareHash(uri2));
+ uri1 = uri1
+ .mutate()
+ .setSpec("https://www.123.com/test/")
+ .finalize();
+ link.uri = uri1;
+ uri2 = uri2
+ .mutate()
+ .setSpec("https://www.123.com/Test/")
+ .finalize();
+ Assert.ok(!link.compareHash(uri2));
+
+ uri1 = uri1
+ .mutate()
+ .setSpec("http://www.123.com/")
+ .finalize();
+ link.uri = uri1;
+ Assert.equal(link.uriHash, "QGLmWuwuTozr3tOfXSf5mg==");
+ uri1 = uri1
+ .mutate()
+ .setSpec("http://www.123.com/test/")
+ .finalize();
+ link.uri = uri1;
+ Assert.equal(link.uriHash, "AG87Ls+GmaUYSUJFETRr3Q==");
+ uri1 = uri1
+ .mutate()
+ .setSpec("https://www.123.com/")
+ .finalize();
+ link.uri = uri1;
+ Assert.equal(link.uriHash, "iSx6UH1a9enVPzUA9JZ42g==");
+}
+
+function test_links() {
+ // links:
+ var link1 = Cc["@mozilla.org/windows-jumplistlink;1"].createInstance(
+ Ci.nsIJumpListLink
+ );
+ var link2 = Cc["@mozilla.org/windows-jumplistlink;1"].createInstance(
+ Ci.nsIJumpListLink
+ );
+
+ var uri1 = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+ .createInstance(Ci.nsIURIMutator)
+ .setSpec("http://www.test.com/")
+ .finalize();
+ var uri2 = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+ .createInstance(Ci.nsIURIMutator)
+ .setSpec("http://www.test.com/")
+ .finalize();
+
+ link1.uri = uri1;
+ link1.uriTitle = "Test";
+ link2.uri = uri2;
+ link2.uriTitle = "Test";
+
+ Assert.ok(link1.equals(link2));
+
+ link2.uriTitle = "Testing";
+
+ Assert.ok(!link1.equals(link2));
+
+ link2.uriTitle = "Test";
+ uri2 = uri2
+ .mutate()
+ .setSpec("http://www.testing.com/")
+ .finalize();
+ link2.uri = uri2;
+
+ Assert.ok(!link1.equals(link2));
+}
+
+function test_shortcuts() {
+ // shortcuts:
+ var sc = Cc["@mozilla.org/windows-jumplistshortcut;1"].createInstance(
+ Ci.nsIJumpListShortcut
+ );
+
+ var handlerApp = Cc[
+ "@mozilla.org/uriloader/local-handler-app;1"
+ ].createInstance(Ci.nsILocalHandlerApp);
+
+ handlerApp.name = "TestApp";
+ handlerApp.detailedDescription = "TestApp detailed description.";
+ handlerApp.appendParameter("-test");
+
+ sc.iconIndex = 1;
+ Assert.equal(sc.iconIndex, 1);
+
+ var faviconPageUri = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+ .createInstance(Ci.nsIURIMutator)
+ .setSpec("http://www.123.com/")
+ .finalize();
+ sc.faviconPageUri = faviconPageUri;
+ Assert.equal(sc.faviconPageUri, faviconPageUri);
+
+ var notepad = Services.dirsvc.get("WinD", Ci.nsIFile);
+ notepad.append("notepad.exe");
+ if (notepad.exists()) {
+ handlerApp.executable = notepad;
+ sc.app = handlerApp;
+ Assert.equal(sc.app.detailedDescription, "TestApp detailed description.");
+ Assert.equal(sc.app.name, "TestApp");
+ Assert.ok(sc.app.parameterExists("-test"));
+ Assert.ok(!sc.app.parameterExists("-notset"));
+ }
+}
+
+async function test_jumplist() {
+ // Jump lists can't register links unless the application is the default
+ // protocol handler for the protocol of the link, so we skip off testing
+ // those in these tests. We'll init the jump list for the xpc shell harness,
+ // add a task item, and commit it.
+
+ // not compiled in
+ if (Ci.nsIWinTaskbar == null) {
+ return;
+ }
+
+ var taskbar = Cc["@mozilla.org/windows-taskbar;1"].getService(
+ Ci.nsIWinTaskbar
+ );
+
+ var builder = taskbar.createJumpListBuilder();
+
+ Assert.notEqual(builder, null);
+
+ // Win7 and up only
+ try {
+ var ver = parseFloat(Services.sysinfo.getProperty("version"));
+ if (ver < 6.1) {
+ Assert.ok(!builder.available);
+ return;
+ }
+ } catch (ex) {}
+
+ Assert.ok(taskbar.available);
+
+ builder.deleteActiveList();
+
+ var items = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
+
+ var sc = Cc["@mozilla.org/windows-jumplistshortcut;1"].createInstance(
+ Ci.nsIJumpListShortcut
+ );
+
+ var handlerApp = Cc[
+ "@mozilla.org/uriloader/local-handler-app;1"
+ ].createInstance(Ci.nsILocalHandlerApp);
+
+ handlerApp.name = "Notepad";
+ handlerApp.detailedDescription = "Testing detailed description.";
+
+ var notepad = Services.dirsvc.get("WinD", Ci.nsIFile);
+ notepad.append("notepad.exe");
+ if (notepad.exists()) {
+ // To ensure "profile-before-change" will fire before
+ // "xpcom-shutdown-threads"
+ do_get_profile();
+
+ handlerApp.executable = notepad;
+ sc.app = handlerApp;
+ items.appendElement(sc);
+
+ var removed = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
+ Assert.ok(builder.initListBuild(removed));
+ Assert.ok(builder.addListToBuild(builder.JUMPLIST_CATEGORY_TASKS, items));
+ Assert.ok(builder.addListToBuild(builder.JUMPLIST_CATEGORY_RECENT));
+ Assert.ok(builder.addListToBuild(builder.JUMPLIST_CATEGORY_FREQUENT));
+ let rv = new Promise(resolve => {
+ builder.commitListBuild(resolve);
+ });
+ Assert.ok(await rv);
+
+ builder.deleteActiveList();
+
+ Assert.ok(builder.initListBuild(removed));
+ Assert.ok(
+ builder.addListToBuild(
+ builder.JUMPLIST_CATEGORY_CUSTOMLIST,
+ items,
+ "Custom List"
+ )
+ );
+ rv = new Promise(resolve => {
+ builder.commitListBuild(resolve);
+ });
+ Assert.ok(await rv);
+
+ builder.deleteActiveList();
+ }
+}
+
+function run_test() {
+ if (mozinfo.os != "win") {
+ return;
+ }
+ test_basics();
+ test_separator();
+ test_hashes();
+ test_links();
+ test_shortcuts();
+
+ run_next_test();
+}
+
+add_task(test_jumplist);
diff --git a/widget/tests/unit/xpcshell.ini b/widget/tests/unit/xpcshell.ini
new file mode 100644
index 0000000000..46beea87e0
--- /dev/null
+++ b/widget/tests/unit/xpcshell.ini
@@ -0,0 +1,9 @@
+[DEFAULT]
+head =
+
+[test_taskbar_jumplistitems.js]
+skip-if = os == "win" && os_version == "10.0" # Bug 1457329
+[test_macsharingservice.js]
+skip-if = os != "mac"
+[test_macwebapputils.js]
+skip-if = os != "mac"
diff --git a/widget/tests/utils.js b/widget/tests/utils.js
new file mode 100644
index 0000000000..d2d68ce8d3
--- /dev/null
+++ b/widget/tests/utils.js
@@ -0,0 +1,27 @@
+function getTestPlugin(pluginName) {
+ var ph = SpecialPowers.Cc["@mozilla.org/plugin/host;1"].getService(
+ SpecialPowers.Ci.nsIPluginHost
+ );
+ var tags = ph.getPluginTags();
+ var name = pluginName || "Test Plug-in";
+ for (var tag of tags) {
+ if (tag.name == name) {
+ return tag;
+ }
+ }
+
+ ok(false, "Could not find plugin tag with plugin name '" + name + "'");
+ return null;
+}
+
+// call this to set the test plugin(s) initially expected enabled state.
+// it will automatically be reset to it's previous value after the test
+// ends
+function setTestPluginEnabledState(newEnabledState, pluginName) {
+ var plugin = getTestPlugin(pluginName);
+ var oldEnabledState = plugin.enabledState;
+ plugin.enabledState = newEnabledState;
+ SimpleTest.registerCleanupFunction(function() {
+ getTestPlugin(pluginName).enabledState = oldEnabledState;
+ });
+}
diff --git a/widget/tests/window_bug429954.xhtml b/widget/tests/window_bug429954.xhtml
new file mode 100644
index 0000000000..ca26d52621
--- /dev/null
+++ b/widget/tests/window_bug429954.xhtml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/window_bug478536.xhtml b/widget/tests/window_bug478536.xhtml
new file mode 100644
index 0000000000..7318eb0bff
--- /dev/null
+++ b/widget/tests/window_bug478536.xhtml
@@ -0,0 +1,211 @@
+
+
+
+
+
+
+
+
+
+
+