From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- docshell/test/browser/Bug1622420Child.sys.mjs | 9 + docshell/test/browser/Bug422543Child.sys.mjs | 98 ++++++ docshell/test/browser/browser.ini | 237 +++++++++++++ .../browser_alternate_fixup_middle_click_link.js | 59 ++++ .../browser/browser_backforward_restore_scroll.js | 54 +++ .../browser/browser_backforward_userinteraction.js | 374 +++++++++++++++++++++ .../browser_backforward_userinteraction_about.js | 67 ++++ ..._backforward_userinteraction_systemprincipal.js | 112 ++++++ .../test/browser/browser_badCertDomainFixup.js | 92 +++++ .../test/browser/browser_bfcache_copycommand.js | 98 ++++++ .../test/browser/browser_browsingContext-01.js | 180 ++++++++++ .../test/browser/browser_browsingContext-02.js | 235 +++++++++++++ .../browser/browser_browsingContext-embedder.js | 156 +++++++++ ...wsingContext-getAllBrowsingContextsInSubtree.js | 53 +++ .../browser_browsingContext-getWindowByName.js | 34 ++ .../browser/browser_browsingContext-webProgress.js | 226 +++++++++++++ .../browser/browser_browsing_context_attached.js | 179 ++++++++++ .../browser/browser_browsing_context_discarded.js | 65 ++++ docshell/test/browser/browser_bug1206879.js | 50 +++ ...ser_bug1309900_crossProcessHistoryNavigation.js | 54 +++ docshell/test/browser/browser_bug1328501.js | 69 ++++ docshell/test/browser/browser_bug1347823.js | 91 +++++ docshell/test/browser/browser_bug134911.js | 57 ++++ .../browser_bug1415918_beforeunload_options.js | 162 +++++++++ docshell/test/browser/browser_bug1543077-3.js | 46 +++ docshell/test/browser/browser_bug1594938.js | 100 ++++++ docshell/test/browser/browser_bug1622420.js | 31 ++ docshell/test/browser/browser_bug1648464-1.js | 46 +++ docshell/test/browser/browser_bug1673702.js | 27 ++ docshell/test/browser/browser_bug1674464.js | 38 +++ docshell/test/browser/browser_bug1688368-1.js | 24 ++ docshell/test/browser/browser_bug1691153.js | 73 ++++ docshell/test/browser/browser_bug1705872.js | 74 ++++ docshell/test/browser/browser_bug1716290-1.js | 24 ++ docshell/test/browser/browser_bug1716290-2.js | 24 ++ docshell/test/browser/browser_bug1716290-3.js | 24 ++ docshell/test/browser/browser_bug1716290-4.js | 24 ++ docshell/test/browser/browser_bug1719178.js | 34 ++ docshell/test/browser/browser_bug1736248-1.js | 34 ++ docshell/test/browser/browser_bug1757005.js | 73 ++++ docshell/test/browser/browser_bug1769189.js | 32 ++ docshell/test/browser/browser_bug1798780.js | 52 +++ docshell/test/browser/browser_bug234628-1.js | 47 +++ docshell/test/browser/browser_bug234628-10.js | 46 +++ docshell/test/browser/browser_bug234628-11.js | 46 +++ docshell/test/browser/browser_bug234628-2.js | 49 +++ docshell/test/browser/browser_bug234628-3.js | 47 +++ docshell/test/browser/browser_bug234628-4.js | 46 +++ docshell/test/browser/browser_bug234628-5.js | 46 +++ docshell/test/browser/browser_bug234628-6.js | 47 +++ docshell/test/browser/browser_bug234628-8.js | 18 + docshell/test/browser/browser_bug234628-9.js | 18 + docshell/test/browser/browser_bug349769.js | 79 +++++ docshell/test/browser/browser_bug388121-1.js | 22 ++ docshell/test/browser/browser_bug388121-2.js | 74 ++++ docshell/test/browser/browser_bug420605.js | 131 ++++++++ docshell/test/browser/browser_bug422543.js | 253 ++++++++++++++ docshell/test/browser/browser_bug441169.js | 44 +++ docshell/test/browser/browser_bug503832.js | 76 +++++ docshell/test/browser/browser_bug554155.js | 33 ++ docshell/test/browser/browser_bug655270.js | 62 ++++ docshell/test/browser/browser_bug655273.js | 56 +++ docshell/test/browser/browser_bug670318.js | 146 ++++++++ docshell/test/browser/browser_bug673087-1.js | 46 +++ docshell/test/browser/browser_bug673087-2.js | 36 ++ docshell/test/browser/browser_bug673467.js | 62 ++++ docshell/test/browser/browser_bug852909.js | 35 ++ docshell/test/browser/browser_bug92473.js | 70 ++++ .../browser_click_link_within_view_source.js | 78 +++++ .../browser_cross_process_csp_inheritance.js | 125 +++++++ .../browser_csp_sandbox_no_script_js_uri.js | 55 +++ docshell/test/browser/browser_csp_uir.js | 89 +++++ .../browser_dataURI_unique_opaque_origin.js | 30 ++ .../test/browser/browser_data_load_inherit_csp.js | 110 ++++++ .../test/browser/browser_fall_back_to_https.js | 73 ++++ .../browser_frameloader_swap_with_bfcache.js | 37 ++ ...owser_history_triggeringprincipal_viewsource.js | 88 +++++ docshell/test/browser/browser_isInitialDocument.js | 319 ++++++++++++++++++ docshell/test/browser/browser_loadURI_postdata.js | 42 +++ .../test/browser/browser_multiple_pushState.js | 25 ++ .../test/browser/browser_onbeforeunload_frame.js | 45 +++ .../browser/browser_onbeforeunload_navigation.js | 165 +++++++++ .../test/browser/browser_onbeforeunload_parent.js | 48 +++ docshell/test/browser/browser_onunload_stop.js | 23 ++ docshell/test/browser/browser_overlink.js | 27 ++ .../test/browser/browser_platform_emulation.js | 70 ++++ .../test/browser/browser_search_notification.js | 49 +++ .../browser/browser_tab_replace_while_loading.js | 83 +++++ docshell/test/browser/browser_tab_touch_events.js | 75 +++++ .../browser_targetTopLevelLinkClicksToBlank.js | 285 ++++++++++++++++ .../test/browser/browser_timelineMarkers-01.js | 46 +++ .../test/browser/browser_timelineMarkers-02.js | 16 + .../browser/browser_timelineMarkers-frame-02.js | 185 ++++++++++ .../browser/browser_title_in_session_history.js | 63 ++++ docshell/test/browser/browser_ua_emulation.js | 71 ++++ .../browser/browser_uriFixupAlternateRedirects.js | 66 ++++ .../test/browser/browser_uriFixupIntegration.js | 104 ++++++ .../browser_viewsource_chrome_to_content.js | 20 ++ .../test/browser/browser_viewsource_multipart.js | 44 +++ docshell/test/browser/dummy_iframe_page.html | 8 + docshell/test/browser/dummy_page.html | 6 + docshell/test/browser/favicon_bug655270.ico | Bin 0 -> 1406 bytes .../browser/file_backforward_restore_scroll.html | 10 + .../file_backforward_restore_scroll.html^headers^ | 1 + docshell/test/browser/file_basic_multipart.sjs | 24 ++ docshell/test/browser/file_bug1046022.html | 54 +++ docshell/test/browser/file_bug1206879.html | 9 + docshell/test/browser/file_bug1328501.html | 27 ++ docshell/test/browser/file_bug1328501_frame.html | 4 + .../test/browser/file_bug1328501_framescript.js | 38 +++ docshell/test/browser/file_bug1543077-3-child.html | 11 + docshell/test/browser/file_bug1543077-3.html | 16 + docshell/test/browser/file_bug1622420.html | 1 + docshell/test/browser/file_bug1648464-1-child.html | 13 + docshell/test/browser/file_bug1648464-1.html | 18 + docshell/test/browser/file_bug1673702.json | 1 + .../test/browser/file_bug1673702.json^headers^ | 1 + docshell/test/browser/file_bug1688368-1.sjs | 44 +++ docshell/test/browser/file_bug1691153.html | 27 ++ docshell/test/browser/file_bug1716290-1.sjs | 21 ++ docshell/test/browser/file_bug1716290-2.sjs | 18 + docshell/test/browser/file_bug1716290-3.sjs | 17 + docshell/test/browser/file_bug1716290-4.sjs | 17 + docshell/test/browser/file_bug1736248-1.html | 4 + docshell/test/browser/file_bug234628-1-child.html | 12 + docshell/test/browser/file_bug234628-1.html | 17 + .../test/browser/file_bug234628-10-child.xhtml | 4 + docshell/test/browser/file_bug234628-10.html | 17 + .../test/browser/file_bug234628-11-child.xhtml | 4 + .../browser/file_bug234628-11-child.xhtml^headers^ | 1 + docshell/test/browser/file_bug234628-11.html | 17 + docshell/test/browser/file_bug234628-2-child.html | 12 + docshell/test/browser/file_bug234628-2.html | 17 + docshell/test/browser/file_bug234628-3-child.html | 13 + docshell/test/browser/file_bug234628-3.html | 18 + docshell/test/browser/file_bug234628-4-child.html | 12 + docshell/test/browser/file_bug234628-4.html | 18 + docshell/test/browser/file_bug234628-5-child.html | Bin 0 -> 498 bytes docshell/test/browser/file_bug234628-5.html | 18 + docshell/test/browser/file_bug234628-6-child.html | Bin 0 -> 540 bytes .../browser/file_bug234628-6-child.html^headers^ | 1 + docshell/test/browser/file_bug234628-6.html | 18 + docshell/test/browser/file_bug234628-8-child.html | 12 + docshell/test/browser/file_bug234628-8.html | 17 + docshell/test/browser/file_bug234628-9-child.html | 12 + docshell/test/browser/file_bug234628-9.html | Bin 0 -> 740 bytes docshell/test/browser/file_bug420605.html | 31 ++ docshell/test/browser/file_bug503832.html | 35 ++ docshell/test/browser/file_bug655270.html | 11 + docshell/test/browser/file_bug670318.html | 23 ++ docshell/test/browser/file_bug673087-1-child.html | 13 + docshell/test/browser/file_bug673087-1.html | Bin 0 -> 432 bytes .../test/browser/file_bug673087-1.html^headers^ | 1 + docshell/test/browser/file_bug673087-2.html | 2 + docshell/test/browser/file_bug852909.pdf | Bin 0 -> 1568 bytes docshell/test/browser/file_bug852909.png | Bin 0 -> 94 bytes .../file_click_link_within_view_source.html | 6 + .../file_cross_process_csp_inheritance.html | 11 + .../browser/file_csp_sandbox_no_script_js_uri.html | 11 + ...file_csp_sandbox_no_script_js_uri.html^headers^ | 1 + docshell/test/browser/file_csp_uir.html | 11 + docshell/test/browser/file_csp_uir_dummy.html | 1 + .../test/browser/file_data_load_inherit_csp.html | 11 + docshell/test/browser/file_multiple_pushState.html | 20 ++ docshell/test/browser/file_onbeforeunload_0.html | 9 + docshell/test/browser/file_onbeforeunload_1.html | 9 + docshell/test/browser/file_onbeforeunload_2.html | 10 + docshell/test/browser/file_onbeforeunload_3.html | 9 + docshell/test/browser/file_open_about_blank.html | 2 + docshell/test/browser/file_slow_load.sjs | 8 + docshell/test/browser/frame-head.js | 114 +++++++ docshell/test/browser/head.js | 258 ++++++++++++++ .../test/browser/head_browser_onbeforeunload.js | 271 +++++++++++++++ docshell/test/browser/onload_message.html | 25 ++ docshell/test/browser/onpageshow_message.html | 41 +++ docshell/test/browser/overlink_test.html | 7 + docshell/test/browser/print_postdata.sjs | 25 ++ docshell/test/browser/redirect_to_example.sjs | 5 + docshell/test/browser/test-form_sjis.html | 24 ++ 179 files changed, 9417 insertions(+) create mode 100644 docshell/test/browser/Bug1622420Child.sys.mjs create mode 100644 docshell/test/browser/Bug422543Child.sys.mjs create mode 100644 docshell/test/browser/browser.ini create mode 100644 docshell/test/browser/browser_alternate_fixup_middle_click_link.js create mode 100644 docshell/test/browser/browser_backforward_restore_scroll.js create mode 100644 docshell/test/browser/browser_backforward_userinteraction.js create mode 100644 docshell/test/browser/browser_backforward_userinteraction_about.js create mode 100644 docshell/test/browser/browser_backforward_userinteraction_systemprincipal.js create mode 100644 docshell/test/browser/browser_badCertDomainFixup.js create mode 100644 docshell/test/browser/browser_bfcache_copycommand.js create mode 100644 docshell/test/browser/browser_browsingContext-01.js create mode 100644 docshell/test/browser/browser_browsingContext-02.js create mode 100644 docshell/test/browser/browser_browsingContext-embedder.js create mode 100644 docshell/test/browser/browser_browsingContext-getAllBrowsingContextsInSubtree.js create mode 100644 docshell/test/browser/browser_browsingContext-getWindowByName.js create mode 100644 docshell/test/browser/browser_browsingContext-webProgress.js create mode 100644 docshell/test/browser/browser_browsing_context_attached.js create mode 100644 docshell/test/browser/browser_browsing_context_discarded.js create mode 100644 docshell/test/browser/browser_bug1206879.js create mode 100644 docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js create mode 100644 docshell/test/browser/browser_bug1328501.js create mode 100644 docshell/test/browser/browser_bug1347823.js create mode 100644 docshell/test/browser/browser_bug134911.js create mode 100644 docshell/test/browser/browser_bug1415918_beforeunload_options.js create mode 100644 docshell/test/browser/browser_bug1543077-3.js create mode 100644 docshell/test/browser/browser_bug1594938.js create mode 100644 docshell/test/browser/browser_bug1622420.js create mode 100644 docshell/test/browser/browser_bug1648464-1.js create mode 100644 docshell/test/browser/browser_bug1673702.js create mode 100644 docshell/test/browser/browser_bug1674464.js create mode 100644 docshell/test/browser/browser_bug1688368-1.js create mode 100644 docshell/test/browser/browser_bug1691153.js create mode 100644 docshell/test/browser/browser_bug1705872.js create mode 100644 docshell/test/browser/browser_bug1716290-1.js create mode 100644 docshell/test/browser/browser_bug1716290-2.js create mode 100644 docshell/test/browser/browser_bug1716290-3.js create mode 100644 docshell/test/browser/browser_bug1716290-4.js create mode 100644 docshell/test/browser/browser_bug1719178.js create mode 100644 docshell/test/browser/browser_bug1736248-1.js create mode 100644 docshell/test/browser/browser_bug1757005.js create mode 100644 docshell/test/browser/browser_bug1769189.js create mode 100644 docshell/test/browser/browser_bug1798780.js create mode 100644 docshell/test/browser/browser_bug234628-1.js create mode 100644 docshell/test/browser/browser_bug234628-10.js create mode 100644 docshell/test/browser/browser_bug234628-11.js create mode 100644 docshell/test/browser/browser_bug234628-2.js create mode 100644 docshell/test/browser/browser_bug234628-3.js create mode 100644 docshell/test/browser/browser_bug234628-4.js create mode 100644 docshell/test/browser/browser_bug234628-5.js create mode 100644 docshell/test/browser/browser_bug234628-6.js create mode 100644 docshell/test/browser/browser_bug234628-8.js create mode 100644 docshell/test/browser/browser_bug234628-9.js create mode 100644 docshell/test/browser/browser_bug349769.js create mode 100644 docshell/test/browser/browser_bug388121-1.js create mode 100644 docshell/test/browser/browser_bug388121-2.js create mode 100644 docshell/test/browser/browser_bug420605.js create mode 100644 docshell/test/browser/browser_bug422543.js create mode 100644 docshell/test/browser/browser_bug441169.js create mode 100644 docshell/test/browser/browser_bug503832.js create mode 100644 docshell/test/browser/browser_bug554155.js create mode 100644 docshell/test/browser/browser_bug655270.js create mode 100644 docshell/test/browser/browser_bug655273.js create mode 100644 docshell/test/browser/browser_bug670318.js create mode 100644 docshell/test/browser/browser_bug673087-1.js create mode 100644 docshell/test/browser/browser_bug673087-2.js create mode 100644 docshell/test/browser/browser_bug673467.js create mode 100644 docshell/test/browser/browser_bug852909.js create mode 100644 docshell/test/browser/browser_bug92473.js create mode 100644 docshell/test/browser/browser_click_link_within_view_source.js create mode 100644 docshell/test/browser/browser_cross_process_csp_inheritance.js create mode 100644 docshell/test/browser/browser_csp_sandbox_no_script_js_uri.js create mode 100644 docshell/test/browser/browser_csp_uir.js create mode 100644 docshell/test/browser/browser_dataURI_unique_opaque_origin.js create mode 100644 docshell/test/browser/browser_data_load_inherit_csp.js create mode 100644 docshell/test/browser/browser_fall_back_to_https.js create mode 100644 docshell/test/browser/browser_frameloader_swap_with_bfcache.js create mode 100644 docshell/test/browser/browser_history_triggeringprincipal_viewsource.js create mode 100644 docshell/test/browser/browser_isInitialDocument.js create mode 100644 docshell/test/browser/browser_loadURI_postdata.js create mode 100644 docshell/test/browser/browser_multiple_pushState.js create mode 100644 docshell/test/browser/browser_onbeforeunload_frame.js create mode 100644 docshell/test/browser/browser_onbeforeunload_navigation.js create mode 100644 docshell/test/browser/browser_onbeforeunload_parent.js create mode 100644 docshell/test/browser/browser_onunload_stop.js create mode 100644 docshell/test/browser/browser_overlink.js create mode 100644 docshell/test/browser/browser_platform_emulation.js create mode 100644 docshell/test/browser/browser_search_notification.js create mode 100644 docshell/test/browser/browser_tab_replace_while_loading.js create mode 100644 docshell/test/browser/browser_tab_touch_events.js create mode 100644 docshell/test/browser/browser_targetTopLevelLinkClicksToBlank.js create mode 100644 docshell/test/browser/browser_timelineMarkers-01.js create mode 100644 docshell/test/browser/browser_timelineMarkers-02.js create mode 100644 docshell/test/browser/browser_timelineMarkers-frame-02.js create mode 100644 docshell/test/browser/browser_title_in_session_history.js create mode 100644 docshell/test/browser/browser_ua_emulation.js create mode 100644 docshell/test/browser/browser_uriFixupAlternateRedirects.js create mode 100644 docshell/test/browser/browser_uriFixupIntegration.js create mode 100644 docshell/test/browser/browser_viewsource_chrome_to_content.js create mode 100644 docshell/test/browser/browser_viewsource_multipart.js create mode 100644 docshell/test/browser/dummy_iframe_page.html create mode 100644 docshell/test/browser/dummy_page.html create mode 100644 docshell/test/browser/favicon_bug655270.ico create mode 100644 docshell/test/browser/file_backforward_restore_scroll.html create mode 100644 docshell/test/browser/file_backforward_restore_scroll.html^headers^ create mode 100644 docshell/test/browser/file_basic_multipart.sjs create mode 100644 docshell/test/browser/file_bug1046022.html create mode 100644 docshell/test/browser/file_bug1206879.html create mode 100644 docshell/test/browser/file_bug1328501.html create mode 100644 docshell/test/browser/file_bug1328501_frame.html create mode 100644 docshell/test/browser/file_bug1328501_framescript.js create mode 100644 docshell/test/browser/file_bug1543077-3-child.html create mode 100644 docshell/test/browser/file_bug1543077-3.html create mode 100644 docshell/test/browser/file_bug1622420.html create mode 100644 docshell/test/browser/file_bug1648464-1-child.html create mode 100644 docshell/test/browser/file_bug1648464-1.html create mode 100644 docshell/test/browser/file_bug1673702.json create mode 100644 docshell/test/browser/file_bug1673702.json^headers^ create mode 100644 docshell/test/browser/file_bug1688368-1.sjs create mode 100644 docshell/test/browser/file_bug1691153.html create mode 100644 docshell/test/browser/file_bug1716290-1.sjs create mode 100644 docshell/test/browser/file_bug1716290-2.sjs create mode 100644 docshell/test/browser/file_bug1716290-3.sjs create mode 100644 docshell/test/browser/file_bug1716290-4.sjs create mode 100644 docshell/test/browser/file_bug1736248-1.html create mode 100644 docshell/test/browser/file_bug234628-1-child.html create mode 100644 docshell/test/browser/file_bug234628-1.html create mode 100644 docshell/test/browser/file_bug234628-10-child.xhtml create mode 100644 docshell/test/browser/file_bug234628-10.html create mode 100644 docshell/test/browser/file_bug234628-11-child.xhtml create mode 100644 docshell/test/browser/file_bug234628-11-child.xhtml^headers^ create mode 100644 docshell/test/browser/file_bug234628-11.html create mode 100644 docshell/test/browser/file_bug234628-2-child.html create mode 100644 docshell/test/browser/file_bug234628-2.html create mode 100644 docshell/test/browser/file_bug234628-3-child.html create mode 100644 docshell/test/browser/file_bug234628-3.html create mode 100644 docshell/test/browser/file_bug234628-4-child.html create mode 100644 docshell/test/browser/file_bug234628-4.html create mode 100644 docshell/test/browser/file_bug234628-5-child.html create mode 100644 docshell/test/browser/file_bug234628-5.html create mode 100644 docshell/test/browser/file_bug234628-6-child.html create mode 100644 docshell/test/browser/file_bug234628-6-child.html^headers^ create mode 100644 docshell/test/browser/file_bug234628-6.html create mode 100644 docshell/test/browser/file_bug234628-8-child.html create mode 100644 docshell/test/browser/file_bug234628-8.html create mode 100644 docshell/test/browser/file_bug234628-9-child.html create mode 100644 docshell/test/browser/file_bug234628-9.html create mode 100644 docshell/test/browser/file_bug420605.html create mode 100644 docshell/test/browser/file_bug503832.html create mode 100644 docshell/test/browser/file_bug655270.html create mode 100644 docshell/test/browser/file_bug670318.html create mode 100644 docshell/test/browser/file_bug673087-1-child.html create mode 100644 docshell/test/browser/file_bug673087-1.html create mode 100644 docshell/test/browser/file_bug673087-1.html^headers^ create mode 100644 docshell/test/browser/file_bug673087-2.html create mode 100644 docshell/test/browser/file_bug852909.pdf create mode 100644 docshell/test/browser/file_bug852909.png create mode 100644 docshell/test/browser/file_click_link_within_view_source.html create mode 100644 docshell/test/browser/file_cross_process_csp_inheritance.html create mode 100644 docshell/test/browser/file_csp_sandbox_no_script_js_uri.html create mode 100644 docshell/test/browser/file_csp_sandbox_no_script_js_uri.html^headers^ create mode 100644 docshell/test/browser/file_csp_uir.html create mode 100644 docshell/test/browser/file_csp_uir_dummy.html create mode 100644 docshell/test/browser/file_data_load_inherit_csp.html create mode 100644 docshell/test/browser/file_multiple_pushState.html create mode 100644 docshell/test/browser/file_onbeforeunload_0.html create mode 100644 docshell/test/browser/file_onbeforeunload_1.html create mode 100644 docshell/test/browser/file_onbeforeunload_2.html create mode 100644 docshell/test/browser/file_onbeforeunload_3.html create mode 100644 docshell/test/browser/file_open_about_blank.html create mode 100644 docshell/test/browser/file_slow_load.sjs create mode 100644 docshell/test/browser/frame-head.js create mode 100644 docshell/test/browser/head.js create mode 100644 docshell/test/browser/head_browser_onbeforeunload.js create mode 100644 docshell/test/browser/onload_message.html create mode 100644 docshell/test/browser/onpageshow_message.html create mode 100644 docshell/test/browser/overlink_test.html create mode 100644 docshell/test/browser/print_postdata.sjs create mode 100644 docshell/test/browser/redirect_to_example.sjs create mode 100644 docshell/test/browser/test-form_sjis.html (limited to 'docshell/test/browser') diff --git a/docshell/test/browser/Bug1622420Child.sys.mjs b/docshell/test/browser/Bug1622420Child.sys.mjs new file mode 100644 index 0000000000..c5520d5943 --- /dev/null +++ b/docshell/test/browser/Bug1622420Child.sys.mjs @@ -0,0 +1,9 @@ +export class Bug1622420Child extends JSWindowActorChild { + receiveMessage(msg) { + switch (msg.name) { + case "hasWindowContextForTopBC": + return !!this.browsingContext.top.currentWindowContext; + } + return null; + } +} diff --git a/docshell/test/browser/Bug422543Child.sys.mjs b/docshell/test/browser/Bug422543Child.sys.mjs new file mode 100644 index 0000000000..524ac33ffd --- /dev/null +++ b/docshell/test/browser/Bug422543Child.sys.mjs @@ -0,0 +1,98 @@ +class SHistoryListener { + constructor() { + this.retval = true; + this.last = "initial"; + } + + OnHistoryNewEntry(aNewURI) { + this.last = "newentry"; + } + + OnHistoryGotoIndex() { + this.last = "gotoindex"; + } + + OnHistoryPurge() { + this.last = "purge"; + } + + OnHistoryReload() { + this.last = "reload"; + return this.retval; + } + + OnHistoryReplaceEntry() {} +} +SHistoryListener.prototype.QueryInterface = ChromeUtils.generateQI([ + "nsISHistoryListener", + "nsISupportsWeakReference", +]); + +let listeners; + +export class Bug422543Child extends JSWindowActorChild { + constructor() { + super(); + } + + actorCreated() { + if (listeners) { + return; + } + + this.shistory = this.docShell.nsIWebNavigation.sessionHistory; + listeners = [new SHistoryListener(), new SHistoryListener()]; + + for (let listener of listeners) { + this.shistory.legacySHistory.addSHistoryListener(listener); + } + } + + cleanup() { + for (let listener of listeners) { + this.shistory.legacySHistory.removeSHistoryListener(listener); + } + this.shistory = null; + listeners = null; + return {}; + } + + getListenerStatus() { + return listeners.map(l => l.last); + } + + resetListeners() { + for (let listener of listeners) { + listener.last = "initial"; + } + + return {}; + } + + notifyReload() { + let history = this.shistory.legacySHistory; + let rval = history.notifyOnHistoryReload(); + return { rval }; + } + + setRetval({ num, val }) { + listeners[num].retval = val; + return {}; + } + + receiveMessage(msg) { + switch (msg.name) { + case "cleanup": + return this.cleanup(); + case "getListenerStatus": + return this.getListenerStatus(); + case "notifyReload": + return this.notifyReload(); + case "resetListeners": + return this.resetListeners(); + case "setRetval": + return this.setRetval(msg.data); + } + return null; + } +} diff --git a/docshell/test/browser/browser.ini b/docshell/test/browser/browser.ini new file mode 100644 index 0000000000..fc3e06d9a3 --- /dev/null +++ b/docshell/test/browser/browser.ini @@ -0,0 +1,237 @@ +[DEFAULT] +support-files = + Bug422543Child.sys.mjs + dummy_page.html + favicon_bug655270.ico + file_bug234628-1-child.html + file_bug234628-1.html + file_bug234628-10-child.xhtml + file_bug234628-10.html + file_bug234628-11-child.xhtml + file_bug234628-11-child.xhtml^headers^ + file_bug234628-11.html + file_bug234628-2-child.html + file_bug234628-2.html + file_bug234628-3-child.html + file_bug234628-3.html + file_bug234628-4-child.html + file_bug234628-4.html + file_bug234628-5-child.html + file_bug234628-5.html + file_bug234628-6-child.html + file_bug234628-6-child.html^headers^ + file_bug234628-6.html + file_bug234628-8-child.html + file_bug234628-8.html + file_bug234628-9-child.html + file_bug234628-9.html + file_bug420605.html + file_bug503832.html + file_bug655270.html + file_bug670318.html + file_bug673087-1.html + file_bug673087-1.html^headers^ + file_bug673087-1-child.html + file_bug673087-2.html + file_bug852909.pdf + file_bug852909.png + file_bug1046022.html + file_bug1206879.html + file_bug1328501.html + file_bug1328501_frame.html + file_bug1328501_framescript.js + file_bug1543077-3-child.html + file_bug1543077-3.html + file_multiple_pushState.html + file_onbeforeunload_0.html + file_onbeforeunload_1.html + file_onbeforeunload_2.html + file_onbeforeunload_3.html + print_postdata.sjs + test-form_sjis.html + browser_timelineMarkers-frame-02.js + head.js + frame-head.js + file_data_load_inherit_csp.html + file_click_link_within_view_source.html + onload_message.html + onpageshow_message.html + file_cross_process_csp_inheritance.html + file_open_about_blank.html + file_slow_load.sjs + file_bug1648464-1.html + file_bug1648464-1-child.html + file_bug1688368-1.sjs + file_bug1691153.html + file_bug1716290-1.sjs + file_bug1716290-2.sjs + file_bug1716290-3.sjs + file_bug1716290-4.sjs + file_bug1736248-1.html + +[browser_alternate_fixup_middle_click_link.js] +https_first_disabled = true +[browser_backforward_userinteraction.js] +support-files = + dummy_iframe_page.html +skip-if = + os == "linux" && bits == 64 && !debug # Bug 1607713 +[browser_backforward_userinteraction_about.js] +[browser_backforward_userinteraction_systemprincipal.js] +skip-if = + os == "win" && os_version == "6.1" # Skip on Azure - frequent failure +[browser_bug1543077-3.js] +[browser_bug1594938.js] +[browser_bug1206879.js] +https_first_disabled = true +[browser_bug1309900_crossProcessHistoryNavigation.js] +https_first_disabled = true +[browser_bug1328501.js] +https_first_disabled = true +[browser_bug1347823.js] +[browser_bug134911.js] +[browser_bug1415918_beforeunload_options.js] +https_first_disabled = true +[browser_bug1622420.js] +support-files = + file_bug1622420.html + Bug1622420Child.sys.mjs +[browser_bug1673702.js] +https_first_disabled = true +skip-if = + os == "linux" && bits == 64 && os_version == "18.04" && debug # Bug 1674513 + os == "win" # Bug 1674513 +support-files = + file_bug1673702.json + file_bug1673702.json^headers^ +[browser_bug1674464.js] +https_first_disabled = true +skip-if = !fission || !crashreporter # On a crash we only keep history when fission is enabled. +[browser_bug1719178.js] +[browser_bug1757005.js] +[browser_bug1769189.js] +[browser_bug1798780.js] +[browser_bug234628-1.js] +[browser_bug234628-10.js] +[browser_bug234628-11.js] +[browser_bug234628-2.js] +[browser_bug234628-3.js] +[browser_bug234628-4.js] +[browser_bug234628-5.js] +[browser_bug234628-6.js] +[browser_bug234628-8.js] +[browser_bug234628-9.js] +[browser_bug349769.js] +[browser_bug388121-1.js] +[browser_bug388121-2.js] +[browser_bug420605.js] +skip-if = verify +[browser_bug422543.js] +https_first_disabled = true +[browser_bug441169.js] +[browser_bug503832.js] +skip-if = verify +[browser_bug554155.js] +[browser_bug655270.js] +[browser_bug655273.js] +[browser_bug670318.js] +skip-if = os == "linux" && (debug || asan || tsan) # Bug 1717403 +[browser_bug673087-1.js] +[browser_bug673087-2.js] +[browser_bug673467.js] +[browser_bug852909.js] +skip-if = (verify && debug && (os == 'win')) +[browser_bug92473.js] +[browser_csp_sandbox_no_script_js_uri.js] +support-files = + file_csp_sandbox_no_script_js_uri.html + file_csp_sandbox_no_script_js_uri.html^headers^ +[browser_data_load_inherit_csp.js] +[browser_dataURI_unique_opaque_origin.js] +https_first_disabled = true +[browser_frameloader_swap_with_bfcache.js] +[browser_backforward_restore_scroll.js] +https_first_disabled = true +support-files = + file_backforward_restore_scroll.html + file_backforward_restore_scroll.html^headers^ +[browser_targetTopLevelLinkClicksToBlank.js] +[browser_title_in_session_history.js] +skip-if = !sessionHistoryInParent +[browser_uriFixupIntegration.js] +[browser_uriFixupAlternateRedirects.js] +https_first_disabled = true +support-files = + redirect_to_example.sjs +[browser_loadURI_postdata.js] +[browser_multiple_pushState.js] +https_first_disabled = true +[browser_onbeforeunload_frame.js] +support-files = head_browser_onbeforeunload.js +[browser_onbeforeunload_parent.js] +support-files = head_browser_onbeforeunload.js +[browser_onbeforeunload_navigation.js] +skip-if = (os == 'win' && !debug) # bug 1300351 +[browser_onunload_stop.js] +https_first_disabled = true +[browser_overlink.js] +support-files = + overlink_test.html +[browser_platform_emulation.js] +[browser_search_notification.js] +[browser_tab_touch_events.js] +[browser_timelineMarkers-01.js] +[browser_timelineMarkers-02.js] +skip-if = true # Bug 1220415 +[browser_ua_emulation.js] +[browser_history_triggeringprincipal_viewsource.js] +https_first_disabled = true +[browser_click_link_within_view_source.js] +[browser_browsingContext-01.js] +https_first_disabled = true +[browser_browsingContext-02.js] +https_first_disabled = true +[browser_browsingContext-getAllBrowsingContextsInSubtree.js] +[browser_browsingContext-getWindowByName.js] +[browser_browsingContext-embedder.js] +[browser_browsingContext-webProgress.js] +skip-if = + os == "linux" && bits == 64 && !debug # Bug 1721261 + os == "win" && os_version == "6.1" # Skip on Azure - frequent failure +https_first_disabled = true +[browser_csp_uir.js] +support-files = + file_csp_uir.html + file_csp_uir_dummy.html +[browser_cross_process_csp_inheritance.js] +https_first_disabled = true +[browser_tab_replace_while_loading.js] +skip-if = (os == 'linux' && bits == 64 && os_version == '18.04') || (os == "win") # Bug 1604237, Bug 1671794 +[browser_browsing_context_attached.js] +https_first_disabled = true +[browser_browsing_context_discarded.js] +https_first_disabled = true +[browser_fall_back_to_https.js] +https_first_disabled = true +skip-if = (os == 'mac') +[browser_badCertDomainFixup.js] +[browser_viewsource_chrome_to_content.js] +[browser_viewsource_multipart.js] +support-files = + file_basic_multipart.sjs +[browser_bug1648464-1.js] +[browser_bug1688368-1.js] +[browser_bug1691153.js] +https_first_disabled = true +[browser_bug1705872.js] +[browser_isInitialDocument.js] +https_first_disabled = true +[browser_bug1716290-1.js] +[browser_bug1716290-2.js] +[browser_bug1716290-3.js] +[browser_bug1716290-4.js] +[browser_bfcache_copycommand.js] +skip-if = + os == "linux" && bits == 64 # Bug 1730593 + os == "win" && os_version == "6.1" # Skip on Azure - frequent failure +[browser_bug1736248-1.js] diff --git a/docshell/test/browser/browser_alternate_fixup_middle_click_link.js b/docshell/test/browser/browser_alternate_fixup_middle_click_link.js new file mode 100644 index 0000000000..8a55e12e52 --- /dev/null +++ b/docshell/test/browser/browser_alternate_fixup_middle_click_link.js @@ -0,0 +1,59 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Check that we don't do alternate fixup when users middle-click + * broken links in the content document. + */ +add_task(async function test_alt_fixup_middle_click() { + await BrowserTestUtils.withNewTab("about:blank", async browser => { + await SpecialPowers.spawn(browser, [], () => { + let link = content.document.createElement("a"); + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + link.href = "http://example/foo"; + link.textContent = "Me, me, click me!"; + content.document.body.append(link); + }); + let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser); + await BrowserTestUtils.synthesizeMouseAtCenter( + "a[href]", + { button: 1 }, + browser + ); + let tab = await newTabPromise; + let { browsingContext } = tab.linkedBrowser; + // Account for the possibility of a race, where the error page has already loaded: + if ( + !browsingContext.currentWindowGlobal?.documentURI.spec.startsWith( + "about:neterror" + ) + ) { + await BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + false, + null, + true + ); + } + // TBH, if the test fails, we probably force-crash because we try to reach + // *www.* example.com, which isn't proxied by the test infrastructure so + // will forcibly abort the test. But we need some asserts so they might as + // well be meaningful: + is( + tab.linkedBrowser.currentURI.spec, + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example/foo", + "URL for tab should be correct." + ); + + ok( + browsingContext.currentWindowGlobal.documentURI.spec.startsWith( + "about:neterror" + ), + "Should be showing error page." + ); + BrowserTestUtils.removeTab(tab); + }); +}); diff --git a/docshell/test/browser/browser_backforward_restore_scroll.js b/docshell/test/browser/browser_backforward_restore_scroll.js new file mode 100644 index 0000000000..2d1dfe624b --- /dev/null +++ b/docshell/test/browser/browser_backforward_restore_scroll.js @@ -0,0 +1,54 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const ROOT = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://mochi.test:8888" +); +const URL1 = ROOT + "file_backforward_restore_scroll.html"; +// eslint-disable-next-line @microsoft/sdl/no-insecure-url +const URL2 = "http://example.net/"; + +const SCROLL0 = 500; +const SCROLL1 = 1000; + +function promiseBrowserLoaded(url) { + return BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, url); +} + +add_task(async function test() { + await BrowserTestUtils.openNewForegroundTab(gBrowser, URL1); + + // Scroll the 2 frames. + let children = gBrowser.selectedBrowser.browsingContext.children; + await SpecialPowers.spawn(children[0], [SCROLL0], scrollY => + content.scrollTo(0, scrollY) + ); + await SpecialPowers.spawn(children[1], [SCROLL1], scrollY => + content.scrollTo(0, scrollY) + ); + + // Navigate forwards then backwards. + let loaded = promiseBrowserLoaded(URL2); + BrowserTestUtils.loadURIString(gBrowser.selectedBrowser, URL2); + await loaded; + + loaded = promiseBrowserLoaded(URL1); + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + content.history.back(); + }); + await loaded; + + // And check the results. + children = gBrowser.selectedBrowser.browsingContext.children; + await SpecialPowers.spawn(children[0], [SCROLL0], scrollY => { + Assert.equal(content.scrollY, scrollY, "frame 0 has correct scroll"); + }); + await SpecialPowers.spawn(children[1], [SCROLL1], scrollY => { + Assert.equal(content.scrollY, scrollY, "frame 1 has correct scroll"); + }); + + gBrowser.removeTab(gBrowser.selectedTab); +}); diff --git a/docshell/test/browser/browser_backforward_userinteraction.js b/docshell/test/browser/browser_backforward_userinteraction.js new file mode 100644 index 0000000000..264299c902 --- /dev/null +++ b/docshell/test/browser/browser_backforward_userinteraction.js @@ -0,0 +1,374 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_PAGE = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "dummy_page.html"; +const IFRAME_PAGE = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "dummy_iframe_page.html"; + +async function assertMenulist(entries, baseURL = TEST_PAGE) { + // Wait for the session data to be flushed before continuing the test + await new Promise(resolve => + SessionStore.getSessionHistory(gBrowser.selectedTab, resolve) + ); + + let backButton = document.getElementById("back-button"); + let contextMenu = document.getElementById("backForwardMenu"); + + info("waiting for the history menu to open"); + + let popupShownPromise = BrowserTestUtils.waitForEvent( + contextMenu, + "popupshown" + ); + EventUtils.synthesizeMouseAtCenter(backButton, { + type: "contextmenu", + button: 2, + }); + await popupShownPromise; + + ok(true, "history menu opened"); + + let nodes = contextMenu.childNodes; + + is( + nodes.length, + entries.length, + "Has the expected number of contextMenu entries" + ); + + for (let i = 0; i < entries.length; i++) { + let node = nodes[i]; + is( + node.getAttribute("uri").replace(/[?|#]/, "!"), + baseURL + "!entry=" + entries[i], + "contextMenu node has the correct uri" + ); + } + + let popupHiddenPromise = BrowserTestUtils.waitForEvent( + contextMenu, + "popuphidden" + ); + contextMenu.hidePopup(); + await popupHiddenPromise; +} + +// There are different ways of loading a page, but they should exhibit roughly the same +// back-forward behavior for the purpose of requiring user interaction. Thus, we +// have a utility function that runs the same test with a parameterized method of loading +// new URLs. +async function runTopLevelTest(loadMethod, useHashes = false) { + let p = useHashes ? "#" : "?"; + + // Test with both pref on and off + for (let requireUserInteraction of [true, false]) { + Services.prefs.setBoolPref( + "browser.navigation.requireUserInteraction", + requireUserInteraction + ); + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + TEST_PAGE + p + "entry=0" + ); + let browser = tab.linkedBrowser; + + assertBackForwardState(false, false); + + await loadMethod(TEST_PAGE + p + "entry=1"); + + assertBackForwardState(true, false); + await assertMenulist([1, 0]); + + await loadMethod(TEST_PAGE + p + "entry=2"); + + assertBackForwardState(true, false); + await assertMenulist(requireUserInteraction ? [2, 0] : [2, 1, 0]); + + await loadMethod(TEST_PAGE + p + "entry=3"); + + info("Adding user interaction for entry=3"); + // Add some user interaction to entry 3 + await BrowserTestUtils.synthesizeMouse( + "body", + 0, + 0, + {}, + browser.browsingContext, + true + ); + + assertBackForwardState(true, false); + await assertMenulist(requireUserInteraction ? [3, 0] : [3, 2, 1, 0]); + + await loadMethod(TEST_PAGE + p + "entry=4"); + + assertBackForwardState(true, false); + await assertMenulist(requireUserInteraction ? [4, 3, 0] : [4, 3, 2, 1, 0]); + + info("Adding user interaction for entry=4"); + // Add some user interaction to entry 4 + await BrowserTestUtils.synthesizeMouse( + "body", + 0, + 0, + {}, + browser.browsingContext, + true + ); + + await loadMethod(TEST_PAGE + p + "entry=5"); + + assertBackForwardState(true, false); + await assertMenulist( + requireUserInteraction ? [5, 4, 3, 0] : [5, 4, 3, 2, 1, 0] + ); + + await goBack(TEST_PAGE + p + "entry=4"); + await goBack(TEST_PAGE + p + "entry=3"); + + if (!requireUserInteraction) { + await goBack(TEST_PAGE + p + "entry=2"); + await goBack(TEST_PAGE + p + "entry=1"); + } + + assertBackForwardState(true, true); + await assertMenulist( + requireUserInteraction ? [5, 4, 3, 0] : [5, 4, 3, 2, 1, 0] + ); + + await goBack(TEST_PAGE + p + "entry=0"); + + assertBackForwardState(false, true); + + if (!requireUserInteraction) { + await goForward(TEST_PAGE + p + "entry=1"); + await goForward(TEST_PAGE + p + "entry=2"); + } + + await goForward(TEST_PAGE + p + "entry=3"); + + assertBackForwardState(true, true); + await assertMenulist( + requireUserInteraction ? [5, 4, 3, 0] : [5, 4, 3, 2, 1, 0] + ); + + await goForward(TEST_PAGE + p + "entry=4"); + + assertBackForwardState(true, true); + await assertMenulist( + requireUserInteraction ? [5, 4, 3, 0] : [5, 4, 3, 2, 1, 0] + ); + + await goForward(TEST_PAGE + p + "entry=5"); + + assertBackForwardState(true, false); + await assertMenulist( + requireUserInteraction ? [5, 4, 3, 0] : [5, 4, 3, 2, 1, 0] + ); + + BrowserTestUtils.removeTab(tab); + } + + Services.prefs.clearUserPref("browser.navigation.requireUserInteraction"); +} + +async function runIframeTest(loadMethod) { + // Test with both pref on and off + for (let requireUserInteraction of [true, false]) { + Services.prefs.setBoolPref( + "browser.navigation.requireUserInteraction", + requireUserInteraction + ); + + // First test the boring case where we only have one iframe. + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + IFRAME_PAGE + "?entry=0" + ); + let browser = tab.linkedBrowser; + + assertBackForwardState(false, false); + + await loadMethod(TEST_PAGE + "?sub_entry=1", "frame1"); + + assertBackForwardState(true, false); + await assertMenulist([0, 0], IFRAME_PAGE); + + await loadMethod(TEST_PAGE + "?sub_entry=2", "frame1"); + + assertBackForwardState(true, false); + await assertMenulist( + requireUserInteraction ? [0, 0] : [0, 0, 0], + IFRAME_PAGE + ); + + let bc = await SpecialPowers.spawn(browser, [], function () { + return content.document.getElementById("frame1").browsingContext; + }); + + // Add some user interaction to sub entry 2 + await BrowserTestUtils.synthesizeMouse("body", 0, 0, {}, bc, true); + + await loadMethod(TEST_PAGE + "?sub_entry=3", "frame1"); + + assertBackForwardState(true, false); + await assertMenulist( + requireUserInteraction ? [0, 0, 0] : [0, 0, 0, 0], + IFRAME_PAGE + ); + + await loadMethod(TEST_PAGE + "?sub_entry=4", "frame1"); + + assertBackForwardState(true, false); + await assertMenulist( + requireUserInteraction ? [0, 0, 0] : [0, 0, 0, 0, 0], + IFRAME_PAGE + ); + + if (!requireUserInteraction) { + await goBack(TEST_PAGE + "?sub_entry=3", true); + } + + await goBack(TEST_PAGE + "?sub_entry=2", true); + + assertBackForwardState(true, true); + await assertMenulist( + requireUserInteraction ? [0, 0, 0] : [0, 0, 0, 0, 0], + IFRAME_PAGE + ); + + await loadMethod(IFRAME_PAGE + "?entry=1"); + + assertBackForwardState(true, false); + await assertMenulist( + requireUserInteraction ? [1, 0, 0] : [1, 0, 0, 0], + IFRAME_PAGE + ); + + BrowserTestUtils.removeTab(tab); + + // Two iframes, now we're talking. + tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + IFRAME_PAGE + "?entry=0" + ); + browser = tab.linkedBrowser; + + await loadMethod(IFRAME_PAGE + "?entry=1"); + + assertBackForwardState(true, false); + await assertMenulist(requireUserInteraction ? [1, 0] : [1, 0], IFRAME_PAGE); + + // Add some user interaction to frame 1. + bc = await SpecialPowers.spawn(browser, [], function () { + return content.document.getElementById("frame1").browsingContext; + }); + await BrowserTestUtils.synthesizeMouse("body", 0, 0, {}, bc, true); + + // Add some user interaction to frame 2. + bc = await SpecialPowers.spawn(browser, [], function () { + return content.document.getElementById("frame2").browsingContext; + }); + await BrowserTestUtils.synthesizeMouse("body", 0, 0, {}, bc, true); + + // Navigate frame 2. + await loadMethod(TEST_PAGE + "?sub_entry=1", "frame2"); + + assertBackForwardState(true, false); + await assertMenulist( + requireUserInteraction ? [1, 1, 0] : [1, 1, 0], + IFRAME_PAGE + ); + + // Add some user interaction to frame 1, again. + bc = await SpecialPowers.spawn(browser, [], function () { + return content.document.getElementById("frame1").browsingContext; + }); + await BrowserTestUtils.synthesizeMouse("body", 0, 0, {}, bc, true); + + // Navigate frame 2, again. + await loadMethod(TEST_PAGE + "?sub_entry=2", "frame2"); + + assertBackForwardState(true, false); + await assertMenulist( + requireUserInteraction ? [1, 1, 1, 0] : [1, 1, 1, 0], + IFRAME_PAGE + ); + + await goBack(TEST_PAGE + "?sub_entry=1", true); + + assertBackForwardState(true, true); + await assertMenulist( + requireUserInteraction ? [1, 1, 1, 0] : [1, 1, 1, 0], + IFRAME_PAGE + ); + + await goBack(TEST_PAGE + "?sub_entry=0", true); + + assertBackForwardState(true, true); + await assertMenulist( + requireUserInteraction ? [1, 1, 1, 0] : [1, 1, 1, 0], + IFRAME_PAGE + ); + + BrowserTestUtils.removeTab(tab); + } + + Services.prefs.clearUserPref("browser.navigation.requireUserInteraction"); +} + +// Test that when the pref is flipped, we are skipping history +// entries without user interaction when following links with hash URIs. +add_task(async function test_hashURI() { + async function followLinkHash(url) { + info(`Creating and following a link to ${url}`); + let browser = gBrowser.selectedBrowser; + let loaded = BrowserTestUtils.waitForLocationChange(gBrowser, url); + await SpecialPowers.spawn(browser, [url], function (url) { + let a = content.document.createElement("a"); + a.href = url; + content.document.body.appendChild(a); + a.click(); + }); + await loaded; + info(`Loaded ${url}`); + } + + await runTopLevelTest(followLinkHash, true); +}); + +// Test that when the pref is flipped, we are skipping history +// entries without user interaction when using history.pushState. +add_task(async function test_pushState() { + await runTopLevelTest(pushState); +}); + +// Test that when the pref is flipped, we are skipping history +// entries without user interaction when following a link. +add_task(async function test_followLink() { + await runTopLevelTest(followLink); +}); + +// Test that when the pref is flipped, we are skipping history +// entries without user interaction when navigating inside an iframe +// using history.pushState. +add_task(async function test_iframe_pushState() { + await runIframeTest(pushState); +}); + +// Test that when the pref is flipped, we are skipping history +// entries without user interaction when navigating inside an iframe +// by following links. +add_task(async function test_iframe_followLink() { + await runIframeTest(followLink); +}); diff --git a/docshell/test/browser/browser_backforward_userinteraction_about.js b/docshell/test/browser/browser_backforward_userinteraction_about.js new file mode 100644 index 0000000000..606fcc45c5 --- /dev/null +++ b/docshell/test/browser/browser_backforward_userinteraction_about.js @@ -0,0 +1,67 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_PAGE = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "dummy_page.html"; + +// Regression test for navigating back after visiting an about: page +// loaded in the parent process. +add_task(async function test_about_back() { + // Test with both pref on and off + for (let requireUserInteraction of [true, false]) { + Services.prefs.setBoolPref( + "browser.navigation.requireUserInteraction", + requireUserInteraction + ); + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + TEST_PAGE + "?entry=0" + ); + let browser = tab.linkedBrowser; + assertBackForwardState(false, false); + + await followLink(TEST_PAGE + "?entry=1"); + assertBackForwardState(true, false); + + await followLink(TEST_PAGE + "?entry=2"); + assertBackForwardState(true, false); + + // Add some user interaction to entry 2 + await BrowserTestUtils.synthesizeMouse("body", 0, 0, {}, browser, true); + + await loadURI("about:config"); + assertBackForwardState(true, false); + + await goBack(TEST_PAGE + "?entry=2"); + assertBackForwardState(true, true); + + if (!requireUserInteraction) { + await goBack(TEST_PAGE + "?entry=1"); + assertBackForwardState(true, true); + } + + await goBack(TEST_PAGE + "?entry=0"); + assertBackForwardState(false, true); + + if (!requireUserInteraction) { + await goForward(TEST_PAGE + "?entry=1"); + assertBackForwardState(true, true); + } + + await goForward(TEST_PAGE + "?entry=2"); + assertBackForwardState(true, true); + + await goForward("about:config"); + assertBackForwardState(true, false); + + BrowserTestUtils.removeTab(tab); + } + + Services.prefs.clearUserPref("browser.navigation.requireUserInteraction"); +}); diff --git a/docshell/test/browser/browser_backforward_userinteraction_systemprincipal.js b/docshell/test/browser/browser_backforward_userinteraction_systemprincipal.js new file mode 100644 index 0000000000..289ed1d133 --- /dev/null +++ b/docshell/test/browser/browser_backforward_userinteraction_systemprincipal.js @@ -0,0 +1,112 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_PAGE = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "dummy_page.html"; + +async function runTest(privilegedLoad) { + let prefVals; + // Test with both pref on and off, unless parent-controlled pref is enabled. + // This distinction can be removed once SHIP is enabled by default. + if ( + Services.prefs.getBoolPref("browser.tabs.documentchannel.parent-controlled") + ) { + prefVals = [false]; + } else { + prefVals = [true, false]; + } + + for (let requireUserInteraction of prefVals) { + Services.prefs.setBoolPref( + "browser.navigation.requireUserInteraction", + requireUserInteraction + ); + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + TEST_PAGE + "?entry=0" + ); + + assertBackForwardState(false, false); + + await followLink(TEST_PAGE + "?entry=1"); + + assertBackForwardState(true, false); + + await followLink(TEST_PAGE + "?entry=2"); + + assertBackForwardState(true, false); + + await followLink(TEST_PAGE + "?entry=3"); + + assertBackForwardState(true, false); + + // Entry 4 will be added through a user action in browser chrome, + // giving user interaction to entry 3. Entry 4 should not gain automatic + // user interaction. + await privilegedLoad(TEST_PAGE + "?entry=4"); + + assertBackForwardState(true, false); + + await followLink(TEST_PAGE + "?entry=5"); + + assertBackForwardState(true, false); + + if (!requireUserInteraction) { + await goBack(TEST_PAGE + "?entry=4"); + } + await goBack(TEST_PAGE + "?entry=3"); + + if (!requireUserInteraction) { + await goBack(TEST_PAGE + "?entry=2"); + await goBack(TEST_PAGE + "?entry=1"); + } + + assertBackForwardState(true, true); + + await goBack(TEST_PAGE + "?entry=0"); + + assertBackForwardState(false, true); + + if (!requireUserInteraction) { + await goForward(TEST_PAGE + "?entry=1"); + await goForward(TEST_PAGE + "?entry=2"); + } + + await goForward(TEST_PAGE + "?entry=3"); + + assertBackForwardState(true, true); + + if (!requireUserInteraction) { + await goForward(TEST_PAGE + "?entry=4"); + } + + await goForward(TEST_PAGE + "?entry=5"); + + assertBackForwardState(true, false); + + BrowserTestUtils.removeTab(tab); + } + + Services.prefs.clearUserPref("browser.navigation.requireUserInteraction"); +} + +// Test that we add a user interaction flag to the previous site when loading +// a new site from user interaction with privileged UI, e.g. through the +// URL bar. +add_task(async function test_urlBar() { + await runTest(async function (url) { + info(`Loading ${url} via the URL bar.`); + let browser = gBrowser.selectedBrowser; + let loaded = BrowserTestUtils.browserLoaded(browser, false, url); + gURLBar.focus(); + gURLBar.value = url; + gURLBar.goButton.click(); + await loaded; + }); +}); diff --git a/docshell/test/browser/browser_badCertDomainFixup.js b/docshell/test/browser/browser_badCertDomainFixup.js new file mode 100644 index 0000000000..2db3eb6701 --- /dev/null +++ b/docshell/test/browser/browser_badCertDomainFixup.js @@ -0,0 +1,92 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// This test checks if we are correctly fixing https URLs by prefixing +// with www. when we encounter a SSL_ERROR_BAD_CERT_DOMAIN error. +// For example, https://example.com -> https://www.example.com. + +const PREF_BAD_CERT_DOMAIN_FIX_ENABLED = + "security.bad_cert_domain_error.url_fix_enabled"; +const PREF_ALLOW_HIJACKING_LOCALHOST = + "network.proxy.allow_hijacking_localhost"; + +const BAD_CERT_DOMAIN_ERROR_URL = "https://badcertdomain.example.com:443"; +const FIXED_URL = "https://www.badcertdomain.example.com/"; + +const BAD_CERT_DOMAIN_ERROR_URL2 = + "https://mismatch.badcertdomain.example.com:443"; +const IPV4_ADDRESS = "https://127.0.0.3:433"; +const BAD_CERT_DOMAIN_ERROR_PORT = "https://badcertdomain.example.com:82"; + +async function verifyErrorPage(errorPageURL) { + let certErrorLoaded = BrowserTestUtils.waitForErrorPage( + gBrowser.selectedBrowser + ); + BrowserTestUtils.loadURIString(gBrowser, errorPageURL); + await certErrorLoaded; + + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () { + let ec; + await ContentTaskUtils.waitForCondition(() => { + ec = content.document.getElementById("errorCode"); + return ec.textContent; + }, "Error code has been set inside the advanced button panel"); + is( + ec.textContent, + "SSL_ERROR_BAD_CERT_DOMAIN", + "Correct error code is shown" + ); + }); +} + +// Test that "www." is prefixed to a https url when we encounter a bad cert domain +// error if the "www." form is included in the certificate's subjectAltNames. +add_task(async function prefixBadCertDomain() { + // Turn off the pref and ensure that we show the error page as expected. + Services.prefs.setBoolPref(PREF_BAD_CERT_DOMAIN_FIX_ENABLED, false); + + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser); + await verifyErrorPage(BAD_CERT_DOMAIN_ERROR_URL); + info("Cert error is shown as expected when the fixup pref is disabled"); + + // Turn on the pref and test that we fix the HTTPS URL. + Services.prefs.setBoolPref(PREF_BAD_CERT_DOMAIN_FIX_ENABLED, true); + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser); + let loadSuccessful = BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser, + false, + FIXED_URL + ); + BrowserTestUtils.loadURIString(gBrowser, BAD_CERT_DOMAIN_ERROR_URL); + await loadSuccessful; + + info("The URL was fixed as expected"); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +// Test that we don't prefix "www." to a https url when we encounter a bad cert domain +// error under certain conditions. +add_task(async function ignoreBadCertDomain() { + Services.prefs.setBoolPref(PREF_BAD_CERT_DOMAIN_FIX_ENABLED, true); + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser); + + // Test for when "www." form is not present in the certificate. + await verifyErrorPage(BAD_CERT_DOMAIN_ERROR_URL2); + info("Certificate error was shown as expected"); + + // Test that urls with IP addresses are not fixed. + Services.prefs.setBoolPref(PREF_ALLOW_HIJACKING_LOCALHOST, true); + await verifyErrorPage(IPV4_ADDRESS); + Services.prefs.clearUserPref(PREF_ALLOW_HIJACKING_LOCALHOST); + info("Certificate error was shown as expected for an IP address"); + + // Test that urls with ports are not fixed. + await verifyErrorPage(BAD_CERT_DOMAIN_ERROR_PORT); + info("Certificate error was shown as expected for a host with port"); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); diff --git a/docshell/test/browser/browser_bfcache_copycommand.js b/docshell/test/browser/browser_bfcache_copycommand.js new file mode 100644 index 0000000000..178aee4913 --- /dev/null +++ b/docshell/test/browser/browser_bfcache_copycommand.js @@ -0,0 +1,98 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +function dummyPageURL(domain, query = "") { + return ( + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + `https://${domain}` + ) + + "dummy_page.html" + + query + ); +} + +async function openContextMenu(browser) { + let contextMenu = document.getElementById("contentAreaContextMenu"); + let awaitPopupShown = BrowserTestUtils.waitForEvent( + contextMenu, + "popupshown" + ); + await BrowserTestUtils.synthesizeMouse( + "body", + 1, + 1, + { + type: "contextmenu", + button: 2, + }, + browser + ); + await awaitPopupShown; +} + +async function closeContextMenu() { + let contextMenu = document.getElementById("contentAreaContextMenu"); + let awaitPopupHidden = BrowserTestUtils.waitForEvent( + contextMenu, + "popuphidden" + ); + contextMenu.hidePopup(); + await awaitPopupHidden; +} + +async function testWithDomain(domain) { + // Passing a query to make sure the next load is never a same-document + // navigation. + let dummy = dummyPageURL("example.org", "?start"); + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, dummy); + let browser = tab.linkedBrowser; + + let sel = await SpecialPowers.spawn(browser, [], function () { + let sel = content.getSelection(); + sel.removeAllRanges(); + sel.selectAllChildren(content.document.body); + return sel.toString(); + }); + + await openContextMenu(browser); + + let copyItem = document.getElementById("context-copy"); + ok(!copyItem.disabled, "Copy item should be enabled if text is selected."); + + await closeContextMenu(); + + let loaded = BrowserTestUtils.browserLoaded(browser, false, null, true); + BrowserTestUtils.loadURIString(browser, dummyPageURL(domain)); + await loaded; + loaded = BrowserTestUtils.waitForLocationChange(gBrowser, dummy); + browser.goBack(); + await loaded; + + let sel2 = await SpecialPowers.spawn(browser, [], function () { + return content.getSelection().toString(); + }); + is(sel, sel2, "Selection should remain when coming out of BFCache."); + + await openContextMenu(browser); + + ok(!copyItem.disabled, "Copy item should be enabled if text is selected."); + + await closeContextMenu(); + + await BrowserTestUtils.removeTab(tab); +} + +add_task(async function testValidSameOrigin() { + await testWithDomain("example.org"); +}); + +add_task(async function testValidCrossOrigin() { + await testWithDomain("example.com"); +}); + +add_task(async function testInvalid() { + await testWithDomain("this.is.invalid"); +}); diff --git a/docshell/test/browser/browser_browsingContext-01.js b/docshell/test/browser/browser_browsingContext-01.js new file mode 100644 index 0000000000..95831d2567 --- /dev/null +++ b/docshell/test/browser/browser_browsingContext-01.js @@ -0,0 +1,180 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const URL = "about:blank"; + +async function getBrowsingContextId(browser, id) { + return SpecialPowers.spawn(browser, [id], async function (id) { + let contextId = content.window.docShell.browsingContext.id; + + let frames = [content.window]; + while (frames.length) { + let frame = frames.pop(); + let target = frame.document.getElementById(id); + if (target) { + contextId = target.docShell.browsingContext.id; + break; + } + + frames = frames.concat(Array.from(frame.frames)); + } + + return contextId; + }); +} + +async function addFrame(browser, id, parentId) { + return SpecialPowers.spawn( + browser, + [{ parentId, id }], + async function ({ parentId, id }) { + let parent = null; + if (parentId) { + let frames = [content.window]; + while (frames.length) { + let frame = frames.pop(); + let target = frame.document.getElementById(parentId); + if (target) { + parent = target.contentWindow.document.body; + break; + } + frames = frames.concat(Array.from(frame.frames)); + } + } else { + parent = content.document.body; + } + + let frame = await new Promise(resolve => { + let frame = content.document.createElement("iframe"); + frame.id = id || ""; + frame.url = "about:blank"; + frame.onload = () => resolve(frame); + parent.appendChild(frame); + }); + + return frame.contentWindow.docShell.browsingContext.id; + } + ); +} + +async function removeFrame(browser, id) { + return SpecialPowers.spawn(browser, [id], async function (id) { + let frames = [content.window]; + while (frames.length) { + let frame = frames.pop(); + let target = frame.document.getElementById(id); + if (target) { + target.remove(); + break; + } + + frames = frames.concat(Array.from(frame.frames)); + } + }); +} + +function getBrowsingContextById(id) { + return BrowsingContext.get(id); +} + +add_task(async function () { + await BrowserTestUtils.withNewTab( + { gBrowser, url: URL }, + async function (browser) { + let topId = await getBrowsingContextId(browser, ""); + let topContext = getBrowsingContextById(topId); + isnot(topContext, null); + is(topContext.parent, null); + is( + topId, + browser.browsingContext.id, + " has the correct browsingContext" + ); + is( + browser.browserId, + topContext.browserId, + "browsing context should have a correct id" + ); + + let id0 = await addFrame(browser, "frame0"); + let browsingContext0 = getBrowsingContextById(id0); + isnot(browsingContext0, null); + is(browsingContext0.parent, topContext); + + await removeFrame(browser, "frame0"); + + is(topContext.children.indexOf(browsingContext0), -1); + + // TODO(farre): Handle browsingContext removal [see Bug 1486719]. + todo_isnot(browsingContext0.parent, topContext); + } + ); +}); + +add_task(async function () { + // If Fission is disabled, the pref is no-op. + await SpecialPowers.pushPrefEnv({ set: [["fission.bfcacheInParent", true]] }); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com" + ) + "dummy_page.html", + }, + async function (browser) { + let path = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com" + ); + await SpecialPowers.spawn(browser, [path], async function (path) { + var bc = new content.BroadcastChannel("browser_browsingContext"); + function waitForMessage(command) { + let p = new Promise(resolve => { + bc.addEventListener("message", e => resolve(e), { once: true }); + }); + command(); + return p; + } + + // Open a new window and wait for the message. + let e1 = await waitForMessage(_ => + content.window.open(path + "onpageshow_message.html", "", "noopener") + ); + + is(e1.data, "pageshow", "Got page show"); + + let e2 = await waitForMessage(_ => bc.postMessage("createiframe")); + is(e2.data.framesLength, 1, "Here we should have an iframe"); + + let e3 = await waitForMessage(_ => bc.postMessage("nextpage")); + + is(e3.data.event, "load"); + is(e3.data.framesLength, 0, "Here there shouldn't be an iframe"); + + // Return to the previous document. N.B. we expect to trigger + // BFCache here, hence we wait for pageshow. + let e4 = await waitForMessage(_ => bc.postMessage("back")); + + is(e4.data, "pageshow"); + + let e5 = await waitForMessage(_ => bc.postMessage("queryframes")); + is(e5.data.framesLength, 1, "And again there should be an iframe"); + + is(e5.outerWindowId, e2.outerWindowId, "BF cache cached outer window"); + is(e5.browsingContextId, e2.browsingContextId, "BF cache cached BC"); + + let e6 = await waitForMessage(_ => bc.postMessage("close")); + is(e6.data, "closed"); + + bc.close(); + }); + } + ); +}); diff --git a/docshell/test/browser/browser_browsingContext-02.js b/docshell/test/browser/browser_browsingContext-02.js new file mode 100644 index 0000000000..8439b869b0 --- /dev/null +++ b/docshell/test/browser/browser_browsingContext-02.js @@ -0,0 +1,235 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async function () { + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:blank" }, + async function (browser) { + const BASE1 = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com" + ); + const BASE2 = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://test1.example.com" + ); + const URL = BASE1 + "onload_message.html"; + let sixth = BrowserTestUtils.waitForNewTab( + gBrowser, + URL + "#sixth", + true, + true + ); + let seventh = BrowserTestUtils.waitForNewTab( + gBrowser, + URL + "#seventh", + true, + true + ); + let browserIds = await SpecialPowers.spawn( + browser, + [{ base1: BASE1, base2: BASE2 }], + async function ({ base1, base2 }) { + let top = content; + top.name = "top"; + top.location.href += "#top"; + + let contexts = { + top: top.location.href, + first: base1 + "dummy_page.html#first", + third: base2 + "dummy_page.html#third", + second: base1 + "dummy_page.html#second", + fourth: base2 + "dummy_page.html#fourth", + fifth: base1 + "dummy_page.html#fifth", + sixth: base1 + "onload_message.html#sixth", + seventh: base1 + "onload_message.html#seventh", + }; + + function addFrame(target, name) { + return content.SpecialPowers.spawn( + target, + [name, contexts[name]], + async (name, context) => { + let doc = this.content.document; + + let frame = doc.createElement("iframe"); + doc.body.appendChild(frame); + frame.name = name; + frame.src = context; + await new Promise(resolve => { + frame.addEventListener("load", resolve, { once: true }); + }); + return frame.browsingContext; + } + ); + } + + function addWindow(target, name, { options, resolve }) { + return content.SpecialPowers.spawn( + target, + [name, contexts[name], options, resolve], + (name, context, options, resolve) => { + let win = this.content.open(context, name, options); + let bc = win && win.docShell.browsingContext; + + if (resolve) { + return new Promise(resolve => + this.content.addEventListener("message", () => resolve(bc)) + ); + } + return Promise.resolve({ name }); + } + ); + } + + // We're going to create a tree that looks like the + // following. + // + // top sixth seventh + // / \ + // / \ / + // first second + // / \ / + // / \ + // third fourth - - - + // / + // / + // fifth + // + // The idea is to have one top level non-auxiliary browsing + // context, five nested, one top level auxiliary with an + // opener, and one top level without an opener. Given that + // set of related and one unrelated browsing contexts we + // wish to confirm that targeting is able to find + // appropriate browsing contexts. + + // WindowGlobalChild.findBrowsingContextWithName requires access + // checks, which can only be performed in the process of the accessor + // WindowGlobalChild. + function findWithName(bc, name) { + return content.SpecialPowers.spawn(bc, [name], name => { + return content.windowGlobalChild.findBrowsingContextWithName( + name + ); + }); + } + + async function reachable(start, target) { + info(start.name, target.name); + is( + await findWithName(start, target.name), + target, + [start.name, "can reach", target.name].join(" ") + ); + } + + async function unreachable(start, target) { + is( + await findWithName(start, target.name), + null, + [start.name, "can't reach", target.name].join(" ") + ); + } + + let first = await addFrame(top, "first"); + info("first"); + let second = await addFrame(top, "second"); + info("second"); + let third = await addFrame(first, "third"); + info("third"); + let fourth = await addFrame(first, "fourth"); + info("fourth"); + let fifth = await addFrame(fourth, "fifth"); + info("fifth"); + let sixth = await addWindow(fourth, "sixth", { resolve: true }); + info("sixth"); + let seventh = await addWindow(fourth, "seventh", { + options: ["noopener"], + }); + info("seventh"); + + let origin1 = [first, second, fifth, sixth]; + let origin2 = [third, fourth]; + + let topBC = BrowsingContext.getFromWindow(top); + let frames = new Map([ + [topBC, [topBC, first, second, third, fourth, fifth, sixth]], + [first, [topBC, ...origin1, third, fourth]], + [second, [topBC, ...origin1, third, fourth]], + [third, [topBC, ...origin2, fifth, sixth]], + [fourth, [topBC, ...origin2, fifth, sixth]], + [fifth, [topBC, ...origin1, third, fourth]], + [sixth, [...origin1, third, fourth]], + ]); + + for (let [start, accessible] of frames) { + for (let frame of frames.keys()) { + if (accessible.includes(frame)) { + await reachable(start, frame); + } else { + await unreachable(start, frame); + } + } + await unreachable(start, seventh); + } + + let topBrowserId = topBC.browserId; + ok(topBrowserId > 0, "Should have a browser ID."); + for (let [name, bc] of Object.entries({ + first, + second, + third, + fourth, + fifth, + })) { + is( + bc.browserId, + topBrowserId, + `${name} frame should have the same browserId as top.` + ); + } + + ok(sixth.browserId > 0, "sixth should have a browserId."); + isnot( + sixth.browserId, + topBrowserId, + "sixth frame should have a different browserId to top." + ); + + return [topBrowserId, sixth.browserId]; + } + ); + + [sixth, seventh] = await Promise.all([sixth, seventh]); + + is( + browser.browserId, + browserIds[0], + "browser should have the right browserId." + ); + is( + browser.browsingContext.browserId, + browserIds[0], + "browser's BrowsingContext should have the right browserId." + ); + is( + sixth.linkedBrowser.browserId, + browserIds[1], + "sixth should have the right browserId." + ); + is( + sixth.linkedBrowser.browsingContext.browserId, + browserIds[1], + "sixth's BrowsingContext should have the right browserId." + ); + + for (let tab of [sixth, seventh]) { + BrowserTestUtils.removeTab(tab); + } + } + ); +}); diff --git a/docshell/test/browser/browser_browsingContext-embedder.js b/docshell/test/browser/browser_browsingContext-embedder.js new file mode 100644 index 0000000000..9473a46eb4 --- /dev/null +++ b/docshell/test/browser/browser_browsingContext-embedder.js @@ -0,0 +1,156 @@ +"use strict"; + +function observeOnce(topic) { + return new Promise(resolve => { + Services.obs.addObserver(function observer(aSubject, aTopic) { + if (topic == aTopic) { + Services.obs.removeObserver(observer, topic); + setTimeout(() => resolve(aSubject), 0); + } + }, topic); + }); +} + +add_task(async function runTest() { + let fissionWindow = await BrowserTestUtils.openNewBrowserWindow({ + fission: true, + remote: true, + }); + + info(`chrome, parent`); + let chromeBC = fissionWindow.docShell.browsingContext; + ok(chromeBC.currentWindowGlobal, "Should have a current WindowGlobal"); + is(chromeBC.embedderWindowGlobal, null, "chrome has no embedder global"); + is(chromeBC.embedderElement, null, "chrome has no embedder element"); + is(chromeBC.parent, null, "chrome has no parent"); + + // Open a new tab, and check that basic frames work out. + let tab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser: fissionWindow.gBrowser, + }); + + info(`root, parent`); + let rootBC = tab.linkedBrowser.browsingContext; + ok(rootBC.currentWindowGlobal, "[parent] root has a window global"); + is( + rootBC.embedderWindowGlobal, + chromeBC.currentWindowGlobal, + "[parent] root has chrome as embedder global" + ); + is( + rootBC.embedderElement, + tab.linkedBrowser, + "[parent] root has browser as embedder element" + ); + is(rootBC.parent, null, "[parent] root has no parent"); + + // Test with an in-process frame + let frameId = await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + info(`root, child`); + let rootBC = content.docShell.browsingContext; + is(rootBC.embedderElement, null, "[child] root has no embedder"); + is(rootBC.parent, null, "[child] root has no parent"); + + info(`frame, child`); + let iframe = content.document.createElement("iframe"); + content.document.body.appendChild(iframe); + + let frameBC = iframe.contentWindow.docShell.browsingContext; + is(frameBC.embedderElement, iframe, "[child] frame embedded within iframe"); + is(frameBC.parent, rootBC, "[child] frame has root as parent"); + + return frameBC.id; + }); + + info(`frame, parent`); + let frameBC = BrowsingContext.get(frameId); + ok(frameBC.currentWindowGlobal, "[parent] frame has a window global"); + is( + frameBC.embedderWindowGlobal, + rootBC.currentWindowGlobal, + "[parent] frame has root as embedder global" + ); + is(frameBC.embedderElement, null, "[parent] frame has no embedder element"); + is(frameBC.parent, rootBC, "[parent] frame has root as parent"); + + // Test with an out-of-process iframe. + + let oopID = await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + info(`creating oop iframe`); + let oop = content.document.createElement("iframe"); + oop.setAttribute("src", "https://example.com"); + content.document.body.appendChild(oop); + + await new Promise(resolve => { + oop.addEventListener("load", resolve, { once: true }); + }); + + info(`oop frame, child`); + let oopBC = oop.frameLoader.browsingContext; + is(oopBC.embedderElement, oop, "[child] oop frame embedded within iframe"); + is( + oopBC.parent, + content.docShell.browsingContext, + "[child] frame has root as parent" + ); + + return oopBC.id; + }); + + info(`oop frame, parent`); + let oopBC = BrowsingContext.get(oopID); + is( + oopBC.embedderWindowGlobal, + rootBC.currentWindowGlobal, + "[parent] oop frame has root as embedder global" + ); + is(oopBC.embedderElement, null, "[parent] oop frame has no embedder element"); + is(oopBC.parent, rootBC, "[parent] oop frame has root as parent"); + + info(`waiting for oop window global`); + ok(oopBC.currentWindowGlobal, "[parent] oop frame has a window global"); + + // Open a new window, and adopt |tab| into it. + + let newWindow = await BrowserTestUtils.openNewBrowserWindow({ + fission: true, + remote: true, + }); + + info(`new chrome, parent`); + let newChromeBC = newWindow.docShell.browsingContext; + ok(newChromeBC.currentWindowGlobal, "Should have a current WindowGlobal"); + is( + newChromeBC.embedderWindowGlobal, + null, + "new chrome has no embedder global" + ); + is(newChromeBC.embedderElement, null, "new chrome has no embedder element"); + is(newChromeBC.parent, null, "new chrome has no parent"); + + isnot(newChromeBC, chromeBC, "different chrome browsing context"); + + info(`adopting tab`); + let newTab = newWindow.gBrowser.adoptTab(tab); + + is( + newTab.linkedBrowser.browsingContext, + rootBC, + "[parent] root browsing context survived" + ); + is( + rootBC.embedderWindowGlobal, + newChromeBC.currentWindowGlobal, + "[parent] embedder window global updated" + ); + is( + rootBC.embedderElement, + newTab.linkedBrowser, + "[parent] embedder element updated" + ); + is(rootBC.parent, null, "[parent] root has no parent"); + + info(`closing window`); + await BrowserTestUtils.closeWindow(newWindow); + await BrowserTestUtils.closeWindow(fissionWindow); +}); diff --git a/docshell/test/browser/browser_browsingContext-getAllBrowsingContextsInSubtree.js b/docshell/test/browser/browser_browsingContext-getAllBrowsingContextsInSubtree.js new file mode 100644 index 0000000000..076383ad87 --- /dev/null +++ b/docshell/test/browser/browser_browsingContext-getAllBrowsingContextsInSubtree.js @@ -0,0 +1,53 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +async function addFrame(url) { + let iframe = content.document.createElement("iframe"); + await new Promise(resolve => { + iframe.addEventListener("load", resolve, { once: true }); + iframe.src = url; + content.document.body.appendChild(iframe); + }); + return iframe.browsingContext; +} + +add_task(async function () { + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:blank" }, + async browser => { + // Add 15 example.com frames to the toplevel document. + let frames = await Promise.all( + Array.from({ length: 15 }).map(_ => + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + SpecialPowers.spawn(browser, ["http://example.com/"], addFrame) + ) + ); + + // Add an example.org subframe to each example.com frame. + let subframes = await Promise.all( + Array.from({ length: 15 }).map((_, i) => + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + SpecialPowers.spawn(frames[i], ["http://example.org/"], addFrame) + ) + ); + + Assert.deepEqual( + subframes[0].getAllBrowsingContextsInSubtree(), + [subframes[0]], + "Childless context only has self in subtree" + ); + Assert.deepEqual( + frames[0].getAllBrowsingContextsInSubtree(), + [frames[0], subframes[0]], + "Single-child context has 2 contexts in subtree" + ); + Assert.deepEqual( + browser.browsingContext.getAllBrowsingContextsInSubtree(), + [browser.browsingContext, ...frames, ...subframes], + "Toplevel context has all subtree contexts" + ); + } + ); +}); diff --git a/docshell/test/browser/browser_browsingContext-getWindowByName.js b/docshell/test/browser/browser_browsingContext-getWindowByName.js new file mode 100644 index 0000000000..e57691b270 --- /dev/null +++ b/docshell/test/browser/browser_browsingContext-getWindowByName.js @@ -0,0 +1,34 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +function addWindow(name) { + var blank = Cc["@mozilla.org/supports-string;1"].createInstance( + Ci.nsISupportsString + ); + blank.data = "about:blank"; + let promise = BrowserTestUtils.waitForNewWindow({ + anyWindow: true, + url: "about:blank", + }); + Services.ww.openWindow( + null, + AppConstants.BROWSER_CHROME_URL, + name, + "chrome,dialog=no", + blank + ); + return promise; +} + +add_task(async function () { + let windows = [await addWindow("first"), await addWindow("second")]; + + for (let w of windows) { + isnot(w, null); + is(Services.ww.getWindowByName(w.name, null), w, `Found ${w.name}`); + } + + await Promise.all(windows.map(BrowserTestUtils.closeWindow)); +}); diff --git a/docshell/test/browser/browser_browsingContext-webProgress.js b/docshell/test/browser/browser_browsingContext-webProgress.js new file mode 100644 index 0000000000..54b5400efd --- /dev/null +++ b/docshell/test/browser/browser_browsingContext-webProgress.js @@ -0,0 +1,226 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async function () { + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:blank" + ); + const browser = tab.linkedBrowser; + const aboutBlankBrowsingContext = browser.browsingContext; + const { webProgress } = aboutBlankBrowsingContext; + ok( + webProgress, + "Got a WebProgress interface on BrowsingContext in the parent process" + ); + is( + webProgress.browsingContext, + browser.browsingContext, + "WebProgress.browsingContext refers to the right BrowsingContext" + ); + + const onLocationChanged = waitForNextLocationChange(webProgress); + const newLocation = "data:text/html;charset=utf-8,first-page"; + let loaded = BrowserTestUtils.browserLoaded(browser); + BrowserTestUtils.loadURIString(browser, newLocation); + await loaded; + + const firstPageBrowsingContext = browser.browsingContext; + const isBfcacheInParentEnabled = + SpecialPowers.Services.appinfo.sessionHistoryInParent && + SpecialPowers.Services.prefs.getBoolPref("fission.bfcacheInParent"); + if (isBfcacheInParentEnabled) { + isnot( + aboutBlankBrowsingContext, + firstPageBrowsingContext, + "With bfcache in parent, navigations spawn a new BrowsingContext" + ); + } else { + is( + aboutBlankBrowsingContext, + firstPageBrowsingContext, + "Without bfcache in parent, navigations reuse the same BrowsingContext" + ); + } + + info("Wait for onLocationChange to be fired"); + { + const { browsingContext, location, request, flags } = + await onLocationChanged; + is( + browsingContext, + firstPageBrowsingContext, + "Location change fires on the new BrowsingContext" + ); + ok(location instanceof Ci.nsIURI); + is(location.spec, newLocation); + ok(request instanceof Ci.nsIChannel); + is(request.URI.spec, newLocation); + is(flags, 0); + } + + const onIframeLocationChanged = waitForNextLocationChange(webProgress); + const iframeLocation = "data:text/html;charset=utf-8,iframe"; + const iframeBC = await SpecialPowers.spawn( + browser, + [iframeLocation], + async url => { + const iframe = content.document.createElement("iframe"); + await new Promise(resolve => { + iframe.addEventListener("load", resolve, { once: true }); + iframe.src = url; + content.document.body.appendChild(iframe); + }); + + return iframe.browsingContext; + } + ); + ok( + iframeBC.webProgress, + "The iframe BrowsingContext also exposes a WebProgress" + ); + { + const { browsingContext, location, request, flags } = + await onIframeLocationChanged; + is( + browsingContext, + iframeBC, + "Iframe location change fires on the iframe BrowsingContext" + ); + ok(location instanceof Ci.nsIURI); + is(location.spec, iframeLocation); + ok(request instanceof Ci.nsIChannel); + is(request.URI.spec, iframeLocation); + is(flags, 0); + } + + const onSecondLocationChanged = waitForNextLocationChange(webProgress); + const onSecondPageDocumentStart = waitForNextDocumentStart(webProgress); + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + const secondLocation = "http://example.com/document-builder.sjs?html=com"; + loaded = BrowserTestUtils.browserLoaded(browser); + BrowserTestUtils.loadURIString(browser, secondLocation); + await loaded; + + const secondPageBrowsingContext = browser.browsingContext; + if (isBfcacheInParentEnabled) { + isnot( + firstPageBrowsingContext, + secondPageBrowsingContext, + "With bfcache in parent, navigations spawn a new BrowsingContext" + ); + } else { + is( + firstPageBrowsingContext, + secondPageBrowsingContext, + "Without bfcache in parent, navigations reuse the same BrowsingContext" + ); + } + { + const { browsingContext, location, request, flags } = + await onSecondLocationChanged; + is( + browsingContext, + secondPageBrowsingContext, + "Second location change fires on the new BrowsingContext" + ); + ok(location instanceof Ci.nsIURI); + is(location.spec, secondLocation); + ok(request instanceof Ci.nsIChannel); + is(request.URI.spec, secondLocation); + is(flags, 0); + } + { + const { browsingContext, request } = await onSecondPageDocumentStart; + is( + browsingContext, + firstPageBrowsingContext, + "STATE_START, when navigating to another process, fires on the BrowsingContext we navigate *from*" + ); + ok(request instanceof Ci.nsIChannel); + is(request.URI.spec, secondLocation); + } + + const onBackLocationChanged = waitForNextLocationChange(webProgress, true); + const onBackDocumentStart = waitForNextDocumentStart(webProgress); + browser.goBack(); + + { + const { browsingContext, location, request, flags } = + await onBackLocationChanged; + is( + browsingContext, + firstPageBrowsingContext, + "location change, when navigating back, fires on the BrowsingContext we navigate *to*" + ); + ok(location instanceof Ci.nsIURI); + is(location.spec, newLocation); + ok(request instanceof Ci.nsIChannel); + is(request.URI.spec, newLocation); + is(flags, 0); + } + { + const { browsingContext, request } = await onBackDocumentStart; + is( + browsingContext, + secondPageBrowsingContext, + "STATE_START, when navigating back, fires on the BrowsingContext we navigate *from*" + ); + ok(request instanceof Ci.nsIChannel); + is(request.URI.spec, newLocation); + } + + BrowserTestUtils.removeTab(tab); +}); + +function waitForNextLocationChange(webProgress, onlyTopLevel = false) { + return new Promise(resolve => { + const wpl = { + QueryInterface: ChromeUtils.generateQI([ + "nsIWebProgressListener", + "nsISupportsWeakReference", + ]), + onLocationChange(progress, request, location, flags) { + if (onlyTopLevel && progress.browsingContext.parent) { + // Ignore non-toplevel. + return; + } + webProgress.removeProgressListener(wpl, Ci.nsIWebProgress.NOTIFY_ALL); + resolve({ + browsingContext: progress.browsingContext, + location, + request, + flags, + }); + }, + }; + // Add a strong reference to the progress listener. + resolve.wpl = wpl; + webProgress.addProgressListener(wpl, Ci.nsIWebProgress.NOTIFY_ALL); + }); +} + +function waitForNextDocumentStart(webProgress) { + return new Promise(resolve => { + const wpl = { + QueryInterface: ChromeUtils.generateQI([ + "nsIWebProgressListener", + "nsISupportsWeakReference", + ]), + onStateChange(progress, request, flags, status) { + if ( + flags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT && + flags & Ci.nsIWebProgressListener.STATE_START + ) { + webProgress.removeProgressListener(wpl, Ci.nsIWebProgress.NOTIFY_ALL); + resolve({ browsingContext: progress.browsingContext, request }); + } + }, + }; + // Add a strong reference to the progress listener. + resolve.wpl = wpl; + webProgress.addProgressListener(wpl, Ci.nsIWebProgress.NOTIFY_ALL); + }); +} diff --git a/docshell/test/browser/browser_browsing_context_attached.js b/docshell/test/browser/browser_browsing_context_attached.js new file mode 100644 index 0000000000..60ef5e4aa6 --- /dev/null +++ b/docshell/test/browser/browser_browsing_context_attached.js @@ -0,0 +1,179 @@ +"use strict"; + +const TEST_PATH = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com" + ) + "dummy_page.html"; + +const TOPIC = "browsing-context-attached"; + +async function observeAttached(callback) { + let attached = new Map(); + + function observer(subject, topic, data) { + is(topic, TOPIC, "observing correct topic"); + ok(BrowsingContext.isInstance(subject), "subject to be a BrowsingContext"); + is(typeof data, "string", "data to be a String"); + info(`*** bc id=${subject.id}, why=${data}`); + attached.set(subject.id, { browsingContext: subject, why: data }); + } + + Services.obs.addObserver(observer, TOPIC); + try { + await callback(); + return attached; + } finally { + Services.obs.removeObserver(observer, TOPIC); + } +} + +add_task(async function toplevelForNewWindow() { + let win; + + let attached = await observeAttached(async () => { + win = await BrowserTestUtils.openNewBrowserWindow(); + }); + + ok( + attached.has(win.browsingContext.id), + "got notification for window's chrome browsing context" + ); + is( + attached.get(win.browsingContext.id).why, + "attach", + "expected reason for chrome browsing context" + ); + + ok( + attached.has(win.gBrowser.selectedBrowser.browsingContext.id), + "got notification for toplevel browsing context" + ); + is( + attached.get(win.gBrowser.selectedBrowser.browsingContext.id).why, + "attach", + "expected reason for toplevel browsing context" + ); + + await BrowserTestUtils.closeWindow(win); +}); + +add_task(async function toplevelForNewTab() { + let tab; + + let attached = await observeAttached(async () => { + tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + }); + + ok( + !attached.has(window.browsingContext.id), + "no notification for the current window's chrome browsing context" + ); + ok( + attached.has(tab.linkedBrowser.browsingContext.id), + "got notification for toplevel browsing context" + ); + is( + attached.get(tab.linkedBrowser.browsingContext.id).why, + "attach", + "expected reason for toplevel browsing context" + ); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function subframe() { + let browsingContext; + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + + let attached = await observeAttached(async () => { + browsingContext = await SpecialPowers.spawn(tab.linkedBrowser, [], () => { + let iframe = content.document.createElement("iframe"); + content.document.body.appendChild(iframe); + iframe.contentWindow.location = "https://example.com/"; + return iframe.browsingContext; + }); + }); + + ok( + !attached.has(window.browsingContext.id), + "no notification for the current window's chrome browsing context" + ); + ok( + !attached.has(tab.linkedBrowser.browsingContext.id), + "no notification for toplevel browsing context" + ); + ok( + attached.has(browsingContext.id), + "got notification for frame's browsing context" + ); + is( + attached.get(browsingContext.id).why, + "attach", + "expected reason for frame's browsing context" + ); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function toplevelReplacedBy() { + let tab; + + let attached = await observeAttached(async () => { + tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:robots"); + }); + + const firstContext = tab.linkedBrowser.browsingContext; + ok( + attached.has(firstContext.id), + "got notification for initial toplevel browsing context" + ); + is( + attached.get(firstContext.id).why, + "attach", + "expected reason for initial toplevel browsing context" + ); + + attached = await observeAttached(async () => { + await loadURI(TEST_PATH); + }); + const secondContext = tab.linkedBrowser.browsingContext; + ok( + attached.has(secondContext.id), + "got notification for replaced toplevel browsing context" + ); + isnot(secondContext, firstContext, "browsing context to be replaced"); + is( + attached.get(secondContext.id).why, + "replace", + "expected reason for replaced toplevel browsing context" + ); + is( + secondContext.browserId, + firstContext.browserId, + "browserId has been kept" + ); + + attached = await observeAttached(async () => { + await loadURI("about:robots"); + }); + const thirdContext = tab.linkedBrowser.browsingContext; + ok( + attached.has(thirdContext.id), + "got notification for replaced toplevel browsing context" + ); + isnot(thirdContext, secondContext, "browsing context to be replaced"); + is( + attached.get(thirdContext.id).why, + "replace", + "expected reason for replaced toplevel browsing context" + ); + is( + thirdContext.browserId, + secondContext.browserId, + "browserId has been kept" + ); + + BrowserTestUtils.removeTab(tab); +}); diff --git a/docshell/test/browser/browser_browsing_context_discarded.js b/docshell/test/browser/browser_browsing_context_discarded.js new file mode 100644 index 0000000000..a300737d4f --- /dev/null +++ b/docshell/test/browser/browser_browsing_context_discarded.js @@ -0,0 +1,65 @@ +"use strict"; + +const TOPIC = "browsing-context-discarded"; + +async function observeDiscarded(browsingContexts, callback) { + let discarded = []; + + let promise = BrowserUtils.promiseObserved(TOPIC, subject => { + ok(BrowsingContext.isInstance(subject), "subject to be a BrowsingContext"); + discarded.push(subject); + + return browsingContexts.every(item => discarded.includes(item)); + }); + await callback(); + await promise; + + return discarded; +} + +add_task(async function toplevelForNewWindow() { + let win = await BrowserTestUtils.openNewBrowserWindow(); + let browsingContext = win.gBrowser.selectedBrowser.browsingContext; + + await observeDiscarded([win.browsingContext, browsingContext], async () => { + await BrowserTestUtils.closeWindow(win); + }); +}); + +add_task(async function toplevelForNewTab() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + let browsingContext = tab.linkedBrowser.browsingContext; + + let discarded = await observeDiscarded([browsingContext], () => { + BrowserTestUtils.removeTab(tab); + }); + + ok( + !discarded.includes(window.browsingContext), + "no notification for the current window's chrome browsing context" + ); +}); + +add_task(async function subframe() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + let browsingContext = await SpecialPowers.spawn(tab.linkedBrowser, [], () => { + let iframe = content.document.createElement("iframe"); + content.document.body.appendChild(iframe); + iframe.contentWindow.location = "https://example.com/"; + return iframe.browsingContext; + }); + + let discarded = await observeDiscarded([browsingContext], async () => { + await SpecialPowers.spawn(tab.linkedBrowser, [], () => { + let iframe = content.document.querySelector("iframe"); + iframe.remove(); + }); + }); + + ok( + !discarded.includes(tab.browsingContext), + "no notification for toplevel browsing context" + ); + + BrowserTestUtils.removeTab(tab); +}); diff --git a/docshell/test/browser/browser_bug1206879.js b/docshell/test/browser/browser_bug1206879.js new file mode 100644 index 0000000000..38e17633b8 --- /dev/null +++ b/docshell/test/browser/browser_bug1206879.js @@ -0,0 +1,50 @@ +add_task(async function () { + let url = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com/" + ) + "file_bug1206879.html"; + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url, true); + + let numLocationChanges = await SpecialPowers.spawn( + tab.linkedBrowser, + [], + async function () { + let webprogress = content.docShell.QueryInterface(Ci.nsIWebProgress); + let locationChangeCount = 0; + let listener = { + onLocationChange(aWebProgress, aRequest, aLocation, aFlags) { + info("onLocationChange: " + aLocation.spec); + locationChangeCount++; + this.resolve(); + }, + QueryInterface: ChromeUtils.generateQI([ + "nsIWebProgressListener", + "nsISupportsWeakReference", + ]), + }; + let locationPromise = new Promise((resolve, reject) => { + listener.resolve = resolve; + }); + webprogress.addProgressListener( + listener, + Ci.nsIWebProgress.NOTIFY_LOCATION + ); + + content.frames[0].history.pushState(null, null, "foo"); + + await locationPromise; + webprogress.removeProgressListener(listener); + + return locationChangeCount; + } + ); + + gBrowser.removeTab(tab); + is( + numLocationChanges, + 1, + "pushState with a different URI should cause a LocationChange event." + ); +}); diff --git a/docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js b/docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js new file mode 100644 index 0000000000..9b99698367 --- /dev/null +++ b/docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(async function runTests() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.navigation.requireUserInteraction", false]], + }); + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:about" + ); + + registerCleanupFunction(function () { + gBrowser.removeTab(tab); + }); + + let browser = tab.linkedBrowser; + + let loaded = BrowserTestUtils.browserLoaded(browser); + BrowserTestUtils.loadURIString(browser, "about:config"); + let href = await loaded; + is(href, "about:config", "Check about:config loaded"); + + // Using a dummy onunload listener to disable the bfcache as that can prevent + // the test browser load detection mechanism from working. + loaded = BrowserTestUtils.browserLoaded(browser); + BrowserTestUtils.loadURIString( + browser, + "data:text/html," + ); + href = await loaded; + is( + href, + "data:text/html,", + "Check data URL loaded" + ); + + loaded = BrowserTestUtils.browserLoaded(browser); + browser.goBack(); + href = await loaded; + is(href, "about:config", "Check we've gone back to about:config"); + + loaded = BrowserTestUtils.browserLoaded(browser); + browser.goForward(); + href = await loaded; + is( + href, + "data:text/html,", + "Check we've gone forward to data URL" + ); +}); diff --git a/docshell/test/browser/browser_bug1328501.js b/docshell/test/browser/browser_bug1328501.js new file mode 100644 index 0000000000..2be74b04d0 --- /dev/null +++ b/docshell/test/browser/browser_bug1328501.js @@ -0,0 +1,69 @@ +const HTML_URL = + "http://mochi.test:8888/browser/docshell/test/browser/file_bug1328501.html"; +const FRAME_URL = + "http://mochi.test:8888/browser/docshell/test/browser/file_bug1328501_frame.html"; +const FRAME_SCRIPT_URL = + "chrome://mochitests/content/browser/docshell/test/browser/file_bug1328501_framescript.js"; +add_task(async function testMultiFrameRestore() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.navigation.requireUserInteraction", false], + // Disable bfcache so that dummy_page.html doesn't enter there. + // The actual test page does already prevent bfcache and the test + // is just for http-on-opening-request handling in the child process. + ["browser.sessionhistory.max_total_viewers", 0], + ], + }); + await BrowserTestUtils.withNewTab( + { gBrowser, url: HTML_URL }, + async function (browser) { + // Navigate 2 subframes and load about:blank. + let browserLoaded = BrowserTestUtils.browserLoaded(browser); + await SpecialPowers.spawn( + browser, + [FRAME_URL], + async function (FRAME_URL) { + function frameLoaded(frame) { + frame.contentWindow.location = FRAME_URL; + return new Promise(r => (frame.onload = r)); + } + let frame1 = content.document.querySelector("#testFrame1"); + let frame2 = content.document.querySelector("#testFrame2"); + ok(frame1, "check found testFrame1"); + ok(frame2, "check found testFrame2"); + await frameLoaded(frame1); + await frameLoaded(frame2); + content.location = "dummy_page.html"; + } + ); + await browserLoaded; + + // Load a frame script to query nsIDOMWindow on "http-on-opening-request", + // which will force about:blank content viewers being created. + browser.messageManager.loadFrameScript(FRAME_SCRIPT_URL, false); + + // The frame script also forwards frames-loaded. + let framesLoaded = BrowserTestUtils.waitForMessage( + browser.messageManager, + "test:frames-loaded" + ); + + browser.goBack(); + await framesLoaded; + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(r => setTimeout(r, 1000)); + await SpecialPowers.spawn(browser, [FRAME_URL], FRAME_URL => { + is( + content.document.querySelector("#testFrame1").contentWindow.location + .href, + FRAME_URL + ); + is( + content.document.querySelector("#testFrame2").contentWindow.location + .href, + FRAME_URL + ); + }); + } + ); +}); diff --git a/docshell/test/browser/browser_bug1347823.js b/docshell/test/browser/browser_bug1347823.js new file mode 100644 index 0000000000..53a968dc12 --- /dev/null +++ b/docshell/test/browser/browser_bug1347823.js @@ -0,0 +1,91 @@ +/** + * Test that session history's expiration tracker would remove bfcache on + * expiration. + */ + +// With bfcache not expired. +add_task(async function testValidCache() { + // Make an unrealistic large timeout. + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.sessionhistory.contentViewerTimeout", 86400], + // If Fission is disabled, the pref is no-op. + ["fission.bfcacheInParent", true], + ], + }); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "data:text/html;charset=utf-8,pageA1" }, + async function (browser) { + // Make a simple modification for bfcache testing. + await SpecialPowers.spawn(browser, [], () => { + content.document.body.textContent = "modified"; + }); + + // Load a random page. + BrowserTestUtils.loadURIString( + browser, + "data:text/html;charset=utf-8,pageA2" + ); + await BrowserTestUtils.browserLoaded(browser); + + // Go back and verify text content. + let awaitPageShow = BrowserTestUtils.waitForContentEvent( + browser, + "pageshow" + ); + browser.goBack(); + await awaitPageShow; + await SpecialPowers.spawn(browser, [], () => { + is(content.document.body.textContent, "modified"); + }); + } + ); +}); + +// With bfcache expired. +add_task(async function testExpiredCache() { + // Make bfcache timeout in 1 sec. + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.sessionhistory.contentViewerTimeout", 1], + // If Fission is disabled, the pref is no-op. + ["fission.bfcacheInParent", true], + ], + }); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "data:text/html;charset=utf-8,pageB1" }, + async function (browser) { + // Make a simple modification for bfcache testing. + await SpecialPowers.spawn(browser, [], () => { + content.document.body.textContent = "modified"; + }); + + // Load a random page. + BrowserTestUtils.loadURIString( + browser, + "data:text/html;charset=utf-8,pageB2" + ); + await BrowserTestUtils.browserLoaded(browser); + + // Wait for 3 times of expiration timeout, hopefully it's evicted... + await SpecialPowers.spawn(browser, [], () => { + return new Promise(resolve => { + content.setTimeout(resolve, 5000); + }); + }); + + // Go back and verify text content. + let awaitPageShow = BrowserTestUtils.waitForContentEvent( + browser, + "pageshow" + ); + browser.goBack(); + await awaitPageShow; + await SpecialPowers.spawn(browser, [], () => { + is(content.document.body.textContent, "pageB1"); + }); + } + ); +}); diff --git a/docshell/test/browser/browser_bug134911.js b/docshell/test/browser/browser_bug134911.js new file mode 100644 index 0000000000..9b52eeab47 --- /dev/null +++ b/docshell/test/browser/browser_bug134911.js @@ -0,0 +1,57 @@ +const TEXT = { + /* The test text decoded correctly as Shift_JIS */ + rightText: + "\u30E6\u30CB\u30B3\u30FC\u30C9\u306F\u3001\u3059\u3079\u3066\u306E\u6587\u5B57\u306B\u56FA\u6709\u306E\u756A\u53F7\u3092\u4ED8\u4E0E\u3057\u307E\u3059", + + enteredText1: "The quick brown fox jumps over the lazy dog", + enteredText2: + "\u03BE\u03B5\u03C3\u03BA\u03B5\u03C0\u03AC\u03B6\u03C9\u0020\u03C4\u1F74\u03BD\u0020\u03C8\u03C5\u03C7\u03BF\u03C6\u03B8\u03CC\u03C1\u03B1\u0020\u03B2\u03B4\u03B5\u03BB\u03C5\u03B3\u03BC\u03AF\u03B1", +}; + +function test() { + waitForExplicitFinish(); + + var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/"; + gBrowser.selectedTab = BrowserTestUtils.addTab( + gBrowser, + rootDir + "test-form_sjis.html" + ); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterOpen); +} + +function afterOpen() { + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then( + afterChangeCharset + ); + + SpecialPowers.spawn(gBrowser.selectedBrowser, [TEXT], function (TEXT) { + content.document.getElementById("testtextarea").value = TEXT.enteredText1; + content.document.getElementById("testinput").value = TEXT.enteredText2; + }).then(() => { + /* Force the page encoding to Shift_JIS */ + BrowserForceEncodingDetection(); + }); +} + +function afterChangeCharset() { + SpecialPowers.spawn(gBrowser.selectedBrowser, [TEXT], function (TEXT) { + is( + content.document.getElementById("testpar").innerHTML, + TEXT.rightText, + "encoding successfully changed" + ); + is( + content.document.getElementById("testtextarea").value, + TEXT.enteredText1, + "text preserved in + +

+ +

Expected text on load:

+

ѓ†ѓjѓRЃ[ѓh‚НЃA‚·‚Ч‚Д‚М•¶Ћљ‚ЙЊЕ—L‚М”ФЌ†‚р•t—^‚µ‚Ь‚·

+

Expected text on resetting the encoding to Shift_JIS:

+

ユニコードは、すべての文字に固有の番号を付与します

+ + -- cgit v1.2.3