From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- toolkit/content/tests/browser/.eslintrc.js | 7 + toolkit/content/tests/browser/audio.ogg | Bin 0 -> 14290 bytes toolkit/content/tests/browser/browser.ini | 75 + .../tests/browser/browser_audioCompeting.js | 115 ++ .../browser_audioCompeting_onlyForActiveAgent.js | 176 +++ .../tests/browser/browser_autoscroll_disabled.js | 67 + .../tests/browser/browser_block_autoplay_media.js | 87 ++ .../content/tests/browser/browser_bug1170531.js | 92 ++ .../content/tests/browser/browser_bug1198465.js | 75 + .../browser_bug295977_autoscroll_overflow.js | 214 +++ toolkit/content/tests/browser/browser_bug451286.js | 152 +++ toolkit/content/tests/browser/browser_bug594509.js | 9 + toolkit/content/tests/browser/browser_bug982298.js | 70 + .../content/tests/browser/browser_contentTitle.js | 16 + .../browser/browser_content_url_annotation.js | 73 + .../browser/browser_crash_previous_frameloader.js | 108 ++ .../browser/browser_default_image_filename.js | 45 + .../tests/browser/browser_f7_caret_browsing.js | 227 +++ toolkit/content/tests/browser/browser_findbar.js | 249 ++++ .../content/tests/browser/browser_isSynthetic.js | 72 + .../browser_keyevents_during_autoscrolling.js | 120 ++ .../tests/browser/browser_label_textlink.js | 38 + .../content/tests/browser/browser_mediaPlayback.js | 30 + .../tests/browser/browser_mediaPlayback_mute.js | 104 ++ .../browser/browser_mediaPlayback_suspended.js | 191 +++ ...rowser_mediaPlayback_suspended_multipleAudio.js | 311 +++++ toolkit/content/tests/browser/browser_mute.js | 16 + toolkit/content/tests/browser/browser_mute2.js | 26 + .../tests/browser/browser_quickfind_editable.js | 47 + .../content/tests/browser/browser_saveImageURL.js | 68 + .../tests/browser/browser_save_resend_postdata.js | 145 ++ .../content/tests/browser/common/mockTransfer.js | 67 + .../content/tests/browser/data/post_form_inner.sjs | 31 + .../content/tests/browser/data/post_form_outer.sjs | 34 + toolkit/content/tests/browser/empty.png | Bin 0 -> 14528 bytes .../content/tests/browser/file_contentTitle.html | 14 + .../content/tests/browser/file_mediaPlayback.html | 9 + .../content/tests/browser/file_mediaPlayback2.html | 12 + .../tests/browser/file_mediaPlaybackFrame.html | 2 + .../tests/browser/file_mediaPlaybackFrame2.html | 2 + .../content/tests/browser/file_multipleAudio.html | 19 + .../tests/browser/file_multiplePlayingAudio.html | 23 + toolkit/content/tests/browser/file_redirect.html | 13 + .../content/tests/browser/file_redirect_to.html | 15 + toolkit/content/tests/browser/head.js | 33 + toolkit/content/tests/browser/image.jpg | Bin 0 -> 24204 bytes toolkit/content/tests/browser/image_page.html | 9 + toolkit/content/tests/chrome/.eslintrc.js | 7 + .../tests/chrome/RegisterUnregisterChrome.js | 161 +++ toolkit/content/tests/chrome/bug263683_window.xul | 210 +++ toolkit/content/tests/chrome/bug304188_window.xul | 94 ++ toolkit/content/tests/chrome/bug331215_window.xul | 102 ++ toolkit/content/tests/chrome/bug360437_window.xul | 120 ++ toolkit/content/tests/chrome/bug366992_window.xul | 57 + toolkit/content/tests/chrome/bug409624_window.xul | 98 ++ toolkit/content/tests/chrome/bug429723_window.xul | 84 ++ toolkit/content/tests/chrome/bug451540_window.xul | 248 ++++ toolkit/content/tests/chrome/bug624329_window.xul | 22 + toolkit/content/tests/chrome/chrome.ini | 199 +++ .../content/tests/chrome/dialog_dialogfocus.xul | 57 + .../tests/chrome/file_about_networking_wsh.py | 9 + .../chrome/file_autocomplete_with_composition.js | 540 ++++++++ .../tests/chrome/findbar_entireword_window.xul | 275 ++++ .../content/tests/chrome/findbar_events_window.xul | 173 +++ toolkit/content/tests/chrome/findbar_window.xul | 756 ++++++++++ .../content/tests/chrome/frame_popup_anchor.xul | 82 ++ .../tests/chrome/frame_popupremoving_frame.xul | 75 + .../chrome/frame_subframe_origin_subframe1.xul | 43 + .../chrome/frame_subframe_origin_subframe2.xul | 39 + .../content/tests/chrome/popup_childframe_node.xul | 2 + toolkit/content/tests/chrome/popup_trigger.js | 859 ++++++++++++ toolkit/content/tests/chrome/rtlchrome/rtl.css | 2 + toolkit/content/tests/chrome/rtlchrome/rtl.dtd | 1 + .../content/tests/chrome/rtlchrome/rtl.manifest | 5 + .../tests/chrome/rtltest/content/dirtest.xul | 25 + .../tests/chrome/rtltest/righttoleft.manifest | 3 + .../tests/chrome/sample_entireword_latin1.html | 11 + .../tests/chrome/test_about_networking.html | 58 + toolkit/content/tests/chrome/test_arrowpanel.xul | 327 +++++ .../content/tests/chrome/test_autocomplete2.xul | 197 +++ .../content/tests/chrome/test_autocomplete3.xul | 188 +++ .../content/tests/chrome/test_autocomplete4.xul | 280 ++++ .../content/tests/chrome/test_autocomplete5.xul | 152 +++ .../chrome/test_autocomplete_delayOnPaste.xul | 128 ++ .../tests/chrome/test_autocomplete_emphasis.xul | 175 +++ .../tests/chrome/test_autocomplete_mac_caret.xul | 74 + .../test_autocomplete_placehold_last_complete.xul | 309 +++++ ...est_autocomplete_with_composition_on_input.html | 64 + ...st_autocomplete_with_composition_on_textbox.xul | 124 ++ toolkit/content/tests/chrome/test_browser_drop.xul | 38 + toolkit/content/tests/chrome/test_bug1048178.xul | 86 ++ toolkit/content/tests/chrome/test_bug253481.xul | 90 ++ toolkit/content/tests/chrome/test_bug263683.xul | 39 + toolkit/content/tests/chrome/test_bug304188.xul | 37 + toolkit/content/tests/chrome/test_bug331215.xul | 38 + toolkit/content/tests/chrome/test_bug360220.xul | 61 + toolkit/content/tests/chrome/test_bug360437.xul | 40 + toolkit/content/tests/chrome/test_bug365773.xul | 67 + toolkit/content/tests/chrome/test_bug366992.xul | 40 + toolkit/content/tests/chrome/test_bug382990.xul | 44 + toolkit/content/tests/chrome/test_bug409624.xul | 39 + toolkit/content/tests/chrome/test_bug418874.xul | 71 + toolkit/content/tests/chrome/test_bug429723.xul | 38 + toolkit/content/tests/chrome/test_bug437844.xul | 95 ++ toolkit/content/tests/chrome/test_bug451540.xul | 39 + toolkit/content/tests/chrome/test_bug457632.xul | 178 +++ toolkit/content/tests/chrome/test_bug460942.xul | 42 + toolkit/content/tests/chrome/test_bug471776.xul | 47 + toolkit/content/tests/chrome/test_bug509732.xul | 53 + toolkit/content/tests/chrome/test_bug554279.xul | 39 + toolkit/content/tests/chrome/test_bug557987.xul | 76 ++ toolkit/content/tests/chrome/test_bug562554.xul | 92 ++ toolkit/content/tests/chrome/test_bug570192.xul | 53 + toolkit/content/tests/chrome/test_bug585946.xul | 51 + toolkit/content/tests/chrome/test_bug624329.xul | 160 +++ toolkit/content/tests/chrome/test_bug792324.xul | 75 + toolkit/content/tests/chrome/test_button.xul | 71 + toolkit/content/tests/chrome/test_chromemargin.xul | 36 + .../tests/chrome/test_closemenu_attribute.xul | 96 ++ .../tests/chrome/test_colorpicker_popup.xul | 148 ++ .../content/tests/chrome/test_contextmenu_list.xul | 288 ++++ toolkit/content/tests/chrome/test_cursorsnap.xul | 127 ++ toolkit/content/tests/chrome/test_datepicker.xul | 415 ++++++ toolkit/content/tests/chrome/test_deck.xul | 133 ++ toolkit/content/tests/chrome/test_dialogfocus.xul | 102 ++ toolkit/content/tests/chrome/test_findbar.xul | 47 + .../tests/chrome/test_findbar_entireword.xul | 41 + .../content/tests/chrome/test_findbar_events.xul | 39 + toolkit/content/tests/chrome/test_focus_anons.xul | 119 ++ toolkit/content/tests/chrome/test_hiddenitems.xul | 89 ++ toolkit/content/tests/chrome/test_hiddenpaging.xul | 161 +++ toolkit/content/tests/chrome/test_keys.xul | 29 + toolkit/content/tests/chrome/test_labelcontrol.xul | 44 + toolkit/content/tests/chrome/test_largemenu.xul | 29 + toolkit/content/tests/chrome/test_menu.xul | 85 ++ .../content/tests/chrome/test_menu_anchored.xul | 77 ++ toolkit/content/tests/chrome/test_menu_hide.xul | 58 + toolkit/content/tests/chrome/test_menuchecks.xul | 147 ++ .../content/tests/chrome/test_menuitem_blink.xul | 106 ++ .../tests/chrome/test_menuitem_commands.xul | 104 ++ toolkit/content/tests/chrome/test_menulist.xul | 314 +++++ .../content/tests/chrome/test_menulist_keynav.xul | 272 ++++ .../tests/chrome/test_menulist_null_value.xul | 96 ++ .../content/tests/chrome/test_menulist_paging.xul | 163 +++ .../tests/chrome/test_menulist_position.xul | 97 ++ toolkit/content/tests/chrome/test_mousescroll.xul | 274 ++++ .../content/tests/chrome/test_notificationbox.xul | 522 +++++++ toolkit/content/tests/chrome/test_panel.xul | 31 + toolkit/content/tests/chrome/test_panel_focus.xul | 38 + .../content/tests/chrome/test_panelfrommenu.xul | 118 ++ toolkit/content/tests/chrome/test_popup_anchor.xul | 30 + .../tests/chrome/test_popup_anchoratrect.xul | 28 + .../content/tests/chrome/test_popup_attribute.xul | 28 + toolkit/content/tests/chrome/test_popup_button.xul | 28 + toolkit/content/tests/chrome/test_popup_coords.xul | 91 ++ toolkit/content/tests/chrome/test_popup_keys.xul | 148 ++ .../tests/chrome/test_popup_moveToAnchor.xul | 84 ++ .../tests/chrome/test_popup_preventdefault.xul | 76 ++ .../chrome/test_popup_preventdefault_chrome.xul | 29 + .../content/tests/chrome/test_popup_recreate.xul | 83 ++ toolkit/content/tests/chrome/test_popup_scaled.xul | 105 ++ toolkit/content/tests/chrome/test_popup_tree.xul | 72 + toolkit/content/tests/chrome/test_popuphidden.xul | 74 + .../content/tests/chrome/test_popupincontent.xul | 131 ++ .../content/tests/chrome/test_popupremoving.xul | 165 +++ .../tests/chrome/test_popupremoving_frame.xul | 80 ++ toolkit/content/tests/chrome/test_position.xul | 136 ++ toolkit/content/tests/chrome/test_preferences.xul | 533 ++++++++ .../tests/chrome/test_preferences_beforeaccept.xul | 55 + .../test_preferences_onsyncfrompreference.xul | 62 + .../content/tests/chrome/test_progressmeter.xul | 74 + toolkit/content/tests/chrome/test_props.xul | 91 ++ toolkit/content/tests/chrome/test_radio.xul | 66 + .../tests/chrome/test_richlist_direction.xul | 138 ++ toolkit/content/tests/chrome/test_righttoleft.xul | 126 ++ toolkit/content/tests/chrome/test_scale.xul | 277 ++++ toolkit/content/tests/chrome/test_scaledrag.xul | 197 +++ .../tests/chrome/test_screenPersistence.xul | 63 + toolkit/content/tests/chrome/test_scrollbar.xul | 137 ++ toolkit/content/tests/chrome/test_showcaret.xul | 101 ++ toolkit/content/tests/chrome/test_sorttemplate.xul | 89 ++ toolkit/content/tests/chrome/test_statusbar.xul | 42 + .../content/tests/chrome/test_subframe_origin.xul | 37 + toolkit/content/tests/chrome/test_tabbox.xul | 224 +++ toolkit/content/tests/chrome/test_tabindex.xul | 120 ++ .../tests/chrome/test_textbox_dictionary.xul | 98 ++ .../tests/chrome/test_textbox_emptytext.xul | 48 + .../content/tests/chrome/test_textbox_number.xul | 353 +++++ .../content/tests/chrome/test_textbox_search.xul | 170 +++ toolkit/content/tests/chrome/test_timepicker.xul | 207 +++ toolkit/content/tests/chrome/test_titlebar.xul | 35 + toolkit/content/tests/chrome/test_toolbar.xul | 227 +++ toolkit/content/tests/chrome/test_tooltip.xul | 28 + .../tests/chrome/test_tooltip_noautohide.xul | 57 + toolkit/content/tests/chrome/test_tree.xul | 84 ++ toolkit/content/tests/chrome/test_tree_hier.xul | 136 ++ .../content/tests/chrome/test_tree_hier_cell.xul | 136 ++ toolkit/content/tests/chrome/test_tree_single.xul | 110 ++ toolkit/content/tests/chrome/test_tree_view.xul | 118 ++ .../content/tests/chrome/window_browser_drop.xul | 254 ++++ .../content/tests/chrome/window_chromemargin.xul | 73 + .../tests/chrome/window_cursorsnap_dialog.xul | 104 ++ .../tests/chrome/window_cursorsnap_wizard.xul | 111 ++ toolkit/content/tests/chrome/window_keys.xul | 202 +++ toolkit/content/tests/chrome/window_largemenu.xul | 425 ++++++ toolkit/content/tests/chrome/window_panel.xul | 312 +++++ .../content/tests/chrome/window_panel_focus.xul | 132 ++ .../content/tests/chrome/window_popup_anchor.xul | 28 + .../tests/chrome/window_popup_anchoratrect.xul | 117 ++ .../tests/chrome/window_popup_attribute.xul | 40 + .../content/tests/chrome/window_popup_button.xul | 41 + .../chrome/window_popup_preventdefault_chrome.xul | 113 ++ .../content/tests/chrome/window_preferences.xul | 73 + .../content/tests/chrome/window_preferences2.xul | 25 + .../content/tests/chrome/window_preferences3.xul | 74 + .../chrome/window_preferences_beforeaccept.xul | 45 + .../chrome/window_preferences_commandretarget.xul | 36 + .../window_preferences_onsyncfrompreference.xul | 42 + .../content/tests/chrome/window_screenPosSize.xul | 17 + toolkit/content/tests/chrome/window_showcaret.xul | 10 + .../tests/chrome/window_subframe_origin.xul | 42 + toolkit/content/tests/chrome/window_titlebar.xul | 223 +++ toolkit/content/tests/chrome/window_tooltip.xul | 311 +++++ toolkit/content/tests/chrome/xul_selectcontrol.js | 390 ++++++ .../tests/fennec-tile-testapp/application.ini | 11 + .../fennec-tile-testapp/chrome/chrome.manifest | 1 + .../chrome/content/BrowserView.js | 694 ++++++++++ .../chrome/content/FooScript.js | 352 +++++ .../chrome/content/TileManager.js | 1018 ++++++++++++++ .../chrome/content/WidgetStack.js | 1438 ++++++++++++++++++++ .../chrome/content/firefoxOverlay.xul | 15 + .../fennec-tile-testapp/chrome/content/foo.xul | 460 +++++++ .../fennec-tile-testapp/chrome/content/main.xul | 7 + .../fennec-tile-testapp/chrome/content/overlay.js | 15 + .../chrome/locale/en-US/tile.dtd | 1 + .../chrome/locale/en-US/tile.properties | 3 + .../fennec-tile-testapp/chrome/skin/overlay.css | 5 + .../defaults/preferences/prefs.js | 2 + .../content/tests/fennec-tile-testapp/install.rdf | 17 + .../content/tests/fennec-tile-testapp/logread.py | 104 ++ toolkit/content/tests/mochitest/mochitest.ini | 5 + .../test_autocomplete_change_after_focus.html | 105 ++ .../tests/mochitest/test_mousecapture.xhtml | 340 +++++ toolkit/content/tests/moz.build | 19 + .../reftests/bug-442419-progressmeter-max-ref.xul | 7 + .../reftests/bug-442419-progressmeter-max.xul | 7 + toolkit/content/tests/reftests/reftest-stylo.list | 6 + toolkit/content/tests/reftests/reftest.list | 2 + .../reftests/textbox-multiline-default-value.xul | 5 + .../tests/reftests/textbox-multiline-empty.xul | 5 + toolkit/content/tests/unit/.eslintrc.js | 7 + .../content/tests/unit/test_contentAreaUtils.js | 80 ++ toolkit/content/tests/unit/xpcshell.ini | 5 + toolkit/content/tests/widgets/.eslintrc.js | 8 + toolkit/content/tests/widgets/audio.ogg | Bin 0 -> 14293 bytes toolkit/content/tests/widgets/audio.wav | Bin 0 -> 1422 bytes toolkit/content/tests/widgets/chrome.ini | 20 + toolkit/content/tests/widgets/head.js | 23 + toolkit/content/tests/widgets/mochitest.ini | 40 + toolkit/content/tests/widgets/popup_shared.js | 424 ++++++ toolkit/content/tests/widgets/seek_with_sound.ogg | Bin 0 -> 299507 bytes .../widgets/test_audiocontrols_dimensions.html | 38 + toolkit/content/tests/widgets/test_bug898940.html | 31 + .../tests/widgets/test_contextmenu_menugroup.xul | 102 ++ .../tests/widgets/test_contextmenu_nested.xul | 138 ++ .../tests/widgets/test_editor_currentURI.xul | 39 + toolkit/content/tests/widgets/test_menubar.xul | 30 + .../tests/widgets/test_mousecapture_area.html | 109 ++ toolkit/content/tests/widgets/test_popupanchor.xul | 430 ++++++ .../content/tests/widgets/test_popupreflows.xul | 111 ++ .../tests/widgets/test_tree_column_reorder.xul | 76 ++ .../content/tests/widgets/test_videocontrols.html | 411 ++++++ .../tests/widgets/test_videocontrols_audio.html | 60 + .../test_videocontrols_audio_direction.html | 31 + .../test_videocontrols_iframe_fullscreen.html | 64 + .../widgets/test_videocontrols_jsdisabled.html | 70 + .../widgets/test_videocontrols_onclickplay.html | 74 + .../widgets/test_videocontrols_standalone.html | 90 ++ .../test_videocontrols_video_direction.html | 31 + .../tests/widgets/test_videocontrols_vtt.html | 133 ++ toolkit/content/tests/widgets/tree_shared.js | 1405 +++++++++++++++++++ toolkit/content/tests/widgets/video.ogg | Bin 0 -> 285310 bytes .../widgets/videocontrols_direction-1-ref.html | 10 + .../tests/widgets/videocontrols_direction-1a.html | 10 + .../tests/widgets/videocontrols_direction-1b.html | 10 + .../tests/widgets/videocontrols_direction-1c.html | 10 + .../tests/widgets/videocontrols_direction-1d.html | 10 + .../tests/widgets/videocontrols_direction-1e.html | 10 + .../widgets/videocontrols_direction-2-ref.html | 10 + .../tests/widgets/videocontrols_direction-2a.html | 10 + .../tests/widgets/videocontrols_direction-2b.html | 10 + .../tests/widgets/videocontrols_direction-2c.html | 10 + .../tests/widgets/videocontrols_direction-2d.html | 10 + .../tests/widgets/videocontrols_direction-2e.html | 10 + .../tests/widgets/videocontrols_direction_test.js | 90 ++ toolkit/content/tests/widgets/videomask.css | 23 + toolkit/content/tests/widgets/window_menubar.xul | 820 +++++++++++ 297 files changed, 34631 insertions(+) create mode 100644 toolkit/content/tests/browser/.eslintrc.js create mode 100644 toolkit/content/tests/browser/audio.ogg create mode 100644 toolkit/content/tests/browser/browser.ini create mode 100644 toolkit/content/tests/browser/browser_audioCompeting.js create mode 100644 toolkit/content/tests/browser/browser_audioCompeting_onlyForActiveAgent.js create mode 100644 toolkit/content/tests/browser/browser_autoscroll_disabled.js create mode 100644 toolkit/content/tests/browser/browser_block_autoplay_media.js create mode 100644 toolkit/content/tests/browser/browser_bug1170531.js create mode 100644 toolkit/content/tests/browser/browser_bug1198465.js create mode 100644 toolkit/content/tests/browser/browser_bug295977_autoscroll_overflow.js create mode 100644 toolkit/content/tests/browser/browser_bug451286.js create mode 100644 toolkit/content/tests/browser/browser_bug594509.js create mode 100644 toolkit/content/tests/browser/browser_bug982298.js create mode 100644 toolkit/content/tests/browser/browser_contentTitle.js create mode 100644 toolkit/content/tests/browser/browser_content_url_annotation.js create mode 100644 toolkit/content/tests/browser/browser_crash_previous_frameloader.js create mode 100644 toolkit/content/tests/browser/browser_default_image_filename.js create mode 100644 toolkit/content/tests/browser/browser_f7_caret_browsing.js create mode 100644 toolkit/content/tests/browser/browser_findbar.js create mode 100644 toolkit/content/tests/browser/browser_isSynthetic.js create mode 100644 toolkit/content/tests/browser/browser_keyevents_during_autoscrolling.js create mode 100644 toolkit/content/tests/browser/browser_label_textlink.js create mode 100644 toolkit/content/tests/browser/browser_mediaPlayback.js create mode 100644 toolkit/content/tests/browser/browser_mediaPlayback_mute.js create mode 100644 toolkit/content/tests/browser/browser_mediaPlayback_suspended.js create mode 100644 toolkit/content/tests/browser/browser_mediaPlayback_suspended_multipleAudio.js create mode 100644 toolkit/content/tests/browser/browser_mute.js create mode 100644 toolkit/content/tests/browser/browser_mute2.js create mode 100644 toolkit/content/tests/browser/browser_quickfind_editable.js create mode 100644 toolkit/content/tests/browser/browser_saveImageURL.js create mode 100644 toolkit/content/tests/browser/browser_save_resend_postdata.js create mode 100644 toolkit/content/tests/browser/common/mockTransfer.js create mode 100644 toolkit/content/tests/browser/data/post_form_inner.sjs create mode 100644 toolkit/content/tests/browser/data/post_form_outer.sjs create mode 100644 toolkit/content/tests/browser/empty.png create mode 100644 toolkit/content/tests/browser/file_contentTitle.html create mode 100644 toolkit/content/tests/browser/file_mediaPlayback.html create mode 100644 toolkit/content/tests/browser/file_mediaPlayback2.html create mode 100644 toolkit/content/tests/browser/file_mediaPlaybackFrame.html create mode 100644 toolkit/content/tests/browser/file_mediaPlaybackFrame2.html create mode 100644 toolkit/content/tests/browser/file_multipleAudio.html create mode 100644 toolkit/content/tests/browser/file_multiplePlayingAudio.html create mode 100644 toolkit/content/tests/browser/file_redirect.html create mode 100644 toolkit/content/tests/browser/file_redirect_to.html create mode 100644 toolkit/content/tests/browser/head.js create mode 100644 toolkit/content/tests/browser/image.jpg create mode 100644 toolkit/content/tests/browser/image_page.html create mode 100644 toolkit/content/tests/chrome/.eslintrc.js create mode 100644 toolkit/content/tests/chrome/RegisterUnregisterChrome.js create mode 100644 toolkit/content/tests/chrome/bug263683_window.xul create mode 100644 toolkit/content/tests/chrome/bug304188_window.xul create mode 100644 toolkit/content/tests/chrome/bug331215_window.xul create mode 100644 toolkit/content/tests/chrome/bug360437_window.xul create mode 100644 toolkit/content/tests/chrome/bug366992_window.xul create mode 100644 toolkit/content/tests/chrome/bug409624_window.xul create mode 100644 toolkit/content/tests/chrome/bug429723_window.xul create mode 100644 toolkit/content/tests/chrome/bug451540_window.xul create mode 100644 toolkit/content/tests/chrome/bug624329_window.xul create mode 100644 toolkit/content/tests/chrome/chrome.ini create mode 100644 toolkit/content/tests/chrome/dialog_dialogfocus.xul create mode 100644 toolkit/content/tests/chrome/file_about_networking_wsh.py create mode 100644 toolkit/content/tests/chrome/file_autocomplete_with_composition.js create mode 100644 toolkit/content/tests/chrome/findbar_entireword_window.xul create mode 100644 toolkit/content/tests/chrome/findbar_events_window.xul create mode 100644 toolkit/content/tests/chrome/findbar_window.xul create mode 100644 toolkit/content/tests/chrome/frame_popup_anchor.xul create mode 100644 toolkit/content/tests/chrome/frame_popupremoving_frame.xul create mode 100644 toolkit/content/tests/chrome/frame_subframe_origin_subframe1.xul create mode 100644 toolkit/content/tests/chrome/frame_subframe_origin_subframe2.xul create mode 100644 toolkit/content/tests/chrome/popup_childframe_node.xul create mode 100644 toolkit/content/tests/chrome/popup_trigger.js create mode 100644 toolkit/content/tests/chrome/rtlchrome/rtl.css create mode 100644 toolkit/content/tests/chrome/rtlchrome/rtl.dtd create mode 100644 toolkit/content/tests/chrome/rtlchrome/rtl.manifest create mode 100644 toolkit/content/tests/chrome/rtltest/content/dirtest.xul create mode 100644 toolkit/content/tests/chrome/rtltest/righttoleft.manifest create mode 100644 toolkit/content/tests/chrome/sample_entireword_latin1.html create mode 100644 toolkit/content/tests/chrome/test_about_networking.html create mode 100644 toolkit/content/tests/chrome/test_arrowpanel.xul create mode 100644 toolkit/content/tests/chrome/test_autocomplete2.xul create mode 100644 toolkit/content/tests/chrome/test_autocomplete3.xul create mode 100644 toolkit/content/tests/chrome/test_autocomplete4.xul create mode 100644 toolkit/content/tests/chrome/test_autocomplete5.xul create mode 100644 toolkit/content/tests/chrome/test_autocomplete_delayOnPaste.xul create mode 100644 toolkit/content/tests/chrome/test_autocomplete_emphasis.xul create mode 100644 toolkit/content/tests/chrome/test_autocomplete_mac_caret.xul create mode 100644 toolkit/content/tests/chrome/test_autocomplete_placehold_last_complete.xul create mode 100644 toolkit/content/tests/chrome/test_autocomplete_with_composition_on_input.html create mode 100644 toolkit/content/tests/chrome/test_autocomplete_with_composition_on_textbox.xul create mode 100644 toolkit/content/tests/chrome/test_browser_drop.xul create mode 100644 toolkit/content/tests/chrome/test_bug1048178.xul create mode 100644 toolkit/content/tests/chrome/test_bug253481.xul create mode 100644 toolkit/content/tests/chrome/test_bug263683.xul create mode 100644 toolkit/content/tests/chrome/test_bug304188.xul create mode 100644 toolkit/content/tests/chrome/test_bug331215.xul create mode 100644 toolkit/content/tests/chrome/test_bug360220.xul create mode 100644 toolkit/content/tests/chrome/test_bug360437.xul create mode 100644 toolkit/content/tests/chrome/test_bug365773.xul create mode 100644 toolkit/content/tests/chrome/test_bug366992.xul create mode 100644 toolkit/content/tests/chrome/test_bug382990.xul create mode 100644 toolkit/content/tests/chrome/test_bug409624.xul create mode 100644 toolkit/content/tests/chrome/test_bug418874.xul create mode 100644 toolkit/content/tests/chrome/test_bug429723.xul create mode 100644 toolkit/content/tests/chrome/test_bug437844.xul create mode 100644 toolkit/content/tests/chrome/test_bug451540.xul create mode 100644 toolkit/content/tests/chrome/test_bug457632.xul create mode 100644 toolkit/content/tests/chrome/test_bug460942.xul create mode 100644 toolkit/content/tests/chrome/test_bug471776.xul create mode 100644 toolkit/content/tests/chrome/test_bug509732.xul create mode 100644 toolkit/content/tests/chrome/test_bug554279.xul create mode 100644 toolkit/content/tests/chrome/test_bug557987.xul create mode 100644 toolkit/content/tests/chrome/test_bug562554.xul create mode 100644 toolkit/content/tests/chrome/test_bug570192.xul create mode 100644 toolkit/content/tests/chrome/test_bug585946.xul create mode 100644 toolkit/content/tests/chrome/test_bug624329.xul create mode 100644 toolkit/content/tests/chrome/test_bug792324.xul create mode 100644 toolkit/content/tests/chrome/test_button.xul create mode 100644 toolkit/content/tests/chrome/test_chromemargin.xul create mode 100644 toolkit/content/tests/chrome/test_closemenu_attribute.xul create mode 100644 toolkit/content/tests/chrome/test_colorpicker_popup.xul create mode 100644 toolkit/content/tests/chrome/test_contextmenu_list.xul create mode 100644 toolkit/content/tests/chrome/test_cursorsnap.xul create mode 100644 toolkit/content/tests/chrome/test_datepicker.xul create mode 100644 toolkit/content/tests/chrome/test_deck.xul create mode 100644 toolkit/content/tests/chrome/test_dialogfocus.xul create mode 100644 toolkit/content/tests/chrome/test_findbar.xul create mode 100644 toolkit/content/tests/chrome/test_findbar_entireword.xul create mode 100644 toolkit/content/tests/chrome/test_findbar_events.xul create mode 100644 toolkit/content/tests/chrome/test_focus_anons.xul create mode 100644 toolkit/content/tests/chrome/test_hiddenitems.xul create mode 100644 toolkit/content/tests/chrome/test_hiddenpaging.xul create mode 100644 toolkit/content/tests/chrome/test_keys.xul create mode 100644 toolkit/content/tests/chrome/test_labelcontrol.xul create mode 100644 toolkit/content/tests/chrome/test_largemenu.xul create mode 100644 toolkit/content/tests/chrome/test_menu.xul create mode 100644 toolkit/content/tests/chrome/test_menu_anchored.xul create mode 100644 toolkit/content/tests/chrome/test_menu_hide.xul create mode 100644 toolkit/content/tests/chrome/test_menuchecks.xul create mode 100644 toolkit/content/tests/chrome/test_menuitem_blink.xul create mode 100644 toolkit/content/tests/chrome/test_menuitem_commands.xul create mode 100644 toolkit/content/tests/chrome/test_menulist.xul create mode 100644 toolkit/content/tests/chrome/test_menulist_keynav.xul create mode 100644 toolkit/content/tests/chrome/test_menulist_null_value.xul create mode 100644 toolkit/content/tests/chrome/test_menulist_paging.xul create mode 100644 toolkit/content/tests/chrome/test_menulist_position.xul create mode 100644 toolkit/content/tests/chrome/test_mousescroll.xul create mode 100644 toolkit/content/tests/chrome/test_notificationbox.xul create mode 100644 toolkit/content/tests/chrome/test_panel.xul create mode 100644 toolkit/content/tests/chrome/test_panel_focus.xul create mode 100644 toolkit/content/tests/chrome/test_panelfrommenu.xul create mode 100644 toolkit/content/tests/chrome/test_popup_anchor.xul create mode 100644 toolkit/content/tests/chrome/test_popup_anchoratrect.xul create mode 100644 toolkit/content/tests/chrome/test_popup_attribute.xul create mode 100644 toolkit/content/tests/chrome/test_popup_button.xul create mode 100644 toolkit/content/tests/chrome/test_popup_coords.xul create mode 100644 toolkit/content/tests/chrome/test_popup_keys.xul create mode 100644 toolkit/content/tests/chrome/test_popup_moveToAnchor.xul create mode 100644 toolkit/content/tests/chrome/test_popup_preventdefault.xul create mode 100644 toolkit/content/tests/chrome/test_popup_preventdefault_chrome.xul create mode 100644 toolkit/content/tests/chrome/test_popup_recreate.xul create mode 100644 toolkit/content/tests/chrome/test_popup_scaled.xul create mode 100644 toolkit/content/tests/chrome/test_popup_tree.xul create mode 100644 toolkit/content/tests/chrome/test_popuphidden.xul create mode 100644 toolkit/content/tests/chrome/test_popupincontent.xul create mode 100644 toolkit/content/tests/chrome/test_popupremoving.xul create mode 100644 toolkit/content/tests/chrome/test_popupremoving_frame.xul create mode 100644 toolkit/content/tests/chrome/test_position.xul create mode 100644 toolkit/content/tests/chrome/test_preferences.xul create mode 100644 toolkit/content/tests/chrome/test_preferences_beforeaccept.xul create mode 100644 toolkit/content/tests/chrome/test_preferences_onsyncfrompreference.xul create mode 100644 toolkit/content/tests/chrome/test_progressmeter.xul create mode 100644 toolkit/content/tests/chrome/test_props.xul create mode 100644 toolkit/content/tests/chrome/test_radio.xul create mode 100644 toolkit/content/tests/chrome/test_richlist_direction.xul create mode 100644 toolkit/content/tests/chrome/test_righttoleft.xul create mode 100644 toolkit/content/tests/chrome/test_scale.xul create mode 100644 toolkit/content/tests/chrome/test_scaledrag.xul create mode 100644 toolkit/content/tests/chrome/test_screenPersistence.xul create mode 100644 toolkit/content/tests/chrome/test_scrollbar.xul create mode 100644 toolkit/content/tests/chrome/test_showcaret.xul create mode 100644 toolkit/content/tests/chrome/test_sorttemplate.xul create mode 100644 toolkit/content/tests/chrome/test_statusbar.xul create mode 100644 toolkit/content/tests/chrome/test_subframe_origin.xul create mode 100644 toolkit/content/tests/chrome/test_tabbox.xul create mode 100644 toolkit/content/tests/chrome/test_tabindex.xul create mode 100644 toolkit/content/tests/chrome/test_textbox_dictionary.xul create mode 100644 toolkit/content/tests/chrome/test_textbox_emptytext.xul create mode 100644 toolkit/content/tests/chrome/test_textbox_number.xul create mode 100644 toolkit/content/tests/chrome/test_textbox_search.xul create mode 100644 toolkit/content/tests/chrome/test_timepicker.xul create mode 100644 toolkit/content/tests/chrome/test_titlebar.xul create mode 100644 toolkit/content/tests/chrome/test_toolbar.xul create mode 100644 toolkit/content/tests/chrome/test_tooltip.xul create mode 100644 toolkit/content/tests/chrome/test_tooltip_noautohide.xul create mode 100644 toolkit/content/tests/chrome/test_tree.xul create mode 100644 toolkit/content/tests/chrome/test_tree_hier.xul create mode 100644 toolkit/content/tests/chrome/test_tree_hier_cell.xul create mode 100644 toolkit/content/tests/chrome/test_tree_single.xul create mode 100644 toolkit/content/tests/chrome/test_tree_view.xul create mode 100644 toolkit/content/tests/chrome/window_browser_drop.xul create mode 100644 toolkit/content/tests/chrome/window_chromemargin.xul create mode 100644 toolkit/content/tests/chrome/window_cursorsnap_dialog.xul create mode 100644 toolkit/content/tests/chrome/window_cursorsnap_wizard.xul create mode 100644 toolkit/content/tests/chrome/window_keys.xul create mode 100644 toolkit/content/tests/chrome/window_largemenu.xul create mode 100644 toolkit/content/tests/chrome/window_panel.xul create mode 100644 toolkit/content/tests/chrome/window_panel_focus.xul create mode 100644 toolkit/content/tests/chrome/window_popup_anchor.xul create mode 100644 toolkit/content/tests/chrome/window_popup_anchoratrect.xul create mode 100644 toolkit/content/tests/chrome/window_popup_attribute.xul create mode 100644 toolkit/content/tests/chrome/window_popup_button.xul create mode 100644 toolkit/content/tests/chrome/window_popup_preventdefault_chrome.xul create mode 100644 toolkit/content/tests/chrome/window_preferences.xul create mode 100644 toolkit/content/tests/chrome/window_preferences2.xul create mode 100644 toolkit/content/tests/chrome/window_preferences3.xul create mode 100644 toolkit/content/tests/chrome/window_preferences_beforeaccept.xul create mode 100644 toolkit/content/tests/chrome/window_preferences_commandretarget.xul create mode 100644 toolkit/content/tests/chrome/window_preferences_onsyncfrompreference.xul create mode 100644 toolkit/content/tests/chrome/window_screenPosSize.xul create mode 100644 toolkit/content/tests/chrome/window_showcaret.xul create mode 100644 toolkit/content/tests/chrome/window_subframe_origin.xul create mode 100644 toolkit/content/tests/chrome/window_titlebar.xul create mode 100644 toolkit/content/tests/chrome/window_tooltip.xul create mode 100644 toolkit/content/tests/chrome/xul_selectcontrol.js create mode 100644 toolkit/content/tests/fennec-tile-testapp/application.ini create mode 100644 toolkit/content/tests/fennec-tile-testapp/chrome/chrome.manifest create mode 100644 toolkit/content/tests/fennec-tile-testapp/chrome/content/BrowserView.js create mode 100644 toolkit/content/tests/fennec-tile-testapp/chrome/content/FooScript.js create mode 100644 toolkit/content/tests/fennec-tile-testapp/chrome/content/TileManager.js create mode 100644 toolkit/content/tests/fennec-tile-testapp/chrome/content/WidgetStack.js create mode 100644 toolkit/content/tests/fennec-tile-testapp/chrome/content/firefoxOverlay.xul create mode 100644 toolkit/content/tests/fennec-tile-testapp/chrome/content/foo.xul create mode 100644 toolkit/content/tests/fennec-tile-testapp/chrome/content/main.xul create mode 100644 toolkit/content/tests/fennec-tile-testapp/chrome/content/overlay.js create mode 100644 toolkit/content/tests/fennec-tile-testapp/chrome/locale/en-US/tile.dtd create mode 100644 toolkit/content/tests/fennec-tile-testapp/chrome/locale/en-US/tile.properties create mode 100644 toolkit/content/tests/fennec-tile-testapp/chrome/skin/overlay.css create mode 100644 toolkit/content/tests/fennec-tile-testapp/defaults/preferences/prefs.js create mode 100644 toolkit/content/tests/fennec-tile-testapp/install.rdf create mode 100644 toolkit/content/tests/fennec-tile-testapp/logread.py create mode 100644 toolkit/content/tests/mochitest/mochitest.ini create mode 100644 toolkit/content/tests/mochitest/test_autocomplete_change_after_focus.html create mode 100644 toolkit/content/tests/mochitest/test_mousecapture.xhtml create mode 100644 toolkit/content/tests/moz.build create mode 100644 toolkit/content/tests/reftests/bug-442419-progressmeter-max-ref.xul create mode 100644 toolkit/content/tests/reftests/bug-442419-progressmeter-max.xul create mode 100644 toolkit/content/tests/reftests/reftest-stylo.list create mode 100644 toolkit/content/tests/reftests/reftest.list create mode 100644 toolkit/content/tests/reftests/textbox-multiline-default-value.xul create mode 100644 toolkit/content/tests/reftests/textbox-multiline-empty.xul create mode 100644 toolkit/content/tests/unit/.eslintrc.js create mode 100644 toolkit/content/tests/unit/test_contentAreaUtils.js create mode 100644 toolkit/content/tests/unit/xpcshell.ini create mode 100644 toolkit/content/tests/widgets/.eslintrc.js create mode 100644 toolkit/content/tests/widgets/audio.ogg create mode 100644 toolkit/content/tests/widgets/audio.wav create mode 100644 toolkit/content/tests/widgets/chrome.ini create mode 100644 toolkit/content/tests/widgets/head.js create mode 100644 toolkit/content/tests/widgets/mochitest.ini create mode 100644 toolkit/content/tests/widgets/popup_shared.js create mode 100644 toolkit/content/tests/widgets/seek_with_sound.ogg create mode 100644 toolkit/content/tests/widgets/test_audiocontrols_dimensions.html create mode 100644 toolkit/content/tests/widgets/test_bug898940.html create mode 100644 toolkit/content/tests/widgets/test_contextmenu_menugroup.xul create mode 100644 toolkit/content/tests/widgets/test_contextmenu_nested.xul create mode 100644 toolkit/content/tests/widgets/test_editor_currentURI.xul create mode 100644 toolkit/content/tests/widgets/test_menubar.xul create mode 100644 toolkit/content/tests/widgets/test_mousecapture_area.html create mode 100644 toolkit/content/tests/widgets/test_popupanchor.xul create mode 100644 toolkit/content/tests/widgets/test_popupreflows.xul create mode 100644 toolkit/content/tests/widgets/test_tree_column_reorder.xul create mode 100644 toolkit/content/tests/widgets/test_videocontrols.html create mode 100644 toolkit/content/tests/widgets/test_videocontrols_audio.html create mode 100644 toolkit/content/tests/widgets/test_videocontrols_audio_direction.html create mode 100644 toolkit/content/tests/widgets/test_videocontrols_iframe_fullscreen.html create mode 100644 toolkit/content/tests/widgets/test_videocontrols_jsdisabled.html create mode 100644 toolkit/content/tests/widgets/test_videocontrols_onclickplay.html create mode 100644 toolkit/content/tests/widgets/test_videocontrols_standalone.html create mode 100644 toolkit/content/tests/widgets/test_videocontrols_video_direction.html create mode 100644 toolkit/content/tests/widgets/test_videocontrols_vtt.html create mode 100644 toolkit/content/tests/widgets/tree_shared.js create mode 100644 toolkit/content/tests/widgets/video.ogg create mode 100644 toolkit/content/tests/widgets/videocontrols_direction-1-ref.html create mode 100644 toolkit/content/tests/widgets/videocontrols_direction-1a.html create mode 100644 toolkit/content/tests/widgets/videocontrols_direction-1b.html create mode 100644 toolkit/content/tests/widgets/videocontrols_direction-1c.html create mode 100644 toolkit/content/tests/widgets/videocontrols_direction-1d.html create mode 100644 toolkit/content/tests/widgets/videocontrols_direction-1e.html create mode 100644 toolkit/content/tests/widgets/videocontrols_direction-2-ref.html create mode 100644 toolkit/content/tests/widgets/videocontrols_direction-2a.html create mode 100644 toolkit/content/tests/widgets/videocontrols_direction-2b.html create mode 100644 toolkit/content/tests/widgets/videocontrols_direction-2c.html create mode 100644 toolkit/content/tests/widgets/videocontrols_direction-2d.html create mode 100644 toolkit/content/tests/widgets/videocontrols_direction-2e.html create mode 100644 toolkit/content/tests/widgets/videocontrols_direction_test.js create mode 100644 toolkit/content/tests/widgets/videomask.css create mode 100644 toolkit/content/tests/widgets/window_menubar.xul (limited to 'toolkit/content/tests') diff --git a/toolkit/content/tests/browser/.eslintrc.js b/toolkit/content/tests/browser/.eslintrc.js new file mode 100644 index 000000000..c764b133d --- /dev/null +++ b/toolkit/content/tests/browser/.eslintrc.js @@ -0,0 +1,7 @@ +"use strict"; + +module.exports = { + "extends": [ + "../../../../testing/mochitest/browser.eslintrc.js" + ] +}; diff --git a/toolkit/content/tests/browser/audio.ogg b/toolkit/content/tests/browser/audio.ogg new file mode 100644 index 000000000..7f1833508 Binary files /dev/null and b/toolkit/content/tests/browser/audio.ogg differ diff --git a/toolkit/content/tests/browser/browser.ini b/toolkit/content/tests/browser/browser.ini new file mode 100644 index 000000000..278b2ffe0 --- /dev/null +++ b/toolkit/content/tests/browser/browser.ini @@ -0,0 +1,75 @@ +[DEFAULT] +support-files = + head.js + file_contentTitle.html + audio.ogg + +[browser_audioCompeting.js] +tags = audiochannel +support-files = + file_multipleAudio.html +[browser_audioCompeting_onlyForActiveAgent.js] +tags = audiochannel +support-files = + file_multiplePlayingAudio.html +[browser_autoscroll_disabled.js] +[browser_block_autoplay_media.js] +tags = audiochannel +support-files = + file_multipleAudio.html +[browser_bug295977_autoscroll_overflow.js] +[browser_bug451286.js] +skip-if = !e10s +[browser_bug594509.js] +[browser_bug982298.js] +[browser_bug1198465.js] +[browser_contentTitle.js] +[browser_crash_previous_frameloader.js] +run-if = e10s && crashreporter +[browser_default_image_filename.js] +[browser_f7_caret_browsing.js] +[browser_findbar.js] +[browser_label_textlink.js] +[browser_isSynthetic.js] +support-files = + empty.png +[browser_keyevents_during_autoscrolling.js] +[browser_save_resend_postdata.js] +support-files = + common/mockTransfer.js + data/post_form_inner.sjs + data/post_form_outer.sjs +skip-if = e10s # Bug ?????? - test directly manipulates content (gBrowser.contentDocument.getElementById("postForm").submit();) +[browser_content_url_annotation.js] +skip-if = !e10s || !crashreporter +support-files = + file_redirect.html + file_redirect_to.html +[browser_bug1170531.js] +[browser_mediaPlayback.js] +tags = audiochannel +support-files = + file_mediaPlayback.html + file_mediaPlaybackFrame.html +[browser_mediaPlayback_mute.js] +tags = audiochannel +support-files = + file_mediaPlayback2.html + file_mediaPlaybackFrame2.html +[browser_mediaPlayback_suspended.js] +tags = audiochannel +support-files = + file_mediaPlayback2.html +[browser_mediaPlayback_suspended_multipleAudio.js] +tags = audiochannel +support-files = + file_multipleAudio.html +[browser_mute.js] +tags = audiochannel +[browser_mute2.js] +tags = audiochannel +[browser_quickfind_editable.js] +[browser_saveImageURL.js] +support-files = + image.jpg + image_page.html diff --git a/toolkit/content/tests/browser/browser_audioCompeting.js b/toolkit/content/tests/browser/browser_audioCompeting.js new file mode 100644 index 000000000..7b6a76c1d --- /dev/null +++ b/toolkit/content/tests/browser/browser_audioCompeting.js @@ -0,0 +1,115 @@ +const PAGE = "https://example.com/browser/toolkit/content/tests/browser/file_multipleAudio.html"; + +function* wait_for_tab_playing_event(tab, expectPlaying) { + if (tab.soundPlaying == expectPlaying) { + ok(true, "The tab should " + (expectPlaying ? "" : "not ") + "be playing"); + } else { + yield BrowserTestUtils.waitForEvent(tab, "TabAttrModified", false, (event) => { + if (event.detail.changed.indexOf("soundplaying") >= 0) { + is(tab.soundPlaying, expectPlaying, "The tab should " + (expectPlaying ? "" : "not ") + "be playing"); + return true; + } + return false; + }); + } +} + +function play_audio_from_invisible_tab () { + return new Promise(resolve => { + var autoPlay = content.document.getElementById('autoplay'); + if (!autoPlay) { + ok(false, "Can't get the audio element!"); + } + + is(autoPlay.paused, true, "Audio in tab 1 was paused by audio competing."); + autoPlay.play(); + autoPlay.onpause = function() { + autoPlay.onpause = null; + ok(true, "Audio in tab 1 can't playback when other tab is playing in foreground."); + resolve(); + }; + }); +} + +function audio_should_keep_playing_even_go_to_background () { + var autoPlay = content.document.getElementById('autoplay'); + if (!autoPlay) { + ok(false, "Can't get the audio element!"); + } + + is(autoPlay.paused, false, "Audio in tab 2 is still playing in the background."); +} + +function play_non_autoplay_audio () { + return new Promise(resolve => { + var autoPlay = content.document.getElementById('autoplay'); + var nonAutoPlay = content.document.getElementById('nonautoplay'); + if (!autoPlay || !nonAutoPlay) { + ok(false, "Can't get the audio element!"); + } + + is(nonAutoPlay.paused, true, "Non-autoplay audio isn't started playing yet."); + nonAutoPlay.play(); + + nonAutoPlay.onplay = function() { + nonAutoPlay.onplay = null; + is(nonAutoPlay.paused, false, "Start Non-autoplay audio."); + is(autoPlay.paused, false, "Autoplay audio is still playing."); + resolve(); + }; + }); +} + +add_task(function* setup_test_preference() { + yield new Promise(resolve => { + SpecialPowers.pushPrefEnv({"set": [ + ["dom.audiochannel.audioCompeting", true], + ["dom.ipc.processCount", 1] + ]}, resolve); + }); +}); + +add_task(function* cross_tabs_audio_competing () { + info("- open tab 1 in foreground -"); + let tab1 = yield BrowserTestUtils.openNewForegroundTab(window.gBrowser, + "about:blank"); + tab1.linkedBrowser.loadURI(PAGE); + yield wait_for_tab_playing_event(tab1, true); + + info("- open tab 2 in foreground -"); + let tab2 = yield BrowserTestUtils.openNewForegroundTab(window.gBrowser, + "about:blank"); + tab2.linkedBrowser.loadURI(PAGE); + yield wait_for_tab_playing_event(tab1, false); + + info("- open tab 3 in foreground -"); + let tab3 = yield BrowserTestUtils.openNewForegroundTab(window.gBrowser, + "about:blank"); + yield ContentTask.spawn(tab2.linkedBrowser, null, + audio_should_keep_playing_even_go_to_background); + + info("- play audio from background tab 1 -"); + yield ContentTask.spawn(tab1.linkedBrowser, null, + play_audio_from_invisible_tab); + + info("- remove tabs -"); + yield BrowserTestUtils.removeTab(tab1); + yield BrowserTestUtils.removeTab(tab2); + yield BrowserTestUtils.removeTab(tab3); +}); + +add_task(function* within_one_tab_audio_competing () { + info("- open tab and play audio1 -"); + let tab = yield BrowserTestUtils.openNewForegroundTab(window.gBrowser, + "about:blank"); + tab.linkedBrowser.loadURI(PAGE); + yield wait_for_tab_playing_event(tab, true); + + info("- play audio2 in the same tab -"); + yield ContentTask.spawn(tab.linkedBrowser, null, + play_non_autoplay_audio); + + info("- remove tab -"); + yield BrowserTestUtils.removeTab(tab); +}); + diff --git a/toolkit/content/tests/browser/browser_audioCompeting_onlyForActiveAgent.js b/toolkit/content/tests/browser/browser_audioCompeting_onlyForActiveAgent.js new file mode 100644 index 000000000..31cd3f624 --- /dev/null +++ b/toolkit/content/tests/browser/browser_audioCompeting_onlyForActiveAgent.js @@ -0,0 +1,176 @@ +const PAGE = "https://example.com/browser/toolkit/content/tests/browser/file_multiplePlayingAudio.html"; + +var SuspendedType = { + NONE_SUSPENDED : 0, + SUSPENDED_PAUSE : 1, + SUSPENDED_BLOCK : 2, + SUSPENDED_PAUSE_DISPOSABLE : 3 +}; + +function wait_for_event(browser, event) { + return BrowserTestUtils.waitForEvent(browser, event, false, (event) => { + is(event.originalTarget, browser, "Event must be dispatched to correct browser."); + return true; + }); +} + +function check_all_audio_suspended(suspendedType) { + var audio1 = content.document.getElementById("audio1"); + var audio2 = content.document.getElementById("audio2"); + if (!audio1 || !audio2) { + ok(false, "Can't get the audio element!"); + } + + is(audio1.computedSuspended, suspendedType, + "The suspeded state of audio1 is correct."); + is(audio2.computedSuspended, suspendedType, + "The suspeded state of audio2 is correct."); +} + +function check_audio1_suspended(suspendedType) { + var audio1 = content.document.getElementById("audio1"); + if (!audio1) { + ok(false, "Can't get the audio element!"); + } + + is(audio1.computedSuspended, suspendedType, + "The suspeded state of audio1 is correct."); +} + +function check_audio2_suspended(suspendedType) { + var audio2 = content.document.getElementById("audio2"); + if (!audio2) { + ok(false, "Can't get the audio element!"); + } + + is(audio2.computedSuspended, suspendedType, + "The suspeded state of audio2 is correct."); +} + +function check_all_audio_pause_state(expectedPauseState) { + var audio1 = content.document.getElementById("audio1"); + var audio2 = content.document.getElementById("audio2"); + if (!audio1 | !audio2) { + ok(false, "Can't get the audio element!"); + } + + is(audio1.paused, expectedPauseState, + "The pause state of audio1 is correct."); + is(audio2.paused, expectedPauseState, + "The pause state of audio2 is correct."); +} + +function check_audio1_pause_state(expectedPauseState) { + var audio1 = content.document.getElementById("audio1"); + if (!audio1) { + ok(false, "Can't get the audio element!"); + } + + is(audio1.paused, expectedPauseState, + "The pause state of audio1 is correct."); +} + +function check_audio2_pause_state(expectedPauseState) { + var audio2 = content.document.getElementById("audio2"); + if (!audio2) { + ok(false, "Can't get the audio element!"); + } + + is(audio2.paused, expectedPauseState, + "The pause state of audio2 is correct."); +} + +function play_audio1_from_page() { + var audio1 = content.document.getElementById("audio1"); + if (!audio1) { + ok(false, "Can't get the audio element!"); + } + + is(audio1.paused, true, "Audio1 is paused."); + audio1.play(); + return new Promise(resolve => { + audio1.onplay = function() { + audio1.onplay = null; + ok(true, "Audio1 started playing."); + resolve(); + } + }); +} + +function stop_audio1_from_page() { + var audio1 = content.document.getElementById("audio1"); + if (!audio1) { + ok(false, "Can't get the audio element!"); + } + + is(audio1.paused, false, "Audio1 is playing."); + audio1.pause(); + return new Promise(resolve => { + audio1.onpause = function() { + audio1.onpause = null; + ok(true, "Audio1 stopped playing."); + resolve(); + } + }); +} + +function* audio_competing_for_active_agent(url, browser) { + browser.loadURI(url); + + info("- page should have playing audio -"); + yield wait_for_event(browser, "DOMAudioPlaybackStarted"); + + info("- the default suspended state of all audio should be non-suspened -"); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_all_audio_suspended); + + info("- only pause playing audio in the page -"); + browser.pauseMedia(true /* disposable */); + + info("- page shouldn't have any playing audio -"); + yield wait_for_event(browser, "DOMAudioPlaybackStopped"); + yield ContentTask.spawn(browser, true /* expect for pause */, + check_all_audio_pause_state); + yield ContentTask.spawn(browser, SuspendedType.SUSPENDED_PAUSE_DISPOSABLE, + check_all_audio_suspended); + + info("- resume audio1 from page -"); + yield ContentTask.spawn(browser, null, + play_audio1_from_page); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_audio1_suspended); + + info("- audio2 should still be suspended -"); + yield ContentTask.spawn(browser, SuspendedType.SUSPENDED_PAUSE_DISPOSABLE, + check_audio2_suspended); + yield ContentTask.spawn(browser, true /* expect for pause */, + check_audio2_pause_state); + + info("- stop audio1 from page -"); + yield ContentTask.spawn(browser, null, + stop_audio1_from_page); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_audio1_suspended); + + info("- audio2 should still be suspended -"); + yield ContentTask.spawn(browser, SuspendedType.SUSPENDED_PAUSE_DISPOSABLE, + check_audio2_suspended); + yield ContentTask.spawn(browser, true /* expect for pause */, + check_audio2_pause_state); + +} + +add_task(function* setup_test_preference() { + yield SpecialPowers.pushPrefEnv({"set": [ + ["media.useAudioChannelService.testing", true], + ["dom.audiochannel.audioCompeting", true], + ["dom.audiochannel.audioCompeting.allAgents", true] + ]}); +}); + +add_task(function* test_suspended_pause_disposable() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank" + }, audio_competing_for_active_agent.bind(this, PAGE)); +}); diff --git a/toolkit/content/tests/browser/browser_autoscroll_disabled.js b/toolkit/content/tests/browser/browser_autoscroll_disabled.js new file mode 100644 index 000000000..07c6174ab --- /dev/null +++ b/toolkit/content/tests/browser/browser_autoscroll_disabled.js @@ -0,0 +1,67 @@ +add_task(function* () +{ + const kPrefName_AutoScroll = "general.autoScroll"; + Services.prefs.setBoolPref(kPrefName_AutoScroll, false); + + let dataUri = 'data:text/html,
\ + \ +'; + + let loadedPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); + gBrowser.loadURI(dataUri); + yield loadedPromise; + + yield BrowserTestUtils.synthesizeMouse("#i", 50, 50, { button: 1 }, + gBrowser.selectedBrowser); + + yield ContentTask.spawn(gBrowser.selectedBrowser, { }, function* () { + var iframe = content.document.getElementById("iframe"); + + if (iframe) { + var e = new iframe.contentWindow.PageTransitionEvent("pagehide", + { bubbles: true, + cancelable: true, + persisted: false }); + iframe.contentDocument.dispatchEvent(e); + iframe.contentDocument.documentElement.dispatchEvent(e); + } + }); + + yield BrowserTestUtils.synthesizeMouse("#i", 100, 100, + { type: "mousemove", clickCount: "0" }, + gBrowser.selectedBrowser); + + // If scrolling didn't work, we wouldn't do any redraws and thus time out, so + // request and force redraws to get the chance to check for scrolling at all. + yield new Promise(resolve => window.requestAnimationFrame(resolve)); + + let msg = yield ContentTask.spawn(gBrowser.selectedBrowser, { }, function* () { + // Skip the first animation frame callback as it's the same callback that + // the browser uses to kick off the scrolling. + return new Promise(resolve => { + function checkScroll() { + let msg = ""; + let elem = content.document.getElementById('i'); + if (elem.scrollTop != 0) { + msg += "element should not have scrolled vertically"; + } + if (elem.scrollLeft != 0) { + msg += "element should not have scrolled horizontally"; + } + + resolve(msg); + } + + content.requestAnimationFrame(checkScroll); + }); + }); + + ok(!msg, "element scroll " + msg); + + // restore the changed prefs + if (Services.prefs.prefHasUserValue(kPrefName_AutoScroll)) + Services.prefs.clearUserPref(kPrefName_AutoScroll); + + // wait for focus to fix a failure in the next test if the latter runs too soon. + yield SimpleTest.promiseFocus(); +}); diff --git a/toolkit/content/tests/browser/browser_block_autoplay_media.js b/toolkit/content/tests/browser/browser_block_autoplay_media.js new file mode 100644 index 000000000..3b2a309b9 --- /dev/null +++ b/toolkit/content/tests/browser/browser_block_autoplay_media.js @@ -0,0 +1,87 @@ +const PAGE = "https://example.com/browser/toolkit/content/tests/browser/file_multipleAudio.html"; + +var SuspendedType = { + NONE_SUSPENDED : 0, + SUSPENDED_PAUSE : 1, + SUSPENDED_BLOCK : 2, + SUSPENDED_PAUSE_DISPOSABLE : 3 +}; + +function* wait_for_tab_playing_event(tab, expectPlaying) { + if (tab.soundPlaying == expectPlaying) { + ok(true, "The tab should " + (expectPlaying ? "" : "not ") + "be playing"); + } else { + yield BrowserTestUtils.waitForEvent(tab, "TabAttrModified", false, (event) => { + if (event.detail.changed.indexOf("soundplaying") >= 0) { + is(tab.soundPlaying, expectPlaying, "The tab should " + (expectPlaying ? "" : "not ") + "be playing"); + return true; + } + return false; + }); + } +} + +function check_audio_suspended(suspendedType) { + var autoPlay = content.document.getElementById('autoplay'); + if (!autoPlay) { + ok(false, "Can't get the audio element!"); + } + + is(autoPlay.computedSuspended, suspendedType, + "The suspeded state of autoplay audio is correct."); +} + +add_task(function* setup_test_preference() { + yield new Promise(resolve => { + SpecialPowers.pushPrefEnv({"set": [ + ["media.useAudioChannelService.testing", true], + ["media.block-autoplay-until-in-foreground", true] + ]}, resolve); + }); +}); + +add_task(function* block_autoplay_media() { + info("- open new background tab1 -"); + let tab1 = window.gBrowser.addTab("about:blank"); + tab1.linkedBrowser.loadURI(PAGE); + yield BrowserTestUtils.browserLoaded(tab1.linkedBrowser); + + info("- should block autoplay media for non-visited tab1 -"); + yield ContentTask.spawn(tab1.linkedBrowser, SuspendedType.SUSPENDED_BLOCK, + check_audio_suspended); + + info("- open new background tab2 -"); + let tab2 = window.gBrowser.addTab("about:blank"); + tab2.linkedBrowser.loadURI(PAGE); + yield BrowserTestUtils.browserLoaded(tab2.linkedBrowser); + + info("- should block autoplay for non-visited tab2 -"); + yield ContentTask.spawn(tab2.linkedBrowser, SuspendedType.SUSPENDED_BLOCK, + check_audio_suspended); + + info("- select tab1 as foreground tab -"); + yield BrowserTestUtils.switchTab(window.gBrowser, tab1); + + info("- media should be unblocked because the tab was visited -"); + yield wait_for_tab_playing_event(tab1, true); + yield ContentTask.spawn(tab1.linkedBrowser, SuspendedType.NONE_SUSPENDED, + check_audio_suspended); + + info("- open another new foreground tab3 -"); + let tab3 = yield BrowserTestUtils.openNewForegroundTab(window.gBrowser, + "about:blank"); + info("- should still play media from tab1 -"); + yield wait_for_tab_playing_event(tab1, true); + yield ContentTask.spawn(tab1.linkedBrowser, SuspendedType.NONE_SUSPENDED, + check_audio_suspended); + + info("- should still block media from tab2 -"); + yield wait_for_tab_playing_event(tab2, false); + yield ContentTask.spawn(tab2.linkedBrowser, SuspendedType.SUSPENDED_BLOCK, + check_audio_suspended); + + info("- remove tabs -"); + yield BrowserTestUtils.removeTab(tab1); + yield BrowserTestUtils.removeTab(tab2); + yield BrowserTestUtils.removeTab(tab3); +}); diff --git a/toolkit/content/tests/browser/browser_bug1170531.js b/toolkit/content/tests/browser/browser_bug1170531.js new file mode 100644 index 000000000..49df5661a --- /dev/null +++ b/toolkit/content/tests/browser/browser_bug1170531.js @@ -0,0 +1,92 @@ +// Test for bug 1170531 +// https://bugzilla.mozilla.org/show_bug.cgi?id=1170531 + +add_task(function* () { + // Get a bunch of DOM nodes + let winUtils = window.QueryInterface(Ci.nsIInterfaceRequestor). + getInterface(Ci.nsIDOMWindowUtils); + + let editMenu = document.getElementById("edit-menu"); + let menubar = editMenu.parentNode; + let menuPopup = editMenu.menupopup; + let editMenuIndex = -1; + for (let i = 0; i < menubar.children.length; i++) { + if (menubar.children[i] === editMenu) { + editMenuIndex = i; + break; + } + } + + let closeMenu = function(aCallback) { + if (OS.Constants.Sys.Name == "Darwin") { + executeSoon(aCallback); + return; + } + + menuPopup.addEventListener("popuphidden", function onPopupHidden() { + menuPopup.removeEventListener("popuphidden", onPopupHidden, false); + executeSoon(aCallback); + }, false); + + executeSoon(function() { + editMenu.open = false; + }); + }; + + let openMenu = function(aCallback) { + if (OS.Constants.Sys.Name == "Darwin") { + goUpdateGlobalEditMenuItems(); + // On OSX, we have a native menu, so it has to be updated. In single process browsers, + // this happens synchronously, but in e10s, we have to wait for the main thread + // to deal with it for us. 1 second should be plenty of time. + setTimeout(aCallback, 1000); + return; + } + + menuPopup.addEventListener("popupshown", function onPopupShown() { + menuPopup.removeEventListener("popupshown", onPopupShown, false); + executeSoon(aCallback); + }, false); + + executeSoon(function() { + editMenu.open = true; + }); + }; + + yield BrowserTestUtils.withNewTab({ gBrowser: gBrowser, url: "about:blank" }, function* (browser) { + let menu_cut_disabled, menu_copy_disabled; + + yield BrowserTestUtils.loadURI(browser, "data:text/html,
hello!
"); + yield BrowserTestUtils.browserLoaded(browser); + browser.focus(); + yield new Promise(resolve => waitForFocus(resolve, window)); + yield new Promise(openMenu); + menu_cut_disabled = menuPopup.querySelector("#menu_cut").getAttribute('disabled') == "true"; + is(menu_cut_disabled, false, "menu_cut should be enabled"); + menu_copy_disabled = menuPopup.querySelector("#menu_copy").getAttribute('disabled') == "true"; + is(menu_copy_disabled, false, "menu_copy should be enabled"); + yield new Promise(closeMenu); + + yield BrowserTestUtils.loadURI(browser, "data:text/html,
hello!
"); + yield BrowserTestUtils.browserLoaded(browser); + browser.focus(); + yield new Promise(resolve => waitForFocus(resolve, window)); + yield new Promise(openMenu); + menu_cut_disabled = menuPopup.querySelector("#menu_cut").getAttribute('disabled') == "true"; + is(menu_cut_disabled, false, "menu_cut should be enabled"); + menu_copy_disabled = menuPopup.querySelector("#menu_copy").getAttribute('disabled') == "true"; + is(menu_copy_disabled, false, "menu_copy should be enabled"); + yield new Promise(closeMenu); + + yield BrowserTestUtils.loadURI(browser, "about:preferences"); + yield BrowserTestUtils.browserLoaded(browser); + browser.focus(); + yield new Promise(resolve => waitForFocus(resolve, window)); + yield new Promise(openMenu); + menu_cut_disabled = menuPopup.querySelector("#menu_cut").getAttribute('disabled') == "true"; + is(menu_cut_disabled, true, "menu_cut should be disabled"); + menu_copy_disabled = menuPopup.querySelector("#menu_copy").getAttribute('disabled') == "true"; + is(menu_copy_disabled, true, "menu_copy should be disabled"); + yield new Promise(closeMenu); + }); +}); diff --git a/toolkit/content/tests/browser/browser_bug1198465.js b/toolkit/content/tests/browser/browser_bug1198465.js new file mode 100644 index 000000000..a9cc83e12 --- /dev/null +++ b/toolkit/content/tests/browser/browser_bug1198465.js @@ -0,0 +1,75 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +var kPrefName = "accessibility.typeaheadfind.prefillwithselection"; +var kEmptyURI = "data:text/html,"; + +// This pref is false by default in OSX; ensure the test still works there. +Services.prefs.setBoolPref(kPrefName, true); + +registerCleanupFunction(function() { + Services.prefs.clearUserPref(kPrefName); +}); + +add_task(function* () { + let aTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, kEmptyURI); + ok(!gFindBarInitialized, "findbar isn't initialized yet"); + + // Note: the use case here is when the user types directly in the findbar + // _before_ it's prefilled with a text selection in the page. + + // So `yield BrowserTestUtils.sendChar()` can't be used here: + // - synthesizing a key in the browser won't actually send it to the + // findbar; the findbar isn't part of the browser content. + // - we need to _not_ wait for _startFindDeferred to be resolved; yielding + // a synthesized keypress on the browser implicitely happens after the + // browser has dispatched its return message with the prefill value for + // the findbar, which essentially nulls these tests. + + let findBar = gFindBar; + is(findBar._findField.value, "", "findbar is empty"); + + // Test 1 + // Any input in the findbar should erase a previous search. + + findBar._findField.value = "xy"; + findBar.startFind(); + is(findBar._findField.value, "xy", "findbar should have xy initial query"); + is(findBar._findField.mInputField, + document.activeElement, + "findbar is now focused"); + + EventUtils.sendChar("z", window); + is(findBar._findField.value, "z", "z erases xy"); + + findBar._findField.value = ""; + ok(!findBar._findField.value, "erase findbar after first test"); + + // Test 2 + // Prefilling the findbar should be ignored if a search has been run. + + findBar.startFind(); + ok(findBar._startFindDeferred, "prefilled value hasn't been fetched yet"); + is(findBar._findField.mInputField, + document.activeElement, + "findbar is still focused"); + + EventUtils.sendChar("a", window); + EventUtils.sendChar("b", window); + is(findBar._findField.value, "ab", "initial ab typed in the findbar"); + + // This resolves _startFindDeferred if it's still pending; let's just skip + // over waiting for the browser's return message that should do this as it + // doesn't really matter. + findBar.onCurrentSelection("foo", true); + ok(!findBar._startFindDeferred, "prefilled value fetched"); + is(findBar._findField.value, "ab", "ab kept instead of prefill value"); + + EventUtils.sendChar("c", window); + is(findBar._findField.value, "abc", "c is appended after ab"); + + // Clear the findField value to make the test run successfully + // for multiple runs in the same browser session. + findBar._findField.value = ""; + yield BrowserTestUtils.removeTab(aTab); +}); diff --git a/toolkit/content/tests/browser/browser_bug295977_autoscroll_overflow.js b/toolkit/content/tests/browser/browser_bug295977_autoscroll_overflow.js new file mode 100644 index 000000000..958afc868 --- /dev/null +++ b/toolkit/content/tests/browser/browser_bug295977_autoscroll_overflow.js @@ -0,0 +1,214 @@ +requestLongerTimeout(2); +add_task(function* () +{ + function pushPref(name, value) { + return new Promise(resolve => SpecialPowers.pushPrefEnv({"set": [[name, value]]}, resolve)); + } + + yield pushPref("general.autoScroll", true); + + const expectScrollNone = 0; + const expectScrollVert = 1; + const expectScrollHori = 2; + const expectScrollBoth = 3; + + var allTests = [ + {dataUri: 'data:text/html,\ +
\ +
\ +
\ +
\ + \ + \ +
\ +
\ + \ + '}, + {elem: 'a', expected: expectScrollNone}, + {elem: 'b', expected: expectScrollBoth}, + {elem: 'c', expected: expectScrollHori}, + {elem: 'd', expected: expectScrollVert}, + {elem: 'e', expected: expectScrollVert}, + {elem: 'f', expected: expectScrollNone}, + {elem: 'g', expected: expectScrollBoth}, + {elem: 'h', expected: expectScrollNone}, + {dataUri: 'data:text/html,
\ + \ + '}, + {elem: 'i', expected: expectScrollVert}, // bug 695121 + {dataUri: 'data:text/html,\ +
\ + \ + '}, + {elem: 'j', expected: expectScrollVert}, // bug 914251 + {dataUri: 'data:text/html,\ +\ +
'}, + {elem: 't', expected: expectScrollBoth}, // bug 1308775 + {dataUri: 'data:text/html,\ +
\ +\ +
\ +
\ +\ +
\ +\ +
filler to make document overflow: scroll;
\ +'}, + {elem: 'k', expected: expectScrollBoth}, + {elem: 'k', expected: expectScrollNone, testwindow: true}, + {elem: 'l', expected: expectScrollNone}, + {elem: 'm', expected: expectScrollVert, testwindow: true}, + {dataUri: 'data:text/html,\ +image map\ +\ + \ +\ +link\ +\ +\ +
\ +'}, + {elem: 'n', expected: expectScrollNone, testwindow: true}, + {elem: 'o', expected: expectScrollNone, testwindow: true}, + {elem: 'p', expected: expectScrollVert, testwindow: true, middlemousepastepref: false}, + {elem: 'q', expected: expectScrollVert, testwindow: true, middlemousepastepref: false}, + {dataUri: 'data:text/html,\ +\ +\ +
\ +'}, + {elem: 'r', expected: expectScrollNone, testwindow: true, middlemousepastepref: true}, + {elem: 's', expected: expectScrollNone, testwindow: true, middlemousepastepref: true} + ]; + + for (let test of allTests) { + if (test.dataUri) { + let loadedPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); + gBrowser.loadURI(test.dataUri); + yield loadedPromise; + continue; + } + + let prefsChanged = (test.middlemousepastepref == false || test.middlemousepastepref == true); + if (prefsChanged) { + yield pushPref("middlemouse.paste", test.middlemousepastepref); + } + + yield BrowserTestUtils.synthesizeMouse("#" + test.elem, 50, 80, { button: 1 }, + gBrowser.selectedBrowser); + + // This ensures bug 605127 is fixed: pagehide in an unrelated document + // should not cancel the autoscroll. + yield ContentTask.spawn(gBrowser.selectedBrowser, { }, function* () { + var iframe = content.document.getElementById("iframe"); + + if (iframe) { + var e = new iframe.contentWindow.PageTransitionEvent("pagehide", + { bubbles: true, + cancelable: true, + persisted: false }); + iframe.contentDocument.dispatchEvent(e); + iframe.contentDocument.documentElement.dispatchEvent(e); + } + }); + + is(document.activeElement, gBrowser.selectedBrowser, "Browser still focused after autoscroll started"); + + yield BrowserTestUtils.synthesizeMouse("#" + test.elem, 100, 100, + { type: "mousemove", clickCount: "0" }, + gBrowser.selectedBrowser); + + if (prefsChanged) { + yield new Promise(resolve => SpecialPowers.popPrefEnv(resolve)); + } + + // Start checking for the scroll. + let firstTimestamp = undefined; + let timeCompensation; + do { + let timestamp = yield new Promise(resolve => window.requestAnimationFrame(resolve)); + if (firstTimestamp === undefined) { + firstTimestamp = timestamp; + } + + // This value is calculated similarly to the value of the same name in + // ClickEventHandler.autoscrollLoop, except here it's cumulative across + // all frames after the first one instead of being based only on the + // current frame. + timeCompensation = (timestamp - firstTimestamp) / 20; + info("timestamp=" + timestamp + " firstTimestamp=" + firstTimestamp + + " timeCompensation=" + timeCompensation); + + // Try to wait until enough time has passed to allow the scroll to happen. + // autoscrollLoop incrementally scrolls during each animation frame, but + // due to how its calculations work, when a frame is very close to the + // previous frame, no scrolling may actually occur during that frame. + // After 100ms's worth of frames, timeCompensation will be 1, making it + // more likely that the accumulated scroll in autoscrollLoop will be >= 1, + // although it also depends on acceleration, which here in this test + // should be > 1 due to how it synthesizes mouse events below. + } while (timeCompensation < 5); + + // Close the autoscroll popup by synthesizing Esc. + EventUtils.synthesizeKey("VK_ESCAPE", {}); + let scrollVert = test.expected & expectScrollVert; + let scrollHori = test.expected & expectScrollHori; + + yield ContentTask.spawn(gBrowser.selectedBrowser, + { scrollVert : scrollVert, + scrollHori: scrollHori, + elemid : test.elem, + checkWindow: test.testwindow }, + function* (args) { + let msg = ""; + if (args.checkWindow) { + if (!((args.scrollVert && content.scrollY > 0) || + (!args.scrollVert && content.scrollY == 0))) { + msg += "Failed: "; + } + msg += 'Window for ' + args.elemid + ' should' + (args.scrollVert ? '' : ' not') + ' have scrolled vertically\n'; + + if (!((args.scrollHori && content.scrollX > 0) || + (!args.scrollHori && content.scrollX == 0))) { + msg += "Failed: "; + } + msg += ' Window for ' + args.elemid + ' should' + (args.scrollHori ? '' : ' not') + ' have scrolled horizontally\n'; + } else { + let elem = content.document.getElementById(args.elemid); + if (!((args.scrollVert && elem.scrollTop > 0) || + (!args.scrollVert && elem.scrollTop == 0))) { + msg += "Failed: "; + } + msg += ' ' + args.elemid + ' should' + (args.scrollVert ? '' : ' not') + ' have scrolled vertically\n'; + if (!((args.scrollHori && elem.scrollLeft > 0) || + (!args.scrollHori && elem.scrollLeft == 0))) { + msg += "Failed: "; + } + msg += args.elemid + ' should' + (args.scrollHori ? '' : ' not') + ' have scrolled horizontally'; + } + + Assert.ok(msg.indexOf("Failed") == -1, msg); + } + ); + + // Before continuing the test, we need to ensure that the IPC + // message that stops autoscrolling has had time to arrive. + yield new Promise(resolve => executeSoon(resolve)); + } + + // remove 2 tabs that were opened by middle-click on links + while (gBrowser.visibleTabs.length > 1) { + gBrowser.removeTab(gBrowser.visibleTabs[gBrowser.visibleTabs.length - 1]); + } + + // wait for focus to fix a failure in the next test if the latter runs too soon. + yield SimpleTest.promiseFocus(); +}); diff --git a/toolkit/content/tests/browser/browser_bug451286.js b/toolkit/content/tests/browser/browser_bug451286.js new file mode 100644 index 000000000..a5dadeb84 --- /dev/null +++ b/toolkit/content/tests/browser/browser_bug451286.js @@ -0,0 +1,152 @@ +Services.scriptloader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js", this); + +add_task(function*() { + const SEARCH_TEXT = "text"; + const DATAURI = "data:text/html," + SEARCH_TEXT; + + // Bug 451286. An iframe that should be highlighted + let visible = ""; + + // Bug 493658. An invisible iframe that shouldn't interfere with + // highlighting matches lying after it in the document + let invisible = ""; + + let uri = DATAURI + invisible + SEARCH_TEXT + visible + SEARCH_TEXT; + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, uri); + let contentRect = tab.linkedBrowser.getBoundingClientRect(); + let noHighlightSnapshot = snapshotRect(window, contentRect); + ok(noHighlightSnapshot, "Got noHighlightSnapshot"); + + yield openFindBarAndWait(); + gFindBar._findField.value = SEARCH_TEXT; + yield findAgainAndWait(); + var matchCase = gFindBar.getElement("find-case-sensitive"); + if (matchCase.checked) + matchCase.doCommand(); + + // Turn on highlighting + yield toggleHighlightAndWait(true); + yield closeFindBarAndWait(); + + // Take snapshot of highlighting + let findSnapshot = snapshotRect(window, contentRect); + ok(findSnapshot, "Got findSnapshot"); + + // Now, remove the highlighting, and take a snapshot to compare + // to our original state + yield openFindBarAndWait(); + yield toggleHighlightAndWait(false); + yield closeFindBarAndWait(); + + let unhighlightSnapshot = snapshotRect(window, contentRect); + ok(unhighlightSnapshot, "Got unhighlightSnapshot"); + + // Select the matches that should have been highlighted manually + yield ContentTask.spawn(tab.linkedBrowser, null, function*() { + let doc = content.document; + let win = doc.defaultView; + + // Create a manual highlight in the visible iframe to test bug 451286 + let iframe = doc.getElementById("visible"); + let ifBody = iframe.contentDocument.body; + let range = iframe.contentDocument.createRange(); + range.selectNodeContents(ifBody.childNodes[0]); + let ifWindow = iframe.contentWindow; + let ifDocShell = ifWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); + + let ifController = ifDocShell.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsISelectionDisplay) + .QueryInterface(Ci.nsISelectionController); + + let frameFindSelection = + ifController.getSelection(ifController.SELECTION_FIND); + frameFindSelection.addRange(range); + + // Create manual highlights in the main document (the matches that lie + // before/after the iframes + let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); + + let controller = docShell.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsISelectionDisplay) + .QueryInterface(Ci.nsISelectionController); + + let docFindSelection = + controller.getSelection(ifController.SELECTION_FIND); + + range = doc.createRange(); + range.selectNodeContents(doc.body.childNodes[0]); + docFindSelection.addRange(range); + range = doc.createRange(); + range.selectNodeContents(doc.body.childNodes[2]); + docFindSelection.addRange(range); + range = doc.createRange(); + range.selectNodeContents(doc.body.childNodes[4]); + docFindSelection.addRange(range); + }); + + // Take snapshot of manual highlighting + let manualSnapshot = snapshotRect(window, contentRect); + ok(manualSnapshot, "Got manualSnapshot"); + + // Test 1: Were the matches in iframe correctly highlighted? + let res = compareSnapshots(findSnapshot, manualSnapshot, true); + ok(res[0], "Matches found in iframe correctly highlighted"); + + // Test 2: Were the matches in iframe correctly unhighlighted? + res = compareSnapshots(noHighlightSnapshot, unhighlightSnapshot, true); + ok(res[0], "Highlighting in iframe correctly removed"); + + yield BrowserTestUtils.removeTab(tab); +}); + +function toggleHighlightAndWait(shouldHighlight) { + return new Promise((resolve) => { + let listener = { + onFindResult() {}, + onHighlightFinished() { + gFindBar.browser.finder.removeResultListener(listener); + resolve(); + }, + onMatchesCountResult() {} + }; + gFindBar.browser.finder.addResultListener(listener); + gFindBar.toggleHighlight(shouldHighlight); + }); +} + +function findAgainAndWait() { + return new Promise(resolve => { + let listener = { + onFindResult() { + gFindBar.browser.finder.removeResultListener(listener); + resolve(); + }, + onHighlightFinished() {}, + onMatchesCountResult() {} + }; + gFindBar.browser.finder.addResultListener(listener); + gFindBar.onFindAgainCommand(); + }); +} + +function* openFindBarAndWait() { + let awaitTransitionEnd = BrowserTestUtils.waitForEvent(gFindBar, "transitionend"); + gFindBar.open(); + yield awaitTransitionEnd; +} + +// This test is comparing snapshots. It is necessary to wait for the gFindBar +// to close before taking the snapshot so the gFindBar does not take up space +// on the new snapshot. +function* closeFindBarAndWait() { + let awaitTransitionEnd = BrowserTestUtils.waitForEvent(gFindBar, "transitionend", false, event => { + return event.propertyName == "visibility"; + }); + gFindBar.close(); + yield awaitTransitionEnd; +} diff --git a/toolkit/content/tests/browser/browser_bug594509.js b/toolkit/content/tests/browser/browser_bug594509.js new file mode 100644 index 000000000..e67b05f85 --- /dev/null +++ b/toolkit/content/tests/browser/browser_bug594509.js @@ -0,0 +1,9 @@ +add_task(function* () { + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:rights"); + + yield ContentTask.spawn(tab.linkedBrowser, null, function* () { + Assert.ok(content.document.getElementById("your-rights"), "about:rights content loaded"); + }); + + yield BrowserTestUtils.removeTab(tab); +}); diff --git a/toolkit/content/tests/browser/browser_bug982298.js b/toolkit/content/tests/browser/browser_bug982298.js new file mode 100644 index 000000000..047340c5c --- /dev/null +++ b/toolkit/content/tests/browser/browser_bug982298.js @@ -0,0 +1,70 @@ +const scrollHtml = + "blank"; + +add_task(function*() { + let url = "data:text/html;base64," + btoa(scrollHtml); + yield BrowserTestUtils.withNewTab({gBrowser, url}, function*(browser) { + let awaitFindResult = new Promise(resolve => { + let listener = { + onFindResult(aData) { + info("got find result"); + browser.finder.removeResultListener(listener); + + ok(aData.result == Ci.nsITypeAheadFind.FIND_FOUND, "should find string"); + resolve(); + }, + onCurrentSelection() {}, + onMatchesCountResult() {} + }; + info("about to add results listener, open find bar, and send 'F' string"); + browser.finder.addResultListener(listener); + }); + gFindBar.onFindCommand(); + EventUtils.sendString("F"); + info("added result listener and sent string 'F'"); + yield awaitFindResult; + + let awaitScrollDone = BrowserTestUtils.waitForMessage(browser.messageManager, "ScrollDone"); + // scroll textarea to bottom + const scrollTest = + "var textarea = content.document.getElementById(\"textarea1\");" + + "textarea.scrollTop = textarea.scrollHeight;" + + "sendAsyncMessage(\"ScrollDone\", { });" + browser.messageManager.loadFrameScript("data:text/javascript;base64," + + btoa(scrollTest), false); + yield awaitScrollDone; + info("got ScrollDone event"); + yield BrowserTestUtils.loadURI(browser, "about:blank"); + yield BrowserTestUtils.browserLoaded(browser); + + ok(browser.currentURI.spec == "about:blank", "got load event for about:blank"); + + let awaitFindResult2 = new Promise(resolve => { + let listener = { + onFindResult(aData) { + info("got find result #2"); + browser.finder.removeResultListener(listener); + resolve(); + }, + onCurrentSelection() {}, + onMatchesCountResult() {} + }; + + browser.finder.addResultListener(listener); + info("added result listener"); + }); + // find again needs delay for crash test + setTimeout(function() { + // ignore exception if occured + try { + info("about to send find again command"); + gFindBar.onFindAgainCommand(false); + info("sent find again command"); + } catch (e) { + info("got exception from onFindAgainCommand: " + e); + } + }, 0); + yield awaitFindResult2; + }); +}); diff --git a/toolkit/content/tests/browser/browser_contentTitle.js b/toolkit/content/tests/browser/browser_contentTitle.js new file mode 100644 index 000000000..e7966e565 --- /dev/null +++ b/toolkit/content/tests/browser/browser_contentTitle.js @@ -0,0 +1,16 @@ +var url = "https://example.com/browser/toolkit/content/tests/browser/file_contentTitle.html"; + +add_task(function*() { + let tab = gBrowser.selectedTab = gBrowser.addTab(url); + let browser = tab.linkedBrowser; + yield new Promise((resolve) => { + addEventListener("TestLocationChange", function listener() { + removeEventListener("TestLocationChange", listener); + resolve(); + }, true, true); + }); + + is(gBrowser.contentTitle, "Test Page", "Should have the right title."); + + gBrowser.removeTab(tab); +}); diff --git a/toolkit/content/tests/browser/browser_content_url_annotation.js b/toolkit/content/tests/browser/browser_content_url_annotation.js new file mode 100644 index 000000000..1a4cee4c6 --- /dev/null +++ b/toolkit/content/tests/browser/browser_content_url_annotation.js @@ -0,0 +1,73 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ +/* global Services, requestLongerTimeout, TestUtils, BrowserTestUtils, + ok, info, dump, is, Ci, Cu, Components, ctypes, privateNoteIntentionalCrash, + gBrowser, add_task, addEventListener, removeEventListener, ContentTask */ + +"use strict"; + +// Running this test in ASAN is slow. +requestLongerTimeout(2); + +/** + * Removes a file from a directory. This is a no-op if the file does not + * exist. + * + * @param directory + * The nsIFile representing the directory to remove from. + * @param filename + * A string for the file to remove from the directory. + */ +function removeFile(directory, filename) { + let file = directory.clone(); + file.append(filename); + if (file.exists()) { + file.remove(false); + } +} + +/** + * Returns the directory where crash dumps are stored. + * + * @return nsIFile + */ +function getMinidumpDirectory() { + let dir = Services.dirsvc.get('ProfD', Ci.nsIFile); + dir.append("minidumps"); + return dir; +} + +/** + * Checks that the URL is correctly annotated on a content process crash. + */ +add_task(function* test_content_url_annotation() { + let url = "https://example.com/browser/toolkit/content/tests/browser/file_redirect.html"; + let redirect_url = "https://example.com/browser/toolkit/content/tests/browser/file_redirect_to.html"; + + yield BrowserTestUtils.withNewTab({ + gBrowser: gBrowser + }, function* (browser) { + ok(browser.isRemoteBrowser, "Should be a remote browser"); + + // file_redirect.html should send us to file_redirect_to.html + let promise = ContentTask.spawn(browser, {}, function* () { + dump('ContentTask starting...\n'); + yield new Promise((resolve) => { + addEventListener("RedirectDone", function listener() { + dump('Got RedirectDone\n'); + removeEventListener("RedirectDone", listener); + resolve(); + }, true, true); + }); + }); + browser.loadURI(url); + yield promise; + + // Crash the tab + let annotations = yield BrowserTestUtils.crashBrowser(browser); + + ok("URL" in annotations, "annotated a URL"); + is(annotations.URL, redirect_url, + "Should have annotated the URL after redirect"); + }); +}); diff --git a/toolkit/content/tests/browser/browser_crash_previous_frameloader.js b/toolkit/content/tests/browser/browser_crash_previous_frameloader.js new file mode 100644 index 000000000..bd50c6ffd --- /dev/null +++ b/toolkit/content/tests/browser/browser_crash_previous_frameloader.js @@ -0,0 +1,108 @@ +"use strict"; + +/** + * Cleans up the .dmp and .extra file from a crash. + * + * @param subject (nsISupports) + * The subject passed through the ipc:content-shutdown + * observer notification when a content process crash has + * occurred. + */ +function cleanUpMinidump(subject) { + Assert.ok(subject instanceof Ci.nsIPropertyBag2, + "Subject needs to be a nsIPropertyBag2 to clean up properly"); + let dumpID = subject.getPropertyAsAString("dumpID"); + + Assert.ok(dumpID, "There should be a dumpID"); + if (dumpID) { + let dir = Services.dirsvc.get("ProfD", Ci.nsIFile); + dir.append("minidumps"); + + let file = dir.clone(); + file.append(dumpID + ".dmp"); + file.remove(true); + + file = dir.clone(); + file.append(dumpID + ".extra"); + file.remove(true); + } +} + +/** + * This test ensures that if a remote frameloader crashes after + * the frameloader owner swaps it out for a new frameloader, + * that a oop-browser-crashed event is not sent to the new + * frameloader's browser element. + */ +add_task(function* test_crash_in_previous_frameloader() { + // On debug builds, crashing tabs results in much thinking, which + // slows down the test and results in intermittent test timeouts, + // so we'll pump up the expected timeout for this test. + requestLongerTimeout(2); + + if (!gMultiProcessBrowser) { + Assert.ok(false, "This test should only be run in multi-process mode."); + return; + } + + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "http://example.com", + }, function*(browser) { + // First, sanity check... + Assert.ok(browser.isRemoteBrowser, + "This browser needs to be remote if this test is going to " + + "work properly."); + + // We will wait for the oop-browser-crashed event to have + // a chance to appear. That event is fired when TabParents + // are destroyed, and that occurs _before_ ContentParents + // are destroyed, so we'll wait on the ipc:content-shutdown + // observer notification, which is fired when a ContentParent + // goes away. After we see this notification, oop-browser-crashed + // events should have fired. + let contentProcessGone = TestUtils.topicObserved("ipc:content-shutdown"); + let sawTabCrashed = false; + let onTabCrashed = () => { + sawTabCrashed = true; + }; + + browser.addEventListener("oop-browser-crashed", onTabCrashed); + + // The name of the game is to cause a crash in a remote browser, + // and then immediately swap out the browser for a non-remote one. + yield ContentTask.spawn(browser, null, function() { + const Cu = Components.utils; + Cu.import("resource://gre/modules/ctypes.jsm"); + Cu.import("resource://gre/modules/Timer.jsm"); + + let dies = function() { + privateNoteIntentionalCrash(); + let zero = new ctypes.intptr_t(8); + let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t)); + badptr.contents + }; + + // When the parent flips the remoteness of the browser, the + // page should receive the pagehide event, which we'll then + // use to crash the frameloader. + addEventListener("pagehide", function() { + dump("\nEt tu, Brute?\n"); + dies(); + }); + }); + + gBrowser.updateBrowserRemoteness(browser, false); + info("Waiting for content process to go away."); + let [subject, data] = yield contentProcessGone; + + // If we don't clean up the minidump, the harness will + // complain. + cleanUpMinidump(subject); + + info("Content process is gone!"); + Assert.ok(!sawTabCrashed, + "Should not have seen the oop-browser-crashed event."); + browser.removeEventListener("oop-browser-crashed", onTabCrashed); + }); +}); diff --git a/toolkit/content/tests/browser/browser_default_image_filename.js b/toolkit/content/tests/browser/browser_default_image_filename.js new file mode 100644 index 000000000..2859d486f --- /dev/null +++ b/toolkit/content/tests/browser/browser_default_image_filename.js @@ -0,0 +1,45 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +var MockFilePicker = SpecialPowers.MockFilePicker; +MockFilePicker.init(window); + +/** + * TestCase for bug 564387 + * + */ +add_task(function* () { + let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); + gBrowser.loadURI("data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7"); + yield loadPromise; + + let popupShownPromise = BrowserTestUtils.waitForEvent(document, "popupshown"); + + yield BrowserTestUtils.synthesizeMouseAtCenter("img", + { type: "contextmenu", button: 2 }, + gBrowser.selectedBrowser); + + yield popupShownPromise; + + let showFilePickerPromise = new Promise(resolve => { + MockFilePicker.showCallback = function(fp) { + is(fp.defaultString, "index.gif"); + resolve(); + } + }); + + registerCleanupFunction(function () { + MockFilePicker.cleanup(); + }); + + // Select "Save Image As" option from context menu + var saveImageAsCommand = document.getElementById("context-saveimage"); + saveImageAsCommand.doCommand(); + + yield showFilePickerPromise; + + let contextMenu = document.getElementById("contentAreaContextMenu"); + let popupHiddenPromise = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden"); + contextMenu.hidePopup(); + yield popupHiddenPromise; +}); diff --git a/toolkit/content/tests/browser/browser_f7_caret_browsing.js b/toolkit/content/tests/browser/browser_f7_caret_browsing.js new file mode 100644 index 000000000..c4b6823d4 --- /dev/null +++ b/toolkit/content/tests/browser/browser_f7_caret_browsing.js @@ -0,0 +1,227 @@ +var gListener = null; +const kURL = "data:text/html;charset=utf-8,Caret browsing is fun."; + +const kPrefShortcutEnabled = "accessibility.browsewithcaret_shortcut.enabled"; +const kPrefWarnOnEnable = "accessibility.warn_on_browsewithcaret"; +const kPrefCaretBrowsingOn = "accessibility.browsewithcaret"; + +var oldPrefs = {}; +for (let pref of [kPrefShortcutEnabled, kPrefWarnOnEnable, kPrefCaretBrowsingOn]) { + oldPrefs[pref] = Services.prefs.getBoolPref(pref); +} + +Services.prefs.setBoolPref(kPrefShortcutEnabled, true); +Services.prefs.setBoolPref(kPrefWarnOnEnable, true); +Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false); + +registerCleanupFunction(function() { + for (let pref of [kPrefShortcutEnabled, kPrefWarnOnEnable, kPrefCaretBrowsingOn]) { + Services.prefs.setBoolPref(pref, oldPrefs[pref]); + } +}); + +// NB: not using BrowserTestUtils.domWindowOpened here because there's no way to +// undo waiting for a window open. If we don't want the window to be opened, and +// wait for it to verify that it indeed does not open, we need to be able to +// then "stop" waiting so that when we next *do* want it to open, our "old" +// listener doesn't fire and do things we don't want (like close the window...). +let gCaretPromptOpeningObserver; +function promiseCaretPromptOpened() { + return new Promise(resolve => { + function observer(subject, topic, data) { + if (topic == "domwindowopened") { + Services.ww.unregisterNotification(observer); + let win = subject.QueryInterface(Ci.nsIDOMWindow); + BrowserTestUtils.waitForEvent(win, "load", false, e => e.target.location.href != "about:blank").then(() => resolve(win)); + gCaretPromptOpeningObserver = null; + } + } + Services.ww.registerNotification(observer); + gCaretPromptOpeningObserver = observer; + }); +} + +function hitF7(async = true) { + let f7 = () => EventUtils.sendKey("F7"); + // Need to not stop execution inside this task: + if (async) { + executeSoon(f7); + } else { + f7(); + } +} + +function syncToggleCaretNoDialog(expected) { + let openedDialog = false; + promiseCaretPromptOpened().then(function(win) { + openedDialog = true; + win.close(); // This will eventually return focus here and allow the test to continue... + }); + // Cause the dialog to appear sync, if it still does. + hitF7(false); + + let expectedStr = expected ? "on." : "off."; + ok(!openedDialog, "Shouldn't open a dialog to turn caret browsing " + expectedStr); + // Need to clean up if the dialog wasn't opened, so the observer doesn't get + // re-triggered later on causing "issues". + if (!openedDialog) { + Services.ww.unregisterNotification(gCaretPromptOpeningObserver); + gCaretPromptOpeningObserver = null; + } + let prefVal = Services.prefs.getBoolPref(kPrefCaretBrowsingOn); + is(prefVal, expected, "Caret browsing should now be " + expectedStr); +} + +function waitForFocusOnInput(browser) +{ + return ContentTask.spawn(browser, null, function* () { + let textEl = content.document.getElementById("in"); + return ContentTaskUtils.waitForCondition(() => { + return content.document.activeElement == textEl; + }, "Input should get focused."); + }); +} + +function focusInput(browser) +{ + return ContentTask.spawn(browser, null, function* () { + let textEl = content.document.getElementById("in"); + textEl.focus(); + }); +} + +add_task(function* checkTogglingCaretBrowsing() { + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, kURL); + yield focusInput(tab.linkedBrowser); + + let promiseGotKey = promiseCaretPromptOpened(); + hitF7(); + let prompt = yield promiseGotKey; + let doc = prompt.document; + is(doc.documentElement.defaultButton, "cancel", "No button should be the default"); + ok(!doc.getElementById("checkbox").checked, "Checkbox shouldn't be checked by default."); + let promiseDialogUnloaded = BrowserTestUtils.waitForEvent(prompt, "unload"); + + doc.documentElement.cancelDialog(); + yield promiseDialogUnloaded; + info("Dialog unloaded"); + yield waitForFocusOnInput(tab.linkedBrowser); + ok(!Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should still be off after cancelling the dialog."); + + promiseGotKey = promiseCaretPromptOpened(); + hitF7(); + prompt = yield promiseGotKey; + + doc = prompt.document; + is(doc.documentElement.defaultButton, "cancel", "No button should be the default"); + ok(!doc.getElementById("checkbox").checked, "Checkbox shouldn't be checked by default."); + promiseDialogUnloaded = BrowserTestUtils.waitForEvent(prompt, "unload"); + + doc.documentElement.acceptDialog(); + yield promiseDialogUnloaded; + info("Dialog unloaded"); + yield waitForFocusOnInput(tab.linkedBrowser); + ok(Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should be on after accepting the dialog."); + + syncToggleCaretNoDialog(false); + + promiseGotKey = promiseCaretPromptOpened(); + hitF7(); + prompt = yield promiseGotKey; + doc = prompt.document; + + is(doc.documentElement.defaultButton, "cancel", "No button should be the default"); + ok(!doc.getElementById("checkbox").checked, "Checkbox shouldn't be checked by default."); + + promiseDialogUnloaded = BrowserTestUtils.waitForEvent(prompt, "unload"); + doc.documentElement.cancelDialog(); + yield promiseDialogUnloaded; + info("Dialog unloaded"); + yield waitForFocusOnInput(tab.linkedBrowser); + + ok(!Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should still be off after cancelling the dialog."); + + Services.prefs.setBoolPref(kPrefShortcutEnabled, true); + Services.prefs.setBoolPref(kPrefWarnOnEnable, true); + Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false); + + yield BrowserTestUtils.removeTab(tab); +}); + +add_task(function* toggleCheckboxNoCaretBrowsing() { + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, kURL); + yield focusInput(tab.linkedBrowser); + + let promiseGotKey = promiseCaretPromptOpened(); + hitF7(); + let prompt = yield promiseGotKey; + let doc = prompt.document; + is(doc.documentElement.defaultButton, "cancel", "No button should be the default"); + let checkbox = doc.getElementById("checkbox"); + ok(!checkbox.checked, "Checkbox shouldn't be checked by default."); + + // Check the box: + checkbox.click(); + + let promiseDialogUnloaded = BrowserTestUtils.waitForEvent(prompt, "unload"); + + // Say no: + doc.documentElement.getButton("cancel").click(); + + yield promiseDialogUnloaded; + info("Dialog unloaded"); + yield waitForFocusOnInput(tab.linkedBrowser); + ok(!Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should still be off."); + ok(!Services.prefs.getBoolPref(kPrefShortcutEnabled), "Shortcut should now be disabled."); + + syncToggleCaretNoDialog(false); + ok(!Services.prefs.getBoolPref(kPrefShortcutEnabled), "Shortcut should still be disabled."); + + Services.prefs.setBoolPref(kPrefShortcutEnabled, true); + Services.prefs.setBoolPref(kPrefWarnOnEnable, true); + Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false); + + yield BrowserTestUtils.removeTab(tab); +}); + + +add_task(function* toggleCheckboxWantCaretBrowsing() { + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, kURL); + yield focusInput(tab.linkedBrowser); + + let promiseGotKey = promiseCaretPromptOpened(); + hitF7(); + let prompt = yield promiseGotKey; + let doc = prompt.document; + is(doc.documentElement.defaultButton, "cancel", "No button should be the default"); + let checkbox = doc.getElementById("checkbox"); + ok(!checkbox.checked, "Checkbox shouldn't be checked by default."); + + // Check the box: + checkbox.click(); + + let promiseDialogUnloaded = BrowserTestUtils.waitForEvent(prompt, "unload"); + + // Say yes: + doc.documentElement.acceptDialog(); + yield promiseDialogUnloaded; + info("Dialog unloaded"); + yield waitForFocusOnInput(tab.linkedBrowser); + ok(Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should now be on."); + ok(Services.prefs.getBoolPref(kPrefShortcutEnabled), "Shortcut should still be enabled."); + ok(!Services.prefs.getBoolPref(kPrefWarnOnEnable), "Should no longer warn when enabling."); + + syncToggleCaretNoDialog(false); + syncToggleCaretNoDialog(true); + syncToggleCaretNoDialog(false); + + Services.prefs.setBoolPref(kPrefShortcutEnabled, true); + Services.prefs.setBoolPref(kPrefWarnOnEnable, true); + Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false); + + yield BrowserTestUtils.removeTab(tab); +}); + + + + diff --git a/toolkit/content/tests/browser/browser_findbar.js b/toolkit/content/tests/browser/browser_findbar.js new file mode 100644 index 000000000..1ab06f632 --- /dev/null +++ b/toolkit/content/tests/browser/browser_findbar.js @@ -0,0 +1,249 @@ +XPCOMUtils.defineLazyModuleGetter(this, "Promise", + "resource://gre/modules/Promise.jsm"); +Components.utils.import("resource://gre/modules/Timer.jsm", this); + +const TEST_PAGE_URI = "data:text/html;charset=utf-8,The letter s."; +// Using 'javascript' schema to bypass E10SUtils.canLoadURIInProcess, because +// it does not allow 'data:' URI to be loaded in the parent process. +const E10S_PARENT_TEST_PAGE_URI = "javascript:document.write('The letter s.');"; + +/** + * Makes sure that the findbar hotkeys (' and /) event listeners + * are added to the system event group and do not get blocked + * by calling stopPropagation on a keypress event on a page. + */ +add_task(function* test_hotkey_event_propagation() { + info("Ensure hotkeys are not affected by stopPropagation."); + + // Opening new tab + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI); + let browser = gBrowser.getBrowserForTab(tab); + let findbar = gBrowser.getFindBar(); + + // Pressing these keys open the findbar. + const HOTKEYS = ["/", "'"]; + + // Checking if findbar appears when any hotkey is pressed. + for (let key of HOTKEYS) { + is(findbar.hidden, true, "Findbar is hidden now."); + gBrowser.selectedTab = tab; + yield SimpleTest.promiseFocus(gBrowser.selectedBrowser); + yield BrowserTestUtils.sendChar(key, browser); + is(findbar.hidden, false, "Findbar should not be hidden."); + yield closeFindbarAndWait(findbar); + } + + // Stop propagation for all keyboard events. + let frameScript = () => { + const stopPropagation = e => e.stopImmediatePropagation(); + let window = content.document.defaultView; + window.removeEventListener("keydown", stopPropagation); + window.removeEventListener("keypress", stopPropagation); + window.removeEventListener("keyup", stopPropagation); + }; + + let mm = browser.messageManager; + mm.loadFrameScript("data:,(" + frameScript.toString() + ")();", false); + + // Checking if findbar still appears when any hotkey is pressed. + for (let key of HOTKEYS) { + is(findbar.hidden, true, "Findbar is hidden now."); + gBrowser.selectedTab = tab; + yield SimpleTest.promiseFocus(gBrowser.selectedBrowser); + yield BrowserTestUtils.sendChar(key, browser); + is(findbar.hidden, false, "Findbar should not be hidden."); + yield closeFindbarAndWait(findbar); + } + + gBrowser.removeTab(tab); +}); + +add_task(function* test_not_found() { + info("Check correct 'Phrase not found' on new tab"); + + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI); + + // Search for the first word. + yield promiseFindFinished("--- THIS SHOULD NEVER MATCH ---", false); + let findbar = gBrowser.getFindBar(); + is(findbar._findStatusDesc.textContent, findbar._notFoundStr, + "Findbar status text should be 'Phrase not found'"); + + gBrowser.removeTab(tab); +}); + +add_task(function* test_found() { + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI); + + // Search for a string that WILL be found, with 'Highlight All' on + yield promiseFindFinished("S", true); + ok(!gBrowser.getFindBar()._findStatusDesc.textContent, + "Findbar status should be empty"); + + gBrowser.removeTab(tab); +}); + +// Setting first findbar to case-sensitive mode should not affect +// new tab find bar. +add_task(function* test_tabwise_case_sensitive() { + let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI); + let findbar1 = gBrowser.getFindBar(); + + let tab2 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI); + let findbar2 = gBrowser.getFindBar(); + + // Toggle case sensitivity for first findbar + findbar1.getElement("find-case-sensitive").click(); + + gBrowser.selectedTab = tab1; + + // Not found for first tab. + yield promiseFindFinished("S", true); + is(findbar1._findStatusDesc.textContent, findbar1._notFoundStr, + "Findbar status text should be 'Phrase not found'"); + + gBrowser.selectedTab = tab2; + + // But it didn't affect the second findbar. + yield promiseFindFinished("S", true); + ok(!findbar2._findStatusDesc.textContent, "Findbar status should be empty"); + + gBrowser.removeTab(tab1); + gBrowser.removeTab(tab2); +}); + +/** + * Navigating from a web page (for example mozilla.org) to an internal page + * (like about:addons) might trigger a change of browser's remoteness. + * 'Remoteness change' means that rendering page content moves from child + * process into the parent process or the other way around. + * This test ensures that findbar properly handles such a change. + */ +add_task(function* test_reinitialization_at_remoteness_change() { + // This test only makes sence in e10s evironment. + if (!gMultiProcessBrowser) { + info("Skipping this test because of non-e10s environment."); + return; + } + + info("Ensure findbar re-initialization at remoteness change."); + + // Load a remote page and trigger findbar construction. + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI); + let browser = gBrowser.getBrowserForTab(tab); + let findbar = gBrowser.getFindBar(); + + // Findbar should operate normally. + yield promiseFindFinished("z", false); + is(findbar._findStatusDesc.textContent, findbar._notFoundStr, + "Findbar status text should be 'Phrase not found'"); + + yield promiseFindFinished("s", false); + ok(!findbar._findStatusDesc.textContent, "Findbar status should be empty"); + + // Moving browser into the parent process and reloading sample data. + ok(browser.isRemoteBrowser, "Browser should be remote now."); + yield promiseRemotenessChange(tab, false); + yield BrowserTestUtils.loadURI(browser, E10S_PARENT_TEST_PAGE_URI); + ok(!browser.isRemoteBrowser, "Browser should not be remote any more."); + + // Findbar should keep operating normally after remoteness change. + yield promiseFindFinished("z", false); + is(findbar._findStatusDesc.textContent, findbar._notFoundStr, + "Findbar status text should be 'Phrase not found'"); + + yield promiseFindFinished("s", false); + ok(!findbar._findStatusDesc.textContent, "Findbar status should be empty"); + + yield BrowserTestUtils.removeTab(tab); +}); + +/** + * Ensure that the initial typed characters aren't lost immediately after + * opening the find bar. + */ +add_task(function* () { + // This test only makes sence in e10s evironment. + if (!gMultiProcessBrowser) { + info("Skipping this test because of non-e10s environment."); + return; + } + + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI); + let browser = tab.linkedBrowser; + + ok(!gFindBarInitialized, "findbar isn't initialized yet"); + + let findBar = gFindBar; + let initialValue = findBar._findField.value; + + EventUtils.synthesizeKey("f", { accelKey: true }, window); + + let promises = [ + BrowserTestUtils.sendChar("a", browser), + BrowserTestUtils.sendChar("b", browser), + BrowserTestUtils.sendChar("c", browser) + ]; + + isnot(document.activeElement, findBar._findField.inputField, + "findbar is not yet focused"); + is(findBar._findField.value, initialValue, "still has initial find query"); + + yield Promise.all(promises); + is(document.activeElement, findBar._findField.inputField, + "findbar is now focused"); + is(findBar._findField.value, "abc", "abc fully entered as find query"); + + yield BrowserTestUtils.removeTab(tab); +}); + +function promiseFindFinished(searchText, highlightOn) { + let deferred = Promise.defer(); + + let findbar = gBrowser.getFindBar(); + findbar.startFind(findbar.FIND_NORMAL); + let highlightElement = findbar.getElement("highlight"); + if (highlightElement.checked != highlightOn) + highlightElement.click(); + executeSoon(() => { + findbar._findField.value = searchText; + + let resultListener; + // When highlighting is on the finder sends a second "FOUND" message after + // the search wraps. This causes timing problems with e10s. waitMore + // forces foundOrTimeout wait for the second "FOUND" message before + // resolving the promise. + let waitMore = highlightOn; + let findTimeout = setTimeout(() => foundOrTimedout(null), 2000); + let foundOrTimedout = function(aData) { + if (aData !== null && waitMore) { + waitMore = false; + return; + } + if (aData === null) + info("Result listener not called, timeout reached."); + clearTimeout(findTimeout); + findbar.browser.finder.removeResultListener(resultListener); + deferred.resolve(); + } + + resultListener = { + onFindResult: foundOrTimedout + }; + findbar.browser.finder.addResultListener(resultListener); + findbar._find(); + }); + + return deferred.promise; +} + +function promiseRemotenessChange(tab, shouldBeRemote) { + return new Promise((resolve) => { + let browser = gBrowser.getBrowserForTab(tab); + tab.addEventListener("TabRemotenessChange", function listener() { + tab.removeEventListener("TabRemotenessChange", listener); + resolve(); + }); + gBrowser.updateBrowserRemoteness(browser, shouldBeRemote); + }); +} diff --git a/toolkit/content/tests/browser/browser_isSynthetic.js b/toolkit/content/tests/browser/browser_isSynthetic.js new file mode 100644 index 000000000..15a341461 --- /dev/null +++ b/toolkit/content/tests/browser/browser_isSynthetic.js @@ -0,0 +1,72 @@ +function LocationChangeListener(browser) { + this.browser = browser; + browser.addProgressListener(this); +} + +LocationChangeListener.prototype = { + wasSynthetic: false, + browser: null, + + destroy: function() { + this.browser.removeProgressListener(this); + }, + + onLocationChange: function(webProgress, request, location, flags) { + this.wasSynthetic = this.browser.isSyntheticDocument; + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, + Ci.nsISupportsWeakReference]) +} + +const FILES = gTestPath.replace("browser_isSynthetic.js", "") + .replace("chrome://mochitests/content/", "http://example.com/"); + +function waitForPageShow(browser) { + return ContentTask.spawn(browser, null, function*() { + Cu.import("resource://gre/modules/PromiseUtils.jsm"); + yield new Promise(resolve => { + let listener = () => { + removeEventListener("pageshow", listener, true); + resolve(); + } + addEventListener("pageshow", listener, true); + }); + }); +} + +add_task(function*() { + let tab = gBrowser.addTab("about:blank"); + let browser = tab.linkedBrowser; + yield BrowserTestUtils.browserLoaded(browser); + let listener = new LocationChangeListener(browser); + + is(browser.isSyntheticDocument, false, "Should not be synthetic"); + + let loadPromise = waitForPageShow(browser); + browser.loadURI("data:text/html;charset=utf-8,"); + yield loadPromise; + is(listener.wasSynthetic, false, "Should not be synthetic"); + is(browser.isSyntheticDocument, false, "Should not be synthetic"); + + loadPromise = waitForPageShow(browser); + browser.loadURI(FILES + "empty.png"); + yield loadPromise; + is(listener.wasSynthetic, true, "Should be synthetic"); + is(browser.isSyntheticDocument, true, "Should be synthetic"); + + loadPromise = waitForPageShow(browser); + browser.goBack(); + yield loadPromise; + is(listener.wasSynthetic, false, "Should not be synthetic"); + is(browser.isSyntheticDocument, false, "Should not be synthetic"); + + loadPromise = waitForPageShow(browser); + browser.goForward(); + yield loadPromise; + is(listener.wasSynthetic, true, "Should be synthetic"); + is(browser.isSyntheticDocument, true, "Should be synthetic"); + + listener.destroy(); + gBrowser.removeTab(tab); +}); diff --git a/toolkit/content/tests/browser/browser_keyevents_during_autoscrolling.js b/toolkit/content/tests/browser/browser_keyevents_during_autoscrolling.js new file mode 100644 index 000000000..3fce47114 --- /dev/null +++ b/toolkit/content/tests/browser/browser_keyevents_during_autoscrolling.js @@ -0,0 +1,120 @@ +add_task(function * () +{ + const kPrefName_AutoScroll = "general.autoScroll"; + Services.prefs.setBoolPref(kPrefName_AutoScroll, true); + + const kNoKeyEvents = 0; + const kKeyDownEvent = 1; + const kKeyPressEvent = 2; + const kKeyUpEvent = 4; + const kAllKeyEvents = 7; + + var expectedKeyEvents; + var dispatchedKeyEvents; + var key; + var root; + + /** + * Encapsulates EventUtils.sendChar(). + */ + function sendChar(aChar) + { + key = aChar; + dispatchedKeyEvents = kNoKeyEvents; + EventUtils.sendChar(key); + is(dispatchedKeyEvents, expectedKeyEvents, + "unexpected key events were dispatched or not dispatched: " + key); + } + + /** + * Encapsulates EventUtils.sendKey(). + */ + function sendKey(aKey) + { + key = aKey; + dispatchedKeyEvents = kNoKeyEvents; + EventUtils.sendKey(key); + is(dispatchedKeyEvents, expectedKeyEvents, + "unexpected key events were dispatched or not dispatched: " + key); + } + + function onKey(aEvent) + { +// if (aEvent.target != root && aEvent.target != root.ownerDocument.body) { +// ok(false, "unknown target: " + aEvent.target.tagName); +// return; +// } + + var keyFlag; + switch (aEvent.type) { + case "keydown": + keyFlag = kKeyDownEvent; + break; + case "keypress": + keyFlag = kKeyPressEvent; + break; + case "keyup": + keyFlag = kKeyUpEvent; + break; + default: + ok(false, "Unknown events: " + aEvent.type); + return; + } + dispatchedKeyEvents |= keyFlag; + is(keyFlag, expectedKeyEvents & keyFlag, aEvent.type + " fired: " + key); + } + + var dataUri = 'data:text/html,'; + + let loadedPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); + gBrowser.loadURI(dataUri); + yield loadedPromise; + + yield SimpleTest.promiseFocus(gBrowser.selectedBrowser); + + window.addEventListener("keydown", onKey, false); + window.addEventListener("keypress", onKey, false); + window.addEventListener("keyup", onKey, false); + + // Test whether the key events are handled correctly under normal condition + expectedKeyEvents = kAllKeyEvents; + sendChar("A"); + + // Start autoscrolling by middle button click on the page + let shownPromise = BrowserTestUtils.waitForEvent(window, "popupshown", false, + event => event.originalTarget.className == "autoscroller"); + yield BrowserTestUtils.synthesizeMouseAtPoint(10, 10, { button: 1 }, + gBrowser.selectedBrowser); + yield shownPromise; + + // Most key events should be eaten by the browser. + expectedKeyEvents = kNoKeyEvents; + sendChar("A"); + sendKey("DOWN"); + sendKey("RETURN"); + sendKey("RETURN"); + sendKey("HOME"); + sendKey("END"); + sendKey("TAB"); + sendKey("RETURN"); + + // Finish autoscrolling by ESC key. Note that only keydown and keypress + // events are eaten because keyup event is fired *after* the autoscrolling + // is finished. + expectedKeyEvents = kKeyUpEvent; + sendKey("ESCAPE"); + + // Test whether the key events are handled correctly under normal condition + expectedKeyEvents = kAllKeyEvents; + sendChar("A"); + + window.removeEventListener("keydown", onKey, false); + window.removeEventListener("keypress", onKey, false); + window.removeEventListener("keyup", onKey, false); + + // restore the changed prefs + if (Services.prefs.prefHasUserValue(kPrefName_AutoScroll)) + Services.prefs.clearUserPref(kPrefName_AutoScroll); + + finish(); +}); diff --git a/toolkit/content/tests/browser/browser_label_textlink.js b/toolkit/content/tests/browser/browser_label_textlink.js new file mode 100644 index 000000000..861086707 --- /dev/null +++ b/toolkit/content/tests/browser/browser_label_textlink.js @@ -0,0 +1,38 @@ +add_task(function* () { + yield BrowserTestUtils.withNewTab({gBrowser, url: "about:config"}, function*(browser) { + let newTabURL = "http://www.example.com/"; + yield ContentTask.spawn(browser, newTabURL, function*(newTabURL) { + let doc = content.document; + let label = doc.createElement("label"); + label.href = newTabURL; + label.id = "textlink-test"; + label.className = "text-link"; + label.textContent = "click me"; + doc.documentElement.append(label); + }); + + // Test that click will open tab in foreground. + let awaitNewTab = BrowserTestUtils.waitForNewTab(gBrowser, newTabURL); + yield BrowserTestUtils.synthesizeMouseAtCenter("#textlink-test", {}, browser); + let newTab = yield awaitNewTab; + is(newTab.linkedBrowser, gBrowser.selectedBrowser, "selected tab should be example page"); + yield BrowserTestUtils.removeTab(gBrowser.selectedTab); + + // Test that ctrl+shift+click/meta+shift+click will open tab in background. + awaitNewTab = BrowserTestUtils.waitForNewTab(gBrowser, newTabURL); + yield BrowserTestUtils.synthesizeMouseAtCenter("#textlink-test", + {ctrlKey: true, metaKey: true, shiftKey: true}, + browser); + yield awaitNewTab; + is(gBrowser.selectedBrowser, browser, "selected tab should be original tab"); + yield BrowserTestUtils.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]); + + // Middle-clicking should open tab in foreground. + awaitNewTab = BrowserTestUtils.waitForNewTab(gBrowser, newTabURL); + yield BrowserTestUtils.synthesizeMouseAtCenter("#textlink-test", + {button: 1}, browser); + newTab = yield awaitNewTab; + is(newTab.linkedBrowser, gBrowser.selectedBrowser, "selected tab should be example page"); + yield BrowserTestUtils.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]); + }); +}); diff --git a/toolkit/content/tests/browser/browser_mediaPlayback.js b/toolkit/content/tests/browser/browser_mediaPlayback.js new file mode 100644 index 000000000..1a6ebfcb8 --- /dev/null +++ b/toolkit/content/tests/browser/browser_mediaPlayback.js @@ -0,0 +1,30 @@ +const PAGE = "https://example.com/browser/toolkit/content/tests/browser/file_mediaPlayback.html"; +const FRAME = "https://example.com/browser/toolkit/content/tests/browser/file_mediaPlaybackFrame.html"; + +function wait_for_event(browser, event) { + return BrowserTestUtils.waitForEvent(browser, event, false, (event) => { + is(event.originalTarget, browser, "Event must be dispatched to correct browser."); + ok(!event.cancelable, "The event should not be cancelable"); + return true; + }); +} + +function* test_on_browser(url, browser) { + browser.loadURI(url); + yield wait_for_event(browser, "DOMAudioPlaybackStarted"); + yield wait_for_event(browser, "DOMAudioPlaybackStopped"); +} + +add_task(function* test_page() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank", + }, test_on_browser.bind(undefined, PAGE)); +}); + +add_task(function* test_frame() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank", + }, test_on_browser.bind(undefined, FRAME)); +}); diff --git a/toolkit/content/tests/browser/browser_mediaPlayback_mute.js b/toolkit/content/tests/browser/browser_mediaPlayback_mute.js new file mode 100644 index 000000000..852fc56fb --- /dev/null +++ b/toolkit/content/tests/browser/browser_mediaPlayback_mute.js @@ -0,0 +1,104 @@ +const PAGE = "https://example.com/browser/toolkit/content/tests/browser/file_mediaPlayback2.html"; +const FRAME = "https://example.com/browser/toolkit/content/tests/browser/file_mediaPlaybackFrame2.html"; + +function wait_for_event(browser, event) { + return BrowserTestUtils.waitForEvent(browser, event, false, (event) => { + is(event.originalTarget, browser, "Event must be dispatched to correct browser."); + return true; + }); +} + +function* test_audio_in_browser() { + function get_audio_element() { + var doc = content.document; + var list = doc.getElementsByTagName('audio'); + if (list.length == 1) { + return list[0]; + } + + // iframe? + list = doc.getElementsByTagName('iframe'); + + var iframe = list[0]; + list = iframe.contentDocument.getElementsByTagName('audio'); + return list[0]; + } + + var audio = get_audio_element(); + return { + computedVolume: audio.computedVolume, + computedMuted: audio.computedMuted + } +} + +function* test_on_browser(url, browser) { + browser.loadURI(url); + yield wait_for_event(browser, "DOMAudioPlaybackStarted"); + + var result = yield ContentTask.spawn(browser, null, test_audio_in_browser); + is(result.computedVolume, 1, "Audio volume is 1"); + is(result.computedMuted, false, "Audio is not muted"); + + ok(!browser.audioMuted, "Audio should not be muted by default"); + browser.mute(); + ok(browser.audioMuted, "Audio should be muted now"); + + yield wait_for_event(browser, "DOMAudioPlaybackStopped"); + + result = yield ContentTask.spawn(browser, null, test_audio_in_browser); + is(result.computedVolume, 0, "Audio volume is 0 when muted"); + is(result.computedMuted, true, "Audio is muted"); +} + +function* test_visibility(url, browser) { + browser.loadURI(url); + yield wait_for_event(browser, "DOMAudioPlaybackStarted"); + + var result = yield ContentTask.spawn(browser, null, test_audio_in_browser); + is(result.computedVolume, 1, "Audio volume is 1"); + is(result.computedMuted, false, "Audio is not muted"); + + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank", + }, function() {}); + + ok(!browser.audioMuted, "Audio should not be muted by default"); + browser.mute(); + ok(browser.audioMuted, "Audio should be muted now"); + + yield wait_for_event(browser, "DOMAudioPlaybackStopped"); + + result = yield ContentTask.spawn(browser, null, test_audio_in_browser); + is(result.computedVolume, 0, "Audio volume is 0 when muted"); + is(result.computedMuted, true, "Audio is muted"); +} + +add_task(function*() { + yield new Promise((resolve) => { + SpecialPowers.pushPrefEnv({"set": [ + ["media.useAudioChannelService.testing", true] + ]}, resolve); + }); +}); + +add_task(function* test_page() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank", + }, test_on_browser.bind(undefined, PAGE)); +}); + +add_task(function* test_frame() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank", + }, test_on_browser.bind(undefined, FRAME)); +}); + +add_task(function* test_frame() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank", + }, test_visibility.bind(undefined, PAGE)); +}); diff --git a/toolkit/content/tests/browser/browser_mediaPlayback_suspended.js b/toolkit/content/tests/browser/browser_mediaPlayback_suspended.js new file mode 100644 index 000000000..ef8bb9dc8 --- /dev/null +++ b/toolkit/content/tests/browser/browser_mediaPlayback_suspended.js @@ -0,0 +1,191 @@ +const PAGE = "https://example.com/browser/toolkit/content/tests/browser/file_mediaPlayback2.html"; + +var SuspendedType = { + NONE_SUSPENDED : 0, + SUSPENDED_PAUSE : 1, + SUSPENDED_BLOCK : 2, + SUSPENDED_PAUSE_DISPOSABLE : 3 +}; + +function wait_for_event(browser, event) { + return BrowserTestUtils.waitForEvent(browser, event, false, (event) => { + is(event.originalTarget, browser, "Event must be dispatched to correct browser."); + return true; + }); +} + +function check_audio_onplay() { + var list = content.document.getElementsByTagName('audio'); + if (list.length != 1) { + ok(false, "There should be only one audio element in page!") + } + + var audio = list[0]; + return new Promise((resolve, reject) => { + audio.onplay = () => { + ok(needToReceiveOnPlay, "Should not receive play event!"); + this.onplay = null; + reject(); + }; + + audio.pause(); + audio.play(); + + setTimeout(() => { + ok(true, "Doesn't receive play event when media was blocked."); + audio.onplay = null; + resolve(); + }, 1000) + }); +} + +function check_audio_suspended(suspendedType) { + var list = content.document.getElementsByTagName('audio'); + if (list.length != 1) { + ok(false, "There should be only one audio element in page!") + } + + var audio = list[0]; + is(audio.computedSuspended, suspendedType, + "The suspended state of MediaElement is correct."); +} + +function check_audio_pause_state(expectedPauseState) { + var list = content.document.getElementsByTagName('audio'); + if (list.length != 1) { + ok(false, "There should be only one audio element in page!") + } + + var audio = list[0]; + if (expectedPauseState) { + is(audio.paused, true, "Audio is paused correctly."); + } else { + is(audio.paused, false, "Audio is resumed correctly."); + } +} + +function* suspended_pause(url, browser) { + info("### Start test for suspended-pause ###"); + browser.loadURI(url); + + info("- page should have playing audio -"); + yield wait_for_event(browser, "DOMAudioPlaybackStarted"); + + info("- the suspended state of audio should be non-suspened -"); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_audio_suspended); + + info("- pause playing audio -"); + browser.pauseMedia(false /* non-disposable */); + yield ContentTask.spawn(browser, true /* expect for pause */, + check_audio_pause_state); + yield ContentTask.spawn(browser, SuspendedType.SUSPENDED_PAUSE, + check_audio_suspended); + + info("- resume paused audio -"); + browser.resumeMedia(); + yield ContentTask.spawn(browser, false /* expect for playing */, + check_audio_pause_state); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_audio_suspended); +} + +function* suspended_pause_disposable(url, browser) { + info("### Start test for suspended-pause-disposable ###"); + browser.loadURI(url); + + info("- page should have playing audio -"); + yield wait_for_event(browser, "DOMAudioPlaybackStarted"); + + info("- the suspended state of audio should be non-suspened -"); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_audio_suspended); + + info("- pause playing audio -"); + browser.pauseMedia(true /* disposable */); + yield ContentTask.spawn(browser, true /* expect for pause */, + check_audio_pause_state); + yield ContentTask.spawn(browser, SuspendedType.SUSPENDED_PAUSE_DISPOSABLE, + check_audio_suspended); + + info("- resume paused audio -"); + browser.resumeMedia(); + yield ContentTask.spawn(browser, false /* expect for playing */, + check_audio_pause_state); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_audio_suspended); +} + +function* suspended_stop_disposable(url, browser) { + info("### Start test for suspended-stop-disposable ###"); + browser.loadURI(url); + + info("- page should have playing audio -"); + yield wait_for_event(browser, "DOMAudioPlaybackStarted"); + + info("- the suspended state of audio should be non-suspened -"); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_audio_suspended); + + info("- stop playing audio -"); + browser.stopMedia(); + yield wait_for_event(browser, "DOMAudioPlaybackStopped"); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_audio_suspended); +} + +function* suspended_block(url, browser) { + info("### Start test for suspended-block ###"); + browser.loadURI(url); + + info("- page should have playing audio -"); + yield wait_for_event(browser, "DOMAudioPlaybackStarted"); + + info("- block playing audio -"); + browser.blockMedia(); + yield ContentTask.spawn(browser, SuspendedType.SUSPENDED_BLOCK, + check_audio_suspended); + yield ContentTask.spawn(browser, null, + check_audio_onplay); + + info("- resume blocked audio -"); + browser.resumeMedia(); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_audio_suspended); +} + +add_task(function* setup_test_preference() { + yield new Promise(resolve => { + SpecialPowers.pushPrefEnv({"set": [ + ["media.useAudioChannelService.testing", true] + ]}, resolve); + }); +}); + +add_task(function* test_suspended_pause() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank" + }, suspended_pause.bind(this, PAGE)); +}); + +add_task(function* test_suspended_pause_disposable() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank" + }, suspended_pause_disposable.bind(this, PAGE)); +}); + +add_task(function* test_suspended_stop_disposable() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank" + }, suspended_stop_disposable.bind(this, PAGE)); +}); + +add_task(function* test_suspended_block() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank" + }, suspended_block.bind(this, PAGE)); +}); diff --git a/toolkit/content/tests/browser/browser_mediaPlayback_suspended_multipleAudio.js b/toolkit/content/tests/browser/browser_mediaPlayback_suspended_multipleAudio.js new file mode 100644 index 000000000..12e2ec077 --- /dev/null +++ b/toolkit/content/tests/browser/browser_mediaPlayback_suspended_multipleAudio.js @@ -0,0 +1,311 @@ +const PAGE = "https://example.com/browser/toolkit/content/tests/browser/file_multipleAudio.html"; + +var SuspendedType = { + NONE_SUSPENDED : 0, + SUSPENDED_PAUSE : 1, + SUSPENDED_BLOCK : 2, + SUSPENDED_PAUSE_DISPOSABLE : 3 +}; + +function wait_for_event(browser, event) { + return BrowserTestUtils.waitForEvent(browser, event, false, (event) => { + is(event.originalTarget, browser, "Event must be dispatched to correct browser."); + return true; + }); +} + +function check_all_audio_suspended(suspendedType) { + var autoPlay = content.document.getElementById('autoplay'); + var nonAutoPlay = content.document.getElementById('nonautoplay'); + if (!autoPlay || !nonAutoPlay) { + ok(false, "Can't get the audio element!"); + } + + is(autoPlay.computedSuspended, suspendedType, + "The suspeded state of autoplay audio is correct."); + is(nonAutoPlay.computedSuspended, suspendedType, + "The suspeded state of non-autoplay audio is correct."); +} + +function check_autoplay_audio_suspended(suspendedType) { + var autoPlay = content.document.getElementById('autoplay'); + if (!autoPlay) { + ok(false, "Can't get the audio element!"); + } + + is(autoPlay.computedSuspended, suspendedType, + "The suspeded state of autoplay audio is correct."); +} + +function check_nonautoplay_audio_suspended(suspendedType) { + var nonAutoPlay = content.document.getElementById('nonautoplay'); + if (!nonAutoPlay) { + ok(false, "Can't get the audio element!"); + } + + is(nonAutoPlay.computedSuspended, suspendedType, + "The suspeded state of non-autoplay audio is correct."); +} + +function check_autoplay_audio_pause_state(expectedPauseState) { + var autoPlay = content.document.getElementById('autoplay'); + if (!autoPlay) { + ok(false, "Can't get the audio element!"); + } + + if (autoPlay.paused == expectedPauseState) { + if (expectedPauseState) { + ok(true, "Audio is paused correctly."); + } else { + ok(true, "Audio is resumed correctly."); + } + } else if (expectedPauseState) { + autoPlay.onpause = function () { + autoPlay.onpause = null; + ok(true, "Audio is paused correctly, checking from onpause."); + } + } else { + autoPlay.onplay = function () { + autoPlay.onplay = null; + ok(true, "Audio is resumed correctly, checking from onplay."); + } + } +} + +function play_nonautoplay_audio_should_be_paused() { + var nonAutoPlay = content.document.getElementById('nonautoplay'); + if (!nonAutoPlay) { + ok(false, "Can't get the audio element!"); + } + + nonAutoPlay.play(); + return new Promise(resolve => { + nonAutoPlay.onpause = function () { + nonAutoPlay.onpause = null; + is(nonAutoPlay.ended, false, "Audio can't be playback."); + resolve(); + } + }); +} + +function all_audio_onresume() { + var autoPlay = content.document.getElementById('autoplay'); + var nonAutoPlay = content.document.getElementById('nonautoplay'); + if (!autoPlay || !nonAutoPlay) { + ok(false, "Can't get the audio element!"); + } + + is(autoPlay.paused, false, "Autoplay audio is resumed."); + is(nonAutoPlay.paused, false, "Non-AutoPlay audio is resumed."); +} + +function all_audio_onpause() { + var autoPlay = content.document.getElementById('autoplay'); + var nonAutoPlay = content.document.getElementById('nonautoplay'); + if (!autoPlay || !nonAutoPlay) { + ok(false, "Can't get the audio element!"); + } + + is(autoPlay.paused, true, "Autoplay audio is paused."); + is(nonAutoPlay.paused, true, "Non-AutoPlay audio is paused."); +} + +function play_nonautoplay_audio_should_play_until_ended() { + var nonAutoPlay = content.document.getElementById('nonautoplay'); + if (!nonAutoPlay) { + ok(false, "Can't get the audio element!"); + } + + nonAutoPlay.play(); + return new Promise(resolve => { + nonAutoPlay.onended = function () { + nonAutoPlay.onended = null; + ok(true, "Audio can be playback until ended."); + resolve(); + } + }); +} + +function no_audio_resumed() { + var autoPlay = content.document.getElementById('autoplay'); + var nonAutoPlay = content.document.getElementById('nonautoplay'); + if (!autoPlay || !nonAutoPlay) { + ok(false, "Can't get the audio element!"); + } + + is(autoPlay.paused && nonAutoPlay.paused, true, "No audio was resumed."); +} + +function play_nonautoplay_audio_should_be_blocked(suspendedType) { + var nonAutoPlay = content.document.getElementById('nonautoplay'); + if (!nonAutoPlay) { + ok(false, "Can't get the audio element!"); + } + + nonAutoPlay.play(); + ok(nonAutoPlay.paused, "The blocked audio can't be playback."); +} + +function* suspended_pause(url, browser) { + info("### Start test for suspended-pause ###"); + browser.loadURI(url); + + info("- page should have playing audio -"); + yield wait_for_event(browser, "DOMAudioPlaybackStarted"); + + info("- the default suspended state of all audio should be non-suspened-"); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_all_audio_suspended); + + info("- pause all audio in the page -"); + browser.pauseMedia(false /* non-disposable */); + yield ContentTask.spawn(browser, true /* expect for pause */, + check_autoplay_audio_pause_state); + yield ContentTask.spawn(browser, SuspendedType.SUSPENDED_PAUSE, + check_autoplay_audio_suspended); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_nonautoplay_audio_suspended); + + info("- no audio can be playback during suspended-paused -"); + yield ContentTask.spawn(browser, null, + play_nonautoplay_audio_should_be_paused); + yield ContentTask.spawn(browser, SuspendedType.SUSPENDED_PAUSE, + check_nonautoplay_audio_suspended); + + info("- both audio should be resumed at the same time -"); + browser.resumeMedia(); + yield ContentTask.spawn(browser, null, + all_audio_onresume); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_all_audio_suspended); + + info("- both audio should be paused at the same time -"); + browser.pauseMedia(false /* non-disposable */); + yield ContentTask.spawn(browser, null, all_audio_onpause); +} + +function* suspended_pause_disposable(url, browser) { + info("### Start test for suspended-pause-disposable ###"); + browser.loadURI(url); + + info("- page should have playing audio -"); + yield wait_for_event(browser, "DOMAudioPlaybackStarted"); + + info("- the default suspended state of all audio should be non-suspened -"); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_all_audio_suspended); + + info("- only pause playing audio in the page -"); + browser.pauseMedia(true /* non-disposable */); + yield ContentTask.spawn(browser, true /* expect for pause */, + check_autoplay_audio_pause_state); + yield ContentTask.spawn(browser, SuspendedType.SUSPENDED_PAUSE_DISPOSABLE, + check_autoplay_audio_suspended); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_nonautoplay_audio_suspended); + + info("- new playing audio should be playback correctly -"); + yield ContentTask.spawn(browser, null, + play_nonautoplay_audio_should_play_until_ended); + + info("- should only resume one audio -"); + browser.resumeMedia(); + yield ContentTask.spawn(browser, false /* expect for playing */, + check_autoplay_audio_pause_state); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_all_audio_suspended); +} + +function* suspended_stop_disposable(url, browser) { + info("### Start test for suspended-stop-disposable ###"); + browser.loadURI(url); + + info("- page should have playing audio -"); + yield wait_for_event(browser, "DOMAudioPlaybackStarted"); + + info("- the default suspended state of all audio should be non-suspened -"); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_all_audio_suspended); + + info("- only stop playing audio in the page -"); + browser.stopMedia(); + yield wait_for_event(browser, "DOMAudioPlaybackStopped"); + yield ContentTask.spawn(browser, true /* expect for pause */, + check_autoplay_audio_pause_state); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_all_audio_suspended); + + info("- new playing audio should be playback correctly -"); + yield ContentTask.spawn(browser, null, + play_nonautoplay_audio_should_play_until_ended); + + info("- no any audio can be resumed by page -"); + browser.resumeMedia(); + yield ContentTask.spawn(browser, null, no_audio_resumed); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_all_audio_suspended); +} + +function* suspended_block(url, browser) { + info("### Start test for suspended-block ###"); + browser.loadURI(url); + + info("- page should have playing audio -"); + yield wait_for_event(browser, "DOMAudioPlaybackStarted"); + + info("- the default suspended state of all audio should be non-suspened-"); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_all_audio_suspended); + + info("- block autoplay audio -"); + browser.blockMedia(); + yield ContentTask.spawn(browser, SuspendedType.SUSPENDED_BLOCK, + check_autoplay_audio_suspended); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_nonautoplay_audio_suspended); + + info("- no audio can be playback during suspended-block -"); + yield ContentTask.spawn(browser, SuspendedType.SUSPENDED_BLOCK, + play_nonautoplay_audio_should_be_blocked); + + info("- both audio should be resumed at the same time -"); + browser.resumeMedia(); + yield ContentTask.spawn(browser, SuspendedType.NONE_SUSPENDED, + check_all_audio_suspended); +} + +add_task(function* setup_test_preference() { + yield new Promise(resolve => { + SpecialPowers.pushPrefEnv({"set": [ + ["media.useAudioChannelService.testing", true] + ]}, resolve); + }); +}); + +add_task(function* test_suspended_pause() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank" + }, suspended_pause.bind(this, PAGE)); +}); + +add_task(function* test_suspended_pause_disposable() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank" + }, suspended_pause_disposable.bind(this, PAGE)); +}); + +add_task(function* test_suspended_stop_disposable() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank" + }, suspended_stop_disposable.bind(this, PAGE)); +}); + +add_task(function* test_suspended_block() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank" + }, suspended_block.bind(this, PAGE)); +}); diff --git a/toolkit/content/tests/browser/browser_mute.js b/toolkit/content/tests/browser/browser_mute.js new file mode 100644 index 000000000..f4829b808 --- /dev/null +++ b/toolkit/content/tests/browser/browser_mute.js @@ -0,0 +1,16 @@ +const PAGE = "data:text/html,page"; + +function* test_on_browser(browser) { + ok(!browser.audioMuted, "Audio should not be muted by default"); + browser.mute(); + ok(browser.audioMuted, "Audio should be muted now"); + browser.unmute(); + ok(!browser.audioMuted, "Audio should be unmuted now"); +} + +add_task(function*() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: PAGE, + }, test_on_browser); +}); diff --git a/toolkit/content/tests/browser/browser_mute2.js b/toolkit/content/tests/browser/browser_mute2.js new file mode 100644 index 000000000..38f415b71 --- /dev/null +++ b/toolkit/content/tests/browser/browser_mute2.js @@ -0,0 +1,26 @@ +const PAGE = "data:text/html,page"; + +function* test_on_browser(browser) { + ok(!browser.audioMuted, "Audio should not be muted by default"); + browser.mute(); + ok(browser.audioMuted, "Audio should be muted now"); + + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: PAGE, + }, test_on_browser2); + + browser.unmute(); + ok(!browser.audioMuted, "Audio should be unmuted now"); +} + +function* test_on_browser2(browser) { + ok(!browser.audioMuted, "Audio should not be muted by default"); +} + +add_task(function*() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: PAGE, + }, test_on_browser); +}); diff --git a/toolkit/content/tests/browser/browser_quickfind_editable.js b/toolkit/content/tests/browser/browser_quickfind_editable.js new file mode 100644 index 000000000..d4ab59744 --- /dev/null +++ b/toolkit/content/tests/browser/browser_quickfind_editable.js @@ -0,0 +1,47 @@ +const PAGE = "data:text/html,
foo
"; +const DESIGNMODE_PAGE = "data:text/html,"; +const HOTKEYS = ["/", "'"]; + +function* test_hotkeys(browser, expected) { + let findbar = gBrowser.getFindBar(); + for (let key of HOTKEYS) { + is(findbar.hidden, true, "findbar is hidden"); + yield BrowserTestUtils.sendChar(key, gBrowser.selectedBrowser); + is(findbar.hidden, expected, "findbar should" + (expected ? "" : " not") + " be hidden"); + if (!expected) { + yield closeFindbarAndWait(findbar); + } + } +} + +function* focus_element(browser, query) { + yield ContentTask.spawn(browser, query, function* focus(query) { + let element = content.document.querySelector(query); + element.focus(); + }); +} + +add_task(function* test_hotkey_on_editable_element() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: PAGE + }, function* do_tests(browser) { + yield test_hotkeys(browser, false); + const ELEMENTS = ["div", "input", "textarea"]; + for (let elem of ELEMENTS) { + yield focus_element(browser, elem); + yield test_hotkeys(browser, true); + yield focus_element(browser, ":root"); + yield test_hotkeys(browser, false); + } + }); +}); + +add_task(function* test_hotkey_on_designMode_document() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: DESIGNMODE_PAGE + }, function* do_tests(browser) { + yield test_hotkeys(browser, true); + }); +}); diff --git a/toolkit/content/tests/browser/browser_saveImageURL.js b/toolkit/content/tests/browser/browser_saveImageURL.js new file mode 100644 index 000000000..75e1cfdcd --- /dev/null +++ b/toolkit/content/tests/browser/browser_saveImageURL.js @@ -0,0 +1,68 @@ +"use strict"; + +const IMAGE_PAGE = "https://example.com/browser/toolkit/content/tests/browser/image_page.html"; +const PREF_UNSAFE_FORBIDDEN = "dom.ipc.cpows.forbid-unsafe-from-browser"; + +MockFilePicker.init(window); +MockFilePicker.returnValue = MockFilePicker.returnCancel; + +registerCleanupFunction(function() { + MockFilePicker.cleanup(); +}); + +function waitForFilePicker() { + return new Promise((resolve) => { + MockFilePicker.showCallback = () => { + MockFilePicker.showCallback = null; + ok(true, "Saw the file picker"); + resolve(); + } + }) +} + +/** + * Test that saveImageURL works when we pass in the aIsContentWindowPrivate + * argument instead of a document. This is the preferred API. + */ +add_task(function* preferred_API() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: IMAGE_PAGE, + }, function*(browser) { + let url = yield ContentTask.spawn(browser, null, function*() { + let image = content.document.getElementById("image"); + return image.href; + }); + + saveImageURL(url, "image.jpg", null, true, false, null, null, null, null, false); + yield waitForFilePicker(); + }); +}); + +/** + * Test that saveImageURL will still work when passed a document instead + * of the aIsContentWindowPrivate argument. This is the deprecated API, and + * will not work in apps using remote browsers having PREF_UNSAFE_FORBIDDEN + * set to true. + */ +add_task(function* deprecated_API() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: IMAGE_PAGE, + }, function*(browser) { + yield pushPrefs([PREF_UNSAFE_FORBIDDEN, false]); + + let url = yield ContentTask.spawn(browser, null, function*() { + let image = content.document.getElementById("image"); + return image.href; + }); + + // Now get the document directly from content. If we run this test with + // e10s-enabled, this will be a CPOW, which is forbidden. We'll just + // pass the XUL document instead to test this interface. + let doc = document; + + saveImageURL(url, "image.jpg", null, true, false, null, doc, null, null); + yield waitForFilePicker(); + }); +}); diff --git a/toolkit/content/tests/browser/browser_save_resend_postdata.js b/toolkit/content/tests/browser/browser_save_resend_postdata.js new file mode 100644 index 000000000..602a13d22 --- /dev/null +++ b/toolkit/content/tests/browser/browser_save_resend_postdata.js @@ -0,0 +1,145 @@ +/* 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/. */ + +var MockFilePicker = SpecialPowers.MockFilePicker; +MockFilePicker.init(window); + +/** + * Test for bug 471962 : + * When saving an inner frame as file only, the POST data of the outer page is + * sent to the address of the inner page. + * + * Test for bug 485196 : + * Web page generated by POST is retried as GET when Save Frame As used, and the + * page is no longer in the cache. + */ +function test() { + waitForExplicitFinish(); + + gBrowser.loadURI("http://mochi.test:8888/browser/toolkit/content/tests/browser/data/post_form_outer.sjs"); + + gBrowser.addEventListener("pageshow", function pageShown(event) { + if (event.target.location == "about:blank") + return; + gBrowser.removeEventListener("pageshow", pageShown); + + // Submit the form in the outer page, then wait for both the outer + // document and the inner frame to be loaded again. + gBrowser.addEventListener("DOMContentLoaded", handleOuterSubmit); + gBrowser.contentDocument.getElementById("postForm").submit(); + }); + + var framesLoaded = 0; + var innerFrame; + + function handleOuterSubmit() { + if (++framesLoaded < 2) + return; + + gBrowser.removeEventListener("DOMContentLoaded", handleOuterSubmit); + + innerFrame = gBrowser.contentDocument.getElementById("innerFrame"); + + // Submit the form in the inner page. + gBrowser.addEventListener("DOMContentLoaded", handleInnerSubmit); + innerFrame.contentDocument.getElementById("postForm").submit(); + } + + function handleInnerSubmit() { + gBrowser.removeEventListener("DOMContentLoaded", handleInnerSubmit); + + // Create the folder the page will be saved into. + var destDir = createTemporarySaveDirectory(); + var file = destDir.clone(); + file.append("no_default_file_name"); + MockFilePicker.returnFiles = [file]; + MockFilePicker.showCallback = function(fp) { + MockFilePicker.filterIndex = 1; // kSaveAsType_URL + }; + + mockTransferCallback = onTransferComplete; + mockTransferRegisterer.register(); + + registerCleanupFunction(function () { + mockTransferRegisterer.unregister(); + MockFilePicker.cleanup(); + destDir.remove(true); + }); + + var docToSave = innerFrame.contentDocument; + // We call internalSave instead of saveDocument to bypass the history + // cache. + internalSave(docToSave.location.href, docToSave, null, null, + docToSave.contentType, false, null, null, + docToSave.referrer ? makeURI(docToSave.referrer) : null, + docToSave, false, null); + } + + function onTransferComplete(downloadSuccess) { + ok(downloadSuccess, "The inner frame should have been downloaded successfully"); + + // Read the entire saved file. + var file = MockFilePicker.returnFiles[0]; + var fileContents = readShortFile(file); + + // Check if outer POST data is found (bug 471962). + is(fileContents.indexOf("inputfield=outer"), -1, + "The saved inner frame does not contain outer POST data"); + + // Check if inner POST data is found (bug 485196). + isnot(fileContents.indexOf("inputfield=inner"), -1, + "The saved inner frame was generated using the correct POST data"); + + finish(); + } +} + +Cc["@mozilla.org/moz/jssubscript-loader;1"] + .getService(Ci.mozIJSSubScriptLoader) + .loadSubScript("chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockTransfer.js", + this); + +function createTemporarySaveDirectory() { + var saveDir = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties) + .get("TmpD", Ci.nsIFile); + saveDir.append("testsavedir"); + if (!saveDir.exists()) + saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755); + return saveDir; +} + +/** + * Reads the contents of the provided short file (up to 1 MiB). + * + * @param aFile + * nsIFile object pointing to the file to be read. + * + * @return + * String containing the raw octets read from the file. + */ +function readShortFile(aFile) { + var inputStream = Cc["@mozilla.org/network/file-input-stream;1"] + .createInstance(Ci.nsIFileInputStream); + inputStream.init(aFile, -1, 0, 0); + try { + var scrInputStream = Cc["@mozilla.org/scriptableinputstream;1"] + .createInstance(Ci.nsIScriptableInputStream); + scrInputStream.init(inputStream); + try { + // Assume that the file is much shorter than 1 MiB. + return scrInputStream.read(1048576); + } + finally { + // Close the scriptable stream after reading, even if the operation + // failed. + scrInputStream.close(); + } + } + finally { + // Close the stream after reading, if it is still open, even if the read + // operation failed. + inputStream.close(); + } +} diff --git a/toolkit/content/tests/browser/common/mockTransfer.js b/toolkit/content/tests/browser/common/mockTransfer.js new file mode 100644 index 000000000..c8b8fc161 --- /dev/null +++ b/toolkit/content/tests/browser/common/mockTransfer.js @@ -0,0 +1,67 @@ +/* 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/. */ + +Cc["@mozilla.org/moz/jssubscript-loader;1"] + .getService(Ci.mozIJSSubScriptLoader) + .loadSubScript("chrome://mochikit/content/tests/SimpleTest/MockObjects.js", this); + +var mockTransferCallback; + +/** + * This "transfer" object implementation continues the currently running test + * when the download is completed, reporting true for success or false for + * failure as the first argument of the testRunner.continueTest function. + */ +function MockTransfer() { + this._downloadIsSuccessful = true; +} + +MockTransfer.prototype = { + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIWebProgressListener, + Ci.nsIWebProgressListener2, + Ci.nsITransfer, + ]), + + /* nsIWebProgressListener */ + onStateChange: function MTFC_onStateChange(aWebProgress, aRequest, + aStateFlags, aStatus) { + // If at least one notification reported an error, the download failed. + if (!Components.isSuccessCode(aStatus)) + this._downloadIsSuccessful = false; + + // If the download is finished + if ((aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) && + (aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK)) + // Continue the test, reporting the success or failure condition. + mockTransferCallback(this._downloadIsSuccessful); + }, + onProgressChange: function () {}, + onLocationChange: function () {}, + onStatusChange: function MTFC_onStatusChange(aWebProgress, aRequest, aStatus, + aMessage) { + // If at least one notification reported an error, the download failed. + if (!Components.isSuccessCode(aStatus)) + this._downloadIsSuccessful = false; + }, + onSecurityChange: function () {}, + + /* nsIWebProgressListener2 */ + onProgressChange64: function () {}, + onRefreshAttempted: function () {}, + + /* nsITransfer */ + init: function() {}, + setSha256Hash: function() {}, + setSignatureInfo: function() {} +}; + +// Create an instance of a MockObjectRegisterer whose methods can be used to +// temporarily replace the default "@mozilla.org/transfer;1" object factory with +// one that provides the mock implementation above. To activate the mock object +// factory, call the "register" method. Starting from that moment, all the +// transfer objects that are requested will be mock objects, until the +// "unregister" method is called. +var mockTransferRegisterer = + new MockObjectRegisterer("@mozilla.org/transfer;1", MockTransfer); diff --git a/toolkit/content/tests/browser/data/post_form_inner.sjs b/toolkit/content/tests/browser/data/post_form_inner.sjs new file mode 100644 index 000000000..ce72159d8 --- /dev/null +++ b/toolkit/content/tests/browser/data/post_form_inner.sjs @@ -0,0 +1,31 @@ +/* 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/. */ + +const CC = Components.Constructor; +const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream"); + +function handleRequest(request, response) +{ + var body = + '\ + \ + Inner POST data: '; + + var bodyStream = new BinaryInputStream(request.bodyInputStream); + var bytes = [], avail = 0; + while ((avail = bodyStream.available()) > 0) + body += String.fromCharCode.apply(String, bodyStream.readByteArray(avail)); + + body += + '
\ + \ + \ +
\ + \ + '; + + response.bodyOutputStream.write(body, body.length); +} diff --git a/toolkit/content/tests/browser/data/post_form_outer.sjs b/toolkit/content/tests/browser/data/post_form_outer.sjs new file mode 100644 index 000000000..89256fcfb --- /dev/null +++ b/toolkit/content/tests/browser/data/post_form_outer.sjs @@ -0,0 +1,34 @@ +/* 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/. */ + +const CC = Components.Constructor; +const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream"); + +function handleRequest(request, response) +{ + var body = + '\ + \ + Outer POST data: '; + + var bodyStream = new BinaryInputStream(request.bodyInputStream); + var bytes = [], avail = 0; + while ((avail = bodyStream.available()) > 0) + body += String.fromCharCode.apply(String, bodyStream.readByteArray(avail)); + + body += + '
\ + \ + \ +
\ + \ + diff --git a/toolkit/content/tests/browser/file_mediaPlaybackFrame2.html b/toolkit/content/tests/browser/file_mediaPlaybackFrame2.html new file mode 100644 index 000000000..d96a4cd4e --- /dev/null +++ b/toolkit/content/tests/browser/file_mediaPlaybackFrame2.html @@ -0,0 +1,2 @@ + + diff --git a/toolkit/content/tests/browser/file_multipleAudio.html b/toolkit/content/tests/browser/file_multipleAudio.html new file mode 100644 index 000000000..5dc37febb --- /dev/null +++ b/toolkit/content/tests/browser/file_multipleAudio.html @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/toolkit/content/tests/browser/file_multiplePlayingAudio.html b/toolkit/content/tests/browser/file_multiplePlayingAudio.html new file mode 100644 index 000000000..ae122506f --- /dev/null +++ b/toolkit/content/tests/browser/file_multiplePlayingAudio.html @@ -0,0 +1,23 @@ + + + + + + + + + + diff --git a/toolkit/content/tests/browser/file_redirect.html b/toolkit/content/tests/browser/file_redirect.html new file mode 100644 index 000000000..4d5fa9dfd --- /dev/null +++ b/toolkit/content/tests/browser/file_redirect.html @@ -0,0 +1,13 @@ + + + + +redirecting... + + +redirectin u bro + + diff --git a/toolkit/content/tests/browser/file_redirect_to.html b/toolkit/content/tests/browser/file_redirect_to.html new file mode 100644 index 000000000..28c0b5371 --- /dev/null +++ b/toolkit/content/tests/browser/file_redirect_to.html @@ -0,0 +1,15 @@ + + + + +redirected! + + +u got redirected, bro + + diff --git a/toolkit/content/tests/browser/head.js b/toolkit/content/tests/browser/head.js new file mode 100644 index 000000000..1c6c2b54f --- /dev/null +++ b/toolkit/content/tests/browser/head.js @@ -0,0 +1,33 @@ +"use strict"; + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "Promise", + "resource://gre/modules/Promise.jsm"); + +/** + * A wrapper for the findbar's method "close", which is not synchronous + * because of animation. + */ +function closeFindbarAndWait(findbar) { + return new Promise((resolve) => { + if (findbar.hidden) { + resolve(); + return; + } + findbar.addEventListener("transitionend", function cont(aEvent) { + if (aEvent.propertyName != "visibility") { + return; + } + findbar.removeEventListener("transitionend", cont); + resolve(); + }); + findbar.close(); + }); +} + +function pushPrefs(...aPrefs) { + let deferred = Promise.defer(); + SpecialPowers.pushPrefEnv({"set": aPrefs}, deferred.resolve); + return deferred.promise; +} diff --git a/toolkit/content/tests/browser/image.jpg b/toolkit/content/tests/browser/image.jpg new file mode 100644 index 000000000..5031808ad Binary files /dev/null and b/toolkit/content/tests/browser/image.jpg differ diff --git a/toolkit/content/tests/browser/image_page.html b/toolkit/content/tests/browser/image_page.html new file mode 100644 index 000000000..522a1d8cf --- /dev/null +++ b/toolkit/content/tests/browser/image_page.html @@ -0,0 +1,9 @@ + + + + +OHAI + + + + diff --git a/toolkit/content/tests/chrome/.eslintrc.js b/toolkit/content/tests/chrome/.eslintrc.js new file mode 100644 index 000000000..2c669d844 --- /dev/null +++ b/toolkit/content/tests/chrome/.eslintrc.js @@ -0,0 +1,7 @@ +"use strict"; + +module.exports = { + "extends": [ + "../../../../testing/mochitest/chrome.eslintrc.js" + ] +}; diff --git a/toolkit/content/tests/chrome/RegisterUnregisterChrome.js b/toolkit/content/tests/chrome/RegisterUnregisterChrome.js new file mode 100644 index 000000000..34f25d2f8 --- /dev/null +++ b/toolkit/content/tests/chrome/RegisterUnregisterChrome.js @@ -0,0 +1,161 @@ +/* This code is mostly copied from chrome/test/unit/head_crtestutils.js */ + +const NS_CHROME_MANIFESTS_FILE_LIST = "ChromeML"; +const XUL_CACHE_PREF = "nglayout.debug.disable_xul_cache"; + +var Cc = Components.classes; +var Ci = Components.interfaces; +var Cr = Components.results; + +var gDirSvc = Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIDirectoryService).QueryInterface(Ci.nsIProperties); +var gChromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]. + getService(Ci.nsIXULChromeRegistry); +var gPrefs = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + +// Create the temporary file in the profile, instead of in TmpD, because +// we know the mochitest harness kills off the profile when it's done. +function copyToTemporaryFile(f) +{ + let tmpd = gDirSvc.get("ProfD", Ci.nsIFile); + tmpf = tmpd.clone(); + tmpf.append("temp.manifest"); + tmpf.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); + tmpf.remove(false); + f.copyTo(tmpd, tmpf.leafName); + return tmpf; +} + +function* dirIter(directory) +{ + var ioSvc = Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService); + var testsDir = ioSvc.newURI(directory, null, null) + .QueryInterface(Ci.nsIFileURL).file; + + let en = testsDir.directoryEntries; + while (en.hasMoreElements()) { + let file = en.getNext(); + yield file.QueryInterface(Ci.nsIFile); + } +} + +function getParent(path) { + let lastSlash = path.lastIndexOf("/"); + if (lastSlash == -1) { + lastSlash = path.lastIndexOf("\\"); + if (lastSlash == -1) { + return ""; + } + return '/' + path.substring(0, lastSlash).replace(/\\/g, '/'); + } + return path.substring(0, lastSlash); +} + +function copyDirToTempProfile(path, subdirname) { + + if (subdirname === undefined) { + subdirname = "mochikit-tmp"; + } + + let tmpdir = gDirSvc.get("ProfD", Ci.nsIFile); + tmpdir.append(subdirname); + tmpdir.createUnique(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o777); + + let rootDir = getParent(path); + if (rootDir == "") { + return tmpdir; + } + + // The SimpleTest directory is hidden + var files = Array.from(dirIter('file://' + rootDir)); + for (f in files) { + files[f].copyTo(tmpdir, ""); + } + return tmpdir; + +} + +function convertChromeURI(chromeURI) +{ + let uri = Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService).newURI(chromeURI, null, null); + return gChromeReg.convertChromeURL(uri); +} + +function chromeURIToFile(chromeURI) +{ + var jar = getJar(chromeURI); + if (jar) { + var tmpDir = extractJarToTmp(jar); + let parts = chromeURI.split('/'); + if (parts[parts.length - 1] != '') { + tmpDir.append(parts[parts.length - 1]); + } + return tmpDir; + } + + return convertChromeURI(chromeURI). + QueryInterface(Ci.nsIFileURL).file; +} + +// Register a chrome manifest temporarily and return a function which un-does +// the registrarion when no longer needed. +function createManifestTemporarily(tempDir, manifestText) +{ + gPrefs.setBoolPref(XUL_CACHE_PREF, true); + + tempDir.append("temp.manifest"); + + let foStream = Cc["@mozilla.org/network/file-output-stream;1"] + .createInstance(Ci.nsIFileOutputStream); + foStream.init(tempDir, + 0x02 | 0x08 | 0x20, 0o664, 0); // write, create, truncate + foStream.write(manifestText, manifestText.length); + foStream.close(); + let tempfile = copyToTemporaryFile(tempDir); + + Components.manager.QueryInterface(Ci.nsIComponentRegistrar). + autoRegister(tempfile); + + gChromeReg.refreshSkins(); + + return function() { + tempfile.fileSize = 0; // truncate the manifest + gChromeReg.checkForNewChrome(); + gChromeReg.refreshSkins(); + gPrefs.clearUserPref(XUL_CACHE_PREF); + } +} + +// Register a chrome manifest temporarily and return a function which un-does +// the registrarion when no longer needed. +function registerManifestTemporarily(manifestURI) +{ + gPrefs.setBoolPref(XUL_CACHE_PREF, true); + + let file = chromeURIToFile(manifestURI); + + let tempfile = copyToTemporaryFile(file); + Components.manager.QueryInterface(Ci.nsIComponentRegistrar). + autoRegister(tempfile); + + gChromeReg.refreshSkins(); + + return function() { + tempfile.fileSize = 0; // truncate the manifest + gChromeReg.checkForNewChrome(); + gChromeReg.refreshSkins(); + gPrefs.clearUserPref(XUL_CACHE_PREF); + } +} + +function registerManifestPermanently(manifestURI) +{ + var chromepath = chromeURIToFile(manifestURI); + + Components.manager.QueryInterface(Ci.nsIComponentRegistrar). + autoRegister(chromepath); + return chromepath; +} diff --git a/toolkit/content/tests/chrome/bug263683_window.xul b/toolkit/content/tests/chrome/bug263683_window.xul new file mode 100644 index 000000000..46985a7ad --- /dev/null +++ b/toolkit/content/tests/chrome/bug263683_window.xul @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/bug304188_window.xul b/toolkit/content/tests/chrome/bug304188_window.xul new file mode 100644 index 000000000..931fd5c73 --- /dev/null +++ b/toolkit/content/tests/chrome/bug304188_window.xul @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/bug331215_window.xul b/toolkit/content/tests/chrome/bug331215_window.xul new file mode 100644 index 000000000..757ce61b8 --- /dev/null +++ b/toolkit/content/tests/chrome/bug331215_window.xul @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/bug360437_window.xul b/toolkit/content/tests/chrome/bug360437_window.xul new file mode 100644 index 000000000..08498b58b --- /dev/null +++ b/toolkit/content/tests/chrome/bug360437_window.xul @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/bug366992_window.xul b/toolkit/content/tests/chrome/bug366992_window.xul new file mode 100644 index 000000000..a1e2ae1af --- /dev/null +++ b/toolkit/content/tests/chrome/bug366992_window.xul @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/bug409624_window.xul b/toolkit/content/tests/chrome/bug409624_window.xul new file mode 100644 index 000000000..002cbe042 --- /dev/null +++ b/toolkit/content/tests/chrome/bug409624_window.xul @@ -0,0 +1,98 @@ + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/bug429723_window.xul b/toolkit/content/tests/chrome/bug429723_window.xul new file mode 100644 index 000000000..28439ae8e --- /dev/null +++ b/toolkit/content/tests/chrome/bug429723_window.xul @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/bug451540_window.xul b/toolkit/content/tests/chrome/bug451540_window.xul new file mode 100644 index 000000000..3c08c95c9 --- /dev/null +++ b/toolkit/content/tests/chrome/bug451540_window.xul @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/bug624329_window.xul b/toolkit/content/tests/chrome/bug624329_window.xul new file mode 100644 index 000000000..efca39d3b --- /dev/null +++ b/toolkit/content/tests/chrome/bug624329_window.xul @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/chrome.ini b/toolkit/content/tests/chrome/chrome.ini new file mode 100644 index 000000000..2b9be4c8e --- /dev/null +++ b/toolkit/content/tests/chrome/chrome.ini @@ -0,0 +1,199 @@ +[DEFAULT] +skip-if = os == 'android' +support-files = + ../widgets/popup_shared.js + ../widgets/tree_shared.js + RegisterUnregisterChrome.js + bug263683_window.xul + bug304188_window.xul + bug331215_window.xul + bug360437_window.xul + bug366992_window.xul + bug409624_window.xul + bug429723_window.xul + bug624329_window.xul + dialog_dialogfocus.xul + file_about_networking_wsh.py + file_autocomplete_with_composition.js + findbar_entireword_window.xul + findbar_events_window.xul + findbar_window.xul + frame_popup_anchor.xul + frame_popupremoving_frame.xul + frame_subframe_origin_subframe1.xul + frame_subframe_origin_subframe2.xul + popup_childframe_node.xul + popup_trigger.js + sample_entireword_latin1.html + window_browser_drop.xul + window_keys.xul + window_largemenu.xul + window_panel.xul + window_popup_anchor.xul + window_popup_anchoratrect.xul + window_popup_attribute.xul + window_popup_button.xul + window_popup_preventdefault_chrome.xul + window_preferences.xul + window_preferences2.xul + window_preferences3.xul + window_preferences_commandretarget.xul + window_screenPosSize.xul + window_showcaret.xul + window_subframe_origin.xul + window_titlebar.xul + window_tooltip.xul + xul_selectcontrol.js + rtlchrome/rtl.css + rtlchrome/rtl.dtd + rtlchrome/rtl.manifest + rtltest/righttoleft.manifest + rtltest/content/dirtest.xul + +[test_about_networking.html] +[test_arrowpanel.xul] +[test_autocomplete2.xul] +[test_autocomplete3.xul] +[test_autocomplete4.xul] +[test_autocomplete5.xul] +[test_autocomplete_delayOnPaste.xul] +subsuite = clipboard +[test_autocomplete_emphasis.xul] +[test_autocomplete_with_composition_on_input.html] +[test_autocomplete_with_composition_on_textbox.xul] +[test_autocomplete_placehold_last_complete.xul] +[test_browser_drop.xul] +[test_bug253481.xul] +subsuite = clipboard +[test_bug263683.xul] +[test_bug304188.xul] +[test_bug331215.xul] +[test_bug360220.xul] +[test_bug360437.xul] +skip-if = os == 'linux' # Bug 1264604 +[test_bug365773.xul] +[test_bug366992.xul] +[test_bug382990.xul] +[test_bug409624.xul] +[test_bug418874.xul] +[test_bug429723.xul] +[test_bug437844.xul] +[test_bug457632.xul] +[test_bug460942.xul] +[test_bug471776.xul] +[test_bug509732.xul] +[test_bug554279.xul] +[test_bug557987.xul] +[test_bug562554.xul] +[test_bug570192.xul] +[test_bug585946.xul] +[test_bug624329.xul] +skip-if = (os == 'mac' && os_version == '10.10') # Unexpectedly perma-passes on OSX 10.10 +[test_bug792324.xul] +[test_bug1048178.xul] +skip-if = toolkit == "cocoa" +[test_button.xul] +[test_closemenu_attribute.xul] +[test_colorpicker_popup.xul] +[test_contextmenu_list.xul] +[test_datepicker.xul] +[test_deck.xul] +[test_dialogfocus.xul] +[test_findbar.xul] +subsuite = clipboard +[test_findbar_entireword.xul] +[test_findbar_events.xul] +[test_focus_anons.xul] +[test_hiddenitems.xul] +[test_hiddenpaging.xul] +[test_keys.xul] +[test_labelcontrol.xul] +[test_largemenu.xul] +skip-if = os == 'linux' && !debug #Bug 1207174 +[test_menu.xul] +[test_menu_anchored.xul] +[test_menu_hide.xul] +[test_menuchecks.xul] +[test_menuitem_blink.xul] +[test_menuitem_commands.xul] +[test_menulist.xul] +[test_menulist_keynav.xul] +[test_menulist_null_value.xul] +[test_menulist_paging.xul] +[test_menulist_position.xul] +[test_mousescroll.xul] +[test_notificationbox.xul] +[test_panel.xul] +[test_panelfrommenu.xul] +[test_popup_anchor.xul] +[test_popup_anchoratrect.xul] +skip-if = os == 'linux' # 1167694 +[test_popup_attribute.xul] +skip-if = os == 'linux' && asan #Bug 1131634 +[test_popup_button.xul] +skip-if = os == 'linux' && asan # Bug 1281360 +[test_popup_coords.xul] +[test_popup_keys.xul] +[test_popup_moveToAnchor.xul] +[test_popup_preventdefault.xul] +[test_popup_preventdefault_chrome.xul] +[test_popup_recreate.xul] +[test_popup_scaled.xul] +[test_popup_tree.xul] +[test_popuphidden.xul] +[test_popupincontent.xul] +[test_popupremoving.xul] +[test_popupremoving_frame.xul] +[test_position.xul] +[test_preferences.xul] +[test_preferences_beforeaccept.xul] +support-files = window_preferences_beforeaccept.xul +[test_preferences_onsyncfrompreference.xul] +support-files = window_preferences_onsyncfrompreference.xul +[test_progressmeter.xul] +[test_props.xul] +[test_radio.xul] +[test_richlist_direction.xul] +[test_righttoleft.xul] +[test_scale.xul] +[test_scaledrag.xul] +[test_screenPersistence.xul] +[test_scrollbar.xul] +[test_showcaret.xul] +[test_sorttemplate.xul] +[test_statusbar.xul] +[test_subframe_origin.xul] +[test_tabbox.xul] +[test_tabindex.xul] +[test_textbox_dictionary.xul] +[test_textbox_emptytext.xul] +[test_textbox_number.xul] +[test_textbox_search.xul] +[test_timepicker.xul] +[test_titlebar.xul] +skip-if = os == "linux" +[test_toolbar.xul] +[test_tooltip.xul] +skip-if = (os == 'mac' && os_version == '10.10') # Bug 1141245, frequent timeouts on OSX 10.10 +[test_tooltip_noautohide.xul] +[test_tree.xul] +[test_tree_hier.xul] +[test_tree_hier_cell.xul] +[test_tree_single.xul] +[test_tree_view.xul] +# test_panel_focus.xul won't work if the Full Keyboard Access preference is set to +# textboxes and lists only, so skip this test on Mac +[test_panel_focus.xul] +support-files = window_panel_focus.xul +skip-if = toolkit == "cocoa" +[test_chromemargin.xul] +support-files = window_chromemargin.xul +skip-if = toolkit == "cocoa" +[test_bug451540.xul] +support-files = bug451540_window.xul +[test_autocomplete_mac_caret.xul] +skip-if = toolkit != "cocoa" +[test_cursorsnap.xul] +disabled = +#skip-if = os != "win" +support-files = window_cursorsnap_dialog.xul window_cursorsnap_wizard.xul diff --git a/toolkit/content/tests/chrome/dialog_dialogfocus.xul b/toolkit/content/tests/chrome/dialog_dialogfocus.xul new file mode 100644 index 000000000..770695ed3 --- /dev/null +++ b/toolkit/content/tests/chrome/dialog_dialogfocus.xul @@ -0,0 +1,57 @@ + + + + + diff --git a/toolkit/content/tests/chrome/file_about_networking_wsh.py b/toolkit/content/tests/chrome/file_about_networking_wsh.py new file mode 100644 index 000000000..17ad250e5 --- /dev/null +++ b/toolkit/content/tests/chrome/file_about_networking_wsh.py @@ -0,0 +1,9 @@ +from mod_pywebsocket import msgutil + +def web_socket_do_extra_handshake(request): + pass + +def web_socket_transfer_data(request): + while not request.client_terminated: + msgutil.receive_message(request) + diff --git a/toolkit/content/tests/chrome/file_autocomplete_with_composition.js b/toolkit/content/tests/chrome/file_autocomplete_with_composition.js new file mode 100644 index 000000000..881e772ad --- /dev/null +++ b/toolkit/content/tests/chrome/file_autocomplete_with_composition.js @@ -0,0 +1,540 @@ +// nsDoTestsForAutoCompleteWithComposition tests autocomplete with composition. +// Users must include SimpleTest.js and EventUtils.js. + +function waitForCondition(condition, nextTest) { + var tries = 0; + var interval = setInterval(function() { + if (condition() || tries >= 30) { + moveOn(); + } + tries++; + }, 100); + var moveOn = function() { clearInterval(interval); nextTest(); }; +} + +function nsDoTestsForAutoCompleteWithComposition(aDescription, + aWindow, + aTarget, + aAutoCompleteController, + aIsFunc, + aGetTargetValueFunc, + aOnFinishFunc) +{ + this._description = aDescription; + this._window = aWindow; + this._target = aTarget; + this._controller = aAutoCompleteController; + + this._is = aIsFunc; + this._getTargetValue = aGetTargetValueFunc; + this._onFinish = aOnFinishFunc; + + this._target.focus(); + + this._DefaultCompleteDefaultIndex = + this._controller.input.completeDefaultIndex; + + this._doTests(); +} + +nsDoTestsForAutoCompleteWithComposition.prototype = { + _window: null, + _target: null, + _controller: null, + _DefaultCompleteDefaultIndex: false, + _description: "", + + _is: null, + _getTargetValue: function () { return "not initialized"; }, + _onFinish: null, + + _doTests: function () + { + if (++this._testingIndex == this._tests.length) { + this._controller.input.completeDefaultIndex = + this._DefaultCompleteDefaultIndex; + this._onFinish(); + return; + } + + var test = this._tests[this._testingIndex]; + if (this._controller.input.completeDefaultIndex != test.completeDefaultIndex) { + this._controller.input.completeDefaultIndex = test.completeDefaultIndex; + } + test.execute(this._window); + + waitForCondition(() => { + return this._controller.searchStatus >= + Components.interfaces.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH; + }, + this._checkResult.bind(this)); + }, + + _checkResult: function () + { + var test = this._tests[this._testingIndex]; + this._is(this._getTargetValue(), test.value, + this._description + ", " + test.description + ": value"); + this._is(this._controller.searchString, test.searchString, + this._description + ", " + test.description +": searchString"); + this._is(this._controller.input.popupOpen, test.popup, + this._description + ", " + test.description + ": popupOpen"); + this._doTests(); + }, + + _testingIndex: -1, + _tests: [ + // Simple composition when popup hasn't been shown. + // The autocomplete popup should not be shown during composition, but + // after compositionend, the popup should be shown. + { description: "compositionstart shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "M", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 1, "length": 0 }, + "key": { key: "M", code: "KeyM", keyCode: KeyboardEvent.DOM_VK_M, + shiftKey: true }, + }, aWindow); + }, popup: false, value: "M", searchString: "" + }, + { description: "modifying composition string shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "Mo", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 2, "length": 0 }, + "key": { key: "o", code: "KeyO", keyCode: KeyboardEvent.DOM_VK_O }, + }, aWindow); + }, popup: false, value: "Mo", searchString: "" + }, + { description: "compositionend should open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositioncommitasis", + key: { key: "KEY_Enter", code: "Enter" } }, aWindow); + }, popup: true, value: "Mo", searchString: "Mo" + }, + // If composition starts when popup is shown, the compositionstart event + // should cause closing the popup. + { description: "compositionstart should close the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "z", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 1, "length": 0 }, + "key": { key: "z", code: "KeyZ", keyCode: KeyboardEvent.DOM_VK_Z }, + }, aWindow); + }, popup: false, value: "Moz", searchString: "Mo" + }, + { description: "modifying composition string shouldn't reopen the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "zi", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 2, "length": 0 }, + "key": { key: "i", code: "KeyI", keyCode: KeyboardEvent.DOM_VK_I }, + }, aWindow); + }, popup: false, value: "Mozi", searchString: "Mo" + }, + { description: "compositionend should research the result and open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositioncommitasis", + key: { key: "KEY_Enter", code: "Enter" } }, aWindow); + }, popup: true, value: "Mozi", searchString: "Mozi" + }, + // If composition is cancelled, the value shouldn't be changed. + { description: "compositionstart should reclose the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "l", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 1, "length": 0 }, + "key": { key: "l", code: "KeyL", keyCode: KeyboardEvent.DOM_VK_L }, + }, aWindow); + }, popup: false, value: "Mozil", searchString: "Mozi" + }, + { description: "modifying composition string shouldn't reopen the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "ll", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 2, "length": 0 }, + "key": { key: "l", code: "KeyL", keyCode: KeyboardEvent.DOM_VK_L }, + }, aWindow); + }, popup: false, value: "Mozill", searchString: "Mozi" + }, + { description: "modifying composition string to empty string shouldn't reopen the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + }, popup: false, value: "Mozi", searchString: "Mozi" + }, + { description: "cancled compositionend should reopen the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositioncommit", data: "", + key: { key: "KEY_Escape", code: "Escape" } }, aWindow); + }, popup: true, value: "Mozi", searchString: "Mozi" + }, + // But if composition replaces some characters and canceled, the search + // string should be the latest value. + { description: "compositionstart with selected string should close the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("VK_LEFT", { shiftKey: true }, aWindow); + synthesizeKey("VK_LEFT", { shiftKey: true }, aWindow); + synthesizeCompositionChange( + { "composition": + { "string": "z", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 1, "length": 0 }, + "key": { key: "z", code: "KeyZ", keyCode: KeyboardEvent.DOM_VK_Z }, + }, aWindow); + }, popup: false, value: "Moz", searchString: "Mozi" + }, + { description: "modifying composition string shouldn't reopen the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "zi", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 2, "length": 0 }, + "key": { key: "i", code: "KeyI", keyCode: KeyboardEvent.DOM_VK_I }, + }, aWindow); + }, popup: false, value: "Mozi", searchString: "Mozi" + }, + { description: "modifying composition string to empty string shouldn't reopen the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + }, popup: false, value: "Mo", searchString: "Mozi" + }, + { description: "canceled compositionend should search the result with the latest value", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositioncommitasis", + key: { key: "KEY_Escape", code: "Escape" } }, aWindow); + }, popup: true, value: "Mo", searchString: "Mo" + }, + // If all characters are removed, the popup should be closed. + { description: "the value becomes empty by backspace, the popup should be closed", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + }, popup: false, value: "", searchString: "" + }, + // composition which is canceled shouldn't cause opening the popup. + { description: "compositionstart shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "M", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 1, "length": 0 }, + "key": { key: "m", code: "KeyM", keyCode: KeyboardEvent.DOM_VK_M, + shiftKey: true }, + }, aWindow); + }, popup: false, value: "M", searchString: "" + }, + { description: "modifying composition string shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "Mo", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 2, "length": 0 }, + "key": { key: "o", code: "KeyO", keyCode: KeyboardEvent.DOM_VK_O }, + }, aWindow); + }, popup: false, value: "Mo", searchString: "" + }, + { description: "modifying composition string to empty string shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + }, popup: false, value: "", searchString: "" + }, + { description: "canceled compositionend shouldn't open the popup if it was closed", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositioncommitasis", + key: { key: "KEY_Escape", code: "Escape" } }, aWindow); + }, popup: false, value: "", searchString: "" + }, + // Down key should open the popup even if the editor is empty. + { description: "DOWN key should open the popup even if the value is empty", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("VK_DOWN", {}, aWindow); + }, popup: true, value: "", searchString: "" + }, + // If popup is open at starting composition, the popup should be reopened + // after composition anyway. + { description: "compositionstart shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "M", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 1, "length": 0 }, + "key": { key: "M", code: "KeyM", keyCode: KeyboardEvent.DOM_VK_M, + shiftKey: true }, + }, aWindow); + }, popup: false, value: "M", searchString: "" + }, + { description: "modifying composition string shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "Mo", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 2, "length": 0 }, + "key": { key: "o", code: "KeyO", keyCode: KeyboardEvent.DOM_VK_O }, + }, aWindow); + }, popup: false, value: "Mo", searchString: "" + }, + { description: "modifying composition string to empty string shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + }, popup: false, value: "", searchString: "" + }, + { description: "canceled compositionend should open the popup if it was opened", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositioncommitasis", + key: { key: "KEY_Escape", code: "Escape" } }, aWindow); + }, popup: true, value: "", searchString: "" + }, + // Type normally, and hit escape, the popup should be closed. + { description: "ESCAPE should close the popup after typing something", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("M", { shiftKey: true }, aWindow); + synthesizeKey("o", { shiftKey: true }, aWindow); + synthesizeKey("VK_ESCAPE", {}, aWindow); + }, popup: false, value: "Mo", searchString: "Mo" + }, + // Even if the popup is closed, composition which is canceled should open + // the popup if the value isn't empty. + // XXX This might not be good behavior, but anyway, this is minor issue... + { description: "compositionstart shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "z", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 1, "length": 0 }, + "key": { key: "z", code: "KeyZ", keyCode: KeyboardEvent.DOM_VK_Z }, + }, aWindow); + }, popup: false, value: "Moz", searchString: "Mo" + }, + { description: "modifying composition string shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "zi", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 2, "length": 0 }, + "key": { key: "i", code: "KeyI", keyCode: KeyboardEvent.DOM_VK_I }, + }, aWindow); + }, popup: false, value: "Mozi", searchString: "Mo" + }, + { description: "modifying composition string to empty string shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + }, popup: false, value: "Mo", searchString: "Mo" + }, + { description: "canceled compositionend shouldn't open the popup if the popup was closed", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositioncommitasis", + key: { key: "KEY_Escape", code: "Escape" } }, aWindow); + }, popup: true, value: "Mo", searchString: "Mo" + }, + // House keeping... + { description: "house keeping for next tests", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + }, popup: false, value: "", searchString: "" + }, + // Testing for nsIAutoCompleteInput.completeDefaultIndex being true. + { description: "compositionstart shouldn't open the popup (completeDefaultIndex is true)", + completeDefaultIndex: true, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "M", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 1, "length": 0 }, + "key": { key: "M", code: "KeyM", keyCode: KeyboardEvent.DOM_VK_M, + shiftKey: true }, + }, aWindow); + }, popup: false, value: "M", searchString: "" + }, + { description: "modifying composition string shouldn't open the popup (completeDefaultIndex is true)", + completeDefaultIndex: true, + execute: function (aWindow) { + synthesizeCompositionChange( + { "composition": + { "string": "Mo", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE } + ] + }, + "caret": { "start": 2, "length": 0 }, + "key": { key: "o", code: "KeyO", keyCode: KeyboardEvent.DOM_VK_O }, + }, aWindow); + }, popup: false, value: "Mo", searchString: "" + }, + { description: "compositionend should open the popup (completeDefaultIndex is true)", + completeDefaultIndex: true, + execute: function (aWindow) { + synthesizeComposition({ type: "compositioncommitasis", + key: { key: "KEY_Enter", code: "Enter" } }, aWindow); + }, popup: true, value: "Mozilla", searchString: "Mo" + }, + // House keeping... + { description: "house keeping for next tests", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + }, popup: false, value: "", searchString: "" + } + ] +}; diff --git a/toolkit/content/tests/chrome/findbar_entireword_window.xul b/toolkit/content/tests/chrome/findbar_entireword_window.xul new file mode 100644 index 000000000..f0da61081 --- /dev/null +++ b/toolkit/content/tests/chrome/findbar_entireword_window.xul @@ -0,0 +1,275 @@ + + + + + + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/findbar_events_window.xul b/toolkit/content/tests/chrome/findbar_events_window.xul new file mode 100644 index 000000000..2bfc52c14 --- /dev/null +++ b/toolkit/content/tests/chrome/findbar_events_window.xul @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/findbar_window.xul b/toolkit/content/tests/chrome/findbar_window.xul new file mode 100644 index 000000000..f17f760fe --- /dev/null +++ b/toolkit/content/tests/chrome/findbar_window.xul @@ -0,0 +1,756 @@ + + + + + + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/frame_popup_anchor.xul b/toolkit/content/tests/chrome/frame_popup_anchor.xul new file mode 100644 index 000000000..be6254ce0 --- /dev/null +++ b/toolkit/content/tests/chrome/frame_popup_anchor.xul @@ -0,0 +1,82 @@ + + + + + + + + diff --git a/toolkit/content/tests/chrome/frame_popupremoving_frame.xul b/toolkit/content/tests/chrome/frame_popupremoving_frame.xul new file mode 100644 index 000000000..e8f00ce7a --- /dev/null +++ b/toolkit/content/tests/chrome/frame_popupremoving_frame.xul @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/frame_subframe_origin_subframe1.xul b/toolkit/content/tests/chrome/frame_subframe_origin_subframe1.xul new file mode 100644 index 000000000..c85083cb7 --- /dev/null +++ b/toolkit/content/tests/chrome/frame_subframe_origin_subframe1.xul @@ -0,0 +1,43 @@ + + + + + + + diff --git a/toolkit/content/tests/chrome/frame_subframe_origin_subframe2.xul b/toolkit/content/tests/chrome/frame_subframe_origin_subframe2.xul new file mode 100644 index 000000000..92ef64b89 --- /dev/null +++ b/toolkit/content/tests/chrome/frame_subframe_origin_subframe2.xul @@ -0,0 +1,39 @@ + + + + + + + diff --git a/toolkit/content/tests/chrome/popup_childframe_node.xul b/toolkit/content/tests/chrome/popup_childframe_node.xul new file mode 100644 index 000000000..512f5f8c2 --- /dev/null +++ b/toolkit/content/tests/chrome/popup_childframe_node.xul @@ -0,0 +1,2 @@ + diff --git a/toolkit/content/tests/chrome/popup_trigger.js b/toolkit/content/tests/chrome/popup_trigger.js new file mode 100644 index 000000000..920d4d070 --- /dev/null +++ b/toolkit/content/tests/chrome/popup_trigger.js @@ -0,0 +1,859 @@ +var gMenuPopup = null; +var gTrigger = null; +var gIsMenu = false; +var gScreenX = -1, gScreenY = -1; +var gCachedEvent = null; +var gCachedEvent2 = null; + +function cacheEvent(modifiers) +{ + var cachedEvent = null; + + var mouseFn = function(event) { + cachedEvent = event; + } + + window.addEventListener("mousedown", mouseFn, false); + synthesizeMouse(document.documentElement, 0, 0, modifiers); + window.removeEventListener("mousedown", mouseFn, false); + + return cachedEvent; +} + +function runTests() +{ + if (screen.height < 768) { + ok(false, "popup tests are likely to fail for screen heights less than 768 pixels"); + } + + gMenuPopup = document.getElementById("thepopup"); + gTrigger = document.getElementById("trigger"); + + gIsMenu = gTrigger.boxObject instanceof MenuBoxObject; + + // a hacky way to get the screen position of the document. Cache the event + // so that we can use it in calls to openPopup. + gCachedEvent = cacheEvent({ shiftKey: true }); + gScreenX = gCachedEvent.screenX; + gScreenY = gCachedEvent.screenY; + gCachedEvent2 = cacheEvent({ altKey: true, ctrlKey: true, shiftKey: true, metaKey: true }); + + startPopupTests(popupTests); +} + +var popupTests = [ +{ + testname: "mouse click on trigger", + events: [ "popupshowing thepopup", "popupshown thepopup" ], + test: function() { + // for menus, no trigger will be set. For non-menus using the popup + // attribute, the trigger will be set to the node with the popup attribute + gExpectedTriggerNode = gIsMenu ? "notset" : gTrigger; + synthesizeMouse(gTrigger, 4, 4, { }); + }, + result: function (testname) { + gExpectedTriggerNode = null; + // menus are the anchor but non-menus are opened at screen coordinates + is(gMenuPopup.anchorNode, gIsMenu ? gTrigger : null, testname + " anchorNode"); + // menus are opened internally, but non-menus have a mouse event which + // triggered them + is(gMenuPopup.triggerNode, gIsMenu ? null : gTrigger, testname + " triggerNode"); + is(document.popupNode, gIsMenu ? null : gTrigger, testname + " document.popupNode"); + is(document.tooltipNode, null, testname + " document.tooltipNode"); + // check to ensure the popup node for a different document isn't used + if (window.opener) + is(window.opener.document.popupNode, null, testname + " opener.document.popupNode"); + + // this will be used in some tests to ensure the size doesn't change + var popuprect = gMenuPopup.getBoundingClientRect(); + gPopupWidth = Math.round(popuprect.width); + gPopupHeight = Math.round(popuprect.height); + + checkActive(gMenuPopup, "", testname); + checkOpen("trigger", testname); + // if a menu, the popup should be opened underneath the menu in the + // 'after_start' position, otherwise it is opened at the mouse position + if (gIsMenu) + compareEdge(gTrigger, gMenuPopup, "after_start", 0, 0, testname); + } +}, +{ + // check that pressing cursor down while there is no selection + // highlights the first item + testname: "cursor down no selection", + events: [ "DOMMenuItemActive item1" ], + test: function() { synthesizeKey("VK_DOWN", { }); }, + result: function(testname) { checkActive(gMenuPopup, "item1", testname); } +}, +{ + // check that pressing cursor up wraps and highlights the last item + testname: "cursor up wrap", + events: [ "DOMMenuItemInactive item1", "DOMMenuItemActive last" ], + test: function() { synthesizeKey("VK_UP", { }); }, + result: function(testname) { + checkActive(gMenuPopup, "last", testname); + } +}, +{ + // check that pressing cursor down wraps and highlights the first item + testname: "cursor down wrap", + events: [ "DOMMenuItemInactive last", "DOMMenuItemActive item1" ], + test: function() { synthesizeKey("VK_DOWN", { }); }, + result: function(testname) { checkActive(gMenuPopup, "item1", testname); } +}, +{ + // check that pressing cursor down highlights the second item + testname: "cursor down", + events: [ "DOMMenuItemInactive item1", "DOMMenuItemActive item2" ], + test: function() { synthesizeKey("VK_DOWN", { }); }, + result: function(testname) { checkActive(gMenuPopup, "item2", testname); } +}, +{ + // check that pressing cursor up highlights the second item + testname: "cursor up", + events: [ "DOMMenuItemInactive item2", "DOMMenuItemActive item1" ], + test: function() { synthesizeKey("VK_UP", { }); }, + result: function(testname) { checkActive(gMenuPopup, "item1", testname); } +}, +{ + // cursor left should not do anything + testname: "cursor left", + test: function() { synthesizeKey("VK_LEFT", { }); }, + result: function(testname) { checkActive(gMenuPopup, "item1", testname); } +}, +{ + // cursor right should not do anything + testname: "cursor right", + test: function() { synthesizeKey("VK_RIGHT", { }); }, + result: function(testname) { checkActive(gMenuPopup, "item1", testname); } +}, +{ + // check cursor down when a disabled item exists in the menu + testname: "cursor down disabled", + events: function() { + // On Windows, disabled items are included when navigating, but on + // other platforms, disabled items are skipped over + if (navigator.platform.indexOf("Win") == 0) { + return [ "DOMMenuItemInactive item1", "DOMMenuItemActive item2" ]; + } + return [ "DOMMenuItemInactive item1", "DOMMenuItemActive amenu" ]; + }, + test: function() { + document.getElementById("item2").disabled = true; + synthesizeKey("VK_DOWN", { }); + } +}, +{ + // check cursor up when a disabled item exists in the menu + testname: "cursor up disabled", + events: function() { + if (navigator.platform.indexOf("Win") == 0) { + return [ "DOMMenuItemInactive item2", "DOMMenuItemActive amenu", + "DOMMenuItemInactive amenu", "DOMMenuItemActive item2", + "DOMMenuItemInactive item2", "DOMMenuItemActive item1" ]; + } + return [ "DOMMenuItemInactive amenu", "DOMMenuItemActive item1" ]; + }, + test: function() { + if (navigator.platform.indexOf("Win") == 0) + synthesizeKey("VK_DOWN", { }); + synthesizeKey("VK_UP", { }); + if (navigator.platform.indexOf("Win") == 0) + synthesizeKey("VK_UP", { }); + } +}, +{ + testname: "mouse click outside", + events: [ "popuphiding thepopup", "popuphidden thepopup", + "DOMMenuItemInactive item1", "DOMMenuInactive thepopup" ], + test: function() { + gMenuPopup.hidePopup(); + // XXXndeakin event simulation fires events outside of the platform specific + // widget code so the popup capturing isn't handled. Thus, the menu won't + // rollup this way. + // synthesizeMouse(gTrigger, 0, -12, { }); + }, + result: function(testname, step) { + is(gMenuPopup.anchorNode, null, testname + " anchorNode"); + is(gMenuPopup.triggerNode, null, testname + " triggerNode"); + is(document.popupNode, null, testname + " document.popupNode"); + checkClosed("trigger", testname); + } +}, +{ + // these tests check to ensure that passing an anchor and position + // puts the popup in the right place + testname: "open popup anchored", + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + steps: ["before_start", "before_end", "after_start", "after_end", + "start_before", "start_after", "end_before", "end_after", "after_pointer", "overlap", + "topleft topleft", "topcenter topleft", "topright topleft", + "leftcenter topright", "rightcenter topright", + "bottomleft bottomleft", "bottomcenter bottomleft", "bottomright bottomleft", + "topleft bottomright", "bottomcenter bottomright", "rightcenter topright"], + test: function(testname, step) { + gExpectedTriggerNode = "notset"; + gMenuPopup.openPopup(gTrigger, step, 0, 0, false, false); + }, + result: function(testname, step) { + // no triggerNode because it was opened without passing an event + gExpectedTriggerNode = null; + is(gMenuPopup.anchorNode, gTrigger, testname + " anchorNode"); + is(gMenuPopup.triggerNode, null, testname + " triggerNode"); + is(document.popupNode, null, testname + " document.popupNode"); + compareEdge(gTrigger, gMenuPopup, step, 0, 0, testname); + } +}, +{ + // these tests check the same but with a 10 pixel margin on the popup + testname: "open popup anchored with margin", + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + steps: ["before_start", "before_end", "after_start", "after_end", + "start_before", "start_after", "end_before", "end_after", "after_pointer", "overlap", + "topleft topleft", "topcenter topleft", "topright topleft", + "leftcenter topright", "rightcenter topright", + "bottomleft bottomleft", "bottomcenter bottomleft", "bottomright bottomleft", + "topleft bottomright", "bottomcenter bottomright", "rightcenter topright"], + test: function(testname, step) { + gMenuPopup.setAttribute("style", "margin: 10px;"); + gMenuPopup.openPopup(gTrigger, step, 0, 0, false, false); + }, + result: function(testname, step) { + var rightmod = step == "before_end" || step == "after_end" || + step == "start_before" || step == "start_after" || + step.match(/topright$/) || step.match(/bottomright$/); + var bottommod = step == "before_start" || step == "before_end" || + step == "start_after" || step == "end_after" || + step.match(/bottomleft$/) || step.match(/bottomright$/); + compareEdge(gTrigger, gMenuPopup, step, rightmod ? -10 : 10, bottommod ? -10 : 10, testname); + gMenuPopup.removeAttribute("style"); + } +}, +{ + // these tests check the same but with a -8 pixel margin on the popup + testname: "open popup anchored with negative margin", + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + steps: ["before_start", "before_end", "after_start", "after_end", + "start_before", "start_after", "end_before", "end_after", "after_pointer", "overlap"], + test: function(testname, step) { + gMenuPopup.setAttribute("style", "margin: -8px;"); + gMenuPopup.openPopup(gTrigger, step, 0, 0, false, false); + }, + result: function(testname, step) { + var rightmod = step == "before_end" || step == "after_end" || + step == "start_before" || step == "start_after"; + var bottommod = step == "before_start" || step == "before_end" || + step == "start_after" || step == "end_after"; + compareEdge(gTrigger, gMenuPopup, step, rightmod ? 8 : -8, bottommod ? 8 : -8, testname); + gMenuPopup.removeAttribute("style"); + } +}, + { + testname: "open popup with large positive margin", + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + steps: ["before_start", "before_end", "after_start", "after_end", + "start_before", "start_after", "end_before", "end_after", "after_pointer", "overlap"], + test: function(testname, step) { + gMenuPopup.setAttribute("style", "margin: 1000px;"); + gMenuPopup.openPopup(gTrigger, step, 0, 0, false, false); + }, + result: function(testname, step) { + var popuprect = gMenuPopup.getBoundingClientRect(); + // as there is more room on the 'end' or 'after' side, popups will always + // appear on the right or bottom corners, depending on which side they are + // allowed to be flipped by. + var expectedleft = step == "before_end" || step == "after_end" ? + 0 : Math.round(window.innerWidth - gPopupWidth); + var expectedtop = step == "start_after" || step == "end_after" ? + 0 : Math.round(window.innerHeight - gPopupHeight); + is(Math.round(popuprect.left), expectedleft, testname + " x position " + step); + is(Math.round(popuprect.top), expectedtop, testname + " y position " + step); + gMenuPopup.removeAttribute("style"); + } +}, +{ + testname: "open popup with large negative margin", + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + steps: ["before_start", "before_end", "after_start", "after_end", + "start_before", "start_after", "end_before", "end_after", "after_pointer", "overlap"], + test: function(testname, step) { + gMenuPopup.setAttribute("style", "margin: -1000px;"); + gMenuPopup.openPopup(gTrigger, step, 0, 0, false, false); + }, + result: function(testname, step) { + var popuprect = gMenuPopup.getBoundingClientRect(); + // using negative margins causes the reverse of positive margins, and + // popups will appear on the left or top corners. + var expectedleft = step == "before_end" || step == "after_end" ? + Math.round(window.innerWidth - gPopupWidth) : 0; + var expectedtop = step == "start_after" || step == "end_after" ? + Math.round(window.innerHeight - gPopupHeight) : 0; + is(Math.round(popuprect.left), expectedleft, testname + " x position " + step); + is(Math.round(popuprect.top), expectedtop, testname + " y position " + step); + gMenuPopup.removeAttribute("style"); + } +}, +{ + testname: "popup with unknown step", + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + test: function() { + gMenuPopup.openPopup(gTrigger, "other", 0, 0, false, false); + }, + result: function (testname) { + var triggerrect = gMenuPopup.getBoundingClientRect(); + var popuprect = gMenuPopup.getBoundingClientRect(); + is(Math.round(popuprect.left), triggerrect.left, testname + " x position "); + is(Math.round(popuprect.top), triggerrect.top, testname + " y position "); + } +}, +{ + // these tests check to ensure that the position attribute can be used + // to set the position of a popup instead of passing it as an argument + testname: "open popup anchored with attribute", + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + steps: ["before_start", "before_end", "after_start", "after_end", + "start_before", "start_after", "end_before", "end_after", "after_pointer", "overlap", + "topcenter topleft", "topright bottomright", "leftcenter topright"], + test: function(testname, step) { + gMenuPopup.setAttribute("position", step); + gMenuPopup.openPopup(gTrigger, "", 0, 0, false, false); + }, + result: function(testname, step) { compareEdge(gTrigger, gMenuPopup, step, 0, 0, testname); } +}, +{ + // this test checks to ensure that the attributes override flag to openPopup + // can be used to override the popup's position. This test also passes an + // event to openPopup to check the trigger node. + testname: "open popup anchored with override", + events: [ "popupshowing thepopup 0010", "popupshown thepopup" ], + test: function(testname, step) { + // attribute overrides the position passed in + gMenuPopup.setAttribute("position", "end_after"); + gExpectedTriggerNode = gCachedEvent.target; + gMenuPopup.openPopup(gTrigger, "before_start", 0, 0, false, true, gCachedEvent); + }, + result: function(testname, step) { + gExpectedTriggerNode = null; + is(gMenuPopup.anchorNode, gTrigger, testname + " anchorNode"); + is(gMenuPopup.triggerNode, gCachedEvent.target, testname + " triggerNode"); + is(document.popupNode, gCachedEvent.target, testname + " document.popupNode"); + compareEdge(gTrigger, gMenuPopup, "end_after", 0, 0, testname); + } +}, +{ + testname: "close popup with escape", + events: [ "popuphiding thepopup", "popuphidden thepopup", + "DOMMenuInactive thepopup", ], + test: function(testname, step) { + synthesizeKey("VK_ESCAPE", { }); + checkClosed("trigger", testname); + } +}, +{ + // check that offsets may be supplied to the openPopup method + testname: "open popup anchored with offsets", + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + test: function(testname, step) { + // attribute is empty so does not override + gMenuPopup.setAttribute("position", ""); + gMenuPopup.openPopup(gTrigger, "before_start", 5, 10, true, true); + }, + result: function(testname, step) { compareEdge(gTrigger, gMenuPopup, "before_start", 5, 10, testname); } +}, +{ + // these tests check to ensure that passing an anchor and position + // puts the popup in the right place + testname: "show popup anchored", + condition: function() { + // only perform this test for popups not in a menu, such as those using + // the popup attribute, as the showPopup implementation in popup.xml + // calls openMenu if the popup is inside a menu + return !gIsMenu; + }, + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + steps: [["topleft", "topleft"], + ["topleft", "topright"], ["topleft", "bottomleft"], + ["topright", "topleft"], ["topright", "bottomright"], + ["bottomleft", "bottomright"], ["bottomleft", "topleft"], + ["bottomright", "bottomleft"], ["bottomright", "topright"]], + test: function(testname, step) { + // the attributes should be ignored + gMenuPopup.setAttribute("popupanchor", "topright"); + gMenuPopup.setAttribute("popupalign", "bottomright"); + gMenuPopup.setAttribute("position", "end_after"); + gMenuPopup.showPopup(gTrigger, -1, -1, "popup", step[0], step[1]); + }, + result: function(testname, step) { + var pos = convertPosition(step[0], step[1]); + compareEdge(gTrigger, gMenuPopup, pos, 0, 0, testname); + gMenuPopup.removeAttribute("popupanchor"); + gMenuPopup.removeAttribute("popupalign"); + gMenuPopup.removeAttribute("position"); + } +}, +{ + testname: "show popup with position", + condition: function() { return !gIsMenu; }, + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + test: function(testname, step) { + gMenuPopup.showPopup(gTrigger, gScreenX + 60, gScreenY + 15, + "context", "topleft", "bottomright"); + }, + result: function(testname, step) { + var rect = gMenuPopup.getBoundingClientRect(); + ok(true, gScreenX + "," + gScreenY); + is(rect.left, 60, testname + " left"); + is(rect.top, 15, testname + " top"); + ok(rect.right, testname + " right is " + rect.right); + ok(rect.bottom, testname + " bottom is " + rect.bottom); + } +}, +{ + // if no anchor is supplied to openPopup, it should be opened relative + // to the viewport. + testname: "open popup unanchored", + events: [ "popupshowing thepopup", "popupshown thepopup" ], + test: function(testname, step) { gMenuPopup.openPopup(null, "after_start", 6, 8, false); }, + result: function(testname, step) { + var rect = gMenuPopup.getBoundingClientRect(); + ok(rect.left == 6 && rect.top == 8 && rect.right && rect.bottom, testname); + } +}, +{ + testname: "activate menuitem with mouse", + events: [ "DOMMenuInactive thepopup", "command item3", + "popuphiding thepopup", "popuphidden thepopup", + "DOMMenuItemInactive item3" ], + test: function(testname, step) { + var item3 = document.getElementById("item3"); + synthesizeMouse(item3, 4, 4, { }); + }, + result: function(testname, step) { checkClosed("trigger", testname); } +}, +{ + testname: "close popup", + condition: function() { return false; }, + events: [ "popuphiding thepopup", "popuphidden thepopup", + "DOMMenuInactive thepopup" ], + test: function(testname, step) { gMenuPopup.hidePopup(); } +}, +{ + testname: "open popup at screen", + events: [ "popupshowing thepopup", "popupshown thepopup" ], + test: function(testname, step) { + gExpectedTriggerNode = "notset"; + gMenuPopup.openPopupAtScreen(gScreenX + 24, gScreenY + 20, false); + }, + result: function(testname, step) { + gExpectedTriggerNode = null; + is(gMenuPopup.anchorNode, null, testname + " anchorNode"); + is(gMenuPopup.triggerNode, null, testname + " triggerNode"); + is(document.popupNode, null, testname + " document.popupNode"); + var rect = gMenuPopup.getBoundingClientRect(); + is(rect.left, 24, testname + " left"); + is(rect.top, 20, testname + " top"); + ok(rect.right, testname + " right is " + rect.right); + ok(rect.bottom, testname + " bottom is " + rect.bottom); + } +}, +{ + // check that pressing a menuitem's accelerator selects it. Note that + // the menuitem with the M accesskey overrides the earlier menuitem that + // begins with M. + testname: "menuitem accelerator", + events: [ "DOMMenuItemActive amenu", "DOMMenuItemInactive amenu", + "DOMMenuInactive thepopup", + "command amenu", "popuphiding thepopup", "popuphidden thepopup", + "DOMMenuItemInactive amenu" + ], + test: function() { synthesizeKey("M", { }); }, + result: function(testname) { checkClosed("trigger", testname); } +}, +{ + testname: "open context popup at screen", + events: [ "popupshowing thepopup 0010", "popupshown thepopup" ], + test: function(testname, step) { + gExpectedTriggerNode = gCachedEvent.target; + gMenuPopup.openPopupAtScreen(gScreenX + 8, gScreenY + 16, true, gCachedEvent); + }, + result: function(testname, step) { + gExpectedTriggerNode = null; + is(gMenuPopup.anchorNode, null, testname + " anchorNode"); + is(gMenuPopup.triggerNode, gCachedEvent.target, testname + " triggerNode"); + is(document.popupNode, gCachedEvent.target, testname + " document.popupNode"); + + var childframe = document.getElementById("childframe"); + if (childframe) { + for (var t = 0; t < 2; t++) { + var child = childframe.contentDocument; + var evt = child.createEvent("Event"); + evt.initEvent("click", true, true); + child.documentElement.dispatchEvent(evt); + is(child.documentElement.getAttribute("data"), "xnull", + "cannot get popupNode from other document"); + child.documentElement.setAttribute("data", "none"); + // now try again with document.popupNode set explicitly + document.popupNode = gCachedEvent.target; + } + } + + var openX = 8; + var openY = 16; + var rect = gMenuPopup.getBoundingClientRect(); + is(rect.left, openX + (platformIsMac() ? 1 : 2), testname + " left"); + is(rect.top, openY + (platformIsMac() ? -6 : 2), testname + " top"); + ok(rect.right, testname + " right is " + rect.right); + ok(rect.bottom, testname + " bottom is " + rect.bottom); + } +}, +{ + // pressing a letter that doesn't correspond to an accelerator, but does + // correspond to the first letter in a menu's label. The menu should not + // close because there is more than one item corresponding to that letter + testname: "menuitem with non accelerator", + events: [ "DOMMenuItemActive one" ], + test: function() { synthesizeKey("O", { }); }, + result: function(testname) { + checkOpen("trigger", testname); + checkActive(gMenuPopup, "one", testname); + } +}, +{ + // pressing the letter again should select the next one that starts with + // that letter + testname: "menuitem with non accelerator again", + events: [ "DOMMenuItemInactive one", "DOMMenuItemActive submenu" ], + test: function() { synthesizeKey("O", { }); }, + result: function(testname) { + // 'submenu' is a menu but it should not be open + checkOpen("trigger", testname); + checkClosed("submenu", testname); + checkActive(gMenuPopup, "submenu", testname); + } +}, +{ + // open the submenu with the cursor right key + testname: "open submenu with cursor right", + events: [ "popupshowing submenupopup", "DOMMenuItemActive submenuitem", + "popupshown submenupopup" ], + test: function() { synthesizeKey("VK_RIGHT", { }); }, + result: function(testname) { + checkOpen("trigger", testname); + checkOpen("submenu", testname); + checkActive(gMenuPopup, "submenu", testname); + checkActive(document.getElementById("submenupopup"), "submenuitem", testname); + } +}, +{ + // close the submenu with the cursor left key + testname: "close submenu with cursor left", + events: [ "popuphiding submenupopup", "popuphidden submenupopup", + "DOMMenuItemInactive submenuitem", "DOMMenuInactive submenupopup", + "DOMMenuItemActive submenu" ], + test: function() { synthesizeKey("VK_LEFT", { }); }, + result: function(testname) { + checkOpen("trigger", testname); + checkClosed("submenu", testname); + checkActive(gMenuPopup, "submenu", testname); + checkActive(document.getElementById("submenupopup"), "", testname); + } +}, +{ + // open the submenu with the enter key + testname: "open submenu with enter", + events: [ "popupshowing submenupopup", "DOMMenuItemActive submenuitem", + "popupshown submenupopup" ], + test: function() { synthesizeKey("VK_RETURN", { }); }, + result: function(testname) { + checkOpen("trigger", testname); + checkOpen("submenu", testname); + checkActive(gMenuPopup, "submenu", testname); + checkActive(document.getElementById("submenupopup"), "submenuitem", testname); + } +}, +{ + // close the submenu with the escape key + testname: "close submenu with escape", + events: [ "popuphiding submenupopup", "popuphidden submenupopup", + "DOMMenuItemInactive submenuitem", "DOMMenuInactive submenupopup", + "DOMMenuItemActive submenu" ], + test: function() { synthesizeKey("VK_ESCAPE", { }); }, + result: function(testname) { + checkOpen("trigger", testname); + checkClosed("submenu", testname); + checkActive(gMenuPopup, "submenu", testname); + checkActive(document.getElementById("submenupopup"), "", testname); + } +}, +{ + // pressing the letter again when the next item is disabled should still + // select the disabled item on Windows, but select the next item on other + // platforms + testname: "menuitem with non accelerator disabled", + events: function() { + if (navigator.platform.indexOf("Win") == 0) { + return [ "DOMMenuItemInactive submenu", "DOMMenuItemActive other", + "DOMMenuItemInactive other", "DOMMenuItemActive item1" ]; + } + return [ "DOMMenuItemInactive submenu", "DOMMenuItemActive last", + "DOMMenuItemInactive last", "DOMMenuItemActive item1" ]; + }, + test: function() { synthesizeKey("O", { }); synthesizeKey("F", { }); }, + result: function(testname) { + checkActive(gMenuPopup, "item1", testname); + } +}, +{ + // pressing a letter that doesn't correspond to an accelerator nor the + // first letter of a menu. This should have no effect. + testname: "menuitem with keypress no accelerator found", + test: function() { synthesizeKey("G", { }); }, + result: function(testname) { + checkOpen("trigger", testname); + checkActive(gMenuPopup, "item1", testname); + } +}, +{ + // when only one menuitem starting with that letter exists, it should be + // selected and the menu closed + testname: "menuitem with non accelerator single", + events: [ "DOMMenuItemInactive item1", "DOMMenuItemActive amenu", + "DOMMenuItemInactive amenu", "DOMMenuInactive thepopup", + "command amenu", "popuphiding thepopup", "popuphidden thepopup", + "DOMMenuItemInactive amenu", + ], + test: function() { synthesizeKey("M", { }); }, + result: function(testname) { + checkClosed("trigger", testname); + checkActive(gMenuPopup, "", testname); + } +}, +{ + testname: "open context popup at screen with all modifiers set", + events: [ "popupshowing thepopup 1111", "popupshown thepopup" ], + autohide: "thepopup", + test: function(testname, step) { + gMenuPopup.openPopupAtScreen(gScreenX + 8, gScreenY + 16, true, gCachedEvent2); + } +}, +{ + testname: "open popup with open property", + events: [ "popupshowing thepopup", "popupshown thepopup" ], + test: function(testname, step) { openMenu(gTrigger); }, + result: function(testname, step) { + checkOpen("trigger", testname); + if (gIsMenu) + compareEdge(gTrigger, gMenuPopup, "after_start", 0, 0, testname); + } +}, +{ + testname: "open submenu with open property", + events: [ "popupshowing submenupopup", "DOMMenuItemActive submenu", + "popupshown submenupopup" ], + test: function(testname, step) { openMenu(document.getElementById("submenu")); }, + result: function(testname, step) { + checkOpen("trigger", testname); + checkOpen("submenu", testname); + // XXXndeakin + // getBoundingClientRect doesn't seem to working right for submenus + // so disable this test for now + // compareEdge(document.getElementById("submenu"), + // document.getElementById("submenupopup"), "end_before", 0, 0, testname); + } +}, +{ + testname: "hidePopup hides entire chain", + events: [ "popuphiding submenupopup", "popuphidden submenupopup", + "popuphiding thepopup", "popuphidden thepopup", + "DOMMenuInactive submenupopup", + "DOMMenuItemInactive submenu", "DOMMenuItemInactive submenu", + "DOMMenuInactive thepopup", ], + test: function() { gMenuPopup.hidePopup(); }, + result: function(testname, step) { + checkClosed("trigger", testname); + checkClosed("submenu", testname); + } +}, +{ + testname: "open submenu with open property without parent open", + test: function(testname, step) { openMenu(document.getElementById("submenu")); }, + result: function(testname, step) { + checkClosed("trigger", testname); + checkClosed("submenu", testname); + } +}, +{ + testname: "open popup with open property and position", + condition: function() { return gIsMenu; }, + events: [ "popupshowing thepopup", "popupshown thepopup" ], + test: function(testname, step) { + gMenuPopup.setAttribute("position", "before_start"); + openMenu(gTrigger); + }, + result: function(testname, step) { + compareEdge(gTrigger, gMenuPopup, "before_start", 0, 0, testname); + } +}, +{ + testname: "close popup with open property", + condition: function() { return gIsMenu; }, + events: [ "popuphiding thepopup", "popuphidden thepopup", + "DOMMenuInactive thepopup" ], + test: function(testname, step) { closeMenu(gTrigger, gMenuPopup); }, + result: function(testname, step) { checkClosed("trigger", testname); } +}, +{ + testname: "open popup with open property, position, anchor and alignment", + condition: function() { return gIsMenu; }, + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + test: function(testname, step) { + gMenuPopup.setAttribute("position", "start_after"); + gMenuPopup.setAttribute("popupanchor", "topright"); + gMenuPopup.setAttribute("popupalign", "bottomright"); + openMenu(gTrigger); + }, + result: function(testname, step) { + compareEdge(gTrigger, gMenuPopup, "start_after", 0, 0, testname); + } +}, +{ + testname: "open popup with open property, anchor and alignment", + condition: function() { return gIsMenu; }, + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + test: function(testname, step) { + gMenuPopup.removeAttribute("position"); + gMenuPopup.setAttribute("popupanchor", "bottomright"); + gMenuPopup.setAttribute("popupalign", "topright"); + openMenu(gTrigger); + }, + result: function(testname, step) { + compareEdge(gTrigger, gMenuPopup, "after_end", 0, 0, testname); + gMenuPopup.removeAttribute("popupanchor"); + gMenuPopup.removeAttribute("popupalign"); + } +}, +{ + testname: "focus and cursor down on trigger", + condition: function() { return gIsMenu; }, + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + test: function(testname, step) { + gTrigger.focus(); + synthesizeKey("VK_DOWN", { altKey: !platformIsMac() }); + }, + result: function(testname, step) { + checkOpen("trigger", testname); + checkActive(gMenuPopup, "", testname); + } +}, +{ + testname: "focus and cursor up on trigger", + condition: function() { return gIsMenu; }, + events: [ "popupshowing thepopup", "popupshown thepopup" ], + test: function(testname, step) { + gTrigger.focus(); + synthesizeKey("VK_UP", { altKey: !platformIsMac() }); + }, + result: function(testname, step) { + checkOpen("trigger", testname); + checkActive(gMenuPopup, "", testname); + } +}, +{ + testname: "select and enter on menuitem", + condition: function() { return gIsMenu; }, + events: [ "DOMMenuItemActive item1", "DOMMenuItemInactive item1", + "DOMMenuInactive thepopup", "command item1", + "popuphiding thepopup", "popuphidden thepopup", + "DOMMenuItemInactive item1" ], + test: function(testname, step) { + synthesizeKey("VK_DOWN", { }); + synthesizeKey("VK_RETURN", { }); + }, + result: function(testname, step) { checkClosed("trigger", testname); } +}, +{ + testname: "focus trigger and key to open", + condition: function() { return gIsMenu; }, + events: [ "popupshowing thepopup", "popupshown thepopup" ], + autohide: "thepopup", + test: function(testname, step) { + gTrigger.focus(); + synthesizeKey(platformIsMac() ? " " : "VK_F4", { }); + }, + result: function(testname, step) { + checkOpen("trigger", testname); + checkActive(gMenuPopup, "", testname); + } +}, +{ + // the menu should only open when the meta or alt key is not pressed + testname: "focus trigger and key wrong modifier", + condition: function() { return gIsMenu; }, + test: function(testname, step) { + gTrigger.focus(); + if (platformIsMac()) + synthesizeKey("VK_F4", { altKey: true }); + else + synthesizeKey("", { metaKey: true }); + }, + result: function(testname, step) { + checkClosed("trigger", testname); + } +}, +{ + testname: "mouse click on disabled menu", + condition: function() { return gIsMenu; }, + test: function(testname, step) { + gTrigger.setAttribute("disabled", "true"); + synthesizeMouse(gTrigger, 4, 4, { }); + }, + result: function(testname, step) { + checkClosed("trigger", testname); + gTrigger.removeAttribute("disabled"); + } +}, +{ + // openPopup should open the menu synchronously, however popupshown + // is fired asynchronously + testname: "openPopup synchronous", + events: [ "popupshowing thepopup", "popupshowing submenupopup", + "popupshown thepopup", "DOMMenuItemActive submenu", + "popupshown submenupopup" ], + test: function(testname, step) { + gMenuPopup.openPopup(gTrigger, "after_start", 0, 0, false, true); + document.getElementById("submenupopup"). + openPopup(gTrigger, "end_before", 0, 0, false, true); + checkOpen("trigger", testname); + checkOpen("submenu", testname); + } +}, +{ + // remove the content nodes for the popup + testname: "remove content", + test: function(testname, step) { + var submenupopup = document.getElementById("submenupopup"); + submenupopup.parentNode.removeChild(submenupopup); + var popup = document.getElementById("thepopup"); + popup.parentNode.removeChild(popup); + } +} + +]; + +function platformIsMac() +{ + return navigator.platform.indexOf("Mac") > -1; +} diff --git a/toolkit/content/tests/chrome/rtlchrome/rtl.css b/toolkit/content/tests/chrome/rtlchrome/rtl.css new file mode 100644 index 000000000..0fea01001 --- /dev/null +++ b/toolkit/content/tests/chrome/rtlchrome/rtl.css @@ -0,0 +1,2 @@ +/* Imitate RTL UI */ +window { direction: rtl; } diff --git a/toolkit/content/tests/chrome/rtlchrome/rtl.dtd b/toolkit/content/tests/chrome/rtlchrome/rtl.dtd new file mode 100644 index 000000000..8b32de674 --- /dev/null +++ b/toolkit/content/tests/chrome/rtlchrome/rtl.dtd @@ -0,0 +1 @@ + diff --git a/toolkit/content/tests/chrome/rtlchrome/rtl.manifest b/toolkit/content/tests/chrome/rtlchrome/rtl.manifest new file mode 100644 index 000000000..a4cc6929b --- /dev/null +++ b/toolkit/content/tests/chrome/rtlchrome/rtl.manifest @@ -0,0 +1,5 @@ +content rtlchrome / + +# Override intl.css with our own CSS file +override chrome://global/locale/intl.css chrome://rtlchrome/rtl.css +override chrome://global/locale/global.dtd chrome://rtlchrome/rtl.dtd diff --git a/toolkit/content/tests/chrome/rtltest/content/dirtest.xul b/toolkit/content/tests/chrome/rtltest/content/dirtest.xul new file mode 100644 index 000000000..b75d41eaa --- /dev/null +++ b/toolkit/content/tests/chrome/rtltest/content/dirtest.xul @@ -0,0 +1,25 @@ + + + + + + + +hbox, vbox { background-color: white; } +hbox:-moz-locale-dir(ltr) { background-color: yellow; } +vbox:-moz-locale-dir(rtl) { background-color: green; } + + + + + + + + +

+

+ +
+
+ + +
diff --git a/toolkit/content/tests/chrome/test_colorpicker_popup.xul b/toolkit/content/tests/chrome/test_colorpicker_popup.xul new file mode 100644 index 000000000..3ac84260b --- /dev/null +++ b/toolkit/content/tests/chrome/test_colorpicker_popup.xul @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + +

+

+ +
+
+ + +
diff --git a/toolkit/content/tests/chrome/test_contextmenu_list.xul b/toolkit/content/tests/chrome/test_contextmenu_list.xul new file mode 100644 index 000000000..157831a58 --- /dev/null +++ b/toolkit/content/tests/chrome/test_contextmenu_list.xul @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + +

+

+ +
+
+ + +
diff --git a/toolkit/content/tests/chrome/test_menuitem_blink.xul b/toolkit/content/tests/chrome/test_menuitem_blink.xul new file mode 100644 index 000000000..319c284fd --- /dev/null +++ b/toolkit/content/tests/chrome/test_menuitem_blink.xul @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + +

+

+ +
+
+ + +
diff --git a/toolkit/content/tests/chrome/test_menuitem_commands.xul b/toolkit/content/tests/chrome/test_menuitem_commands.xul new file mode 100644 index 000000000..e31774ccc --- /dev/null +++ b/toolkit/content/tests/chrome/test_menuitem_commands.xul @@ -0,0 +1,104 @@ + + + + + + + + + diff --git a/toolkit/content/tests/chrome/test_popup_anchor.xul b/toolkit/content/tests/chrome/test_popup_anchor.xul new file mode 100644 index 000000000..5839c52a3 --- /dev/null +++ b/toolkit/content/tests/chrome/test_popup_anchor.xul @@ -0,0 +1,30 @@ + + + + + + + + + +

+

+ +
+
+ + +
diff --git a/toolkit/content/tests/chrome/test_popup_anchoratrect.xul b/toolkit/content/tests/chrome/test_popup_anchoratrect.xul new file mode 100644 index 000000000..c12e22502 --- /dev/null +++ b/toolkit/content/tests/chrome/test_popup_anchoratrect.xul @@ -0,0 +1,28 @@ + + + + + + + + + + + +

+

+ +
+
+ + +
diff --git a/toolkit/content/tests/chrome/test_popup_attribute.xul b/toolkit/content/tests/chrome/test_popup_attribute.xul new file mode 100644 index 000000000..2a256078d --- /dev/null +++ b/toolkit/content/tests/chrome/test_popup_attribute.xul @@ -0,0 +1,28 @@ + + + + + + + + + + + +

+

+ +
+
+ + +
diff --git a/toolkit/content/tests/chrome/test_popup_button.xul b/toolkit/content/tests/chrome/test_popup_button.xul new file mode 100644 index 000000000..3803e465f --- /dev/null +++ b/toolkit/content/tests/chrome/test_popup_button.xul @@ -0,0 +1,28 @@ + + + + + + + + + + + +

+

+ +
+
+ + +
diff --git a/toolkit/content/tests/chrome/test_popup_coords.xul b/toolkit/content/tests/chrome/test_popup_coords.xul new file mode 100644 index 000000000..4597b5cc0 --- /dev/null +++ b/toolkit/content/tests/chrome/test_popup_coords.xul @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + +

+

+ +
+
+ + +
diff --git a/toolkit/content/tests/chrome/test_popup_preventdefault_chrome.xul b/toolkit/content/tests/chrome/test_popup_preventdefault_chrome.xul new file mode 100644 index 000000000..46f14cd6a --- /dev/null +++ b/toolkit/content/tests/chrome/test_popup_preventdefault_chrome.xul @@ -0,0 +1,29 @@ + + + + + + + + + +

+

+ +
+
+ + +
diff --git a/toolkit/content/tests/chrome/test_popup_recreate.xul b/toolkit/content/tests/chrome/test_popup_recreate.xul new file mode 100644 index 000000000..14822acbd --- /dev/null +++ b/toolkit/content/tests/chrome/test_popup_recreate.xul @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + +

+

+ +
+
+ + +
diff --git a/toolkit/content/tests/chrome/test_popup_scaled.xul b/toolkit/content/tests/chrome/test_popup_scaled.xul new file mode 100644 index 000000000..6bbf6c653 --- /dev/null +++ b/toolkit/content/tests/chrome/test_popup_scaled.xul @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + diff --git a/toolkit/content/tests/chrome/window_titlebar.xul b/toolkit/content/tests/chrome/window_titlebar.xul new file mode 100644 index 000000000..e27782153 --- /dev/null +++ b/toolkit/content/tests/chrome/window_titlebar.xul @@ -0,0 +1,223 @@ + + + + + + + + diff --git a/toolkit/content/tests/chrome/window_tooltip.xul b/toolkit/content/tests/chrome/window_tooltip.xul new file mode 100644 index 000000000..087c91c3e --- /dev/null +++ b/toolkit/content/tests/chrome/window_tooltip.xul @@ -0,0 +1,311 @@ + + + + + + + + + + + + + + +