From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- widget/tests/TestChromeMargin.cpp | 130 + widget/tests/browser/browser.toml | 90 + .../browser/browser_test_AZERTY_digit_shortcut.js | 84 + widget/tests/browser/browser_test_ContentCache.js | 296 + .../tests/browser/browser_test_InputContextURI.js | 156 + .../browser/browser_test_clipboard_contextmenu.js | 127 + .../tests/browser/browser_test_clipboardcache.js | 137 + .../tests/browser/browser_test_fullscreen_size.js | 66 + ...tenteditable_on_focus_move_in_remote_content.js | 122 + ...ditable_on_readonly_change_in_remote_content.js | 261 + ...n_designMode_on_focus_move_in_remote_content.js | 116 + ...r_test_ime_state_in_plugin_in_remote_content.js | 120 + ...in_text_control_on_reframe_in_remote_content.js | 78 + ...e_on_editable_state_change_in_remote_content.js | 297 + ...st_ime_state_on_focus_move_in_remote_content.js | 128 + ...state_on_input_type_change_in_remote_content.js | 70 + ...e_state_on_readonly_change_in_remote_content.js | 68 + .../tests/browser/browser_test_scrollbar_colors.js | 146 + widget/tests/browser/browser_test_swipe_gesture.js | 1274 +++ widget/tests/browser/file_ime_state_tests.html | 48 + widget/tests/browser/helper_scrollbar_colors.html | 22 + widget/tests/browser/helper_swipe_gesture.html | 20 + widget/tests/bug586713_window.xhtml | 50 + widget/tests/chrome.toml | 200 + widget/tests/clipboard_helper.js | 230 + widget/tests/empty_window.xhtml | 4 + widget/tests/file_bug596600.html | 4 + widget/tests/file_ime_state_test_helper.js | 197 + .../file_input_events_on_deactive_window.html | 5 + widget/tests/file_secure_input.html | 1 + widget/tests/file_test_clipboard.js | 153 + widget/tests/file_test_clipboard_asyncGetData.js | 170 + widget/tests/file_test_clipboard_asyncSetData.js | 179 + ..._state_in_contenteditable_on_readonly_change.js | 616 ++ ...le_test_ime_state_in_text_control_on_reframe.js | 190 + widget/tests/file_test_ime_state_on_focus_move.js | 1588 +++ .../file_test_ime_state_on_input_type_change.js | 315 + .../file_test_ime_state_on_readonly_change.js | 242 + widget/tests/gtest/MockWinWidget.cpp | 77 + widget/tests/gtest/MockWinWidget.h | 85 + widget/tests/gtest/TestTimeConverter.cpp | 265 + widget/tests/gtest/TestTouchResampler.cpp | 941 ++ widget/tests/gtest/TestWinHeaderOnlyUtils.cpp | 37 + widget/tests/gtest/TestWinMessageLoggingUtils.cpp | 101 + .../tests/gtest/TestWinWindowOcclusionTracker.cpp | 162 + .../TestWinWindowOcclusionTrackerInteractive.cpp | 402 + widget/tests/gtest/moz.build | 27 + widget/tests/mochitest.toml | 53 + widget/tests/moz.build | 125 + widget/tests/native_menus_window.xhtml | 282 + widget/tests/standalone_native_menu_window.xhtml | 374 + widget/tests/system_font_changes.xhtml | 63 + widget/tests/taskbar_previews.xhtml | 116 + ...AltGr_key_events_in_web_content_on_windows.html | 106 + widget/tests/test_actionhint.html | 114 + widget/tests/test_alwaysontop_focus.xhtml | 38 + widget/tests/test_assign_event_data.html | 708 ++ widget/tests/test_autocapitalize.html | 62 + widget/tests/test_bug1123480.xhtml | 155 + widget/tests/test_bug343416.xhtml | 191 + widget/tests/test_bug428405.xhtml | 168 + widget/tests/test_bug429954.xhtml | 42 + widget/tests/test_bug444800.xhtml | 97 + widget/tests/test_bug466599.xhtml | 102 + widget/tests/test_bug478536.xhtml | 33 + widget/tests/test_bug485118.xhtml | 72 + widget/tests/test_bug517396.xhtml | 53 + widget/tests/test_bug522217.xhtml | 35 + widget/tests/test_bug538242.xhtml | 55 + widget/tests/test_bug565392.html | 62 + widget/tests/test_bug586713.xhtml | 29 + widget/tests/test_bug593307.xhtml | 40 + widget/tests/test_bug596600.xhtml | 190 + widget/tests/test_bug673301.xhtml | 33 + widget/tests/test_bug760802.xhtml | 81 + widget/tests/test_clipboard.html | 16 + widget/tests/test_clipboard_asyncGetData.html | 19 + .../tests/test_clipboard_asyncGetData_chrome.html | 19 + widget/tests/test_clipboard_asyncSetData.html | 19 + .../tests/test_clipboard_asyncSetData_chrome.html | 19 + widget/tests/test_clipboard_cache_chrome.html | 231 + widget/tests/test_clipboard_chrome.html | 16 + widget/tests/test_clipboard_owner_chrome.html | 75 + .../tests/test_composition_text_querycontent.xhtml | 34 + .../tests/test_contextmenu_by_mouse_on_unix.html | 105 + ...ntenteditable_on_readonly_change_in_parent.html | 72 + .../tests/test_ime_state_in_plugin_in_parent.html | 92 + ...state_in_text_control_on_reframe_in_parent.html | 42 + ...e_state_on_editable_state_change_in_parent.html | 263 + .../test_ime_state_on_focus_move_in_parent.html | 88 + ...t_ime_state_on_input_type_change_in_parent.html | 39 + ...est_ime_state_on_readonly_change_in_parent.html | 31 + widget/tests/test_ime_state_others_in_parent.html | 153 + .../test_input_events_on_deactive_window.xhtml | 233 + widget/tests/test_key_event_counts.xhtml | 90 + widget/tests/test_keycodes.xhtml | 5647 ++++++++++ .../tests/test_keypress_event_with_alt_on_mac.html | 106 + .../test_mouse_event_with_control_on_mac.html | 116 + 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_panel_mouse_coords.xhtml | 78 + widget/tests/test_picker_no_crash.html | 30 + widget/tests/test_platform_colors.xhtml | 95 + widget/tests/test_position_on_resize.xhtml | 90 + widget/tests/test_secure_input.html | 141 + widget/tests/test_sizemode_events.xhtml | 148 + widget/tests/test_standalone_native_menu.xhtml | 29 + .../test_surrogate_pair_native_key_handling.xhtml | 178 + widget/tests/test_system_font_changes.xhtml | 28 + widget/tests/test_system_status_bar.xhtml | 53 + widget/tests/test_taskbar_progress.xhtml | 117 + widget/tests/test_textScaleFactor_system_font.html | 139 + widget/tests/test_transferable_overflow.xhtml | 155 + widget/tests/test_wheeltransaction.xhtml | 27 + widget/tests/unit/test_macsharingservice.js | 61 + widget/tests/unit/test_macwebapputils.js | 34 + .../tests/unit/test_taskbar_legacyjumplistitems.js | 229 + widget/tests/unit/xpcshell.toml | 11 + 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 | 35 + .../window_composition_text_querycontent.xhtml | 10923 +++++++++++++++++++ widget/tests/window_imestate_iframes.html | 358 + widget/tests/window_mouse_scroll_win.html | 1516 +++ widget/tests/window_mouse_scroll_win_2.html | 6 + widget/tests/window_picker_no_crash_child.html | 6 + widget/tests/window_state_windows.xhtml | 80 + widget/tests/window_wheeltransaction.xhtml | 1569 +++ 132 files changed, 38001 insertions(+) create mode 100644 widget/tests/TestChromeMargin.cpp create mode 100644 widget/tests/browser/browser.toml create mode 100644 widget/tests/browser/browser_test_AZERTY_digit_shortcut.js create mode 100644 widget/tests/browser/browser_test_ContentCache.js create mode 100644 widget/tests/browser/browser_test_InputContextURI.js create mode 100644 widget/tests/browser/browser_test_clipboard_contextmenu.js create mode 100644 widget/tests/browser/browser_test_clipboardcache.js create mode 100644 widget/tests/browser/browser_test_fullscreen_size.js create mode 100644 widget/tests/browser/browser_test_ime_state_in_contenteditable_on_focus_move_in_remote_content.js create mode 100644 widget/tests/browser/browser_test_ime_state_in_contenteditable_on_readonly_change_in_remote_content.js create mode 100644 widget/tests/browser/browser_test_ime_state_in_designMode_on_focus_move_in_remote_content.js create mode 100644 widget/tests/browser/browser_test_ime_state_in_plugin_in_remote_content.js create mode 100644 widget/tests/browser/browser_test_ime_state_in_text_control_on_reframe_in_remote_content.js create mode 100644 widget/tests/browser/browser_test_ime_state_on_editable_state_change_in_remote_content.js create mode 100644 widget/tests/browser/browser_test_ime_state_on_focus_move_in_remote_content.js create mode 100644 widget/tests/browser/browser_test_ime_state_on_input_type_change_in_remote_content.js create mode 100644 widget/tests/browser/browser_test_ime_state_on_readonly_change_in_remote_content.js create mode 100644 widget/tests/browser/browser_test_scrollbar_colors.js create mode 100644 widget/tests/browser/browser_test_swipe_gesture.js create mode 100644 widget/tests/browser/file_ime_state_tests.html create mode 100644 widget/tests/browser/helper_scrollbar_colors.html create mode 100644 widget/tests/browser/helper_swipe_gesture.html create mode 100644 widget/tests/bug586713_window.xhtml create mode 100644 widget/tests/chrome.toml create mode 100644 widget/tests/clipboard_helper.js create mode 100644 widget/tests/empty_window.xhtml create mode 100644 widget/tests/file_bug596600.html create mode 100644 widget/tests/file_ime_state_test_helper.js 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/file_test_clipboard.js create mode 100644 widget/tests/file_test_clipboard_asyncGetData.js create mode 100644 widget/tests/file_test_clipboard_asyncSetData.js create mode 100644 widget/tests/file_test_ime_state_in_contenteditable_on_readonly_change.js create mode 100644 widget/tests/file_test_ime_state_in_text_control_on_reframe.js create mode 100644 widget/tests/file_test_ime_state_on_focus_move.js create mode 100644 widget/tests/file_test_ime_state_on_input_type_change.js create mode 100644 widget/tests/file_test_ime_state_on_readonly_change.js create mode 100644 widget/tests/gtest/MockWinWidget.cpp create mode 100644 widget/tests/gtest/MockWinWidget.h create mode 100644 widget/tests/gtest/TestTimeConverter.cpp create mode 100644 widget/tests/gtest/TestTouchResampler.cpp create mode 100644 widget/tests/gtest/TestWinHeaderOnlyUtils.cpp create mode 100644 widget/tests/gtest/TestWinMessageLoggingUtils.cpp create mode 100644 widget/tests/gtest/TestWinWindowOcclusionTracker.cpp create mode 100644 widget/tests/gtest/TestWinWindowOcclusionTrackerInteractive.cpp create mode 100644 widget/tests/gtest/moz.build create mode 100644 widget/tests/mochitest.toml create mode 100644 widget/tests/moz.build create mode 100644 widget/tests/native_menus_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_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.html create mode 100644 widget/tests/test_clipboard_asyncGetData.html create mode 100644 widget/tests/test_clipboard_asyncGetData_chrome.html create mode 100644 widget/tests/test_clipboard_asyncSetData.html create mode 100644 widget/tests/test_clipboard_asyncSetData_chrome.html create mode 100644 widget/tests/test_clipboard_cache_chrome.html create mode 100644 widget/tests/test_clipboard_chrome.html create mode 100644 widget/tests/test_clipboard_owner_chrome.html create mode 100644 widget/tests/test_composition_text_querycontent.xhtml create mode 100644 widget/tests/test_contextmenu_by_mouse_on_unix.html create mode 100644 widget/tests/test_ime_state_in_contenteditable_on_readonly_change_in_parent.html create mode 100644 widget/tests/test_ime_state_in_plugin_in_parent.html create mode 100644 widget/tests/test_ime_state_in_text_control_on_reframe_in_parent.html create mode 100644 widget/tests/test_ime_state_on_editable_state_change_in_parent.html create mode 100644 widget/tests/test_ime_state_on_focus_move_in_parent.html create mode 100644 widget/tests/test_ime_state_on_input_type_change_in_parent.html create mode 100644 widget/tests/test_ime_state_on_readonly_change_in_parent.html create mode 100644 widget/tests/test_ime_state_others_in_parent.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_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_position_on_resize.xhtml 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_surrogate_pair_native_key_handling.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_textScaleFactor_system_font.html 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_legacyjumplistitems.js create mode 100644 widget/tests/unit/xpcshell.toml 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/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.toml b/widget/tests/browser/browser.toml new file mode 100644 index 0000000000..506fe1a998 --- /dev/null +++ b/widget/tests/browser/browser.toml @@ -0,0 +1,90 @@ +[DEFAULT] +skip-if = ["os == 'android'"] + +["browser_test_AZERTY_digit_shortcut.js"] +skip-if = ["os == 'linux'"] # Linux build has not implemented sendNativeKeyEvent yet + +["browser_test_ContentCache.js"] + +["browser_test_InputContextURI.js"] + +["browser_test_clipboard_contextmenu.js"] + +["browser_test_clipboardcache.js"] +skip-if = [ + "os == 'win' && bits == 32 && !debug", # Bug 1759422 + "os == 'linux'", # Bug 1792749 +] + +["browser_test_fullscreen_size.js"] + +["browser_test_ime_state_in_contenteditable_on_focus_move_in_remote_content.js"] +support-files = [ + "file_ime_state_tests.html", + "../file_ime_state_test_helper.js", + "../file_test_ime_state_on_focus_move.js", +] + +["browser_test_ime_state_in_contenteditable_on_readonly_change_in_remote_content.js"] +support-files = [ + "file_ime_state_tests.html", + "../file_ime_state_test_helper.js", + "../file_test_ime_state_in_contenteditable_on_readonly_change.js", +] + +["browser_test_ime_state_in_designMode_on_focus_move_in_remote_content.js"] +support-files = [ + "file_ime_state_tests.html", + "../file_ime_state_test_helper.js", + "../file_test_ime_state_on_focus_move.js", +] + +["browser_test_ime_state_in_plugin_in_remote_content.js"] +support-files = ["../file_ime_state_test_helper.js"] + +["browser_test_ime_state_in_text_control_on_reframe_in_remote_content.js"] +support-files = [ + "../file_ime_state_test_helper.js", + "../file_test_ime_state_in_text_control_on_reframe.js", +] + +["browser_test_ime_state_on_editable_state_change_in_remote_content.js"] +support-files = ["../file_ime_state_test_helper.js"] + +["browser_test_ime_state_on_focus_move_in_remote_content.js"] +support-files = [ + "file_ime_state_tests.html", + "../file_ime_state_test_helper.js", + "../file_test_ime_state_on_focus_move.js", +] + +["browser_test_ime_state_on_input_type_change_in_remote_content.js"] +skip-if = ["true"] # Bug 1817704 +support-files = [ + "file_ime_state_tests.html", + "../file_ime_state_test_helper.js", + "../file_test_ime_state_on_input_type_change.js", +] + +["browser_test_ime_state_on_readonly_change_in_remote_content.js"] +support-files = [ + "file_ime_state_tests.html", + "../file_ime_state_test_helper.js", + "../file_test_ime_state_on_readonly_change.js", +] + +["browser_test_scrollbar_colors.js"] +skip-if = ["os == 'linux'"] # bug 1460109 +support-files = ["helper_scrollbar_colors.html"] + +["browser_test_swipe_gesture.js"] +skip-if = [ + "win11_2009 && bits == 32 && !debug", # Bug 1759422 + "verify", # Bug 1800022 + "os == 'linux'", # Bug 1784772 +] +support-files = [ + "helper_swipe_gesture.html", + "!/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js", + "!/gfx/layers/apz/test/mochitest/apz_test_utils.js", +] diff --git a/widget/tests/browser/browser_test_AZERTY_digit_shortcut.js b/widget/tests/browser/browser_test_AZERTY_digit_shortcut.js new file mode 100644 index 0000000000..ef5112ac01 --- /dev/null +++ b/widget/tests/browser/browser_test_AZERTY_digit_shortcut.js @@ -0,0 +1,84 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async function () { + let tabs = []; + for (let i = 0; i < 10; i++) { + const tab = BrowserTestUtils.addTab(gBrowser); + tabs.push(tab); + } + const kIsMac = AppConstants.platform == "macosx"; + + await BrowserTestUtils.withNewTab( + "https://example.com/browser/toolkit/content/tests/browser/file_empty.html", + async function (browser) { + let NativeKeyConstants = {}; + Services.scriptloader.loadSubScript( + "chrome://mochikit/content/tests/SimpleTest/NativeKeyCodes.js", + NativeKeyConstants + ); + + function promiseSynthesizeAccelHyphenMinusWithAZERTY() { + return new Promise(resolve => + EventUtils.synthesizeNativeKey( + EventUtils.KEYBOARD_LAYOUT_FRENCH_PC, + kIsMac + ? NativeKeyConstants.MAC_VK_ANSI_6 + : NativeKeyConstants.WIN_VK_6, + { accelKey: true }, + kIsMac ? "-" : "", + kIsMac ? "-" : "", + resolve + ) + ); + } + + async function waitForCondition(aFunc) { + for (let i = 0; i < 60; i++) { + await new Promise(resolve => + requestAnimationFrame(() => requestAnimationFrame(resolve)) + ); + if (aFunc(ZoomManager.getFullZoomForBrowser(browser))) { + return true; + } + } + return false; + } + + const minZoomLevel = ZoomManager.MIN; + while (true) { + const currentZoom = ZoomManager.getFullZoomForBrowser(browser); + if (minZoomLevel == currentZoom) { + break; + } + info(`Trying to zoom out: ${currentZoom}`); + await promiseSynthesizeAccelHyphenMinusWithAZERTY(); + if (!(await waitForCondition(aZoomLevel => aZoomLevel < currentZoom))) { + ok(false, `Failed to zoom out from ${currentZoom}`); + return; + } + } + + await promiseSynthesizeAccelHyphenMinusWithAZERTY(); + await waitForCondition(() => false); + is( + gBrowser.selectedBrowser, + browser, + "Tab shouldn't be changed by Ctrl+- of AZERTY keyboard layout" + ); + // Reset the zoom before going to the next test. + EventUtils.synthesizeKey("0", { accelKey: true }); + await waitForCondition(aZoomLevel => aZoomLevel == 1); + } + ); + + while (tabs.length) { + await new Promise(resolve => { + const tab = tabs.shift(); + BrowserTestUtils.waitForTabClosing(tab).then(resolve); + BrowserTestUtils.removeTab(tab); + }); + } +}); diff --git a/widget/tests/browser/browser_test_ContentCache.js b/widget/tests/browser/browser_test_ContentCache.js new file mode 100644 index 0000000000..7b64e00f13 --- /dev/null +++ b/widget/tests/browser/browser_test_ContentCache.js @@ -0,0 +1,296 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async function () { + const TIP = Cc["@mozilla.org/text-input-processor;1"].createInstance( + Ci.nsITextInputProcessor + ); + let notifications = []; + const observer = (aTIP, aNotification) => { + switch (aNotification.type) { + case "request-to-commit": + aTIP.commitComposition(); + break; + case "request-to-cancel": + aTIP.cancelComposition(); + break; + case "notify-end-input-transaction": + case "notify-focus": + case "notify-blur": + case "notify-text-change": + case "notify-selection-change": + notifications.push(aNotification); + break; + } + return true; + }; + + function checkNotifications(aExpectedNotifications, aDescription) { + for (const expectedNotification of aExpectedNotifications) { + const notification = notifications.find( + element => element.type == expectedNotification.type + ); + if (expectedNotification.expected) { + isnot( + notification, + undefined, + `"${expectedNotification.type}" should be notified ${aDescription}` + ); + } else { + is( + notification, + undefined, + `"${expectedNotification.type}" should not be notified ${aDescription}` + ); + } + } + } + + ok( + TIP.beginInputTransaction(window, observer), + "nsITextInputProcessor.beingInputTransaction should return true" + ); + ok( + TIP.beginInputTransactionForTests(window, observer), + "nsITextInputProcessor.beginInputTransactionForTests should return true" + ); + + await BrowserTestUtils.withNewTab( + "https://example.com/browser/toolkit/content/tests/browser/file_empty.html", + async function (browser) { + ok(browser.isRemoteBrowser, "This test passes only in e10s mode"); + + // IMEContentObserver flushes pending IME notifications at next vsync + // after something happens. Therefore, after doing something in content + // process, we need to guarantee that IMEContentObserver has a change to + // send IME notifications to the main process with calling this function. + function waitForSendingIMENotificationsInContent() { + return SpecialPowers.spawn(browser, [], async () => { + await new Promise(resolve => + content.requestAnimationFrame(() => + content.requestAnimationFrame(resolve) + ) + ); + }); + } + + /** + * Test when empty editor gets focus + */ + notifications = []; + await SpecialPowers.spawn(browser, [], () => { + content.document.body.innerHTML = "

"; + const editor = content.document.querySelector("div[contenteditable]"); + editor.focus(); + }); + + await waitForSendingIMENotificationsInContent(); + + (function () { + checkNotifications( + [ + { type: "notify-focus", expected: true }, + { type: "notify-blur", expected: false }, + { type: "notify-end-input-transaction", expected: false }, + { type: "notify-text-change", expected: false }, + { type: "notify-selection-change", expected: false }, + ], + "after empty editor gets focus" + ); + const text = EventUtils.synthesizeQueryTextContent(0, 1000); + ok( + text?.succeeded, + "query text content should succeed after empty editor gets focus" + ); + if (text?.succeeded) { + is( + text.text.replace(/[\r\n]/g, ""), + "", + "text should be only line breaks after empty editor gets focus" + ); + } + const selection = EventUtils.synthesizeQuerySelectedText(); + ok( + selection?.succeeded, + "query selected text should succeed after empty editor gets focus" + ); + if (selection?.succeeded) { + ok( + !selection.notFound, + "query selected text should find a selection range after empty editor gets focus" + ); + if (!selection.notFound) { + is( + selection.text, + "", + "selection should be collapsed after empty editor gets focus" + ); + } + } + })(); + + /** + * Test when there is non-collapsed selection + */ + notifications = []; + await SpecialPowers.spawn(browser, [], () => { + const editor = content.document.querySelector("div[contenteditable]"); + editor.innerHTML = "

abc

def

"; + content + .getSelection() + .setBaseAndExtent( + editor.querySelector("p").firstChild, + 2, + editor.querySelector("p + p").firstChild, + 1 + ); + }); + + await waitForSendingIMENotificationsInContent(); + + (function () { + checkNotifications( + [ + { type: "notify-focus", expected: false }, + { type: "notify-blur", expected: false }, + { type: "notify-end-input-transaction", expected: false }, + { type: "notify-text-change", expected: true }, + { type: "notify-selection-change", expected: true }, + ], + "after modifying focused editor" + ); + const text = EventUtils.synthesizeQueryTextContent(0, 1000); + ok( + text?.succeeded, + "query text content should succeed after modifying focused editor" + ); + if (text?.succeeded) { + is( + text.text.trim().replace(/\r\n/g, "\n").replace(/\n\n+/g, "\n"), + "abc\ndef", + "text should include the both paragraph's text after modifying focused editor" + ); + } + const selection = EventUtils.synthesizeQuerySelectedText(); + ok( + selection?.succeeded, + "query selected text should succeed after modifying focused editor" + ); + if (selection?.succeeded) { + ok( + !selection.notFound, + "query selected text should find a selection range after modifying focused editor" + ); + if (!selection.notFound) { + is( + selection.text + .trim() + .replace(/\r\n/g, "\n") + .replace(/\n\n+/g, "\n"), + "c\nd", + "selection should have the selected characters in the both paragraphs after modifying focused editor" + ); + } + } + })(); + + /** + * Test when there is no selection ranges + */ + notifications = []; + await SpecialPowers.spawn(browser, [], () => { + content.getSelection().removeAllRanges(); + }); + + await waitForSendingIMENotificationsInContent(); + + (function () { + checkNotifications( + [ + { type: "notify-focus", expected: false }, + { type: "notify-blur", expected: false }, + { type: "notify-end-input-transaction", expected: false }, + { type: "notify-text-change", expected: false }, + { type: "notify-selection-change", expected: true }, + ], + "after removing all selection ranges from the focused editor" + ); + const text = EventUtils.synthesizeQueryTextContent(0, 1000); + ok( + text?.succeeded, + "query text content should succeed after removing all selection ranges from the focused editor" + ); + if (text?.succeeded) { + is( + text.text.trim().replace(/\r\n/g, "\n").replace(/\n\n+/g, "\n"), + "abc\ndef", + "text should include the both paragraph's text after removing all selection ranges from the focused editor" + ); + } + const selection = EventUtils.synthesizeQuerySelectedText(); + ok( + selection?.succeeded, + "query selected text should succeed after removing all selection ranges from the focused editor" + ); + if (selection?.succeeded) { + ok( + selection.notFound, + "query selected text should find no selection range after removing all selection ranges from the focused editor" + ); + } + })(); + + /** + * Test when no editable element has focus. + */ + notifications = []; + await SpecialPowers.spawn(browser, [], () => { + content.document.body.innerHTML = "abcdef"; + }); + + await waitForSendingIMENotificationsInContent(); + + (function () { + checkNotifications( + [ + { type: "notify-focus", expected: false }, + { type: "notify-blur", expected: true }, + ], + "removing editor should make ContentCacheInParent not have any data" + ); + const text = EventUtils.synthesizeQueryTextContent(0, 1000); + ok( + !text?.succeeded, + "query text content should fail because no editable element has focus" + ); + const selection = EventUtils.synthesizeQuerySelectedText(); + ok( + !selection?.succeeded, + "query selected text should fail because no editable element has focus" + ); + const caret = EventUtils.synthesizeQueryCaretRect(0); + ok( + !caret?.succeeded, + "query caret rect should fail because no editable element has focus" + ); + const textRect = EventUtils.synthesizeQueryTextRect(0, 5, false); + ok( + !textRect?.succeeded, + "query text rect should fail because no editable element has focus" + ); + const textRectArray = EventUtils.synthesizeQueryTextRectArray(0, 5); + ok( + !textRectArray?.succeeded, + "query text rect array should fail because no editable element has focus" + ); + const editorRect = EventUtils.synthesizeQueryEditorRect(); + todo( + !editorRect?.succeeded, + "query editor rect should fail because no editable element has focus" + ); + })(); + } + ); +}); diff --git a/widget/tests/browser/browser_test_InputContextURI.js b/widget/tests/browser/browser_test_InputContextURI.js new file mode 100644 index 0000000000..52f05d90f9 --- /dev/null +++ b/widget/tests/browser/browser_test_InputContextURI.js @@ -0,0 +1,156 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const gDOMWindowUtils = EventUtils._getDOMWindowUtils(window); + +function promiseURLBarFocus() { + const waitForFocusInURLBar = BrowserTestUtils.waitForEvent(gURLBar, "focus"); + gURLBar.blur(); + gURLBar.focus(); + return Promise.all([ + waitForFocusInURLBar, + TestUtils.waitForCondition( + () => + gDOMWindowUtils.IMEStatus === Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED && + gDOMWindowUtils.inputContextOrigin === + Ci.nsIDOMWindowUtils.INPUT_CONTEXT_ORIGIN_MAIN + ), + ]); +} + +function promiseIMEStateEnabledByRemote() { + return TestUtils.waitForCondition( + () => + gDOMWindowUtils.IMEStatus === Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED && + gDOMWindowUtils.inputContextOrigin === + Ci.nsIDOMWindowUtils.INPUT_CONTEXT_ORIGIN_CONTENT + ); +} + +async function test_url_bar_url(aDesc) { + await promiseURLBarFocus(); + + is( + gDOMWindowUtils.inputContextURI, + null, + `When the search bar has focus, input context URI should be null because of in chrome document (${aDesc})` + ); +} + +async function test_input_in_http_or_https(aIsHTTPS) { + await promiseURLBarFocus(); + + const scheme = aIsHTTPS ? "https" : "http"; + const url = `${scheme}://example.com/browser/toolkit/content/tests/browser/file_empty.html`; + await BrowserTestUtils.withNewTab(url, async browser => { + ok(browser.isRemoteBrowser, "This test passes only in e10s mode"); + + await SpecialPowers.spawn(browser, [], async () => { + content.document.body.innerHTML = ""; + const input = content.document.querySelector("input"); + input.focus(); + + // Wait for a tick for flushing IMEContentObserver's pending notifications. + await new Promise(resolve => + content.requestAnimationFrame(() => + content.requestAnimationFrame(resolve) + ) + ); + }); + + await promiseIMEStateEnabledByRemote(); + if (!gDOMWindowUtils.inputContextURI) { + ok( + false, + `Input context should have valid URI when the scheme of focused tab's URL is ${scheme}` + ); + return; + } + is( + gDOMWindowUtils.inputContextURI.spec, + url, + `Input context should have the document URI when the scheme of focused tab's URL is ${scheme}` + ); + }); +} + +add_task(async () => { + await test_url_bar_url("first check"); +}); +add_task(async () => { + await test_input_in_http_or_https(true); +}); +add_task(async () => { + await test_url_bar_url("check after remote content sets the URI"); +}); +add_task(async () => { + await test_input_in_http_or_https(false); +}); + +add_task(async function test_input_in_data() { + await BrowserTestUtils.withNewTab("data:text/html,", async browser => { + ok(browser.isRemoteBrowser, "This test passes only in e10s mode"); + + await SpecialPowers.spawn(browser, [], async () => { + const input = content.document.querySelector("input"); + input.focus(); + + // Wait for a tick for flushing IMEContentObserver's pending notifications. + await new Promise(resolve => + content.requestAnimationFrame(() => + content.requestAnimationFrame(resolve) + ) + ); + }); + + await promiseIMEStateEnabledByRemote(); + is( + gDOMWindowUtils.inputContextURI, + null, + "Input context should not have data URI" + ); + }); +}); + +add_task(async function test_omit_private_things_in_URL() { + await SpecialPowers.pushPrefEnv({ + set: [["network.auth.confirmAuth.enabled", false]], + }); + await promiseURLBarFocus(); + + await BrowserTestUtils.withNewTab( + "https://username:password@example.com/browser/toolkit/content/tests/browser/file_empty.html?query=some#ref", + async browser => { + ok(browser.isRemoteBrowser, "This test passes only in e10s mode"); + + await SpecialPowers.spawn(browser, [], async () => { + content.document.body.innerHTML = ""; + const input = content.document.querySelector("input"); + input.focus(); + + // Wait for a tick for flushing IMEContentObserver's pending notifications. + await new Promise(resolve => + content.requestAnimationFrame(() => + content.requestAnimationFrame(resolve) + ) + ); + }); + + await promiseIMEStateEnabledByRemote(); + if (!gDOMWindowUtils.inputContextURI) { + ok( + false, + `Input context should have valid URI even when the URL contains some private things` + ); + return; + } + is( + gDOMWindowUtils.inputContextURI.spec, + "https://example.com/browser/toolkit/content/tests/browser/file_empty.html", + `Input context should have the document URI which omit some private things in the URL` + ); + } + ); +}); diff --git a/widget/tests/browser/browser_test_clipboard_contextmenu.js b/widget/tests/browser/browser_test_clipboard_contextmenu.js new file mode 100644 index 0000000000..4d268d5be4 --- /dev/null +++ b/widget/tests/browser/browser_test_clipboard_contextmenu.js @@ -0,0 +1,127 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; + +const clipboard = SpecialPowers.Services.clipboard; +const clipboardTypes = [ + clipboard.kGlobalClipboard, + clipboard.kSelectionClipboard, + clipboard.kFindClipboard, + clipboard.kSelectionCache, +]; +const supportedClipboardTypes = clipboardTypes.filter(type => + clipboard.isClipboardTypeSupported(type) +); + +const kPasteMenuPopupId = "clipboardReadPasteMenuPopup"; +const kPasteMenuItemId = "clipboardReadPasteMenuItem"; + +function waitForPasteMenuPopupEvent(aEventSuffix) { + // The element with id `kPasteMenuPopupId` is inserted dynamically, hence + // calling `BrowserTestUtils.waitForEvent` instead of + // `BrowserTestUtils.waitForPopupEvent`. + return BrowserTestUtils.waitForEvent( + document, + "popup" + aEventSuffix, + false /* capture */, + e => { + return e.target.getAttribute("id") == kPasteMenuPopupId; + } + ); +} + +async function waitForPasteContextMenu() { + await waitForPasteMenuPopupEvent("shown"); + const pasteButton = document.getElementById(kPasteMenuItemId); + info("Wait for paste button enabled"); + await BrowserTestUtils.waitForMutationCondition( + pasteButton, + { attributeFilter: ["disabled"] }, + () => !pasteButton.disabled, + "Wait for paste button enabled" + ); +} + +function promiseClickPasteButton() { + info("Wait for clicking paste contextmenu"); + const pasteButton = document.getElementById(kPasteMenuItemId); + let promise = BrowserTestUtils.waitForEvent(pasteButton, "click"); + EventUtils.synthesizeMouseAtCenter(pasteButton, {}); + return promise; +} + +async function clipboardAsyncGetData(aBrowser, aClipboardType) { + await SpecialPowers.spawn(aBrowser, [aClipboardType], async type => { + return new Promise((resolve, reject) => { + SpecialPowers.Services.clipboard.asyncGetData( + ["text/plain"], + type, + content.browsingContext.currentWindowContext, + content.document.nodePrincipal, + { + QueryInterface: SpecialPowers.ChromeUtils.generateQI([ + "nsIAsyncClipboardGetCallback", + ]), + // nsIAsyncClipboardGetCallback + onSuccess: aAsyncGetClipboardData => { + resolve(); + }, + onError: aResult => { + reject(aResult); + }, + } + ); + }); + }); +} + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + // Avoid paste button delay enabling making test too long. + ["security.dialog_enable_delay", 0], + ], + }); +}); + +supportedClipboardTypes.forEach(type => { + add_task(async function test_clipboard_contextmenu() { + await BrowserTestUtils.withNewTab( + "https://example.com", + async function (browser) { + info(`Test clipboard contextmenu for clipboard type ${type}`); + let pasteContextMenuPromise = waitForPasteContextMenu(); + const asyncRead = clipboardAsyncGetData(browser, type); + await pasteContextMenuPromise; + + // We don't allow requests for different clipboard type to be + // consolidated, so when the context menu is shown for a specific + // clipboard type and has not yet got user response, any new requests + // for a different type should be rejected. + info( + "Test other clipboard types before interact with paste contextmenu" + ); + for (let otherType of supportedClipboardTypes) { + if (type == otherType) { + continue; + } + + info(`Test other clipboard type ${otherType}`); + await Assert.rejects( + clipboardAsyncGetData(browser, otherType), + ex => ex == Cr.NS_ERROR_DOM_NOT_ALLOWED_ERR, + `Request for clipboard type ${otherType} should be rejected` + ); + } + + await promiseClickPasteButton(); + try { + await asyncRead; + ok(true, `nsIClipboard.asyncGetData() should success`); + } catch (e) { + ok(false, `nsIClipboard.asyncGetData() should not fail with ${e}`); + } + } + ); + }); +}); diff --git a/widget/tests/browser/browser_test_clipboardcache.js b/widget/tests/browser/browser_test_clipboardcache.js new file mode 100644 index 0000000000..8cb6adb8b5 --- /dev/null +++ b/widget/tests/browser/browser_test_clipboardcache.js @@ -0,0 +1,137 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; + +// 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 = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + 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. + + // Path from nsAnonymousTemporaryFile.cpp, GetTempDir. + dir.initWithPath(PathUtils.join(PathUtils.tempDir, "mozilla-temp-files")); + } else { + 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/browser/browser_test_fullscreen_size.js b/widget/tests/browser/browser_test_fullscreen_size.js new file mode 100644 index 0000000000..dace46603c --- /dev/null +++ b/widget/tests/browser/browser_test_fullscreen_size.js @@ -0,0 +1,66 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; + +function waitForReflow(aWindow) { + return new Promise(resolve => { + aWindow.requestAnimationFrame(() => { + aWindow.requestAnimationFrame(resolve); + }); + }); +} + +add_task(async function fullscreen_size() { + let win = await BrowserTestUtils.openNewBrowserWindow({}); + win.gBrowser.selectedBrowser.focus(); + + info("Enter browser fullscreen mode"); + let promise = Promise.all([ + BrowserTestUtils.waitForEvent(win, "fullscreen"), + BrowserTestUtils.waitForEvent(win, "resize"), + ]); + win.fullScreen = true; + await promise; + + info("Await reflow of the chrome window"); + await waitForReflow(win); + + is(win.innerHeight, win.outerHeight, "Check height"); + is(win.innerWidth, win.outerWidth, "Check width"); + + await BrowserTestUtils.closeWindow(win); +}); + +// https://bugzilla.mozilla.org/show_bug.cgi?id=1830721 +add_task(async function fullscreen_size_moz_appearance() { + const win = await BrowserTestUtils.openNewBrowserWindow({}); + win.gBrowser.selectedBrowser.focus(); + + info("Add -moz-appearance style to chrome document"); + const style = win.document.createElement("style"); + style.innerHTML = ` + #main-window { + -moz-appearance: button; + } + `; + win.document.head.appendChild(style); + + info("Await reflow of the chrome window"); + await waitForReflow(win); + + info("Enter browser fullscreen mode"); + let promise = Promise.all([ + BrowserTestUtils.waitForEvent(win, "fullscreen"), + BrowserTestUtils.waitForEvent(win, "resize"), + ]); + win.fullScreen = true; + await promise; + + info("Await reflow of the chrome window"); + await waitForReflow(win); + + is(win.innerHeight, win.outerHeight, "Check height"); + is(win.innerWidth, win.outerWidth, `Check width`); + + await BrowserTestUtils.closeWindow(win); +}); diff --git a/widget/tests/browser/browser_test_ime_state_in_contenteditable_on_focus_move_in_remote_content.js b/widget/tests/browser/browser_test_ime_state_in_contenteditable_on_focus_move_in_remote_content.js new file mode 100644 index 0000000000..50b19f0cc3 --- /dev/null +++ b/widget/tests/browser/browser_test_ime_state_in_contenteditable_on_focus_move_in_remote_content.js @@ -0,0 +1,122 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* import-globals-from ../file_ime_state_test_helper.js */ +/* import-globals-from ../file_test_ime_state_on_focus_move.js */ + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_ime_state_test_helper.js", + this +); +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_test_ime_state_on_focus_move.js", + this +); +add_task(async function () { + await BrowserTestUtils.withNewTab( + "https://example.com/browser/widget/tests/browser/file_ime_state_tests.html", + async function (browser) { + const tipWrapper = new TIPWrapper(window); + ok( + tipWrapper.isAvailable(), + "TextInputProcessor should've been initialized" + ); + + // isnot is used in file_test_ime_state_on_focus_move.js, but it's not + // defined as the alias of Assert.notEqual in browser-chrome tests. + // Therefore, we need to define it here. + // eslint-disable-next-line no-unused-vars + const isnot = Assert.notEqual; + + async function runIMEStateOnFocusMoveTests(aDescription) { + await (async function test_IMEState_without_focused_element() { + const checker = new IMEStateWhenNoActiveElementTester(aDescription); + const expectedData = await SpecialPowers.spawn( + browser, + [aDescription], + description => { + const runner = + content.wrappedJSObject.createIMEStateWhenNoActiveElementTester( + description + ); + return runner.run(content.document, content.window); + } + ); + checker.check(expectedData); + })(); + for ( + let index = 0; + index < IMEStateOnFocusMoveTester.numberOfTests; + ++index + ) { + const checker = new IMEStateOnFocusMoveTester(aDescription, index); + const expectedData = await SpecialPowers.spawn( + browser, + [aDescription, index], + (description, aIndex) => { + content.wrappedJSObject.runner = + content.wrappedJSObject.createIMEStateOnFocusMoveTester( + description, + aIndex, + content.window + ); + return content.wrappedJSObject.runner.prepareToRun( + content.document.querySelector("div") + ); + } + ); + checker.prepareToCheck(expectedData, tipWrapper); + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.run(); + }); + checker.check(expectedData); + + if (checker.canTestOpenCloseState(expectedData)) { + for (const defaultOpenState of [false, true]) { + const expectedOpenStateData = await SpecialPowers.spawn( + browser, + [], + () => { + return content.wrappedJSObject.runner.prepareToRunOpenCloseTest( + content.document.querySelector("div") + ); + } + ); + checker.prepareToCheckOpenCloseTest( + defaultOpenState, + expectedOpenStateData + ); + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runOpenCloseTest(); + }); + checker.checkOpenCloseTest(expectedOpenStateData); + } + } + await SpecialPowers.spawn(browser, [], () => { + content.wrappedJSObject.runner.destroy(); + content.wrappedJSObject.runner = undefined; + }); + checker.destroy(); + } // for loop iterating test of IMEStateOnFocusMoveTester + } // definition of runIMEStateOnFocusMoveTests + + // test for contentEditable="true" + await SpecialPowers.spawn(browser, [], async () => { + content.document + .querySelector("div") + .setAttribute("contenteditable", "true"); + }); + await runIMEStateOnFocusMoveTests("in div[contenteditable]"); + + // test for contentEditable="false" + await SpecialPowers.spawn(browser, [], async () => { + content.document + .querySelector("div") + .setAttribute("contenteditable", "false"); + }); + await runIMEStateOnFocusMoveTests('in div[contenteditable="false"]'); + } + ); +}); diff --git a/widget/tests/browser/browser_test_ime_state_in_contenteditable_on_readonly_change_in_remote_content.js b/widget/tests/browser/browser_test_ime_state_in_contenteditable_on_readonly_change_in_remote_content.js new file mode 100644 index 0000000000..33217d1d2c --- /dev/null +++ b/widget/tests/browser/browser_test_ime_state_in_contenteditable_on_readonly_change_in_remote_content.js @@ -0,0 +1,261 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* import-globals-from ../file_ime_state_test_helper.js */ +/* import-globals-from ../file_test_ime_state_in_contenteditable_on_readonly_change.js */ + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_ime_state_test_helper.js", + this +); +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_test_ime_state_in_contenteditable_on_readonly_change.js", + this +); +add_task(async function () { + await BrowserTestUtils.withNewTab( + "https://example.com/browser/widget/tests/browser/file_ime_state_tests.html", + async function (browser) { + const tipWrapper = new TIPWrapper(window); + ok( + tipWrapper.isAvailable(), + "TextInputProcessor should've been initialized" + ); + + await (async function test_ime_state_in_contenteditable_on_readonly_change() { + const expectedDataOfInitialization = await SpecialPowers.spawn( + browser, + [], + () => { + content.document.body.innerHTML = "

"; + content.wrappedJSObject.runner = + content.wrappedJSObject.createIMEStateInContentEditableOnReadonlyChangeTester(); + const editingHost = content.document.querySelector( + "div[contenteditable]" + ); + return content.wrappedJSObject.runner.prepareToRun( + editingHost, + editingHost, + content.window + ); + } + ); + const tester = new IMEStateInContentEditableOnReadonlyChangeTester(); + tester.checkResultOfPreparation( + expectedDataOfInitialization, + window, + tipWrapper + ); + const expectedDataOfReadonly = await SpecialPowers.spawn( + browser, + [], + () => { + return content.wrappedJSObject.runner.runToMakeHTMLEditorReadonly(); + } + ); + tester.checkResultOfMakingHTMLEditorReadonly(expectedDataOfReadonly); + const expectedDataOfEditable = await SpecialPowers.spawn( + browser, + [], + () => { + return content.wrappedJSObject.runner.runToMakeHTMLEditorEditable(); + } + ); + tester.checkResultOfMakingHTMLEditorEditable(expectedDataOfEditable); + const expectedDataOfFinalization = await SpecialPowers.spawn( + browser, + [], + () => { + return content.wrappedJSObject.runner.runToRemoveContentEditableAttribute(); + } + ); + tester.checkResultOfRemovingContentEditableAttribute( + expectedDataOfFinalization + ); + tester.clear(); + })(); + + await (async function test_ime_state_in_button_in_contenteditable_on_readonly_change() { + const expectedDataOfInitialization = await SpecialPowers.spawn( + browser, + [], + () => { + content.document.body.innerHTML = + "

"; + content.wrappedJSObject.runner = + content.wrappedJSObject.createIMEStateInContentEditableOnReadonlyChangeTester(); + const editingHost = content.document.querySelector( + "div[contenteditable]" + ); + return content.wrappedJSObject.runner.prepareToRun( + editingHost, + editingHost.querySelector("button"), + content.window + ); + } + ); + const tester = new IMEStateInContentEditableOnReadonlyChangeTester(); + tester.checkResultOfPreparation( + expectedDataOfInitialization, + window, + tipWrapper + ); + const expectedDataOfReadonly = await SpecialPowers.spawn( + browser, + [], + () => { + return content.wrappedJSObject.runner.runToMakeHTMLEditorReadonly(); + } + ); + tester.checkResultOfMakingHTMLEditorReadonly(expectedDataOfReadonly); + const expectedDataOfEditable = await SpecialPowers.spawn( + browser, + [], + () => { + return content.wrappedJSObject.runner.runToMakeHTMLEditorEditable(); + } + ); + tester.checkResultOfMakingHTMLEditorEditable(expectedDataOfEditable); + const expectedDataOfFinalization = await SpecialPowers.spawn( + browser, + [], + () => { + return content.wrappedJSObject.runner.runToRemoveContentEditableAttribute(); + } + ); + tester.checkResultOfRemovingContentEditableAttribute( + expectedDataOfFinalization + ); + tester.clear(); + })(); + + await (async function test_ime_state_of_text_controls_in_contenteditable_on_readonly_change() { + const tester = + new IMEStateOfTextControlInContentEditableOnReadonlyChangeTester(); + await SpecialPowers.spawn(browser, [], () => { + content.document.body.innerHTML = "
"; + content.wrappedJSObject.runner = + content.wrappedJSObject.createIMEStateOfTextControlInContentEditableOnReadonlyChangeTester(); + }); + for ( + let index = 0; + index < + IMEStateOfTextControlInContentEditableOnReadonlyChangeTester.numberOfTextControlTypes; + index++ + ) { + const expectedDataOfInitialization = await SpecialPowers.spawn( + browser, + [index], + aIndex => { + const editingHost = content.document.querySelector("div"); + return content.wrappedJSObject.runner.prepareToRun( + aIndex, + editingHost, + content.window + ); + } + ); + tester.checkResultOfPreparation( + expectedDataOfInitialization, + window, + tipWrapper + ); + const expectedDataOfMakingParentEditingHost = + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runToMakeParentEditingHost(); + }); + tester.checkResultOfMakingParentEditingHost( + expectedDataOfMakingParentEditingHost + ); + const expectedDataOfMakingHTMLEditorReadonly = + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runToMakeHTMLEditorReadonly(); + }); + tester.checkResultOfMakingHTMLEditorReadonly( + expectedDataOfMakingHTMLEditorReadonly + ); + const expectedDataOfMakingHTMLEditorEditable = + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runToMakeHTMLEditorEditable(); + }); + tester.checkResultOfMakingHTMLEditorEditable( + expectedDataOfMakingHTMLEditorEditable + ); + const expectedDataOfMakingParentNonEditable = + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runToMakeParentNonEditingHost(); + }); + tester.checkResultOfMakingParentNonEditable( + expectedDataOfMakingParentNonEditable + ); + tester.clear(); + } + })(); + + await (async function test_ime_state_outside_contenteditable_on_readonly_change() { + const tester = + new IMEStateOutsideContentEditableOnReadonlyChangeTester(); + await SpecialPowers.spawn(browser, [], () => { + content.document.body.innerHTML = "
"; + content.wrappedJSObject.runner = + content.wrappedJSObject.createIMEStateOutsideContentEditableOnReadonlyChangeTester(); + }); + for ( + let index = 0; + index < + IMEStateOutsideContentEditableOnReadonlyChangeTester.numberOfFocusTargets; + index++ + ) { + const expectedDataOfInitialization = await SpecialPowers.spawn( + browser, + [index], + aIndex => { + const editingHost = content.document.querySelector("div"); + return content.wrappedJSObject.runner.prepareToRun( + aIndex, + editingHost, + content.window + ); + } + ); + tester.checkResultOfPreparation( + expectedDataOfInitialization, + window, + tipWrapper + ); + const expectedDataOfMakingParentEditingHost = + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runToMakeParentEditingHost(); + }); + tester.checkResultOfMakingParentEditingHost( + expectedDataOfMakingParentEditingHost + ); + const expectedDataOfMakingHTMLEditorReadonly = + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runToMakeHTMLEditorReadonly(); + }); + tester.checkResultOfMakingHTMLEditorReadonly( + expectedDataOfMakingHTMLEditorReadonly + ); + const expectedDataOfMakingHTMLEditorEditable = + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runToMakeHTMLEditorEditable(); + }); + tester.checkResultOfMakingHTMLEditorEditable( + expectedDataOfMakingHTMLEditorEditable + ); + const expectedDataOfMakingParentNonEditable = + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runToMakeParentNonEditingHost(); + }); + tester.checkResultOfMakingParentNonEditable( + expectedDataOfMakingParentNonEditable + ); + tester.clear(); + } + })(); + } + ); +}); diff --git a/widget/tests/browser/browser_test_ime_state_in_designMode_on_focus_move_in_remote_content.js b/widget/tests/browser/browser_test_ime_state_in_designMode_on_focus_move_in_remote_content.js new file mode 100644 index 0000000000..5ea5990e96 --- /dev/null +++ b/widget/tests/browser/browser_test_ime_state_in_designMode_on_focus_move_in_remote_content.js @@ -0,0 +1,116 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* import-globals-from ../file_ime_state_test_helper.js */ +/* import-globals-from ../file_test_ime_state_on_focus_move.js */ + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_ime_state_test_helper.js", + this +); +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_test_ime_state_on_focus_move.js", + this +); +add_task(async function () { + await BrowserTestUtils.withNewTab( + "https://example.com/browser/widget/tests/browser/file_ime_state_tests.html", + async function (browser) { + const tipWrapper = new TIPWrapper(window); + ok( + tipWrapper.isAvailable(), + "TextInputProcessor should've been initialized" + ); + + // isnot is used in file_test_ime_state_on_focus_move.js, but it's not + // defined as the alias of Assert.notEqual in browser-chrome tests. + // Therefore, we need to define it here. + // eslint-disable-next-line no-unused-vars + const isnot = Assert.notEqual; + + async function runIMEStateOnFocusMoveTests(aDescription) { + await (async function test_IMEState_without_focused_element() { + const checker = new IMEStateWhenNoActiveElementTester(aDescription); + const expectedData = await SpecialPowers.spawn( + browser, + [aDescription], + description => { + const runner = + content.wrappedJSObject.createIMEStateWhenNoActiveElementTester( + description + ); + return runner.run(content.document, content.window); + } + ); + checker.check(expectedData); + })(); + for ( + let index = 0; + index < IMEStateOnFocusMoveTester.numberOfTests; + ++index + ) { + const checker = new IMEStateOnFocusMoveTester(aDescription, index); + const expectedData = await SpecialPowers.spawn( + browser, + [aDescription, index], + (description, aIndex) => { + content.wrappedJSObject.runner = + content.wrappedJSObject.createIMEStateOnFocusMoveTester( + description, + aIndex, + content.window + ); + return content.wrappedJSObject.runner.prepareToRun( + content.document.querySelector("div") + ); + } + ); + checker.prepareToCheck(expectedData, tipWrapper); + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.run(); + }); + checker.check(expectedData); + + if (checker.canTestOpenCloseState(expectedData)) { + for (const defaultOpenState of [false, true]) { + const expectedOpenStateData = await SpecialPowers.spawn( + browser, + [], + () => { + return content.wrappedJSObject.runner.prepareToRunOpenCloseTest( + content.document.querySelector("div") + ); + } + ); + checker.prepareToCheckOpenCloseTest( + defaultOpenState, + expectedOpenStateData + ); + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runOpenCloseTest(); + }); + checker.checkOpenCloseTest(expectedOpenStateData); + } + } + await SpecialPowers.spawn(browser, [], () => { + content.wrappedJSObject.runner.destroy(); + content.wrappedJSObject.runner = undefined; + }); + checker.destroy(); + } // for loop iterating test of IMEStateOnFocusMoveTester + } // definition of runIMEStateOnFocusMoveTests + + // test designMode + await SpecialPowers.spawn(browser, [], async () => { + content.document.designMode = "on"; + }); + await runIMEStateOnFocusMoveTests('in designMode="on"'); + await SpecialPowers.spawn(browser, [], async () => { + content.document.designMode = "off"; + }); + await runIMEStateOnFocusMoveTests('in designMode="off"'); + } + ); +}); diff --git a/widget/tests/browser/browser_test_ime_state_in_plugin_in_remote_content.js b/widget/tests/browser/browser_test_ime_state_in_plugin_in_remote_content.js new file mode 100644 index 0000000000..0862b51080 --- /dev/null +++ b/widget/tests/browser/browser_test_ime_state_in_plugin_in_remote_content.js @@ -0,0 +1,120 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* import-globals-from ../file_ime_state_test_helper.js */ + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_ime_state_test_helper.js", + this +); +add_task(async function () { + await BrowserTestUtils.withNewTab( + "https://example.com/browser/toolkit/content/tests/browser/file_empty.html", + async function (browser) { + const tipWrapper = new TIPWrapper(window); + ok( + tipWrapper.isAvailable(), + "TextInputProcessor should've been initialized" + ); + + await SpecialPowers.spawn(browser, [], () => { + content.wrappedJSObject.waitForIMEContentObserverSendingNotifications = + () => { + return new content.window.Promise(resolve => + content.window.requestAnimationFrame(() => + content.window.requestAnimationFrame(resolve) + ) + ); + }; + content.document.body.innerHTML = + ''; + }); + + await SpecialPowers.spawn(browser, [], () => { + content.document.activeElement?.blur(); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + "IME enabled state should be disabled when no element has focus" + ); + ok( + !tipWrapper.IMEHasFocus, + "IME should not have focus when no element has focus" + ); + + await SpecialPowers.spawn(browser, [], () => { + content.document.querySelector("object").focus(); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + "IME enabled state should be disabled when an for plugin has focus" + ); + ok( + !tipWrapper.IMEHasFocus, + "IME enabled state should not have focus when an for plugin has focus" + ); + + await SpecialPowers.spawn(browser, [], () => { + content.document.querySelector("object").blur(); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + "IME enabled state should be disabled when an for plugin gets blurred" + ); + ok( + !tipWrapper.IMEHasFocus, + "IME should not have focus when an for plugin gets blurred" + ); + + await SpecialPowers.spawn(browser, [], () => { + content.document.querySelector("object").focus(); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + "IME enabled state should be disabled when an for plugin gets focused again" + ); + ok( + !tipWrapper.IMEHasFocus, + "IME should not have focus when an for plugin gets focused again" + ); + + await SpecialPowers.spawn(browser, [], () => { + content.document.querySelector("object").remove(); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + "IME enabled state should be disabled when focused for plugin is removed from the document" + ); + ok( + !tipWrapper.IMEHasFocus, + "IME should not have focus when focused for plugin is removed from the document" + ); + + await SpecialPowers.spawn(browser, [], () => { + content.document.querySelector("input").focus(); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED, + "IME enabled state should be enabled after gets focus" + ); + ok( + tipWrapper.IMEHasFocus, + "IME should have focus after gets focus" + ); + } + ); +}); diff --git a/widget/tests/browser/browser_test_ime_state_in_text_control_on_reframe_in_remote_content.js b/widget/tests/browser/browser_test_ime_state_in_text_control_on_reframe_in_remote_content.js new file mode 100644 index 0000000000..4d8acab1ff --- /dev/null +++ b/widget/tests/browser/browser_test_ime_state_in_text_control_on_reframe_in_remote_content.js @@ -0,0 +1,78 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* import-globals-from ../file_ime_state_test_helper.js */ +/* import-globals-from ../file_test_ime_state_in_text_control_on_reframe.js */ + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_ime_state_test_helper.js", + this +); +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_test_ime_state_in_text_control_on_reframe.js", + this +); +add_task(async function () { + await BrowserTestUtils.withNewTab( + "https://example.com/browser/widget/tests/browser/file_ime_state_tests.html", + async function (browser) { + const tipWrapper = new TIPWrapper(window); + ok( + tipWrapper.isAvailable(), + "TextInputProcessor should've been initialized" + ); + + await (async function test_ime_state_outside_contenteditable_on_readonly_change() { + const tester = new IMEStateInTextControlOnReframeTester(); + await SpecialPowers.spawn(browser, [], () => { + content.document.body.innerHTML = "
"; + content.wrappedJSObject.runner = + content.wrappedJSObject.createIMEStateInTextControlOnReframeTester(); + }); + for ( + let index = 0; + index < IMEStateInTextControlOnReframeTester.numberOfTextControlTypes; + index++ + ) { + tipWrapper.clearFocusBlurNotifications(); + const expectedData1 = await SpecialPowers.spawn( + browser, + [index], + aIndex => { + return content.wrappedJSObject.runner.prepareToRun( + aIndex, + content.document, + content.window + ); + } + ); + tipWrapper.typeA(); + await SpecialPowers.spawn(browser, [], () => { + return new Promise(resolve => + content.window.requestAnimationFrame(() => + content.window.requestAnimationFrame(resolve) + ) + ); + }); + tester.checkResultAfterTypingA(expectedData1, window, tipWrapper); + + const expectedData2 = await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.prepareToRun2(); + }); + tipWrapper.typeA(); + await SpecialPowers.spawn(browser, [], () => { + return new Promise(resolve => + content.window.requestAnimationFrame(() => + content.window.requestAnimationFrame(resolve) + ) + ); + }); + tester.checkResultAfterTypingA2(expectedData2); + tester.clear(); + } + })(); + } + ); +}); diff --git a/widget/tests/browser/browser_test_ime_state_on_editable_state_change_in_remote_content.js b/widget/tests/browser/browser_test_ime_state_on_editable_state_change_in_remote_content.js new file mode 100644 index 0000000000..8c38f97b72 --- /dev/null +++ b/widget/tests/browser/browser_test_ime_state_on_editable_state_change_in_remote_content.js @@ -0,0 +1,297 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* import-globals-from ../file_ime_state_test_helper.js */ + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_ime_state_test_helper.js", + this +); +add_task(async function () { + await BrowserTestUtils.withNewTab( + "https://example.com/browser/toolkit/content/tests/browser/file_empty.html", + async function (browser) { + const tipWrapper = new TIPWrapper(window); + ok( + tipWrapper.isAvailable(), + "TextInputProcessor should've been initialized" + ); + + await SpecialPowers.spawn(browser, [], () => { + content.wrappedJSObject.waitForIMEContentObserverSendingNotifications = + () => { + return new content.window.Promise(resolve => + content.window.requestAnimationFrame(() => + content.window.requestAnimationFrame(resolve) + ) + ); + }; + content.wrappedJSObject.resetIMEStateWithFocusMove = () => { + const input = content.document.createElement("input"); + content.document.body.appendChild(input); + input.focus(); + input.remove(); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }; + content.document.body.innerHTML = "
"; + }); + + function resetIMEStateWithFocusMove() { + return SpecialPowers.spawn(browser, [], () => { + const input = content.document.createElement("input"); + content.document.body.appendChild(input); + input.focus(); + input.remove(); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + } + + await (async function test_setting_contenteditable_of_focused_div() { + await SpecialPowers.spawn(browser, [], () => { + const div = content.document.querySelector("div"); + div.setAttribute("tabindex", "0"); + div.focus(); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + "test_setting_contenteditable_of_focused_div: IME should be disabled when non-editable
has focus" + ); + await SpecialPowers.spawn(browser, [], () => { + content.document + .querySelector("div") + .setAttribute("contenteditable", ""); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED, + "test_setting_contenteditable_of_focused_div: IME should be enabled when contenteditable of focused
is set" + ); + ok( + tipWrapper.IMEHasFocus, + "test_setting_contenteditable_of_focused_div: IME should have focus when contenteditable of focused
is set" + ); + await SpecialPowers.spawn(browser, [], () => { + content.document + .querySelector("div") + .removeAttribute("contenteditable"); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + "test_setting_contenteditable_of_focused_div: IME should be disabled when contenteditable of focused
is removed" + ); + ok( + !tipWrapper.IMEHasFocus, + "test_setting_contenteditable_of_focused_div: IME should not have focus when contenteditable of focused
is removed" + ); + await SpecialPowers.spawn(browser, [], () => { + content.document.querySelector("div").removeAttribute("tabindex"); + }); + })(); + + await resetIMEStateWithFocusMove(); + + await (async function test_removing_contenteditable_of_non_last_editable_div() { + await SpecialPowers.spawn(browser, [], async () => { + const div = content.document.querySelector("div"); + div.setAttribute("tabindex", "0"); + div.setAttribute("contenteditable", ""); + const anotherEditableDiv = content.document.createElement("div"); + anotherEditableDiv.setAttribute("contenteditable", ""); + div.parentElement.appendChild(anotherEditableDiv); + div.focus(); + await content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + div.removeAttribute("contenteditable"); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + "test_removing_contenteditable_of_non_last_editable_div: IME should be disabled when contenteditable of focused
is removed" + ); + ok( + !tipWrapper.IMEHasFocus, + "test_removing_contenteditable_of_non_last_editable_div: IME should not have focus when contenteditable of focused
is removed" + ); + await SpecialPowers.spawn(browser, [], () => { + const divs = content.document.querySelectorAll("div"); + divs[1].remove(); + divs[0].removeAttribute("tabindex"); + }); + })(); + + await resetIMEStateWithFocusMove(); + + await (async function test_setting_designMode() { + await SpecialPowers.spawn(browser, [], () => { + content.window.focus(); + content.document.designMode = "on"; + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED, + 'test_setting_designMode: IME should be enabled when designMode is set to "on"' + ); + ok( + tipWrapper.IMEHasFocus, + 'test_setting_designMode: IME should have focus when designMode is set to "on"' + ); + await SpecialPowers.spawn(browser, [], () => { + content.document.designMode = "off"; + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + 'test_setting_designMode: IME should be disabled when designMode is set to "off"' + ); + ok( + !tipWrapper.IMEHasFocus, + 'test_setting_designMode: IME should not have focus when designMode is set to "off"' + ); + })(); + + await resetIMEStateWithFocusMove(); + + async function test_setting_content_editable_of_body_when_shadow_DOM_has_focus( + aMode + ) { + await SpecialPowers.spawn(browser, [aMode], mode => { + const div = content.document.querySelector("div"); + const shadow = div.attachShadow({ mode }); + content.wrappedJSObject.divInShadow = + content.document.createElement("div"); + content.wrappedJSObject.divInShadow.setAttribute("tabindex", "0"); + shadow.appendChild(content.wrappedJSObject.divInShadow); + content.wrappedJSObject.divInShadow.focus(); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + `test_setting_content_editable_of_body_when_shadow_DOM_has_focus(${aMode}): IME should be disabled when non-editable
in a shadow DOM has focus` + ); + await SpecialPowers.spawn(browser, [], () => { + content.document.body.setAttribute("contenteditable", ""); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + // todo_is because of bug 1807597. Gecko does not update focus when focused + // element becomes an editable child. Therefore, cannot initialize + // HTMLEditor with the new editing host. + todo_is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED, + `test_setting_content_editable_of_body_when_shadow_DOM_has_focus(${aMode}): IME should be enabled when the becomes editable` + ); + todo( + tipWrapper.IMEHasFocus, + `test_setting_content_editable_of_body_when_shadow_DOM_has_focus(${aMode}): IME should have focus when the becomes editable` + ); + await SpecialPowers.spawn(browser, [], () => { + content.document.body.removeAttribute("contenteditable"); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + `test_setting_content_editable_of_body_when_shadow_DOM_has_focus)${aMode}): IME should be disabled when the becomes not editable` + ); + ok( + !tipWrapper.IMEHasFocus, + `test_setting_content_editable_of_body_when_shadow_DOM_has_focus)${aMode}): IME should not have focus when the becomes not editable` + ); + await SpecialPowers.spawn(browser, [], () => { + content.document.querySelector("div").remove(); + content.document.body.appendChild( + content.document.createElement("div") + ); + }); + } + + async function test_setting_designMode_when_shadow_DOM_has_focus(aMode) { + await SpecialPowers.spawn(browser, [aMode], mode => { + const div = content.document.querySelector("div"); + const shadow = div.attachShadow({ mode }); + content.wrappedJSObject.divInShadow = + content.document.createElement("div"); + content.wrappedJSObject.divInShadow.setAttribute("tabindex", "0"); + shadow.appendChild(content.wrappedJSObject.divInShadow); + content.wrappedJSObject.divInShadow.focus(); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + `test_setting_designMode_when_shadow_DOM_has_focus(${aMode}): IME should be disabled when non-editable
in a shadow DOM has focus` + ); + await SpecialPowers.spawn(browser, [], () => { + content.document.designMode = "on"; + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + `test_setting_designMode_when_shadow_DOM_has_focus(${aMode}): IME should stay disabled when designMode is set` + ); + ok( + !tipWrapper.IMEHasFocus, + `test_setting_designMode_when_shadow_DOM_has_focus(${aMode}): IME should not have focus when designMode is set` + ); + await SpecialPowers.spawn(browser, [], () => { + content.wrappedJSObject.divInShadow.setAttribute( + "contenteditable", + "" + ); + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + // todo_is because of bug 1807597. Gecko does not update focus when focused + // document is into the design mode. Therefore, cannot initialize + // HTMLEditor with the document node properly. + todo_is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED, + `test_setting_designMode_when_shadow_DOM_has_focus(${aMode}): IME should be enabled when focused
in a shadow DOM becomes editable` + ); + todo( + tipWrapper.IMEHasFocus, + `test_setting_designMode_when_shadow_DOM_has_focus(${aMode}): IME should have focus when focused
in a shadow DOM becomes editable` + ); + await SpecialPowers.spawn(browser, [], () => { + content.document.designMode = "off"; + return content.wrappedJSObject.waitForIMEContentObserverSendingNotifications(); + }); + is( + window.windowUtils.IMEStatus, + Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED, + `test_setting_designMode_when_shadow_DOM_has_focus(${aMode}): IME should be disabled when designMode is unset` + ); + ok( + !tipWrapper.IMEHasFocus, + `test_setting_designMode_when_shadow_DOM_has_focus(${aMode}): IME should not have focus when designMode is unset` + ); + await SpecialPowers.spawn(browser, [], () => { + content.document.querySelector("div").remove(); + content.document.body.appendChild( + content.document.createElement("div") + ); + }); + } + + for (const mode of ["open", "closed"]) { + await test_setting_content_editable_of_body_when_shadow_DOM_has_focus( + mode + ); + await resetIMEStateWithFocusMove(); + await test_setting_designMode_when_shadow_DOM_has_focus(mode); + await resetIMEStateWithFocusMove(); + } + } + ); +}); diff --git a/widget/tests/browser/browser_test_ime_state_on_focus_move_in_remote_content.js b/widget/tests/browser/browser_test_ime_state_on_focus_move_in_remote_content.js new file mode 100644 index 0000000000..3916d3d47c --- /dev/null +++ b/widget/tests/browser/browser_test_ime_state_on_focus_move_in_remote_content.js @@ -0,0 +1,128 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* import-globals-from ../file_ime_state_test_helper.js */ +/* import-globals-from ../file_test_ime_state_on_focus_move.js */ + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_ime_state_test_helper.js", + this +); +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_test_ime_state_on_focus_move.js", + this +); +add_task(async function () { + await BrowserTestUtils.withNewTab( + "https://example.com/browser/widget/tests/browser/file_ime_state_tests.html", + async function (browser) { + const tipWrapper = new TIPWrapper(window); + ok( + tipWrapper.isAvailable(), + "TextInputProcessor should've been initialized" + ); + + // isnot is used in file_test_ime_state_on_focus_move.js, but it's not + // defined as the alias of Assert.notEqual in browser-chrome tests. + // Therefore, we need to define it here. + // eslint-disable-next-line no-unused-vars + const isnot = Assert.notEqual; + + async function runIMEStateOnFocusMoveTests(aDescription) { + await (async function test_IMEState_without_focused_element() { + const checker = new IMEStateWhenNoActiveElementTester(aDescription); + const expectedData = await SpecialPowers.spawn( + browser, + [aDescription], + description => { + const runner = + content.wrappedJSObject.createIMEStateWhenNoActiveElementTester( + description + ); + return runner.run(content.document, content.window); + } + ); + checker.check(expectedData); + })(); + for ( + let index = 0; + index < IMEStateOnFocusMoveTester.numberOfTests; + ++index + ) { + const checker = new IMEStateOnFocusMoveTester(aDescription, index); + const expectedData = await SpecialPowers.spawn( + browser, + [aDescription, index], + (description, aIndex) => { + content.wrappedJSObject.runner = + content.wrappedJSObject.createIMEStateOnFocusMoveTester( + description, + aIndex, + content.window + ); + return content.wrappedJSObject.runner.prepareToRun( + content.document.querySelector("div") + ); + } + ); + checker.prepareToCheck(expectedData, tipWrapper); + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.run(); + }); + checker.check(expectedData); + + if (checker.canTestOpenCloseState(expectedData)) { + for (const defaultOpenState of [false, true]) { + const expectedOpenStateData = await SpecialPowers.spawn( + browser, + [], + () => { + return content.wrappedJSObject.runner.prepareToRunOpenCloseTest( + content.document.querySelector("div") + ); + } + ); + checker.prepareToCheckOpenCloseTest( + defaultOpenState, + expectedOpenStateData + ); + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runOpenCloseTest(); + }); + checker.checkOpenCloseTest(expectedOpenStateData); + } + } + await SpecialPowers.spawn(browser, [], () => { + content.wrappedJSObject.runner.destroy(); + content.wrappedJSObject.runner = undefined; + }); + checker.destroy(); + } // for loop iterating test of IMEStateOnFocusMoveTester + } // definition of runIMEStateOnFocusMoveTests + + // test for normal contents. + await runIMEStateOnFocusMoveTests("in non-editable container"); + + // test for removing contentEditable + await SpecialPowers.spawn(browser, [], async () => { + content.document + .querySelector("div") + .setAttribute("contenteditable", "true"); + content.document.querySelector("div").focus(); + await new Promise(resolve => + content.window.requestAnimationFrame(() => + content.window.requestAnimationFrame(resolve) + ) + ); + content.document + .querySelector("div") + .removeAttribute("contenteditable"); + }); + await runIMEStateOnFocusMoveTests( + "after removing contenteditable from the container" + ); + } + ); +}); diff --git a/widget/tests/browser/browser_test_ime_state_on_input_type_change_in_remote_content.js b/widget/tests/browser/browser_test_ime_state_on_input_type_change_in_remote_content.js new file mode 100644 index 0000000000..2a4bc4c332 --- /dev/null +++ b/widget/tests/browser/browser_test_ime_state_on_input_type_change_in_remote_content.js @@ -0,0 +1,70 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* import-globals-from ../file_ime_state_test_helper.js */ +/* import-globals-from ../file_test_ime_state_on_input_type_change.js */ + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_ime_state_test_helper.js", + this +); +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_test_ime_state_on_input_type_change.js", + this +); +add_task(async function () { + await BrowserTestUtils.withNewTab( + "https://example.com/browser/widget/tests/browser/file_ime_state_tests.html", + async function (browser) { + const tipWrapper = new TIPWrapper(window); + ok( + tipWrapper.isAvailable(), + "TextInputProcessor should've been initialized" + ); + + for ( + let srcIndex = 0; + srcIndex < IMEStateOnInputTypeChangeTester.numberOfTests; + srcIndex++ + ) { + const tester = new IMEStateOnInputTypeChangeTester(srcIndex); + for ( + let destIndex = 0; + destIndex < IMEStateOnInputTypeChangeTester.numberOfTests; + destIndex++ + ) { + const expectedResultBefore = await SpecialPowers.spawn( + browser, + [srcIndex, destIndex], + (aSrcIndex, aDestIndex) => { + content.wrappedJSObject.runner = + content.wrappedJSObject.createIMEStateOnInputTypeChangeTester( + aSrcIndex + ); + return content.wrappedJSObject.runner.prepareToRun( + aDestIndex, + content.window, + content.document.body + ); + } + ); + if (expectedResultBefore === false) { + continue; + } + tester.checkBeforeRun(expectedResultBefore, tipWrapper); + const expectedResult = await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.run(); + }); + tester.checkResult(expectedResultBefore, expectedResult); + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.clear(); + }); + tipWrapper.clearFocusBlurNotifications(); + } + tester.clear(); + } + } + ); +}); diff --git a/widget/tests/browser/browser_test_ime_state_on_readonly_change_in_remote_content.js b/widget/tests/browser/browser_test_ime_state_on_readonly_change_in_remote_content.js new file mode 100644 index 0000000000..a0c0019328 --- /dev/null +++ b/widget/tests/browser/browser_test_ime_state_on_readonly_change_in_remote_content.js @@ -0,0 +1,68 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* import-globals-from ../file_ime_state_test_helper.js */ +/* import-globals-from ../file_test_ime_state_on_readonly_change.js */ + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_ime_state_test_helper.js", + this +); +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/widget/tests/browser/file_test_ime_state_on_readonly_change.js", + this +); +add_task(async function () { + await BrowserTestUtils.withNewTab( + "https://example.com/browser/widget/tests/browser/file_ime_state_tests.html", + async function (browser) { + const tipWrapper = new TIPWrapper(window); + ok( + tipWrapper.isAvailable(), + "TextInputProcessor should've been initialized" + ); + + const tester = new IMEStateOnReadonlyChangeTester(); + for ( + let i = 0; + i < IMEStateOnReadonlyChangeTester.numberOfTextControlTypes; + i++ + ) { + const expectedResultBefore = await SpecialPowers.spawn( + browser, + [i], + aIndex => { + content.wrappedJSObject.runner = + content.wrappedJSObject.createIMEStateOnReadonlyChangeTester( + aIndex + ); + return content.wrappedJSObject.runner.prepareToRun( + aIndex, + content.window, + content.document.body + ); + } + ); + tester.checkBeforeRun(expectedResultBefore, tipWrapper); + const expectedResultOfMakingTextControlReadonly = + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runToMakeTextControlReadonly(); + }); + tester.checkResultOfMakingTextControlReadonly( + expectedResultOfMakingTextControlReadonly + ); + const expectedResultOfMakingTextControlEditable = + await SpecialPowers.spawn(browser, [], () => { + return content.wrappedJSObject.runner.runToMakeTextControlEditable(); + }); + tester.checkResultOfMakingTextControlEditable( + expectedResultOfMakingTextControlEditable + ); + tipWrapper.clearFocusBlurNotifications(); + tester.clear(); + } + } + ); +}); diff --git a/widget/tests/browser/browser_test_scrollbar_colors.js b/widget/tests/browser/browser_test_scrollbar_colors.js new file mode 100644 index 0000000000..2152412071 --- /dev/null +++ b/widget/tests/browser/browser_test_scrollbar_colors.js @@ -0,0 +1,146 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ + +"use strict"; + +add_task(async () => { + const URL_ROOT = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + "http://mochi.test:8888/" + ); + + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + URL_ROOT + "helper_scrollbar_colors.html" + ); + + await SpecialPowers.spawn(tab.linkedBrowser, [], () => { + ChromeUtils.defineESModuleGetters(this, { + WindowsVersionInfo: + "resource://gre/modules/components-utils/WindowsVersionInfo.sys.mjs", + }); + + Services.scriptloader.loadSubScript( + "chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js", + this + ); + + // == Native theme == + + const WIN_REFERENCES = [ + // Yellow background + ["255,255,0", 6889], + // Blue scrollbar face + ["0,0,255", 540], + // Cyan scrollbar track + ["0,255,255", 2487], + ]; + + const MAC_REFERENCES = [ + // Yellow background + ["255,255,0", 7225], + // Blue scrollbar face + ["0,0,255", 416], + // Cyan scrollbar track + ["0,255,255", 1760], + ]; + + // Values have been updated from 8100, 720, 1180 for linux1804 + const LINUX_REFERENCES = [ + // Yellow background + ["255,255,0", 7744], + // Blue scrollbar face + ["0,0,255", 1104], + // Cyan scrollbar track + ["0,255,255", 1152], + ]; + + // == Non-native theme == + + const WIN10_NNT_REFERENCES = [ + // Yellow background + ["255,255,0", 6889], + // Blue scrollbar face + ["0,0,255", 612], + // Cyan scrollbar track + ["0,255,255", 2355], + ]; + + const WIN11_NNT_REFERENCES = [ + // Yellow background + ["255,255,0", 6889], + // Blue scrollbar face + ["0,0,255", 324], + // Cyan scrollbar track + ["0,255,255", 2787], + ]; + + const MAC_NNT_REFERENCES = MAC_REFERENCES; + + const LINUX_NNT_REFERENCES = [ + // Yellow background + ["255,255,0", 7744], + // Blue scrollbar face + ["0,0,255", 368], + // Cyan scrollbar track + ["0,255,255", 1852], + ]; + + function countPixels(canvas) { + let result = new Map(); + let ctx = canvas.getContext("2d"); + let image = ctx.getImageData(0, 0, canvas.width, canvas.height); + let data = image.data; + let size = image.width * image.height; + for (let i = 0; i < size; i++) { + let key = data.subarray(i * 4, i * 4 + 3).toString(); + let value = result.get(key); + value = value ? value : 0; + result.set(key, value + 1); + } + return result; + } + + let outer = content.document.querySelector(".outer"); + let outerRect = outer.getBoundingClientRect(); + if ( + outerRect.width == outer.clientWidth && + outerRect.height == outer.clientHeight + ) { + ok(true, "Using overlay scrollbar, skip this test"); + return; + } + content.document.querySelector("#style").textContent = ` + .outer { scrollbar-color: blue cyan; } + `; + + let canvas = snapshotRect(content.window, outerRect); + let stats = countPixels(canvas); + let isNNT = SpecialPowers.getBoolPref("widget.non-native-theme.enabled"); + + let references; + if (content.navigator.platform.startsWith("Win")) { + if (!isNNT) { + references = WIN_REFERENCES; + } else if (WindowsVersionInfo.get().buildNumber >= 22000) { + // Windows 11 NNT + references = WIN11_NNT_REFERENCES; + } else { + // Windows 10 NNT + references = WIN10_NNT_REFERENCES; + } + } else if (content.navigator.platform.startsWith("Mac")) { + references = isNNT ? MAC_NNT_REFERENCES : MAC_REFERENCES; + } else if (content.navigator.platform.startsWith("Linux")) { + references = isNNT ? LINUX_NNT_REFERENCES : LINUX_REFERENCES; + } else { + ok(false, "Unsupported platform"); + } + for (let [color, count] of references) { + let value = stats.get(color); + is(value, count, `Pixel count of color ${color}`); + } + }); + + BrowserTestUtils.removeTab(tab); +}); diff --git a/widget/tests/browser/browser_test_swipe_gesture.js b/widget/tests/browser/browser_test_swipe_gesture.js new file mode 100644 index 0000000000..0ac85d80c8 --- /dev/null +++ b/widget/tests/browser/browser_test_swipe_gesture.js @@ -0,0 +1,1274 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ + +"use strict"; + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/gfx/layers/apz/test/mochitest/apz_test_utils.js", + this +); + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js", + this +); + +async function waitForWhile() { + await new Promise(resolve => { + requestIdleCallback(resolve, { timeout: 300 }); + }); + await new Promise(r => requestAnimationFrame(r)); +} + +requestLongerTimeout(2); + +add_task(async () => { + // Set the default values for an OS that supports swipe to nav, except for + // pixel-size which varies by OS, we vary it in differente tests in this file. + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["widget.swipe.velocity-twitch-tolerance", 0.0000001], + // Set the velocity-contribution to 0 so we can exactly control the + // values in the swipe tracker via the delta in the events that we send. + ["widget.swipe.success-velocity-contribution", 0.0], + ["widget.swipe.pixel-size", 550.0], + ], + }); + + const firstPage = "about:about"; + const secondPage = "about:mozilla"; + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + firstPage, + true /* waitForLoad */ + ); + + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage); + + // Make sure we can go back to the previous page. + ok(gBrowser.webNavigation.canGoBack); + // and we cannot go forward to the next page. + ok(!gBrowser.webNavigation.canGoForward); + + let wheelEventCount = 0; + tab.linkedBrowser.addEventListener("wheel", () => { + wheelEventCount++; + }); + + // Send a pan that starts a navigate back but doesn't have enough delta to do + // anything. Don't send the pan end because we want to check the opacity + // before the MSD animation in SwipeTracker starts which can temporarily put + // us at 1 opacity. + await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 0.9); + await panLeftToRightUpdate(tab.linkedBrowser, 100, 100, 0.9); + + // Check both getComputedStyle instead of element.style.opacity because we use a transition on the opacity. + let computedOpacity = window + .getComputedStyle(gHistorySwipeAnimation._prevBox) + .getPropertyValue("opacity"); + is(computedOpacity, "1", "opacity of prevbox is 1"); + let opacity = gHistorySwipeAnimation._prevBox.style.opacity; + is(opacity, "", "opacity style isn't explicitly set"); + + const isTranslatingIcon = + Services.prefs.getIntPref( + "browser.swipe.navigation-icon-start-position", + 0 + ) != 0 || + Services.prefs.getIntPref( + "browser.swipe.navigation-icon-end-position", + 0 + ) != 0; + if (isTranslatingIcon != 0) { + isnot( + window + .getComputedStyle(gHistorySwipeAnimation._prevBox) + .getPropertyValue("translate"), + "none", + "translate of prevbox is not `none` during gestures" + ); + } + + await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 0.9); + + // NOTE: We only get a wheel event for the beginPhase, rest of events have + // been captured by the swipe gesture module. + is(wheelEventCount, 1, "Received a wheel event"); + + await waitForWhile(); + // Make sure any navigation didn't happen. + is(tab.linkedBrowser.currentURI.spec, secondPage); + + // Try to navigate backward. + wheelEventCount = 0; + let startLoadingPromise = BrowserTestUtils.browserStarted( + tab.linkedBrowser, + firstPage + ); + let stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + firstPage + ); + await panLeftToRight(tab.linkedBrowser, 100, 100, 1); + // NOTE: We only get a wheel event for the beginPhase, rest of events have + // been captured by the swipe gesture module. + is(wheelEventCount, 1, "Received a wheel event"); + + // The element.style opacity will be 0 because we set it to 0 on successful navigation, however + // we have a tranisition on it so the computed style opacity will still be 1 because the transition hasn't started yet. + computedOpacity = window + .getComputedStyle(gHistorySwipeAnimation._prevBox) + .getPropertyValue("opacity"); + ok(computedOpacity == 1, "computed opacity of prevbox is 1"); + opacity = gHistorySwipeAnimation._prevBox.style.opacity; + ok(opacity == 0, "element.style opacity of prevbox 0"); + + if (isTranslatingIcon) { + // We don't have a transition for translate property so that we still have + // some amount of translate. + isnot( + window + .getComputedStyle(gHistorySwipeAnimation._prevBox) + .getPropertyValue("translate"), + "none", + "translate of prevbox is not `none` during the opacity transition" + ); + } + + // Make sure the gesture triggered going back to the previous page. + await Promise.all([startLoadingPromise, stoppedLoadingPromise]); + + ok(gBrowser.webNavigation.canGoForward); + + BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); +}); + +// Same test as above but pixel-size is increased and the multipliers passed to panLeftToRight correspondingly increased. +add_task(async () => { + // Set the default values for an OS that supports swipe to nav, except for + // pixel-size which varies by OS, we vary it in differente tests + // in this file. + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["widget.swipe.velocity-twitch-tolerance", 0.0000001], + // Set the velocity-contribution to 0 so we can exactly control the + // values in the swipe tracker via the delta in the events that we send. + ["widget.swipe.success-velocity-contribution", 0.0], + ["widget.swipe.pixel-size", 1100.0], + ], + }); + + const firstPage = "about:about"; + const secondPage = "about:mozilla"; + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + firstPage, + true /* waitForLoad */ + ); + + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage); + + // Make sure we can go back to the previous page. + ok(gBrowser.webNavigation.canGoBack); + // and we cannot go forward to the next page. + ok(!gBrowser.webNavigation.canGoForward); + + let wheelEventCount = 0; + tab.linkedBrowser.addEventListener("wheel", () => { + wheelEventCount++; + }); + + // Send a pan that starts a navigate back but doesn't have enough delta to do + // anything. Don't send the pan end because we want to check the opacity + // before the MSD animation in SwipeTracker starts which can temporarily put + // us at 1 opacity. + await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 1.8); + await panLeftToRightUpdate(tab.linkedBrowser, 100, 100, 1.8); + + // Check both getComputedStyle instead of element.style.opacity because we use a transition on the opacity. + let computedOpacity = window + .getComputedStyle(gHistorySwipeAnimation._prevBox) + .getPropertyValue("opacity"); + is(computedOpacity, "1", "opacity of prevbox is 1"); + let opacity = gHistorySwipeAnimation._prevBox.style.opacity; + is(opacity, "", "opacity style isn't explicitly set"); + + await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 1.8); + + // NOTE: We only get a wheel event for the beginPhase, rest of events have + // been captured by the swipe gesture module. + is(wheelEventCount, 1, "Received a wheel event"); + + await waitForWhile(); + // Make sure any navigation didn't happen. + is(tab.linkedBrowser.currentURI.spec, secondPage); + + // Try to navigate backward. + wheelEventCount = 0; + let startLoadingPromise = BrowserTestUtils.browserStarted( + tab.linkedBrowser, + firstPage + ); + let stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + firstPage + ); + await panLeftToRight(tab.linkedBrowser, 100, 100, 2); + // NOTE: We only get a wheel event for the beginPhase, rest of events have + // been captured by the swipe gesture module. + is(wheelEventCount, 1, "Received a wheel event"); + + // The element.style opacity will be 0 because we set it to 0 on successful navigation, however + // we have a tranisition on it so the computed style opacity will still be 1 because the transition hasn't started yet. + computedOpacity = window + .getComputedStyle(gHistorySwipeAnimation._prevBox) + .getPropertyValue("opacity"); + ok(computedOpacity == 1, "computed opacity of prevbox is 1"); + opacity = gHistorySwipeAnimation._prevBox.style.opacity; + ok(opacity == 0, "element.style opacity of prevbox 0"); + + // Make sure the gesture triggered going back to the previous page. + await Promise.all([startLoadingPromise, stoppedLoadingPromise]); + + ok(gBrowser.webNavigation.canGoForward); + + BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); +}); + +add_task(async () => { + // Set the default values for an OS that supports swipe to nav, except for + // pixel-size which varies by OS, we vary it in different tests + // in this file. + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["widget.swipe.velocity-twitch-tolerance", 0.0000001], + // Set the velocity-contribution to 1 (default 0.05f) so velocity is a + // large contribution to the success value in SwipeTracker.cpp so it + // pushes us into success territory without going into success territory + // purely from th deltas. + ["widget.swipe.success-velocity-contribution", 2.0], + ["widget.swipe.pixel-size", 550.0], + ], + }); + + async function runTest() { + const firstPage = "about:about"; + const secondPage = "about:mozilla"; + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + firstPage, + true /* waitForLoad */ + ); + + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage); + + // Make sure we can go back to the previous page. + ok(gBrowser.webNavigation.canGoBack); + // and we cannot go forward to the next page. + ok(!gBrowser.webNavigation.canGoForward); + + let wheelEventCount = 0; + tab.linkedBrowser.addEventListener("wheel", () => { + wheelEventCount++; + }); + + let startLoadingPromise = BrowserTestUtils.browserStarted( + tab.linkedBrowser, + firstPage + ); + let stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + firstPage + ); + let startTime = performance.now(); + await panLeftToRight(tab.linkedBrowser, 100, 100, 0.2); + let endTime = performance.now(); + + // If sending the events took too long then we might not have been able + // to generate enough velocity. + // The value 230 was picked based on try runs, in particular test verify + // runs on mac were the long pole, and when we get times near this we can + // still achieve the required velocity. + if (endTime - startTime > 230) { + BrowserTestUtils.removeTab(tab); + return false; + } + + // NOTE: We only get a wheel event for the beginPhase, rest of events have + // been captured by the swipe gesture module. + is(wheelEventCount, 1, "Received a wheel event"); + + // The element.style opacity will be 0 because we set it to 0 on successful navigation, however + // we have a tranisition on it so the computed style opacity will still be 1 because the transition hasn't started yet. + let computedOpacity = window + .getComputedStyle(gHistorySwipeAnimation._prevBox) + .getPropertyValue("opacity"); + ok(computedOpacity == 1, "computed opacity of prevbox is 1"); + let opacity = gHistorySwipeAnimation._prevBox.style.opacity; + ok(opacity == 0, "element.style opacity of prevbox 0"); + + // Make sure the gesture triggered going back to the previous page. + await Promise.all([startLoadingPromise, stoppedLoadingPromise]); + + ok(gBrowser.webNavigation.canGoForward); + + BrowserTestUtils.removeTab(tab); + + return true; + } + + let numTries = 15; + while (numTries > 0) { + await new Promise(r => requestAnimationFrame(r)); + await new Promise(resolve => requestIdleCallback(resolve)); + await new Promise(r => requestAnimationFrame(r)); + + // runTest return value indicates if test was able to run to the end. + if (await runTest()) { + break; + } + numTries--; + } + ok(numTries > 0, "never ran the test"); + await SpecialPowers.popPrefEnv(); +}); + +add_task(async () => { + // Set the default values for an OS that supports swipe to nav, except for + // pixel-size which varies by OS, we vary it in differente tests + // in this file. + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["widget.swipe.velocity-twitch-tolerance", 0.0000001], + // Set the velocity-contribution to 0 so we can exactly control the + // values in the swipe tracker via the delta in the events that we send. + ["widget.swipe.success-velocity-contribution", 0.0], + ["widget.swipe.pixel-size", 550.0], + ], + }); + + const firstPage = "about:about"; + const secondPage = "about:mozilla"; + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + firstPage, + true /* waitForLoad */ + ); + + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage); + + // Make sure we can go back to the previous page. + ok(gBrowser.webNavigation.canGoBack); + // and we cannot go forward to the next page. + ok(!gBrowser.webNavigation.canGoForward); + + let startLoadingPromise = BrowserTestUtils.browserStarted( + tab.linkedBrowser, + firstPage + ); + let stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + firstPage + ); + await panLeftToRight(tab.linkedBrowser, 100, 100, 2); + + // Make sure the gesture triggered going back to the previous page. + await Promise.all([startLoadingPromise, stoppedLoadingPromise]); + + ok(gBrowser.webNavigation.canGoForward); + + while ( + gHistorySwipeAnimation._prevBox != null || + gHistorySwipeAnimation._nextBox != null + ) { + await new Promise(r => requestAnimationFrame(r)); + } + + ok( + gHistorySwipeAnimation._prevBox == null && + gHistorySwipeAnimation._nextBox == null + ); + + BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); +}); + +add_task(async () => { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["widget.swipe.velocity-twitch-tolerance", 0.0000001], + // Set the velocity-contribution to 0 so we can exactly control the + // values in the swipe tracker via the delta in the events that we send. + ["widget.swipe.success-velocity-contribution", 0.0], + ["widget.swipe.pixel-size", 550.0], + ], + }); + + function swipeGestureEndPromise() { + return new Promise(resolve => { + let promiseObserver = { + handleEvent(aEvent) { + switch (aEvent.type) { + case "MozSwipeGestureEnd": + gBrowser.tabbox.removeEventListener( + "MozSwipeGestureEnd", + promiseObserver, + true + ); + resolve(); + break; + } + }, + }; + gBrowser.tabbox.addEventListener( + "MozSwipeGestureEnd", + promiseObserver, + true + ); + }); + } + + const firstPage = "about:about"; + const secondPage = "about:mozilla"; + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + firstPage, + true /* waitForLoad */ + ); + + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage); + + // Make sure we can go back to the previous page. + ok(gBrowser.webNavigation.canGoBack); + // and we cannot go forward to the next page. + ok(!gBrowser.webNavigation.canGoForward); + + let numSwipeGestureEndEvents = 0; + var anObserver = { + handleEvent(aEvent) { + switch (aEvent.type) { + case "MozSwipeGestureEnd": + numSwipeGestureEndEvents++; + break; + } + }, + }; + + gBrowser.tabbox.addEventListener("MozSwipeGestureEnd", anObserver, true); + + let gestureEndPromise = swipeGestureEndPromise(); + + is( + numSwipeGestureEndEvents, + 0, + "expected no MozSwipeGestureEnd got " + numSwipeGestureEndEvents + ); + + // Send a pan that starts a navigate back but doesn't have enough delta to do + // anything. + await panLeftToRight(tab.linkedBrowser, 100, 100, 0.9); + + await waitForWhile(); + // Make sure any navigation didn't happen. + is(tab.linkedBrowser.currentURI.spec, secondPage); + // end event comes after a swipe that does not navigate + await gestureEndPromise; + is( + numSwipeGestureEndEvents, + 1, + "expected one MozSwipeGestureEnd got " + numSwipeGestureEndEvents + ); + + // Try to navigate backward. + let startLoadingPromise = BrowserTestUtils.browserStarted( + tab.linkedBrowser, + firstPage + ); + let stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + firstPage + ); + + gestureEndPromise = swipeGestureEndPromise(); + + await panLeftToRight(tab.linkedBrowser, 100, 100, 1); + + // Make sure the gesture triggered going back to the previous page. + await Promise.all([startLoadingPromise, stoppedLoadingPromise]); + + ok(gBrowser.webNavigation.canGoForward); + + await gestureEndPromise; + + is( + numSwipeGestureEndEvents, + 2, + "expected one MozSwipeGestureEnd got " + (numSwipeGestureEndEvents - 1) + ); + + gBrowser.tabbox.removeEventListener("MozSwipeGestureEnd", anObserver, true); + + BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); +}); + +add_task(async () => { + // success-velocity-contribution is very high and pixel-size is + // very low so that one swipe goes over the threshold asap. + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["widget.swipe.velocity-twitch-tolerance", 0.0000001], + ["widget.swipe.success-velocity-contribution", 999999.0], + ["widget.swipe.pixel-size", 1.0], + ], + }); + + const firstPage = "about:about"; + const secondPage = "about:mozilla"; + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + firstPage, + true /* waitForLoad */ + ); + + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage); + + // Make sure we can go back to the previous page. + ok(gBrowser.webNavigation.canGoBack); + // and we cannot go forward to the next page. + ok(!gBrowser.webNavigation.canGoForward); + + // Navigate backward. + let startLoadingPromise = BrowserTestUtils.browserStarted( + tab.linkedBrowser, + firstPage + ); + let stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + firstPage + ); + + await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 100); + + ok(gHistorySwipeAnimation._prevBox != null, "should have prevbox"); + let transitionCancelPromise = new Promise(resolve => { + gHistorySwipeAnimation._prevBox.addEventListener( + "transitioncancel", + event => { + if ( + event.propertyName == "opacity" && + event.target == gHistorySwipeAnimation._prevBox + ) { + resolve(); + } + }, + { once: true } + ); + }); + let transitionStartPromise = new Promise(resolve => { + gHistorySwipeAnimation._prevBox.addEventListener( + "transitionstart", + event => { + if ( + event.propertyName == "opacity" && + event.target == gHistorySwipeAnimation._prevBox + ) { + resolve(); + } + }, + { once: true } + ); + }); + + await panLeftToRightUpdate(tab.linkedBrowser, 100, 100, 100); + await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 100); + + // Make sure the gesture triggered going back to the previous page. + await Promise.all([startLoadingPromise, stoppedLoadingPromise]); + + ok(gBrowser.webNavigation.canGoForward); + + await Promise.any([transitionStartPromise, transitionCancelPromise]); + + await TestUtils.waitForCondition(() => { + return ( + gHistorySwipeAnimation._prevBox == null && + gHistorySwipeAnimation._nextBox == null + ); + }); + + // Navigate forward and check the forward navigation icon box state. + startLoadingPromise = BrowserTestUtils.browserStarted( + tab.linkedBrowser, + secondPage + ); + stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + secondPage + ); + + await panRightToLeftBegin(tab.linkedBrowser, 100, 100, 100); + + ok(gHistorySwipeAnimation._nextBox != null, "should have nextbox"); + transitionCancelPromise = new Promise(resolve => { + gHistorySwipeAnimation._nextBox.addEventListener( + "transitioncancel", + event => { + if ( + event.propertyName == "opacity" && + event.target == gHistorySwipeAnimation._nextBox + ) { + resolve(); + } + } + ); + }); + transitionStartPromise = new Promise(resolve => { + gHistorySwipeAnimation._nextBox.addEventListener( + "transitionstart", + event => { + if ( + event.propertyName == "opacity" && + event.target == gHistorySwipeAnimation._nextBox + ) { + resolve(); + } + } + ); + }); + + await panRightToLeftUpdate(tab.linkedBrowser, 100, 100, 100); + await panRightToLeftEnd(tab.linkedBrowser, 100, 100, 100); + + // Make sure the gesture triggered going forward to the next page. + await Promise.all([startLoadingPromise, stoppedLoadingPromise]); + + ok(gBrowser.webNavigation.canGoBack); + + await Promise.any([transitionStartPromise, transitionCancelPromise]); + + await TestUtils.waitForCondition(() => { + return ( + gHistorySwipeAnimation._nextBox == null && + gHistorySwipeAnimation._prevBox == null + ); + }); + + BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); +}); + +// A simple test case on RTL. +add_task(async () => { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["widget.swipe.velocity-twitch-tolerance", 0.0000001], + ["widget.swipe.success-velocity-contribution", 0.5], + ["intl.l10n.pseudo", "bidi"], + ], + }); + + const newWin = await BrowserTestUtils.openNewBrowserWindow(); + + const firstPage = "about:about"; + const secondPage = "about:mozilla"; + const tab = await BrowserTestUtils.openNewForegroundTab( + newWin.gBrowser, + firstPage, + true /* waitForLoad */ + ); + + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage); + + // Make sure we can go back to the previous page. + ok(newWin.gBrowser.webNavigation.canGoBack); + // and we cannot go forward to the next page. + ok(!newWin.gBrowser.webNavigation.canGoForward); + + // Make sure that our gesture support stuff has been initialized in the new + // browser window. + await TestUtils.waitForCondition(() => { + return newWin.gHistorySwipeAnimation.active; + }); + + // Try to navigate backward. + let startLoadingPromise = BrowserTestUtils.browserStarted( + tab.linkedBrowser, + firstPage + ); + let stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + firstPage + ); + await panRightToLeft(tab.linkedBrowser, 100, 100, 1); + await Promise.all([startLoadingPromise, stoppedLoadingPromise]); + + ok(newWin.gBrowser.webNavigation.canGoForward); + + // Now try to navigate forward again. + startLoadingPromise = BrowserTestUtils.browserStarted( + tab.linkedBrowser, + secondPage + ); + stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + secondPage + ); + await panLeftToRight(tab.linkedBrowser, 100, 100, 1); + await Promise.all([startLoadingPromise, stoppedLoadingPromise]); + + ok(newWin.gBrowser.webNavigation.canGoBack); + + await BrowserTestUtils.closeWindow(newWin); + await SpecialPowers.popPrefEnv(); +}); + +add_task(async () => { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["widget.swipe.velocity-twitch-tolerance", 0.0000001], + ["widget.swipe.success-velocity-contribution", 0.5], + ["apz.overscroll.enabled", true], + ["apz.test.logging_enabled", true], + ], + }); + + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:about", + true /* waitForLoad */ + ); + + const URL_ROOT = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + "http://mochi.test:8888/" + ); + BrowserTestUtils.startLoadingURIString( + tab.linkedBrowser, + URL_ROOT + "helper_swipe_gesture.html" + ); + await BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + false /* includeSubFrames */, + URL_ROOT + "helper_swipe_gesture.html" + ); + + // Make sure we can go back to the previous page. + ok(gBrowser.webNavigation.canGoBack); + + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + // Set `overscroll-behavior-x: contain` and flush it. + content.document.documentElement.style.overscrollBehaviorX = "contain"; + content.document.documentElement.getBoundingClientRect(); + await content.wrappedJSObject.promiseApzFlushedRepaints(); + }); + + // Start a pan gesture but keep touching. + await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 2); + + // Flush APZ pending requests to make sure the pan gesture has been processed. + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + await content.wrappedJSObject.promiseApzFlushedRepaints(); + }); + + const isOverscrolled = await SpecialPowers.spawn( + tab.linkedBrowser, + [], + () => { + const scrollId = SpecialPowers.DOMWindowUtils.getViewId( + content.document.scrollingElement + ); + const data = SpecialPowers.DOMWindowUtils.getCompositorAPZTestData(); + return data.additionalData.some(entry => { + return ( + entry.key == scrollId && + entry.value.split(",").includes("overscrolled") + ); + }); + } + ); + + ok(isOverscrolled, "The root scroller should have overscrolled"); + + // Finish the pan gesture. + await panLeftToRightUpdate(tab.linkedBrowser, 100, 100, 2); + await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 2); + + // And wait a while to give a chance to navigate. + await waitForWhile(); + + // Make sure any navigation didn't happen. + is(tab.linkedBrowser.currentURI.spec, URL_ROOT + "helper_swipe_gesture.html"); + + BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); +}); + +// A test case to make sure the short circuit path for swipe-to-navigations in +// APZ works, i.e. cases where we know for sure that the target APZC for a given +// pan-start event isn't scrollable in the pan-start event direction. +add_task(async () => { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["apz.overscroll.enabled", true], + ], + }); + + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:about", + true /* waitForLoad */ + ); + + const URL_ROOT = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + "http://mochi.test:8888/" + ); + BrowserTestUtils.startLoadingURIString( + tab.linkedBrowser, + URL_ROOT + "helper_swipe_gesture.html" + ); + await BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + false /* includeSubFrames */, + URL_ROOT + "helper_swipe_gesture.html" + ); + + // Make sure the content can allow both of overscrolling and + // swipe-to-navigations. + const overscrollBehaviorX = await SpecialPowers.spawn( + tab.linkedBrowser, + [], + () => { + return content.window.getComputedStyle(content.document.documentElement) + .overscrollBehaviorX; + } + ); + is(overscrollBehaviorX, "auto"); + + // Make sure we can go back to the previous page. + ok(gBrowser.webNavigation.canGoBack); + + // Start a pan gesture but keep touching. + await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 2); + + // The above pan event should invoke a SwipeGestureStart event immediately so + // that the swipe-to-navigation icon box should be uncollapsed to show it. + ok(!gHistorySwipeAnimation._prevBox.collapsed); + + // Finish the pan gesture, i.e. sending a pan-end event, otherwise a new + // pan-start event in the next will also generate a pan-interrupt event which + // will break the test. + await panLeftToRightUpdate(tab.linkedBrowser, 100, 100, 2); + await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 2); + + BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); +}); + +add_task(async () => { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["widget.swipe.velocity-twitch-tolerance", 0.0000001], + ["widget.swipe.success-velocity-contribution", 0.5], + ["apz.overscroll.enabled", true], + ["apz.test.logging_enabled", true], + ], + }); + + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:about", + true /* waitForLoad */ + ); + + const URL_ROOT = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + "http://mochi.test:8888/" + ); + BrowserTestUtils.startLoadingURIString( + tab.linkedBrowser, + URL_ROOT + "helper_swipe_gesture.html" + ); + await BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + false /* includeSubFrames */, + URL_ROOT + "helper_swipe_gesture.html" + ); + + // Make sure we can go back to the previous page. + ok(gBrowser.webNavigation.canGoBack); + + // Start a pan gesture but keep touching. + await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 2); + + // Flush APZ pending requests to make sure the pan gesture has been processed. + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + await content.wrappedJSObject.promiseApzFlushedRepaints(); + }); + + const isOverscrolled = await SpecialPowers.spawn( + tab.linkedBrowser, + [], + () => { + const scrollId = SpecialPowers.DOMWindowUtils.getViewId( + content.document.scrollingElement + ); + const data = SpecialPowers.DOMWindowUtils.getCompositorAPZTestData(); + return data.additionalData.some(entry => { + return entry.key == scrollId && entry.value.includes("overscrolled"); + }); + } + ); + + ok(!isOverscrolled, "The root scroller should not have overscrolled"); + + await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 0); + + BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); +}); + +add_task(async () => { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["widget.swipe.velocity-twitch-tolerance", 0.0000001], + ["widget.swipe.success-velocity-contribution", 0.5], + ], + }); + + // Load three pages and go to the second page so that it can be navigated + // to both back and forward. + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:about", + true /* waitForLoad */ + ); + + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, "about:mozilla"); + await BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + false /* includeSubFrames */, + "about:mozilla" + ); + + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, "about:home"); + await BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + false /* includeSubFrames */, + "about:home" + ); + + gBrowser.goBack(); + await BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + false /* includeSubFrames */, + "about:mozilla" + ); + + // Make sure we can go back and go forward. + ok(gBrowser.webNavigation.canGoBack); + ok(gBrowser.webNavigation.canGoForward); + + // Start a history back pan gesture but keep touching. + await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 1); + + ok( + !gHistorySwipeAnimation._prevBox.collapsed, + "The icon box for the previous navigation should NOT be collapsed" + ); + ok( + gHistorySwipeAnimation._nextBox.collapsed, + "The icon box for the next navigation should be collapsed" + ); + + // Pan back to the opposite direction so that the gesture should be cancelled. + // eslint-disable-next-line no-undef + await NativePanHandler.promiseNativePanEvent( + tab.linkedBrowser, + 100, + 100, + // eslint-disable-next-line no-undef + NativePanHandler.delta, + 0, + // eslint-disable-next-line no-undef + NativePanHandler.updatePhase + ); + + ok( + gHistorySwipeAnimation._prevBox.collapsed, + "The icon box for the previous navigation should be collapsed" + ); + ok( + gHistorySwipeAnimation._nextBox.collapsed, + "The icon box for the next navigation should be collapsed" + ); + + await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 0); + + BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); +}); + +add_task(async () => { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["widget.swipe.velocity-twitch-tolerance", 0.0000001], + ["widget.swipe.success-velocity-contribution", 0.5], + ["apz.overscroll.enabled", true], + ["apz.overscroll.damping", 5.0], + ["apz.content_response_timeout", 0], + ], + }); + + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:about", + true /* waitForLoad */ + ); + + const URL_ROOT = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + "http://mochi.test:8888/" + ); + + // Load a horizontal scrollable content. + BrowserTestUtils.startLoadingURIString( + tab.linkedBrowser, + URL_ROOT + "helper_swipe_gesture.html" + ); + await BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + false /* includeSubFrames */, + URL_ROOT + "helper_swipe_gesture.html" + ); + + // Make sure we can go back to the previous page. + ok(gBrowser.webNavigation.canGoBack); + + // Shift the horizontal scroll position slightly to make the content + // overscrollable. + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + content.document.documentElement.scrollLeft = 1; + content.document.documentElement.getBoundingClientRect(); + await content.wrappedJSObject.promiseApzFlushedRepaints(); + }); + + // Swipe horizontally to overscroll. + await panLeftToRight(tab.linkedBrowser, 1, 100, 1); + + // Swipe again over the overscroll gutter. + await panLeftToRight(tab.linkedBrowser, 1, 100, 1); + + // Wait the overscroll gutter is restored. + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + // For some reasons using functions in apz_test_native_event_utils.js + // sometimes causes "TypeError content.wrappedJSObject.XXXX is not a + // function" error, so we observe "APZ:TransformEnd" instead of using + // promiseTransformEnd(). + await new Promise((resolve, reject) => { + SpecialPowers.Services.obs.addObserver(function observer( + subject, + topic, + data + ) { + try { + SpecialPowers.Services.obs.removeObserver(observer, topic); + resolve([subject, data]); + } catch (ex) { + SpecialPowers.Services.obs.removeObserver(observer, topic); + reject(ex); + } + }, + "APZ:TransformEnd"); + }); + }); + + // Set up an APZ aware event listener and... + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + content.document.documentElement.addEventListener("wheel", e => {}, { + passive: false, + }); + await content.wrappedJSObject.promiseApzFlushedRepaints(); + }); + + // Try to swipe back again without overscrolling to make sure swipe-navigation + // works with the APZ aware event listener. + await panLeftToRight(tab.linkedBrowser, 100, 100, 1); + + let startLoadingPromise = BrowserTestUtils.browserStarted( + tab.linkedBrowser, + "about:about" + ); + let stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + "about:about" + ); + + await Promise.all([startLoadingPromise, stoppedLoadingPromise]); + + ok(gBrowser.webNavigation.canGoForward); + + BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); +}); + +// NOTE: This test listens wheel events so that it causes an overscroll issue +// (bug 1800022). To avoid the bug, we need to run this test case at the end +// of this file. +add_task(async () => { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"], + ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"], + ["widget.disable-swipe-tracker", false], + ["widget.swipe.velocity-twitch-tolerance", 0.0000001], + ["widget.swipe.success-velocity-contribution", 0.5], + ], + }); + + const firstPage = "about:about"; + const secondPage = "about:mozilla"; + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + firstPage, + true /* waitForLoad */ + ); + + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage); + + // Make sure we can go back to the previous page. + ok(gBrowser.webNavigation.canGoBack); + // and we cannot go forward to the next page. + ok(!gBrowser.webNavigation.canGoForward); + + let wheelEventCount = 0; + tab.linkedBrowser.addEventListener("wheel", () => { + wheelEventCount++; + }); + + // Try to navigate forward. + await panRightToLeft(tab.linkedBrowser, 100, 100, 1); + // NOTE: The last endPhase shouldn't fire a wheel event since + // its delta is zero. + is(wheelEventCount, 2, "Received 2 wheel events"); + + await waitForWhile(); + // Make sure any navigation didn't happen. + is(tab.linkedBrowser.currentURI.spec, secondPage); + + // Try to navigate backward. + wheelEventCount = 0; + let startLoadingPromise = BrowserTestUtils.browserStarted( + tab.linkedBrowser, + firstPage + ); + let stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + firstPage + ); + await panLeftToRight(tab.linkedBrowser, 100, 100, 1); + // NOTE: We only get a wheel event for the beginPhase, rest of events have + // been captured by the swipe gesture module. + is(wheelEventCount, 1, "Received a wheel event"); + + // Make sure the gesture triggered going back to the previous page. + await Promise.all([startLoadingPromise, stoppedLoadingPromise]); + + ok(gBrowser.webNavigation.canGoForward); + + // Now try to navigate forward again. + wheelEventCount = 0; + startLoadingPromise = BrowserTestUtils.browserStarted( + tab.linkedBrowser, + secondPage + ); + stoppedLoadingPromise = BrowserTestUtils.browserStopped( + tab.linkedBrowser, + secondPage + ); + await panRightToLeft(tab.linkedBrowser, 100, 100, 1); + is(wheelEventCount, 1, "Received a wheel event"); + + await Promise.all([startLoadingPromise, stoppedLoadingPromise]); + + ok(gBrowser.webNavigation.canGoBack); + + // Now try to navigate backward again but with preventDefault-ed event + // handler. + wheelEventCount = 0; + let wheelEventListener = event => { + event.preventDefault(); + }; + tab.linkedBrowser.addEventListener("wheel", wheelEventListener); + await panLeftToRight(tab.linkedBrowser, 100, 100, 1); + is(wheelEventCount, 3, "Received all wheel events"); + + await waitForWhile(); + // Make sure any navigation didn't happen. + is(tab.linkedBrowser.currentURI.spec, secondPage); + + // Now drop the event handler and disable the swipe tracker and try to swipe + // again. + wheelEventCount = 0; + tab.linkedBrowser.removeEventListener("wheel", wheelEventListener); + await SpecialPowers.pushPrefEnv({ + set: [["widget.disable-swipe-tracker", true]], + }); + + await panLeftToRight(tab.linkedBrowser, 100, 100, 1); + is(wheelEventCount, 3, "Received all wheel events"); + + await waitForWhile(); + // Make sure any navigation didn't happen. + is(tab.linkedBrowser.currentURI.spec, secondPage); + + BrowserTestUtils.removeTab(tab); + await SpecialPowers.popPrefEnv(); +}); diff --git a/widget/tests/browser/file_ime_state_tests.html b/widget/tests/browser/file_ime_state_tests.html new file mode 100644 index 0000000000..d6b63f1e52 --- /dev/null +++ b/widget/tests/browser/file_ime_state_tests.html @@ -0,0 +1,48 @@ + + + + + + + + + + + + +
+ diff --git a/widget/tests/browser/helper_scrollbar_colors.html b/widget/tests/browser/helper_scrollbar_colors.html new file mode 100644 index 0000000000..e6001906e2 --- /dev/null +++ b/widget/tests/browser/helper_scrollbar_colors.html @@ -0,0 +1,22 @@ + + + +Test for scrollbar-*-color properties + + +
+
+
+
+ diff --git a/widget/tests/browser/helper_swipe_gesture.html b/widget/tests/browser/helper_swipe_gesture.html new file mode 100644 index 0000000000..1fa79dbbf3 --- /dev/null +++ b/widget/tests/browser/helper_swipe_gesture.html @@ -0,0 +1,20 @@ + + + + + + +
+ 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.toml b/widget/tests/chrome.toml new file mode 100644 index 0000000000..08d02d3c36 --- /dev/null +++ b/widget/tests/chrome.toml @@ -0,0 +1,200 @@ +[DEFAULT] +skip-if = ["os == 'android'"] +support-files = [ + "empty_window.xhtml", + "clipboard_helper.js", +] + +["test_alwaysontop_focus.xhtml"] + +# Privacy relevant + +["test_bug1123480.xhtml"] +skip-if = ["win11_2009 && bits == 32"] + +["test_bug343416.xhtml"] +skip-if = ["debug"] + +["test_bug428405.xhtml"] +run-if = ["os == 'mac'"] # Cocoa widget test + +["test_bug429954.xhtml"] +support-files = ["window_bug429954.xhtml"] + +["test_bug444800.xhtml"] + +["test_bug466599.xhtml"] +run-if = ["os == 'mac'"] # Cocoa widget test + +["test_bug478536.xhtml"] +skip-if = ["true"] # Bug 561929 +support-files = ["window_bug478536.xhtml"] + +["test_bug485118.xhtml"] +run-if = ["os == 'mac'"] # Cocoa widget test + +["test_bug517396.xhtml"] +skip-if = ["verify && os == 'win'"] + +["test_bug522217.xhtml"] +tags = "fullscreen" +run-if = ["os == 'mac'"] # Cocoa widget test +support-files = ["window_bug522217.xhtml"] + +["test_bug538242.xhtml"] +support-files = ["window_bug538242.xhtml"] + +["test_bug565392.html"] +run-if = ["os == 'win'"] + +["test_bug586713.xhtml"] +run-if = ["os == 'mac'"] # Cocoa widget test +support-files = ["bug586713_window.xhtml"] + +["test_bug593307.xhtml"] +support-files = [ + "window_bug593307_offscreen.xhtml", + "window_bug593307_centerscreen.xhtml", +] + +["test_bug596600.xhtml"] +support-files = "file_bug596600.html" +run-if = ["os == 'mac'"] # Cocoa widget test + +["test_bug673301.xhtml"] +run-if = ["os == 'mac'"] # Cocoa widget test + +["test_bug760802.xhtml"] + +["test_clipboard_chrome.html"] +support-files = "file_test_clipboard.js" + +["test_clipboard_asyncGetData_chrome.html"] +support-files = "file_test_clipboard_asyncGetData.js" + +["test_clipboard_asyncSetData_chrome.html"] +support-files = "file_test_clipboard_asyncSetData.js" + +["test_clipboard_cache_chrome.html"] + +["test_clipboard_owner_chrome.html"] + +["test_composition_text_querycontent.xhtml"] +support-files = ["window_composition_text_querycontent.xhtml"] + +["test_ime_state_in_contenteditable_on_readonly_change_in_parent.html"] +support-files = [ + "file_ime_state_test_helper.js", + "file_test_ime_state_in_contenteditable_on_readonly_change.js", +] + +["test_ime_state_in_plugin_in_parent.html"] +support-files = ["file_ime_state_test_helper.js"] + +["test_ime_state_in_text_control_on_reframe_in_parent.html"] +support-files = [ + "file_ime_state_test_helper.js", + "file_test_ime_state_in_text_control_on_reframe.js", +] + +["test_ime_state_on_editable_state_change_in_parent.html"] +support-files = ["file_ime_state_test_helper.js"] + +["test_ime_state_on_focus_move_in_parent.html"] +support-files = [ + "file_ime_state_test_helper.js", + "file_test_ime_state_on_focus_move.js", +] + +["test_ime_state_on_input_type_change_in_parent.html"] +skip-if = ["true"] # Bug 1817704 +support-files = [ + "file_ime_state_test_helper.js", + "file_test_ime_state_on_input_type_change.js", +] + +["test_ime_state_on_readonly_change_in_parent.html"] +support-files = [ + "file_ime_state_test_helper.js", + "file_test_ime_state_on_readonly_change.js", +] + +["test_ime_state_others_in_parent.html"] +support-files = ["window_imestate_iframes.html"] + +["test_input_events_on_deactive_window.xhtml"] +support-files = ["file_input_events_on_deactive_window.html"] + +["test_key_event_counts.xhtml"] +run-if = ["os == 'mac'"] # Cocoa widget test + +["test_keycodes.xhtml"] + +["test_mouse_scroll.xhtml"] +run-if = ["os == 'win'"] # windows widget test +support-files = [ + "window_mouse_scroll_win.html", + "window_mouse_scroll_win_2.html", +] + +["test_native_key_bindings_mac.html"] +run-if = ["os == 'mac'"] # Cocoa widget test +skip-if = [ + "verify", +] + +["test_native_menus.xhtml"] +run-if = ["os == 'mac'"] # Cocoa widget test +support-files = ["native_menus_window.xhtml"] + +["test_panel_mouse_coords.xhtml"] +skip-if = ["os == 'win'"] # bug 1009955 + +["test_platform_colors.xhtml"] +skip-if = ["true"] # Bug 1207190 + +["test_position_on_resize.xhtml"] +skip-if = [ + "verify && os == 'win'", + "os == 'linux' && bits == 64", # Bug 1616760 +] + +["test_secure_input.html"] +run-if = ["os == 'mac'"] # Cocoa widget test +support-files = ["file_secure_input.html"] + +["test_sizemode_events.xhtml"] + +["test_standalone_native_menu.xhtml"] +run-if = ["os == 'mac'"] # Cocoa widget test +support-files = ["standalone_native_menu_window.xhtml"] + +["test_surrogate_pair_native_key_handling.xhtml"] +run-if = ["os == 'win'"] # Windows widget test + +["test_system_font_changes.xhtml"] +support-files = ["system_font_changes.xhtml"] +run-if = ["os == 'linux'"] # Currently the test works on only gtk3 + +["test_system_status_bar.xhtml"] +run-if = ["os == 'mac'"] # Cocoa widget test + +["test_taskbar_progress.xhtml"] +skip-if = [ + "os == 'linux'", + "os == 'android'", + "win10_2009 && !ccov", # Bug 1456811 +] + +["test_transferable_overflow.xhtml"] +skip-if = [ + "verify && apple_catalina", + "verify && os == 'linux'", +] + +["test_wheeltransaction.xhtml"] +support-files = ["window_wheeltransaction.xhtml"] + +# Windows +# taskbar_previews.xhtml +# window_state_windows.xhtml diff --git a/widget/tests/clipboard_helper.js b/widget/tests/clipboard_helper.js new file mode 100644 index 0000000000..96787468fb --- /dev/null +++ b/widget/tests/clipboard_helper.js @@ -0,0 +1,230 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const Cc = SpecialPowers.Cc; +const Ci = SpecialPowers.Ci; +const Cr = SpecialPowers.Cr; +const clipboard = SpecialPowers.Services.clipboard; +const clipboardTypes = [ + clipboard.kGlobalClipboard, + clipboard.kSelectionClipboard, + clipboard.kFindClipboard, + clipboard.kSelectionCache, +]; + +function emptyClipboardData(aType) { + // XXX gtk doesn't support emptying clipboard data which is stored from + // other application (bug 1853884). As a workaround, we set dummy data + // to the clipboard first to ensure the subsequent emptyClipboard call + // works. + if (navigator.platform.includes("Linux")) { + writeStringToClipboard("foo", "text/plain", aType); + } + + clipboard.emptyClipboard(aType); +} + +function cleanupAllClipboard() { + clipboardTypes.forEach(function (type) { + if (clipboard.isClipboardTypeSupported(type)) { + info(`cleanup clipboard ${type}`); + emptyClipboardData(type); + } + }); +} + +function generateRandomString() { + return "random number: " + Math.random(); +} + +function generateNewTransferable(aFlavor, aStr) { + let trans = Cc["@mozilla.org/widget/transferable;1"].createInstance( + Ci.nsITransferable + ); + trans.init(null); + trans.addDataFlavor(aFlavor); + + let supportsStr = Cc["@mozilla.org/supports-string;1"].createInstance( + Ci.nsISupportsString + ); + supportsStr.data = aStr; + trans.setTransferData(aFlavor, supportsStr); + + return trans; +} + +function addStringToTransferable(aFlavor, aStr, aTrans) { + aTrans.addDataFlavor(aFlavor); + + let supportsStr = Cc["@mozilla.org/supports-string;1"].createInstance( + Ci.nsISupportsString + ); + supportsStr.data = aStr; + aTrans.setTransferData(aFlavor, supportsStr); +} + +function updateStringToTransferable(aFlavor, aStr, aTrans) { + let supportsStr = Cc["@mozilla.org/supports-string;1"].createInstance( + Ci.nsISupportsString + ); + supportsStr.data = aStr; + aTrans.setTransferData(aFlavor, supportsStr); +} + +function writeStringToClipboard( + aStr, + aFlavor, + aClipboardType, + aClipboardOwner = null, + aAsync = false +) { + let trans = Cc["@mozilla.org/widget/transferable;1"].createInstance( + Ci.nsITransferable + ); + trans.init(null); + trans.addDataFlavor(aFlavor); + + let supportsStr = Cc["@mozilla.org/supports-string;1"].createInstance( + Ci.nsISupportsString + ); + supportsStr.data = aStr; + trans.setTransferData(aFlavor, supportsStr); + + if (aAsync) { + let request = clipboard.asyncSetData(aClipboardType); + request.setData(trans, aClipboardOwner); + return; + } + + clipboard.setData(trans, aClipboardOwner, aClipboardType); + // XXX gtk doesn't support get empty text data from clipboard, bug 1852983. + if (aStr == "" && navigator.platform.includes("Linux")) { + todo_is( + getClipboardData(aFlavor, aClipboardType), + "", + `Should get empty string on clipboard type ${aClipboardType}` + ); + } else { + is( + getClipboardData(aFlavor, aClipboardType), + // On Windows, widget adds extra data into HTML clipboard. + aFlavor == "text/html" && navigator.platform.includes("Win") + ? `\n${aStr}\n\n` + : aStr, + "ensure clipboard data is set" + ); + } +} + +function writeRandomStringToClipboard( + aFlavor, + aClipboardType, + aClipboardOwner = null, + aAsync = false +) { + let randomString = generateRandomString(); + writeStringToClipboard( + randomString, + aFlavor, + aClipboardType, + aClipboardOwner, + aAsync + ); + return randomString; +} + +function getClipboardData(aFlavor, aClipboardType) { + var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance( + Ci.nsITransferable + ); + trans.init(null); + trans.addDataFlavor(aFlavor); + clipboard.getData( + trans, + aClipboardType, + SpecialPowers.wrap(window).browsingContext.currentWindowContext + ); + + try { + var data = SpecialPowers.createBlankObject(); + trans.getTransferData(aFlavor, data); + return data.value.QueryInterface(SpecialPowers.Ci.nsISupportsString).data; + } catch (ex) { + // If the clipboard is empty getTransferData will throw. + return null; + } +} + +function asyncGetClipboardData(aClipboardType) { + return new Promise((resolve, reject) => { + try { + clipboard.asyncGetData( + ["text/plain", "text/html", "image/png"], + aClipboardType, + null, + SpecialPowers.Services.scriptSecurityManager.getSystemPrincipal(), + { + QueryInterface: SpecialPowers.ChromeUtils.generateQI([ + "nsIAsyncClipboardGetCallback", + ]), + // nsIAsyncClipboardGetCallback + onSuccess: SpecialPowers.wrapCallback(function ( + aAsyncGetClipboardData + ) { + resolve(aAsyncGetClipboardData); + }), + onError: SpecialPowers.wrapCallback(function (aResult) { + reject(aResult); + }), + } + ); + } catch (e) { + ok(false, `asyncGetData should not throw`); + reject(e); + } + }); +} + +function asyncClipboardRequestGetData(aRequest, aFlavor, aThrows = false) { + return new Promise((resolve, reject) => { + var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance( + Ci.nsITransferable + ); + trans.init(null); + trans.addDataFlavor(aFlavor); + try { + aRequest.getData(trans, aResult => { + if (aResult != Cr.NS_OK) { + reject(aResult); + return; + } + + try { + var data = SpecialPowers.createBlankObject(); + trans.getTransferData(aFlavor, data); + resolve(data.value.QueryInterface(Ci.nsISupportsString).data); + } catch (ex) { + // XXX: should widget set empty string to transferable when there no + // data in system clipboard? + resolve(""); + } + }); + ok( + !aThrows, + `nsIAsyncGetClipboardData.getData should ${ + aThrows ? "throw" : "success" + }` + ); + } catch (e) { + ok( + aThrows, + `nsIAsyncGetClipboardData.getData should ${ + aThrows ? "throw" : "success" + }` + ); + reject(e); + } + }); +} 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_ime_state_test_helper.js b/widget/tests/file_ime_state_test_helper.js new file mode 100644 index 0000000000..0cee5c036f --- /dev/null +++ b/widget/tests/file_ime_state_test_helper.js @@ -0,0 +1,197 @@ +"use strict"; + +function IsIMEOpenStateSupported() { + // We support to control IME open state on Windows and Mac actually. However, + // we cannot test it on Mac if the current keyboard layout is not CJK. And also + // we cannot test it on Win32 if the system didn't be installed IME. So, + // currently we should not run the open state testing. + return false; +} + +/** + * @param {Node} aNode + */ +function nodeIsInShadowDOM(aNode) { + for (let node = aNode; node; node = node.parentNode) { + if (node instanceof ShadowRoot) { + return true; + } + if (node == node.parentNode) { + break; + } + } + return false; +} + +/** + * @param {Node} aNode + */ +function nodeIsInDesignMode(aNode) { + return ( + aNode.isConnected && + !nodeIsInShadowDOM(aNode) && + aNode.ownerDocument.designMode == "on" + ); +} + +/** + * param {Node} aNode + */ +function getEditingHost(aNode) { + if (nodeIsInDesignMode(aNode)) { + return aNode.ownerDocument.documentElement; + } + for ( + let element = + aNode.nodeType == Node.ELEMENT_NODE ? aNode : aNode.parentElement; + element; + element = element.parentElement + ) { + const contenteditable = element.getAttribute("contenteditable"); + if (contenteditable === "true" || contenteditable === "") { + return element; + } + if (contenteditable === "false") { + return null; + } + } + return null; +} + +/** + * @param {Node} aNode + */ +function nodeIsEditable(aNode) { + if (nodeIsInDesignMode(aNode)) { + return true; + } + if (!aNode.isConnected) { + return false; + } + return getEditingHost(aNode) != null; +} + +/** + * @param {Element} aElement + */ +function elementIsEditingHost(aElement) { + return ( + nodeIsEditable(aElement) && + (!aElement.parentElement || !getEditingHost(aElement) == aElement) + ); +} + +/** + * @returns {Element} Retrieve focused element. If focused element is a element + * in UA widget, this returns its host element. E.g., when + * a button in the controls of
+
+
+
+ + diff --git a/widget/tests/test_alwaysontop_focus.xhtml b/widget/tests/test_alwaysontop_focus.xhtml new file mode 100644 index 0000000000..b9cc3ee33c --- /dev/null +++ b/widget/tests/test_alwaysontop_focus.xhtml @@ -0,0 +1,38 @@ + + + + + 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..1da9bb535f
--- /dev/null
+++ b/widget/tests/test_assign_event_data.html
@@ -0,0 +1,708 @@
+
+
+
+  Testing ns*Event::Assign*EventData()
+  
+  
+  
+  
+  
+
+
+
+ + + hyper link + span +
+
form
+
 
+
+ +
+
+ + + diff --git a/widget/tests/test_autocapitalize.html b/widget/tests/test_autocapitalize.html new file mode 100644 index 0000000000..de628d1190 --- /dev/null +++ b/widget/tests/test_autocapitalize.html @@ -0,0 +1,62 @@ + + + +Tests for autocapitalize that is used by software keyboard + + + + + +

+ + +
+
+
+
+
+
+
+
+
+
+
+

+

+

+

+
+ +
+
+
+ + diff --git a/widget/tests/test_bug1123480.xhtml b/widget/tests/test_bug1123480.xhtml new file mode 100644 index 0000000000..18a40202fd --- /dev/null +++ b/widget/tests/test_bug1123480.xhtml @@ -0,0 +1,155 @@ + + + + + + nsTransferable PBM Overflow Selection Test + + + + + Mozilla Bug 1123480 + + diff --git a/widget/tests/test_bug343416.xhtml b/widget/tests/test_bug343416.xhtml new file mode 100644 index 0000000000..bf4dbbb9b4 --- /dev/null +++ b/widget/tests/test_bug343416.xhtml @@ -0,0 +1,191 @@ + + + + + + + + + diff --git a/widget/tests/test_bug428405.xhtml b/widget/tests/test_bug428405.xhtml new file mode 100644 index 0000000000..25d796ab7b --- /dev/null +++ b/widget/tests/test_bug428405.xhtml @@ -0,0 +1,168 @@ + + + + + + + + + + +

+ +

+  
+
+
diff --git a/widget/tests/test_bug429954.xhtml b/widget/tests/test_bug429954.xhtml new file mode 100644 index 0000000000..40de88cd32 --- /dev/null +++ b/widget/tests/test_bug429954.xhtml @@ -0,0 +1,42 @@ + + + + + + + + + diff --git a/widget/tests/test_bug444800.xhtml b/widget/tests/test_bug444800.xhtml new file mode 100644 index 0000000000..f6d3535d72 --- /dev/null +++ b/widget/tests/test_bug444800.xhtml @@ -0,0 +1,97 @@ + + + + + + + diff --git a/widget/tests/test_bug466599.xhtml b/widget/tests/test_bug466599.xhtml new file mode 100644 index 0000000000..95b3593437 --- /dev/null +++ b/widget/tests/test_bug466599.xhtml @@ -0,0 +1,102 @@ + + + + + + + diff --git a/widget/tests/test_bug478536.xhtml b/widget/tests/test_bug478536.xhtml new file mode 100644 index 0000000000..383c0bb42f --- /dev/null +++ b/widget/tests/test_bug478536.xhtml @@ -0,0 +1,33 @@ + + + + + + + Test for Bug 478536 + + + diff --git a/widget/tests/test_bug485118.xhtml b/widget/tests/test_bug485118.xhtml new file mode 100644 index 0000000000..5c635f2982 --- /dev/null +++ b/widget/tests/test_bug485118.xhtml @@ -0,0 +1,72 @@ + + + + + + + + + diff --git a/widget/tests/test_bug517396.xhtml b/widget/tests/test_bug517396.xhtml new file mode 100644 index 0000000000..c88baf49ab --- /dev/null +++ b/widget/tests/test_bug517396.xhtml @@ -0,0 +1,53 @@ + + + + + + + + + diff --git a/widget/tests/test_bug522217.xhtml b/widget/tests/test_bug522217.xhtml new file mode 100644 index 0000000000..0fa55a65e8 --- /dev/null +++ b/widget/tests/test_bug522217.xhtml @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/widget/tests/test_bug538242.xhtml b/widget/tests/test_bug538242.xhtml new file mode 100644 index 0000000000..4608a74e35 --- /dev/null +++ b/widget/tests/test_bug538242.xhtml @@ -0,0 +1,55 @@ + + + + + + + + + diff --git a/widget/tests/test_bug565392.html b/widget/tests/test_bug565392.html new file mode 100644 index 0000000000..b50053f23a --- /dev/null +++ b/widget/tests/test_bug565392.html @@ -0,0 +1,62 @@ + + + + + Test for Bug 565392 + + + + +Mozilla Bug 565392 +

+ +
+
+
+ + diff --git a/widget/tests/test_bug586713.xhtml b/widget/tests/test_bug586713.xhtml new file mode 100644 index 0000000000..4733202264 --- /dev/null +++ b/widget/tests/test_bug586713.xhtml @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/widget/tests/test_bug593307.xhtml b/widget/tests/test_bug593307.xhtml new file mode 100644 index 0000000000..770dd390cb --- /dev/null +++ b/widget/tests/test_bug593307.xhtml @@ -0,0 +1,40 @@ + + + + + + + + + diff --git a/widget/tests/test_bug596600.xhtml b/widget/tests/test_bug596600.xhtml new file mode 100644 index 0000000000..4acdab79bc --- /dev/null +++ b/widget/tests/test_bug596600.xhtml @@ -0,0 +1,190 @@ + + + + + + + + diff --git a/widget/tests/test_bug673301.xhtml b/widget/tests/test_bug673301.xhtml new file mode 100644 index 0000000000..663f18397e --- /dev/null +++ b/widget/tests/test_bug673301.xhtml @@ -0,0 +1,33 @@ + + + + + + + + diff --git a/widget/tests/test_bug760802.xhtml b/widget/tests/test_bug760802.xhtml new file mode 100644 index 0000000000..831b4dea93 --- /dev/null +++ b/widget/tests/test_bug760802.xhtml @@ -0,0 +1,81 @@ + + + + + + + diff --git a/widget/tests/test_clipboard.html b/widget/tests/test_clipboard.html new file mode 100644 index 0000000000..35ad84ad73 --- /dev/null +++ b/widget/tests/test_clipboard.html @@ -0,0 +1,16 @@ + + + + +Test for Bug 948065 + + + + + + + + + diff --git a/widget/tests/test_clipboard_asyncGetData.html b/widget/tests/test_clipboard_asyncGetData.html new file mode 100644 index 0000000000..0cb3dc2aa1 --- /dev/null +++ b/widget/tests/test_clipboard_asyncGetData.html @@ -0,0 +1,19 @@ + + + + +Test for Bug 1852947 + + + + + +

+ +

+
+
+
+
diff --git a/widget/tests/test_clipboard_asyncGetData_chrome.html b/widget/tests/test_clipboard_asyncGetData_chrome.html
new file mode 100644
index 0000000000..d4e44185a5
--- /dev/null
+++ b/widget/tests/test_clipboard_asyncGetData_chrome.html
@@ -0,0 +1,19 @@
+
+
+
+
+Test for Bug 1852947
+
+
+
+
+
+

+ +

+
+
+
+
diff --git a/widget/tests/test_clipboard_asyncSetData.html b/widget/tests/test_clipboard_asyncSetData.html
new file mode 100644
index 0000000000..05e2ca714b
--- /dev/null
+++ b/widget/tests/test_clipboard_asyncSetData.html
@@ -0,0 +1,19 @@
+
+
+
+
+Test for Bug 1712122
+
+
+
+
+
+

+ +

+
+
+
+
diff --git a/widget/tests/test_clipboard_asyncSetData_chrome.html b/widget/tests/test_clipboard_asyncSetData_chrome.html
new file mode 100644
index 0000000000..61afb9067b
--- /dev/null
+++ b/widget/tests/test_clipboard_asyncSetData_chrome.html
@@ -0,0 +1,19 @@
+
+
+
+
+Test for Bug 1712122
+
+
+
+
+
+

+ +

+
+
+
+
diff --git a/widget/tests/test_clipboard_cache_chrome.html b/widget/tests/test_clipboard_cache_chrome.html
new file mode 100644
index 0000000000..55b6d41589
--- /dev/null
+++ b/widget/tests/test_clipboard_cache_chrome.html
@@ -0,0 +1,231 @@
+
+
+
+
+Test for Bug 1812543
+
+
+
+
+
+

+ +

+
+
+
diff --git a/widget/tests/test_clipboard_chrome.html b/widget/tests/test_clipboard_chrome.html
new file mode 100644
index 0000000000..387e3975b3
--- /dev/null
+++ b/widget/tests/test_clipboard_chrome.html
@@ -0,0 +1,16 @@
+
+
+
+
+Test for Bug 948065
+
+
+
+
+
+
+
+
+
diff --git a/widget/tests/test_clipboard_owner_chrome.html b/widget/tests/test_clipboard_owner_chrome.html
new file mode 100644
index 0000000000..4759b2b14c
--- /dev/null
+++ b/widget/tests/test_clipboard_owner_chrome.html
@@ -0,0 +1,75 @@
+
+
+
+
+Test for Bug 1812078
+
+
+
+
+
+

+ +

+
+
+
diff --git a/widget/tests/test_composition_text_querycontent.xhtml b/widget/tests/test_composition_text_querycontent.xhtml
new file mode 100644
index 0000000000..48b7af8100
--- /dev/null
+++ b/widget/tests/test_composition_text_querycontent.xhtml
@@ -0,0 +1,34 @@
+
+
+
+
+
+  
+
diff --git a/widget/tests/test_contextmenu_by_mouse_on_unix.html b/widget/tests/test_contextmenu_by_mouse_on_unix.html
new file mode 100644
index 0000000000..2b1f643dfc
--- /dev/null
+++ b/widget/tests/test_contextmenu_by_mouse_on_unix.html
@@ -0,0 +1,105 @@
+
+
+
+Test to fire contextmenu event by widget level
+
+
+
+
+
+
+
+
+
+ + diff --git a/widget/tests/test_ime_state_in_contenteditable_on_readonly_change_in_parent.html b/widget/tests/test_ime_state_in_contenteditable_on_readonly_change_in_parent.html new file mode 100644 index 0000000000..8d8662a8d8 --- /dev/null +++ b/widget/tests/test_ime_state_in_contenteditable_on_readonly_change_in_parent.html @@ -0,0 +1,72 @@ + + + Test for IME state of contenteditable on readonly state change + + + + + + +

+ diff --git a/widget/tests/test_ime_state_in_plugin_in_parent.html b/widget/tests/test_ime_state_in_plugin_in_parent.html new file mode 100644 index 0000000000..9f3892ab88 --- /dev/null +++ b/widget/tests/test_ime_state_in_plugin_in_parent.html @@ -0,0 +1,92 @@ + + + Test for IME state on plugin + + + + + + + + + + diff --git a/widget/tests/test_ime_state_in_text_control_on_reframe_in_parent.html b/widget/tests/test_ime_state_in_text_control_on_reframe_in_parent.html new file mode 100644 index 0000000000..ab38806261 --- /dev/null +++ b/widget/tests/test_ime_state_in_text_control_on_reframe_in_parent.html @@ -0,0 +1,42 @@ + + + Test for IME state of contenteditable on readonly state change + + + + + + + + diff --git a/widget/tests/test_ime_state_on_editable_state_change_in_parent.html b/widget/tests/test_ime_state_on_editable_state_change_in_parent.html new file mode 100644 index 0000000000..a1b307a51f --- /dev/null +++ b/widget/tests/test_ime_state_on_editable_state_change_in_parent.html @@ -0,0 +1,263 @@ + + + + + Test for IME state management at changing editable state + + + + + +
+ + + diff --git a/widget/tests/test_ime_state_on_focus_move_in_parent.html b/widget/tests/test_ime_state_on_focus_move_in_parent.html new file mode 100644 index 0000000000..fd74d61c7e --- /dev/null +++ b/widget/tests/test_ime_state_on_focus_move_in_parent.html @@ -0,0 +1,88 @@ + + + + + Test for IME state management on focus move in parent process + + + + + + + +
+ + + diff --git a/widget/tests/test_ime_state_on_input_type_change_in_parent.html b/widget/tests/test_ime_state_on_input_type_change_in_parent.html new file mode 100644 index 0000000000..2644c31e3f --- /dev/null +++ b/widget/tests/test_ime_state_on_input_type_change_in_parent.html @@ -0,0 +1,39 @@ + + + Test for IME state on input type change + + + + + + + + + diff --git a/widget/tests/test_ime_state_on_readonly_change_in_parent.html b/widget/tests/test_ime_state_on_readonly_change_in_parent.html new file mode 100644 index 0000000000..0557856542 --- /dev/null +++ b/widget/tests/test_ime_state_on_readonly_change_in_parent.html @@ -0,0 +1,31 @@ + + + Test for IME state on readonly state change + + + + + + + + + diff --git a/widget/tests/test_ime_state_others_in_parent.html b/widget/tests/test_ime_state_others_in_parent.html new file mode 100644 index 0000000000..e6ae0ab272 --- /dev/null +++ b/widget/tests/test_ime_state_others_in_parent.html @@ -0,0 +1,153 @@ + + + Test for IME state controlling in some special cases + + + + + + +
+ +

+
+
+
diff --git a/widget/tests/test_input_events_on_deactive_window.xhtml b/widget/tests/test_input_events_on_deactive_window.xhtml
new file mode 100644
index 0000000000..d54699f76c
--- /dev/null
+++ b/widget/tests/test_input_events_on_deactive_window.xhtml
@@ -0,0 +1,233 @@
+
+
+
+
+
+  
+
diff --git a/widget/tests/test_key_event_counts.xhtml b/widget/tests/test_key_event_counts.xhtml
new file mode 100644
index 0000000000..6eda6a52fb
--- /dev/null
+++ b/widget/tests/test_key_event_counts.xhtml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+  
+
+
diff --git a/widget/tests/test_keycodes.xhtml b/widget/tests/test_keycodes.xhtml
new file mode 100644
index 0000000000..aea6aaae98
--- /dev/null
+++ b/widget/tests/test_keycodes.xhtml
@@ -0,0 +1,5647 @@
+
+
+
+
+
+  
+
+
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..01d4100f97
--- /dev/null
+++ b/widget/tests/test_keypress_event_with_alt_on_mac.html
@@ -0,0 +1,106 @@
+
+
+
+  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..52ce206d35 --- /dev/null +++ b/widget/tests/test_mouse_event_with_control_on_mac.html @@ -0,0 +1,116 @@ + + + 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_native_menus.xhtml b/widget/tests/test_native_menus.xhtml new file mode 100644 index 0000000000..d62c57f21c --- /dev/null +++ b/widget/tests/test_native_menus.xhtml @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/widget/tests/test_panel_mouse_coords.xhtml b/widget/tests/test_panel_mouse_coords.xhtml new file mode 100644 index 0000000000..43c4e10249 --- /dev/null +++ b/widget/tests/test_panel_mouse_coords.xhtml @@ -0,0 +1,78 @@ + + + + + + + diff --git a/widget/tests/test_picker_no_crash.html b/widget/tests/test_picker_no_crash.html new file mode 100644 index 0000000000..dbb75627b5 --- /dev/null +++ b/widget/tests/test_picker_no_crash.html @@ -0,0 +1,30 @@ + +Test for crashes when the parent window of a file picker is closed via script + + + + diff --git a/widget/tests/test_platform_colors.xhtml b/widget/tests/test_platform_colors.xhtml new file mode 100644 index 0000000000..8f9860d85b --- /dev/null +++ b/widget/tests/test_platform_colors.xhtml @@ -0,0 +1,95 @@ + + + + + + + + diff --git a/widget/tests/test_position_on_resize.xhtml b/widget/tests/test_position_on_resize.xhtml new file mode 100644 index 0000000000..a7c5551018 --- /dev/null +++ b/widget/tests/test_position_on_resize.xhtml @@ -0,0 +1,90 @@ + + + + + + + + + +

+

+ +
+
+ + +
diff --git a/widget/tests/test_secure_input.html b/widget/tests/test_secure_input.html new file mode 100644 index 0000000000..846465b4c2 --- /dev/null +++ b/widget/tests/test_secure_input.html @@ -0,0 +1,141 @@ + + + + Test for secure input mode + + + + + + + +
+
+ +

+
+
+
+
+
+
+

+
+ + + + diff --git a/widget/tests/test_sizemode_events.xhtml b/widget/tests/test_sizemode_events.xhtml new file mode 100644 index 0000000000..bd1e3a38d1 --- /dev/null +++ b/widget/tests/test_sizemode_events.xhtml @@ -0,0 +1,148 @@ + + + + + + + + diff --git a/widget/tests/test_standalone_native_menu.xhtml b/widget/tests/test_standalone_native_menu.xhtml new file mode 100644 index 0000000000..96e41036c3 --- /dev/null +++ b/widget/tests/test_standalone_native_menu.xhtml @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/widget/tests/test_surrogate_pair_native_key_handling.xhtml b/widget/tests/test_surrogate_pair_native_key_handling.xhtml new file mode 100644 index 0000000000..98834e1206 --- /dev/null +++ b/widget/tests/test_surrogate_pair_native_key_handling.xhtml @@ -0,0 +1,178 @@ + + + + + + + + + diff --git a/widget/tests/test_system_font_changes.xhtml b/widget/tests/test_system_font_changes.xhtml new file mode 100644 index 0000000000..036c775463 --- /dev/null +++ b/widget/tests/test_system_font_changes.xhtml @@ -0,0 +1,28 @@ + + + + + + + + diff --git a/widget/tests/test_system_status_bar.xhtml b/widget/tests/test_system_status_bar.xhtml new file mode 100644 index 0000000000..f2348fa6f5 --- /dev/null +++ b/widget/tests/test_system_status_bar.xhtml @@ -0,0 +1,53 @@ + + + + + + + diff --git a/widget/tests/test_taskbar_progress.xhtml b/widget/tests/test_taskbar_progress.xhtml new file mode 100644 index 0000000000..f2494a27bb --- /dev/null +++ b/widget/tests/test_taskbar_progress.xhtml @@ -0,0 +1,117 @@ + + + + + + + + +

+ +

+  
+
+
diff --git a/widget/tests/test_textScaleFactor_system_font.html b/widget/tests/test_textScaleFactor_system_font.html new file mode 100644 index 0000000000..2d0333e5fa --- /dev/null +++ b/widget/tests/test_textScaleFactor_system_font.html @@ -0,0 +1,139 @@ + + + + + Test that system font sizing is independent from ui.textScaleFactor + + + + + + +

Default text.

+ + + diff --git a/widget/tests/test_transferable_overflow.xhtml b/widget/tests/test_transferable_overflow.xhtml new file mode 100644 index 0000000000..dca9edcc61 --- /dev/null +++ b/widget/tests/test_transferable_overflow.xhtml @@ -0,0 +1,155 @@ + + + + + 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..f6b0a8e3fc --- /dev/null +++ b/widget/tests/unit/test_macsharingservice.js @@ -0,0 +1,61 @@ +/* -*- 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 + ); + + // Ensure these URL's are accepted without error by the getSharingProviders() + // method. This does not test if the URL's are interpreted correctly by + // the platform implementation and does not test that the URL will be + // successfully shared to the target application if the shareURL method is + // used. It does indicate the Mac API's used to get the sharing providers + // successfully created a URL object for the URL provided and returned at + // least one provider. + let urls = [ + "http://example.org", + "http://example.org/#", + "http://example.org/dkl??", + "http://example.org/dkl?a=b;c=d#thisisaref", + "http://example.org/dkl?a=b;c=d#thisisaref#double", + "http://example.org/#/", + "http://example.org/#/#", + "http://example.org/#/#/", + // This test fails due to the '|' in the path which needs additional + // encoding before conversion to NSURL. See bug 1740565. + // "http://example.org/foo/bar/x|page.html#this_is_a_fragment", + "http://example.org/page.html#this_is_a_fragment", + "http://example.org/page.html#this_is_a_fragment#and_another", + "http://example.org/foo/bar;#foo", + "http://example.org/a file with spaces.html", + "https://chat.mozilla.org/#/room/#macdev:mozilla.org", + "https://chat.mozilla.org/#/room/%23macdev:mozilla.org", + ]; + + urls.forEach(url => testGetSharingProvidersForUrl(sharingService, url)); +} + +function testGetSharingProvidersForUrl(sharingService, url) { + let providers = sharingService.getSharingProviders(url); + 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_legacyjumplistitems.js b/widget/tests/unit/test_taskbar_legacyjumplistitems.js new file mode 100644 index 0000000000..e0173fd29e --- /dev/null +++ b/widget/tests/unit/test_taskbar_legacyjumplistitems.js @@ -0,0 +1,229 @@ +/* -*- 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. + +function test_basics() { + var item = Cc["@mozilla.org/windows-legacyjumplistitem;1"].createInstance( + Ci.nsILegacyJumpListItem + ); + + var sep = Cc["@mozilla.org/windows-legacyjumplistseparator;1"].createInstance( + Ci.nsILegacyJumpListSeparator + ); + + var shortcut = Cc[ + "@mozilla.org/windows-legacyjumplistshortcut;1" + ].createInstance(Ci.nsILegacyJumpListShortcut); + + var link = Cc["@mozilla.org/windows-legacyjumplistlink;1"].createInstance( + Ci.nsILegacyJumpListLink + ); + + 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-legacyjumplistseparator;1" + ].createInstance(Ci.nsILegacyJumpListSeparator); + + Assert.ok(item.type == Ci.nsILegacyJumpListItem.JUMPLIST_ITEM_SEPARATOR); +} + +function test_links() { + // links: + var link1 = Cc["@mozilla.org/windows-legacyjumplistlink;1"].createInstance( + Ci.nsILegacyJumpListLink + ); + var link2 = Cc["@mozilla.org/windows-legacyjumplistlink;1"].createInstance( + Ci.nsILegacyJumpListLink + ); + + 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-legacyjumplistshortcut;1"].createInstance( + Ci.nsILegacyJumpListShortcut + ); + + 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_legacyjumplist() { + // 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 + ); + + // Since we're only testing the general functionality of the JumpListBuilder + // et. al, we can just test the non-private browsing version. + // (The only difference between the two at this level is the App User Model ID.) + var builder = taskbar.createLegacyJumpListBuilder(false); + + 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-legacyjumplistshortcut;1"].createInstance( + Ci.nsILegacyJumpListShortcut + ); + + 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_links(); + test_shortcuts(); + + run_next_test(); +} + +add_task(test_legacyjumplist); diff --git a/widget/tests/unit/xpcshell.toml b/widget/tests/unit/xpcshell.toml new file mode 100644 index 0000000000..4e702ca356 --- /dev/null +++ b/widget/tests/unit/xpcshell.toml @@ -0,0 +1,11 @@ +[DEFAULT] +head = "" + +["test_macsharingservice.js"] +run-if = ["os == 'mac'"] + +["test_macwebapputils.js"] +run-if = ["os == 'mac'"] + +["test_taskbar_legacyjumplistitems.js"] +skip-if = ["os == 'win'"] 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 @@ + + + + + + + diff --git a/widget/tests/window_bug522217.xhtml b/widget/tests/window_bug522217.xhtml new file mode 100644 index 0000000000..80eb4b6e5a --- /dev/null +++ b/widget/tests/window_bug522217.xhtml @@ -0,0 +1,80 @@ + + + + + + + diff --git a/widget/tests/window_bug538242.xhtml b/widget/tests/window_bug538242.xhtml new file mode 100644 index 0000000000..fb878b1383 --- /dev/null +++ b/widget/tests/window_bug538242.xhtml @@ -0,0 +1,3 @@ + + diff --git a/widget/tests/window_bug593307_centerscreen.xhtml b/widget/tests/window_bug593307_centerscreen.xhtml new file mode 100644 index 0000000000..dd73e42f84 --- /dev/null +++ b/widget/tests/window_bug593307_centerscreen.xhtml @@ -0,0 +1,26 @@ + + + + + + + diff --git a/widget/tests/window_bug593307_offscreen.xhtml b/widget/tests/window_bug593307_offscreen.xhtml new file mode 100644 index 0000000000..10ab701a55 --- /dev/null +++ b/widget/tests/window_bug593307_offscreen.xhtml @@ -0,0 +1,35 @@ + + + + + + + diff --git a/widget/tests/window_composition_text_querycontent.xhtml b/widget/tests/window_composition_text_querycontent.xhtml new file mode 100644 index 0000000000..db3b10ea30 --- /dev/null +++ b/widget/tests/window_composition_text_querycontent.xhtml @@ -0,0 +1,10923 @@ + + + + + + + + diff --git a/widget/tests/window_imestate_iframes.html b/widget/tests/window_imestate_iframes.html new file mode 100644 index 0000000000..c8b182977f --- /dev/null +++ b/widget/tests/window_imestate_iframes.html @@ -0,0 +1,358 @@ + + + Test for IME state controling and focus moving for iframes + + + + + +

+ +
+
+ + +
+
+
+
+ +
+

+ + + + diff --git a/widget/tests/window_mouse_scroll_win.html b/widget/tests/window_mouse_scroll_win.html new file mode 100644 index 0000000000..bf90abb1b5 --- /dev/null +++ b/widget/tests/window_mouse_scroll_win.html @@ -0,0 +1,1516 @@ + + + Test for mouse scroll handling on Windows + + + + + +
+

1st <p>.

+

2nd <p>.

+
+ + + + diff --git a/widget/tests/window_mouse_scroll_win_2.html b/widget/tests/window_mouse_scroll_win_2.html new file mode 100644 index 0000000000..c8d3762405 --- /dev/null +++ b/widget/tests/window_mouse_scroll_win_2.html @@ -0,0 +1,6 @@ + + + + Helper file for window_mouse_scroll_win.html + + diff --git a/widget/tests/window_picker_no_crash_child.html b/widget/tests/window_picker_no_crash_child.html new file mode 100644 index 0000000000..c980f979be --- /dev/null +++ b/widget/tests/window_picker_no_crash_child.html @@ -0,0 +1,6 @@ + +Picker window +
+ + +
diff --git a/widget/tests/window_state_windows.xhtml b/widget/tests/window_state_windows.xhtml new file mode 100644 index 0000000000..60989db144 --- /dev/null +++ b/widget/tests/window_state_windows.xhtml @@ -0,0 +1,80 @@ + + + + + + + + + + + +

+ +

+  
+
diff --git a/widget/tests/window_wheeltransaction.xhtml b/widget/tests/window_wheeltransaction.xhtml new file mode 100644 index 0000000000..f3c081b105 --- /dev/null +++ b/widget/tests/window_wheeltransaction.xhtml @@ -0,0 +1,1569 @@ + + + + + + + -- cgit v1.2.3