From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../base/content/test/about/POSTSearchEngine.xml | 6 + browser/base/content/test/about/browser.ini | 59 + .../content/test/about/browser_aboutCertError.js | 548 ++++++ .../test/about/browser_aboutCertError_clockSkew.js | 153 ++ .../test/about/browser_aboutCertError_exception.js | 221 +++ .../test/about/browser_aboutCertError_mitm.js | 158 ++ .../browser_aboutCertError_noSubjectAltName.js | 67 + .../about/browser_aboutCertError_offlineSupport.js | 51 + .../test/about/browser_aboutCertError_telemetry.js | 164 ++ .../test/about/browser_aboutDialog_distribution.js | 66 + .../test/about/browser_aboutHome_search_POST.js | 104 ++ .../about/browser_aboutHome_search_composing.js | 110 ++ .../about/browser_aboutHome_search_searchbar.js | 44 + .../about/browser_aboutHome_search_suggestion.js | 78 + .../about/browser_aboutHome_search_telemetry.js | 101 + .../content/test/about/browser_aboutNetError.js | 245 +++ .../test/about/browser_aboutNetError_csp_iframe.js | 153 ++ .../about/browser_aboutNetError_native_fallback.js | 174 ++ .../test/about/browser_aboutNetError_trr.js | 189 ++ .../test/about/browser_aboutNetError_xfo_iframe.js | 139 ++ .../about/browser_aboutNewTab_bookmarksToolbar.js | 311 ++++ .../browser_aboutNewTab_bookmarksToolbarEmpty.js | 158 ++ ...rowser_aboutNewTab_bookmarksToolbarNewWindow.js | 82 + .../browser_aboutNewTab_bookmarksToolbarPrefs.js | 74 + .../content/test/about/browser_aboutStopReload.js | 169 ++ .../content/test/about/browser_aboutSupport.js | 146 ++ .../browser_aboutSupport_newtab_security_state.js | 19 + .../test/about/browser_aboutSupport_places.js | 45 + .../base/content/test/about/browser_bug435325.js | 58 + .../base/content/test/about/browser_bug633691.js | 32 + browser/base/content/test/about/csp_iframe.sjs | 33 + browser/base/content/test/about/dummy_page.html | 9 + browser/base/content/test/about/head.js | 220 +++ .../base/content/test/about/iframe_page_csp.html | 16 + .../base/content/test/about/iframe_page_xfo.html | 16 + browser/base/content/test/about/print_postdata.sjs | 25 + .../content/test/about/searchSuggestionEngine.sjs | 9 + .../content/test/about/searchSuggestionEngine.xml | 11 + .../base/content/test/about/slow_loading_page.sjs | 29 + browser/base/content/test/about/xfo_iframe.sjs | 34 + browser/base/content/test/alerts/browser.ini | 22 + .../test/alerts/browser_notification_close.js | 107 ++ .../alerts/browser_notification_do_not_disturb.js | 160 ++ .../alerts/browser_notification_open_settings.js | 80 + .../browser_notification_remove_permission.js | 86 + .../test/alerts/browser_notification_replace.js | 66 + .../alerts/browser_notification_tab_switching.js | 117 ++ .../test/alerts/file_dom_notifications.html | 39 + browser/base/content/test/alerts/head.js | 73 + browser/base/content/test/backforward/browser.ini | 2 + .../test/backforward/browser_history_menu.js | 175 ++ browser/base/content/test/caps/browser.ini | 6 + .../caps/browser_principalSerialization_csp.js | 106 ++ .../caps/browser_principalSerialization_json.js | 161 ++ .../browser_principalSerialization_version1.js | 159 ++ .../base/content/test/captivePortal/browser.ini | 12 + .../captivePortal/browser_CaptivePortalWatcher.js | 125 ++ .../browser_CaptivePortalWatcher_1.js | 108 ++ .../browser_captivePortalTabReference.js | 65 + .../browser_captivePortal_certErrorUI.js | 221 +++ .../browser_captivePortal_https_only.js | 73 + .../browser_closeCapPortalTabCanonicalURL.js | 152 ++ browser/base/content/test/captivePortal/head.js | 260 +++ browser/base/content/test/chrome/chrome.ini | 4 + .../content/test/chrome/test_aboutCrashed.xhtml | 77 + .../test/chrome/test_aboutRestartRequired.xhtml | 76 + browser/base/content/test/contentTheme/browser.ini | 3 + .../browser_contentTheme_in_process_tab.js | 80 + browser/base/content/test/contextMenu/browser.ini | 91 + .../content/test/contextMenu/browser_bug1798178.js | 89 + .../test/contextMenu/browser_contextmenu.js | 1943 ++++++++++++++++++++ .../contextMenu/browser_contextmenu_badiframe.js | 182 ++ .../browser_contextmenu_contenteditable.js | 118 ++ .../test/contextMenu/browser_contextmenu_iframe.js | 73 + .../test/contextMenu/browser_contextmenu_input.js | 387 ++++ .../contextMenu/browser_contextmenu_inspect.js | 61 + .../contextMenu/browser_contextmenu_keyword.js | 198 ++ .../contextMenu/browser_contextmenu_linkopen.js | 109 ++ .../browser_contextmenu_loadblobinnewtab.html | 56 + .../browser_contextmenu_loadblobinnewtab.js | 186 ++ .../browser_contextmenu_save_blocked.js | 78 + .../browser_contextmenu_share_macosx.js | 144 ++ .../contextMenu/browser_contextmenu_share_win.js | 77 + .../contextMenu/browser_contextmenu_shareurl.html | 2 + .../contextMenu/browser_contextmenu_spellcheck.js | 334 ++++ .../test/contextMenu/browser_contextmenu_touch.js | 94 + .../test/contextMenu/browser_copy_image_link.js | 40 + .../contextMenu/browser_strip_on_share_link.js | 151 ++ .../test/contextMenu/browser_utilityOverlay.js | 78 + .../contextMenu/browser_utilityOverlayPrincipal.js | 72 + .../content/test/contextMenu/browser_view_image.js | 197 ++ .../base/content/test/contextMenu/bug1798178.sjs | 9 + .../content/test/contextMenu/contextmenu_common.js | 437 +++++ .../content/test/contextMenu/ctxmenu-image.png | Bin 0 -> 5401 bytes browser/base/content/test/contextMenu/doggy.png | Bin 0 -> 46876 bytes .../content/test/contextMenu/file_bug1798178.html | 5 + browser/base/content/test/contextMenu/firebird.png | Bin 0 -> 16179 bytes .../content/test/contextMenu/firebird.png^headers^ | 2 + .../test/contextMenu/subtst_contextmenu.html | 61 + .../test/contextMenu/subtst_contextmenu_input.html | 30 + .../contextMenu/subtst_contextmenu_keyword.html | 17 + .../contextMenu/subtst_contextmenu_webext.html | 12 + .../test/contextMenu/subtst_contextmenu_xul.xhtml | 9 + .../test/contextMenu/test_contextmenu_iframe.html | 11 + .../test/contextMenu/test_contextmenu_links.html | 14 + .../contextMenu/test_view_image_inline_svg.html | 15 + .../test_view_image_revoked_cached_blob.html | 40 + browser/base/content/test/favicons/accept.html | 9 + browser/base/content/test/favicons/accept.sjs | 15 + browser/base/content/test/favicons/auth_test.html | 11 + browser/base/content/test/favicons/auth_test.png | 0 .../content/test/favicons/auth_test.png^headers^ | 2 + browser/base/content/test/favicons/blank.html | 6 + browser/base/content/test/favicons/browser.ini | 113 ++ .../content/test/favicons/browser_bug408415.js | 34 + .../content/test/favicons/browser_bug550565.js | 35 + .../test/favicons/browser_favicon_accept.js | 30 + .../content/test/favicons/browser_favicon_auth.js | 27 + .../content/test/favicons/browser_favicon_cache.js | 50 + .../test/favicons/browser_favicon_change.js | 33 + .../browser_favicon_change_not_in_document.js | 55 + .../test/favicons/browser_favicon_credentials.js | 89 + .../test/favicons/browser_favicon_crossorigin.js | 61 + .../content/test/favicons/browser_favicon_load.js | 168 ++ .../test/favicons/browser_favicon_nostore.js | 169 ++ .../test/favicons/browser_favicon_referer.js | 62 + .../content/test/favicons/browser_favicon_store.js | 56 + .../test/favicons/browser_icon_discovery.js | 136 ++ .../test/favicons/browser_invalid_href_fallback.js | 29 + .../test/favicons/browser_missing_favicon.js | 36 + .../content/test/favicons/browser_mixed_content.js | 26 + .../browser_multiple_icons_in_short_timeframe.js | 37 + .../content/test/favicons/browser_oversized.js | 25 + .../test/favicons/browser_preferred_icons.js | 140 ++ .../base/content/test/favicons/browser_redirect.js | 20 + .../content/test/favicons/browser_rich_icons.js | 50 + .../base/content/test/favicons/browser_rooticon.js | 24 + .../favicons/browser_subframe_favicons_not_used.js | 22 + .../content/test/favicons/browser_title_flicker.js | 185 ++ .../base/content/test/favicons/cookie_favicon.html | 11 + .../base/content/test/favicons/cookie_favicon.sjs | 26 + browser/base/content/test/favicons/credentials.png | Bin 0 -> 580 bytes .../content/test/favicons/credentials.png^headers^ | 3 + .../base/content/test/favicons/credentials1.html | 10 + .../base/content/test/favicons/credentials2.html | 10 + .../base/content/test/favicons/crossorigin.html | 10 + browser/base/content/test/favicons/crossorigin.png | Bin 0 -> 580 bytes .../content/test/favicons/crossorigin.png^headers^ | 1 + .../content/test/favicons/datauri-favicon.html | 8 + browser/base/content/test/favicons/discovery.html | 8 + .../test/favicons/file_bug970276_favicon1.ico | Bin 0 -> 1406 bytes .../test/favicons/file_bug970276_favicon2.ico | Bin 0 -> 1406 bytes .../test/favicons/file_bug970276_popup1.html | 14 + .../test/favicons/file_bug970276_popup2.html | 12 + .../base/content/test/favicons/file_favicon.html | 11 + .../base/content/test/favicons/file_favicon.png | Bin 0 -> 344 bytes .../test/favicons/file_favicon.png^headers^ | 1 + .../content/test/favicons/file_favicon_change.html | 13 + .../file_favicon_change_not_in_document.html | 20 + .../test/favicons/file_favicon_no_referrer.html | 11 + .../test/favicons/file_favicon_redirect.html | 12 + .../test/favicons/file_favicon_redirect.ico | 0 .../favicons/file_favicon_redirect.ico^headers^ | 2 + .../test/favicons/file_favicon_thirdParty.html | 11 + .../content/test/favicons/file_generic_favicon.ico | Bin 0 -> 1406 bytes .../test/favicons/file_insecure_favicon.html | 11 + .../content/test/favicons/file_invalid_href.html | 12 + .../base/content/test/favicons/file_mask_icon.html | 11 + .../base/content/test/favicons/file_rich_icon.html | 12 + .../content/test/favicons/file_with_favicon.html | 12 + .../test/favicons/file_with_slow_favicon.html | 10 + browser/base/content/test/favicons/head.js | 98 + browser/base/content/test/favicons/icon.svg | 11 + browser/base/content/test/favicons/large.png | Bin 0 -> 21237 bytes .../base/content/test/favicons/large_favicon.html | 12 + browser/base/content/test/favicons/moz.png | Bin 0 -> 580 bytes browser/base/content/test/favicons/no-store.html | 11 + browser/base/content/test/favicons/no-store.png | Bin 0 -> 580 bytes .../content/test/favicons/no-store.png^headers^ | 1 + browser/base/content/test/favicons/rich_moz_1.png | Bin 0 -> 580 bytes browser/base/content/test/favicons/rich_moz_2.png | Bin 0 -> 580 bytes browser/base/content/test/forms/browser.ini | 21 + .../base/content/test/forms/browser_selectpopup.js | 913 +++++++++ .../test/forms/browser_selectpopup_colors.js | 867 +++++++++ .../content/test/forms/browser_selectpopup_dir.js | 21 + .../test/forms/browser_selectpopup_large.js | 338 ++++ .../test/forms/browser_selectpopup_searchfocus.js | 36 + .../forms/browser_selectpopup_text_transform.js | 40 + .../test/forms/browser_selectpopup_toplevel.js | 19 + .../test/forms/browser_selectpopup_user_input.js | 90 + .../test/forms/browser_selectpopup_width.js | 49 + .../test/forms/browser_selectpopup_xhtml.js | 36 + browser/base/content/test/forms/head.js | 51 + .../test/fullscreen/FullscreenFrame.sys.mjs | 103 ++ browser/base/content/test/fullscreen/browser.ini | 31 + .../content/test/fullscreen/browser_bug1557041.js | 47 + .../content/test/fullscreen/browser_bug1620341.js | 108 ++ .../fullscreen/browser_fullscreen_api_fission.js | 252 +++ .../fullscreen/browser_fullscreen_context_menu.js | 142 ++ .../fullscreen/browser_fullscreen_cross_origin.js | 64 + .../fullscreen/browser_fullscreen_enterInUrlbar.js | 56 + .../fullscreen/browser_fullscreen_from_minimize.js | 82 + .../browser_fullscreen_keydown_reservation.js | 112 ++ .../test/fullscreen/browser_fullscreen_menus.js | 72 + .../test/fullscreen/browser_fullscreen_newtab.js | 55 + .../fullscreen/browser_fullscreen_newwindow.js | 83 + .../browser_fullscreen_permissions_prompt.js | 160 ++ .../test/fullscreen/browser_fullscreen_warning.js | 280 +++ .../fullscreen/browser_fullscreen_window_focus.js | 110 ++ .../fullscreen/browser_fullscreen_window_open.js | 102 + .../base/content/test/fullscreen/fullscreen.html | 12 + .../content/test/fullscreen/fullscreen_frame.html | 9 + browser/base/content/test/fullscreen/head.js | 164 ++ .../test/fullscreen/open_and_focus_helper.html | 56 + .../base/content/test/general/alltabslistener.html | 8 + .../base/content/test/general/app_bug575561.html | 18 + .../test/general/app_subframe_bug575561.html | 12 + browser/base/content/test/general/audio.ogg | Bin 0 -> 14293 bytes browser/base/content/test/general/browser.ini | 416 +++++ .../content/test/general/browser_accesskeys.js | 202 ++ .../test/general/browser_addCertException.js | 77 + .../test/general/browser_alltabslistener.js | 331 ++++ .../test/general/browser_backButtonFitts.js | 40 + .../browser_beforeunload_duplicate_dialogs.js | 114 ++ .../content/test/general/browser_bug1261299.js | 112 ++ .../content/test/general/browser_bug1297539.js | 122 ++ .../content/test/general/browser_bug1299667.js | 70 + .../base/content/test/general/browser_bug321000.js | 91 + .../base/content/test/general/browser_bug356571.js | 100 + .../base/content/test/general/browser_bug380960.js | 18 + .../base/content/test/general/browser_bug406216.js | 64 + .../base/content/test/general/browser_bug417483.js | 50 + .../base/content/test/general/browser_bug424101.js | 72 + .../base/content/test/general/browser_bug427559.js | 41 + .../base/content/test/general/browser_bug431826.js | 56 + .../base/content/test/general/browser_bug432599.js | 109 ++ .../base/content/test/general/browser_bug455852.js | 27 + .../base/content/test/general/browser_bug462289.js | 144 ++ .../base/content/test/general/browser_bug462673.js | 66 + .../base/content/test/general/browser_bug477014.js | 36 + .../base/content/test/general/browser_bug479408.js | 23 + .../test/general/browser_bug479408_sample.html | 4 + .../base/content/test/general/browser_bug481560.js | 16 + .../base/content/test/general/browser_bug484315.js | 14 + .../base/content/test/general/browser_bug491431.js | 42 + .../base/content/test/general/browser_bug495058.js | 53 + .../base/content/test/general/browser_bug519216.js | 48 + .../base/content/test/general/browser_bug520538.js | 27 + .../base/content/test/general/browser_bug521216.js | 68 + .../base/content/test/general/browser_bug533232.js | 56 + .../base/content/test/general/browser_bug537013.js | 168 ++ .../base/content/test/general/browser_bug537474.js | 20 + .../base/content/test/general/browser_bug563588.js | 42 + .../base/content/test/general/browser_bug565575.js | 21 + .../base/content/test/general/browser_bug567306.js | 65 + .../base/content/test/general/browser_bug575561.js | 118 ++ .../base/content/test/general/browser_bug577121.js | 27 + .../base/content/test/general/browser_bug578534.js | 31 + .../base/content/test/general/browser_bug579872.js | 26 + .../base/content/test/general/browser_bug581253.js | 74 + .../base/content/test/general/browser_bug585785.js | 48 + .../base/content/test/general/browser_bug585830.js | 27 + .../base/content/test/general/browser_bug594131.js | 25 + .../base/content/test/general/browser_bug596687.js | 28 + .../base/content/test/general/browser_bug597218.js | 40 + .../base/content/test/general/browser_bug609700.js | 28 + .../base/content/test/general/browser_bug623893.js | 50 + .../base/content/test/general/browser_bug624734.js | 49 + .../base/content/test/general/browser_bug664672.js | 27 + .../base/content/test/general/browser_bug676619.js | 225 +++ .../base/content/test/general/browser_bug710878.js | 49 + .../base/content/test/general/browser_bug724239.js | 56 + .../base/content/test/general/browser_bug734076.js | 195 ++ .../base/content/test/general/browser_bug749738.js | 32 + .../test/general/browser_bug763468_perwindowpb.js | 57 + .../test/general/browser_bug767836_perwindowpb.js | 72 + .../base/content/test/general/browser_bug817947.js | 51 + .../base/content/test/general/browser_bug832435.js | 26 + .../base/content/test/general/browser_bug882977.js | 33 + .../base/content/test/general/browser_bug963945.js | 26 + .../base/content/test/general/browser_clipboard.js | 290 +++ .../test/general/browser_clipboard_pastefile.js | 133 ++ .../test/general/browser_contentAltClick.js | 205 +++ .../test/general/browser_contentAreaClick.js | 329 ++++ .../base/content/test/general/browser_ctrlTab.js | 464 +++++ .../general/browser_datachoices_notification.js | 287 +++ .../test/general/browser_documentnavigation.js | 493 +++++ .../browser_domFullscreen_fullscreenMode.js | 237 +++ .../test/general/browser_double_close_tab.js | 120 ++ browser/base/content/test/general/browser_drag.js | 64 + .../content/test/general/browser_duplicateIDs.js | 11 + .../content/test/general/browser_findbarClose.js | 47 + .../content/test/general/browser_focusonkeydown.js | 34 + .../test/general/browser_fullscreen-window-open.js | 366 ++++ .../content/test/general/browser_gestureSupport.js | 1132 ++++++++++++ .../content/test/general/browser_hide_removing.js | 27 + .../base/content/test/general/browser_homeDrop.js | 117 ++ ...rowser_invalid_uri_back_forward_manipulation.js | 48 + .../test/general/browser_lastAccessedTab.js | 62 + .../test/general/browser_menuButtonFitts.js | 69 + .../test/general/browser_middleMouse_noJSPaste.js | 49 + .../base/content/test/general/browser_minimize.js | 49 + .../browser_modifiedclick_inherit_principal.js | 42 + .../content/test/general/browser_newTabDrop.js | 221 +++ .../content/test/general/browser_newWindowDrop.js | 230 +++ ...browser_new_http_window_opened_from_file_tab.js | 63 + .../test/general/browser_newwindow_focus.js | 93 + .../content/test/general/browser_plainTextLinks.js | 237 +++ .../content/test/general/browser_printpreview.js | 43 + .../general/browser_private_browsing_window.js | 133 ++ .../test/general/browser_private_no_prompt.js | 12 + .../content/test/general/browser_refreshBlocker.js | 209 +++ .../content/test/general/browser_relatedTabs.js | 74 + .../test/general/browser_remoteTroubleshoot.js | 130 ++ .../browser_remoteWebNavigation_postdata.js | 53 + .../test/general/browser_restore_isAppTab.js | 87 + .../test/general/browser_save_link-perwindowpb.js | 214 +++ .../browser_save_link_when_window_navigates.js | 197 ++ .../browser_save_private_link_perwindowpb.js | 127 ++ .../content/test/general/browser_save_video.js | 99 + .../test/general/browser_save_video_frame.js | 103 ++ .../test/general/browser_selectTabAtIndex.js | 89 + .../base/content/test/general/browser_star_hsts.js | 87 + .../content/test/general/browser_star_hsts.sjs | 12 + .../browser_storagePressure_notification.js | 182 ++ .../base/content/test/general/browser_tabDrop.js | 207 +++ .../general/browser_tab_close_dependent_window.js | 35 + .../test/general/browser_tab_detach_restore.js | 54 + .../general/browser_tab_drag_drop_perwindow.js | 423 +++++ .../content/test/general/browser_tab_dragdrop.js | 257 +++ .../content/test/general/browser_tab_dragdrop2.js | 65 + .../general/browser_tab_dragdrop2_frame1.xhtml | 158 ++ .../test/general/browser_tab_dragdrop_embed.html | 2 + .../base/content/test/general/browser_tabfocus.js | 811 ++++++++ .../test/general/browser_tabkeynavigation.js | 223 +++ .../general/browser_tabs_close_beforeunload.js | 69 + .../content/test/general/browser_tabs_isActive.js | 235 +++ .../content/test/general/browser_tabs_owner.js | 40 + ...r_testOpenNewRemoteTabsFromNonRemoteBrowsers.js | 144 ++ .../content/test/general/browser_typeAheadFind.js | 31 + .../general/browser_unknownContentType_title.js | 88 + .../content/test/general/browser_unloaddialogs.js | 40 + .../general/browser_viewSourceInTabOnViewSource.js | 60 + .../test/general/browser_visibleFindSelection.js | 62 + .../content/test/general/browser_visibleTabs.js | 125 ++ .../browser_visibleTabs_bookmarkAllPages.js | 35 + .../test/general/browser_visibleTabs_tabPreview.js | 52 + .../test/general/browser_windowactivation.js | 112 ++ .../content/test/general/browser_zbug569342.js | 77 + browser/base/content/test/general/bug792517-2.html | 5 + browser/base/content/test/general/bug792517.html | 5 + browser/base/content/test/general/bug792517.sjs | 13 + .../content/test/general/clipboard_pastefile.html | 52 + .../content/test/general/close_beforeunload.html | 8 + .../close_beforeunload_opens_second_tab.html | 3 + .../base/content/test/general/download_page.html | 72 + .../base/content/test/general/download_page_1.txt | 1 + .../base/content/test/general/download_page_2.txt | 1 + .../download_with_content_disposition_header.sjs | 19 + browser/base/content/test/general/dummy.ics | 13 + .../base/content/test/general/dummy.ics^headers^ | 1 + browser/base/content/test/general/dummy_page.html | 9 + .../general/file_documentnavigation_frameset.html | 12 + .../test/general/file_double_close_tab.html | 15 + .../test/general/file_fullscreen-window-open.html | 22 + .../test/general/file_window_activation.html | 4 + .../test/general/file_window_activation2.html | 1 + .../test/general/file_with_link_to_http.html | 9 + browser/base/content/test/general/head.js | 347 ++++ browser/base/content/test/general/moz.png | Bin 0 -> 580 bytes .../general/navigating_window_with_download.html | 7 + .../base/content/test/general/print_postdata.sjs | 25 + .../content/test/general/redirect_download.sjs | 11 + .../base/content/test/general/refresh_header.sjs | 24 + browser/base/content/test/general/refresh_meta.sjs | 36 + .../base/content/test/general/test_bug462673.html | 18 + .../base/content/test/general/test_bug628179.html | 9 + .../test/general/test_remoteTroubleshoot.html | 50 + browser/base/content/test/general/title_test.svg | 59 + .../test/general/unknownContentType_file.pif | 1 + .../general/unknownContentType_file.pif^headers^ | 1 + browser/base/content/test/general/video.ogg | Bin 0 -> 285310 bytes browser/base/content/test/general/web_video.html | 10 + browser/base/content/test/general/web_video1.ogv | Bin 0 -> 28942 bytes .../content/test/general/web_video1.ogv^headers^ | 3 + browser/base/content/test/gesture/browser.ini | 1 + .../test/gesture/browser_gesture_navigation.js | 233 +++ .../content/test/historySwipeAnimation/browser.ini | 1 + .../browser_historySwipeAnimation.js | 49 + browser/base/content/test/keyboard/browser.ini | 19 + .../test/keyboard/browser_bookmarks_shortcut.js | 140 ++ .../browser_cancel_caret_browsing_in_content.js | 91 + .../content/test/keyboard/browser_popup_keyNav.js | 50 + .../test/keyboard/browser_toolbarButtonKeyPress.js | 336 ++++ .../content/test/keyboard/browser_toolbarKeyNav.js | 641 +++++++ browser/base/content/test/keyboard/file_empty.html | 8 + .../content/test/keyboard/focusableContent.html | 1 + browser/base/content/test/keyboard/head.js | 55 + browser/base/content/test/menubar/browser.ini | 9 + .../test/menubar/browser_file_close_tabs.js | 60 + .../menubar/browser_file_menu_import_wizard.js | 27 + .../content/test/menubar/browser_file_share.js | 136 ++ .../base/content/test/menubar/file_shareurl.html | 2 + .../base/content/test/metaTags/bad_meta_tags.html | 14 + browser/base/content/test/metaTags/browser.ini | 9 + .../content/test/metaTags/browser_bad_meta_tags.js | 37 + .../content/test/metaTags/browser_meta_tags.js | 57 + browser/base/content/test/metaTags/head.js | 19 + browser/base/content/test/metaTags/meta_tags.html | 29 + .../base/content/test/notificationbox/browser.ini | 3 + .../browser_notification_stacking.js | 78 + .../browser_notificationbar_telemetry.js | 219 +++ .../browser_tabnotificationbox_switch_tabs.js | 142 ++ browser/base/content/test/outOfProcess/browser.ini | 15 + .../outOfProcess/browser_basic_outofprocess.js | 149 ++ .../test/outOfProcess/browser_controller.js | 127 ++ .../test/outOfProcess/browser_promisefocus.js | 262 +++ .../base/content/test/outOfProcess/file_base.html | 5 + .../content/test/outOfProcess/file_frame1.html | 5 + .../content/test/outOfProcess/file_frame2.html | 11 + .../content/test/outOfProcess/file_innerframe.html | 3 + browser/base/content/test/outOfProcess/head.js | 85 + browser/base/content/test/pageActions/browser.ini | 7 + .../pageActions/browser_PageActions_bookmark.js | 130 ++ .../pageActions/browser_PageActions_overflow.js | 257 +++ .../browser_PageActions_removeExtension.js | 338 ++++ browser/base/content/test/pageActions/head.js | 163 ++ browser/base/content/test/pageStyle/browser.ini | 16 + .../pageStyle/browser_disable_author_style_oop.js | 100 + .../test/pageStyle/browser_page_style_menu.js | 174 ++ .../pageStyle/browser_page_style_menu_update.js | 49 + browser/base/content/test/pageStyle/head.js | 30 + .../base/content/test/pageStyle/page_style.html | 8 + .../test/pageStyle/page_style_only_alternates.html | 5 + .../content/test/pageStyle/page_style_sample.html | 45 + browser/base/content/test/pageStyle/style.css | 1 + browser/base/content/test/pageinfo/all_images.html | 15 + browser/base/content/test/pageinfo/browser.ini | 27 + .../browser_pageinfo_firstPartyIsolation.js | 89 + .../test/pageinfo/browser_pageinfo_iframe_media.js | 31 + .../test/pageinfo/browser_pageinfo_image_info.js | 57 + .../test/pageinfo/browser_pageinfo_images.js | 93 + .../test/pageinfo/browser_pageinfo_permissions.js | 258 +++ .../content/test/pageinfo/browser_pageinfo_rtl.js | 28 + .../test/pageinfo/browser_pageinfo_security.js | 354 ++++ .../pageinfo/browser_pageinfo_separate_private.js | 49 + .../test/pageinfo/browser_pageinfo_svg_image.js | 34 + browser/base/content/test/pageinfo/iframes.html | 8 + browser/base/content/test/pageinfo/image.html | 5 + browser/base/content/test/pageinfo/svg_image.html | 11 + .../test/performance/PerfTestHelpers.sys.mjs | 79 + .../performance/StartupContentSubframe.sys.mjs | 55 + browser/base/content/test/performance/browser.ini | 90 + .../content/test/performance/browser_appmenu.js | 129 ++ .../test/performance/browser_panel_vsync.js | 69 + .../test/performance/browser_preferences_usage.js | 282 +++ .../content/test/performance/browser_startup.js | 245 +++ .../test/performance/browser_startup_content.js | 196 ++ .../browser_startup_content_mainthreadio.js | 438 +++++ .../browser_startup_content_subframe.js | 150 ++ .../test/performance/browser_startup_flicker.js | 85 + .../performance/browser_startup_hiddenwindow.js | 50 + .../test/performance/browser_startup_images.js | 136 ++ .../performance/browser_startup_mainthreadio.js | 881 +++++++++ .../test/performance/browser_startup_syncIPC.js | 449 +++++ .../content/test/performance/browser_tabclose.js | 108 ++ .../test/performance/browser_tabclose_grow.js | 91 + .../content/test/performance/browser_tabdetach.js | 118 ++ .../content/test/performance/browser_tabopen.js | 201 ++ .../test/performance/browser_tabopen_squeeze.js | 100 + .../browser_tabstrip_overflow_underflow.js | 200 ++ .../content/test/performance/browser_tabswitch.js | 123 ++ .../browser_toolbariconcolor_restyles.js | 65 + .../performance/browser_urlbar_keyed_search.js | 27 + .../test/performance/browser_urlbar_search.js | 27 + .../performance/browser_vsync_accessibility.js | 20 + .../test/performance/browser_window_resize.js | 132 ++ .../test/performance/browser_windowclose.js | 58 + .../content/test/performance/browser_windowopen.js | 182 ++ .../base/content/test/performance/file_empty.html | 1 + browser/base/content/test/performance/head.js | 971 ++++++++++ .../content/test/performance/hidpi/browser.ini | 7 + .../base/content/test/performance/io/browser.ini | 33 + .../content/test/performance/lowdpi/browser.ini | 8 + browser/base/content/test/performance/moz.build | 17 + browser/base/content/test/performance/triage.json | 62 + browser/base/content/test/perftest.ini | 1 + .../content/test/perftest_browser_xhtml_dom.js | 85 + browser/base/content/test/permissions/browser.ini | 41 + .../test/permissions/browser_autoplay_blocked.html | 14 + .../test/permissions/browser_autoplay_blocked.js | 357 ++++ .../permissions/browser_autoplay_blocked_slow.sjs | 36 + .../test/permissions/browser_autoplay_js.html | 16 + .../test/permissions/browser_autoplay_muted.html | 14 + .../browser_canvas_fingerprinting_resistance.js | 383 ++++ .../permissions/browser_canvas_rfp_exclusion.js | 194 ++ .../permissions/browser_permission_delegate_geo.js | 279 +++ .../test/permissions/browser_permissions.js | 569 ++++++ .../browser_permissions_delegate_vibrate.js | 46 + .../browser_permissions_handling_user_input.js | 99 + .../permissions/browser_permissions_postPrompt.js | 104 ++ .../test/permissions/browser_reservedkey.js | 312 ++++ .../permissions/browser_site_scoped_permissions.js | 106 ++ .../permissions/browser_temporary_permissions.js | 118 ++ .../browser_temporary_permissions_expiry.js | 208 +++ .../browser_temporary_permissions_navigation.js | 239 +++ .../browser_temporary_permissions_tabs.js | 148 ++ browser/base/content/test/permissions/dummy.js | 1 + browser/base/content/test/permissions/empty.html | 8 + browser/base/content/test/permissions/head.js | 28 + .../base/content/test/permissions/permissions.html | 49 + .../permissions/temporary_permissions_frame.html | 12 + .../temporary_permissions_subframe.html | 11 + browser/base/content/test/plugins/browser.ini | 14 + .../base/content/test/plugins/browser_bug797677.js | 45 + .../test/plugins/browser_enable_DRM_prompt.js | 232 +++ .../plugins/browser_globalplugin_crashinfobar.js | 63 + ...rowser_private_browsing_eme_persistent_state.js | 59 + browser/base/content/test/plugins/empty_file.html | 9 + browser/base/content/test/plugins/head.js | 205 +++ .../content/test/plugins/plugin_bug797677.html | 5 + browser/base/content/test/plugins/plugin_test.html | 9 + .../content/test/popupNotifications/browser.ini | 38 + .../test/popupNotifications/browser_displayURI.js | 159 ++ .../browser_popupNotification.js | 394 ++++ .../browser_popupNotification_2.js | 315 ++++ .../browser_popupNotification_3.js | 377 ++++ .../browser_popupNotification_4.js | 290 +++ .../browser_popupNotification_5.js | 501 +++++ .../browser_popupNotification_accesskey.js | 44 + .../browser_popupNotification_checkbox.js | 248 +++ ..._popupNotification_hide_after_identity_panel.js | 36 + ...pupNotification_hide_after_protections_panel.js | 44 + .../browser_popupNotification_keyboard.js | 273 +++ .../browser_popupNotification_learnmore.js | 64 + .../browser_popupNotification_no_anchors.js | 288 +++ .../browser_popupNotification_security_delay.js | 296 +++ ...browser_popupNotification_selection_required.js | 57 + .../browser_reshow_in_background.js | 72 + .../base/content/test/popupNotifications/head.js | 367 ++++ browser/base/content/test/popups/browser.ini | 69 + .../base/content/test/popups/browser_popupUI.js | 192 ++ .../content/test/popups/browser_popup_blocker.js | 155 ++ .../test/popups/browser_popup_blocker_frames.js | 100 + .../popups/browser_popup_blocker_identity_block.js | 242 +++ .../test/popups/browser_popup_blocker_iframes.js | 186 ++ .../test/popups/browser_popup_close_main_window.js | 84 + .../content/test/popups/browser_popup_frames.js | 128 ++ .../test/popups/browser_popup_inner_outer_size.js | 120 ++ .../test/popups/browser_popup_linux_move.js | 56 + .../test/popups/browser_popup_linux_resize.js | 53 + .../base/content/test/popups/browser_popup_move.js | 6 + .../test/popups/browser_popup_move_instant.js | 6 + .../test/popups/browser_popup_new_window_resize.js | 51 + .../test/popups/browser_popup_new_window_size.js | 90 + .../content/test/popups/browser_popup_resize.js | 6 + .../test/popups/browser_popup_resize_instant.js | 6 + .../test/popups/browser_popup_resize_repeat.js | 6 + .../popups/browser_popup_resize_repeat_instant.js | 6 + .../test/popups/browser_popup_resize_revert.js | 6 + .../popups/browser_popup_resize_revert_instant.js | 6 + browser/base/content/test/popups/head.js | 574 ++++++ .../base/content/test/popups/popup_blocker.html | 13 + .../base/content/test/popups/popup_blocker2.html | 10 + .../test/popups/popup_blocker_10_popups.html | 14 + .../base/content/test/popups/popup_blocker_a.html | 1 + .../base/content/test/popups/popup_blocker_b.html | 1 + .../content/test/popups/popup_blocker_frame.html | 27 + browser/base/content/test/popups/popup_size.html | 16 + .../content/test/protectionsUI/benignPage.html | 18 + .../base/content/test/protectionsUI/browser.ini | 63 + .../test/protectionsUI/browser_protectionsUI.js | 713 +++++++ .../test/protectionsUI/browser_protectionsUI_3.js | 224 +++ .../browser_protectionsUI_background_tabs.js | 74 + .../browser_protectionsUI_categories.js | 300 +++ .../browser_protectionsUI_cookie_banner.js | 475 +++++ .../browser_protectionsUI_cookies_subview.js | 537 ++++++ .../browser_protectionsUI_cryptominers.js | 306 +++ ...browser_protectionsUI_email_trackers_subview.js | 179 ++ .../protectionsUI/browser_protectionsUI_fetch.js | 39 + .../browser_protectionsUI_fingerprinters.js | 303 +++ .../browser_protectionsUI_icon_state.js | 223 +++ .../browser_protectionsUI_milestones.js | 95 + .../browser_protectionsUI_open_preferences.js | 155 ++ .../browser_protectionsUI_pbmode_exceptions.js | 175 ++ .../browser_protectionsUI_report_breakage.js | 404 ++++ .../browser_protectionsUI_shield_visibility.js | 124 ++ .../browser_protectionsUI_socialtracking.js | 321 ++++ .../protectionsUI/browser_protectionsUI_state.js | 405 ++++ .../browser_protectionsUI_state_reset.js | 129 ++ .../browser_protectionsUI_subview_shim.js | 403 ++++ .../browser_protectionsUI_telemetry.js | 89 + .../browser_protectionsUI_trackers_subview.js | 134 ++ .../content/test/protectionsUI/containerPage.html | 6 + .../content/test/protectionsUI/cookiePage.html | 13 + .../content/test/protectionsUI/cookieServer.sjs | 24 + .../test/protectionsUI/cookieSetterPage.html | 6 + .../test/protectionsUI/emailTrackingPage.html | 12 + .../content/test/protectionsUI/embeddedPage.html | 6 + .../protectionsUI/file_protectionsUI_fetch.html | 17 + .../test/protectionsUI/file_protectionsUI_fetch.js | 2 + .../file_protectionsUI_fetch.js^headers^ | 1 + browser/base/content/test/protectionsUI/head.js | 221 +++ .../base/content/test/protectionsUI/sandboxed.html | 12 + .../test/protectionsUI/sandboxed.html^headers^ | 1 + .../base/content/test/protectionsUI/trackingAPI.js | 77 + .../content/test/protectionsUI/trackingPage.html | 13 + browser/base/content/test/referrer/browser.ini | 35 + .../referrer/browser_referrer_click_pinned_tab.js | 82 + .../test/referrer/browser_referrer_middle_click.js | 25 + .../browser_referrer_middle_click_in_container.js | 33 + .../browser_referrer_open_link_in_container_tab.js | 80 + ...browser_referrer_open_link_in_container_tab2.js | 43 + ...browser_referrer_open_link_in_container_tab3.js | 81 + .../browser_referrer_open_link_in_private.js | 33 + .../referrer/browser_referrer_open_link_in_tab.js | 27 + .../browser_referrer_open_link_in_window.js | 28 + ...er_referrer_open_link_in_window_in_container.js | 39 + .../test/referrer/browser_referrer_simple_click.js | 27 + .../test/referrer/file_referrer_policyserver.sjs | 41 + .../referrer/file_referrer_policyserver_attr.sjs | 41 + .../test/referrer/file_referrer_testserver.sjs | 30 + browser/base/content/test/referrer/head.js | 311 ++++ browser/base/content/test/sanitize/browser.ini | 19 + .../test/sanitize/browser_cookiePermission.js | 1 + .../sanitize/browser_cookiePermission_aboutURL.js | 101 + .../browser_cookiePermission_containers.js | 1 + .../browser_cookiePermission_subDomains.js | 290 +++ .../sanitize/browser_purgehistory_clears_sh.js | 71 + .../sanitize/browser_sanitize-cookie-exceptions.js | 274 +++ .../test/sanitize/browser_sanitize-formhistory.js | 28 + .../test/sanitize/browser_sanitize-history.js | 132 ++ .../test/sanitize/browser_sanitize-offlineData.js | 255 +++ .../browser_sanitize-passwordDisabledHosts.js | 28 + .../sanitize/browser_sanitize-sitepermissions.js | 37 + .../test/sanitize/browser_sanitize-timespans.js | 1194 ++++++++++++ .../test/sanitize/browser_sanitizeDialog.js | 833 +++++++++ browser/base/content/test/sanitize/dummy.js | 0 browser/base/content/test/sanitize/dummy_page.html | 9 + browser/base/content/test/sanitize/head.js | 329 ++++ browser/base/content/test/sidebar/browser.ini | 8 + .../content/test/sidebar/browser_sidebar_adopt.js | 74 + .../sidebar/browser_sidebar_app_locale_changed.js | 111 ++ .../content/test/sidebar/browser_sidebar_keys.js | 108 ++ .../content/test/sidebar/browser_sidebar_move.js | 72 + .../test/sidebar/browser_sidebar_persist.js | 37 + .../test/sidebar/browser_sidebar_switcher.js | 64 + browser/base/content/test/siteIdentity/browser.ini | 152 ++ .../browser_about_blank_same_document_tabswitch.js | 79 + .../test/siteIdentity/browser_bug1045809.js | 105 ++ .../content/test/siteIdentity/browser_bug822367.js | 254 +++ .../content/test/siteIdentity/browser_bug902156.js | 171 ++ .../content/test/siteIdentity/browser_bug906190.js | 340 ++++ .../siteIdentity/browser_check_identity_state.js | 882 +++++++++ .../browser_check_identity_state_pdf.js | 77 + .../browser_csp_block_all_mixedcontent.js | 60 + .../siteIdentity/browser_deprecatedTLSVersions.js | 94 + .../siteIdentity/browser_geolocation_indicator.js | 381 ++++ .../test/siteIdentity/browser_getSecurityInfo.js | 35 + .../siteIdentity/browser_identityBlock_flicker.js | 52 + .../siteIdentity/browser_identityBlock_focus.js | 126 ++ .../siteIdentity/browser_identityIcon_img_url.js | 148 ++ .../browser_identityPopup_HttpsOnlyMode.js | 191 ++ .../browser_identityPopup_clearSiteData.js | 245 +++ ...owser_identityPopup_clearSiteData_extensions.js | 80 + .../browser_identityPopup_custom_roots.js | 82 + .../siteIdentity/browser_identityPopup_focus.js | 120 ++ .../test/siteIdentity/browser_identity_UI.js | 192 ++ .../test/siteIdentity/browser_iframe_navigation.js | 108 ++ .../browser_ignore_same_page_navigation.js | 50 + .../test/siteIdentity/browser_mcb_redirect.js | 360 ++++ .../browser_mixedContentFramesOnHttp.js | 37 + .../browser_mixedContentFromOnunload.js | 68 + .../browser_mixed_content_cert_override.js | 69 + .../browser_mixed_content_with_navigation.js | 131 ++ .../browser_mixed_passive_content_indicator.js | 18 + .../browser_mixedcontent_securityflags.js | 71 + .../siteIdentity/browser_navigation_failures.js | 166 ++ .../siteIdentity/browser_no_mcb_for_loopback.js | 88 + .../test/siteIdentity/browser_no_mcb_for_onions.js | 41 + .../siteIdentity/browser_no_mcb_on_http_site.js | 133 ++ .../browser_secure_transport_insecure_scheme.js | 185 ++ .../browser_session_store_pageproxystate.js | 92 + .../test/siteIdentity/browser_tab_sharing_state.js | 96 + .../test/siteIdentity/dummy_iframe_page.html | 10 + .../base/content/test/siteIdentity/dummy_page.html | 10 + .../test/siteIdentity/file_bug1045809_1.html | 7 + .../test/siteIdentity/file_bug1045809_2.html | 7 + .../test/siteIdentity/file_bug822367_1.html | 18 + .../content/test/siteIdentity/file_bug822367_1.js | 1 + .../test/siteIdentity/file_bug822367_2.html | 16 + .../test/siteIdentity/file_bug822367_3.html | 27 + .../test/siteIdentity/file_bug822367_4.html | 18 + .../content/test/siteIdentity/file_bug822367_4.js | 2 + .../test/siteIdentity/file_bug822367_4B.html | 18 + .../test/siteIdentity/file_bug822367_5.html | 23 + .../test/siteIdentity/file_bug822367_6.html | 16 + .../content/test/siteIdentity/file_bug902156.js | 6 + .../test/siteIdentity/file_bug902156_1.html | 15 + .../test/siteIdentity/file_bug902156_2.html | 17 + .../test/siteIdentity/file_bug902156_3.html | 15 + .../content/test/siteIdentity/file_bug906190.js | 6 + .../content/test/siteIdentity/file_bug906190.sjs | 18 + .../test/siteIdentity/file_bug906190_1.html | 15 + .../test/siteIdentity/file_bug906190_2.html | 15 + .../test/siteIdentity/file_bug906190_3_4.html | 14 + .../siteIdentity/file_bug906190_redirected.html | 15 + .../file_csp_block_all_mixedcontent.html | 11 + .../file_csp_block_all_mixedcontent.js | 3 + .../file_mixedContentFramesOnHttp.html | 14 + .../file_mixedContentFromOnunload.html | 18 + .../file_mixedContentFromOnunload_test1.html | 14 + .../file_mixedContentFromOnunload_test2.html | 15 + .../siteIdentity/file_mixedPassiveContent.html | 13 + .../base/content/test/siteIdentity/file_pdf.pdf | 12 + .../content/test/siteIdentity/file_pdf_blob.html | 18 + browser/base/content/test/siteIdentity/head.js | 435 +++++ .../test/siteIdentity/iframe_navigation.html | 44 + .../content/test/siteIdentity/insecure_opener.html | 9 + .../test/siteIdentity/open-self-from-frame.html | 6 + .../test/siteIdentity/simple_mixed_passive.html | 1 + .../test-mixedcontent-securityerrors.html | 21 + .../test_mcb_double_redirect_image.html | 23 + .../test/siteIdentity/test_mcb_redirect.html | 15 + .../content/test/siteIdentity/test_mcb_redirect.js | 5 + .../test/siteIdentity/test_mcb_redirect.sjs | 29 + .../test/siteIdentity/test_mcb_redirect_image.html | 23 + .../siteIdentity/test_no_mcb_for_loopback.html | 56 + .../test/siteIdentity/test_no_mcb_for_onions.html | 29 + .../siteIdentity/test_no_mcb_on_http_site_font.css | 11 + .../test_no_mcb_on_http_site_font.html | 44 + .../test_no_mcb_on_http_site_font2.css | 1 + .../test_no_mcb_on_http_site_font2.html | 45 + .../siteIdentity/test_no_mcb_on_http_site_img.css | 3 + .../siteIdentity/test_no_mcb_on_http_site_img.html | 44 + browser/base/content/test/startup/browser.ini | 2 + .../startup/browser_preXULSkeletonUIRegistry.js | 136 ++ browser/base/content/test/static/browser.ini | 22 + .../test/static/browser_all_files_referenced.js | 1093 +++++++++++ .../browser_misused_characters_in_strings.js | 276 +++ .../content/test/static/browser_parsable_css.js | 590 ++++++ .../content/test/static/browser_parsable_script.js | 167 ++ .../test/static/browser_sentence_case_strings.js | 279 +++ .../test/static/browser_title_case_menus.js | 158 ++ .../static/bug1262648_string_with_newlines.dtd | 3 + browser/base/content/test/static/dummy_page.html | 9 + browser/base/content/test/static/head.js | 177 ++ browser/base/content/test/statuspanel/browser.ini | 7 + .../statuspanel/browser_show_statuspanel_idn.js | 28 + .../statuspanel/browser_show_statuspanel_twice.js | 29 + browser/base/content/test/statuspanel/head.js | 58 + browser/base/content/test/sync/browser.ini | 13 + .../test/sync/browser_contextmenu_sendpage.js | 465 +++++ .../test/sync/browser_contextmenu_sendtab.js | 362 ++++ .../base/content/test/sync/browser_fxa_badge.js | 70 + .../content/test/sync/browser_fxa_web_channel.html | 158 ++ .../content/test/sync/browser_fxa_web_channel.js | 282 +++ browser/base/content/test/sync/browser_sync.js | 751 ++++++++ .../content/test/sync/browser_synced_tabs_view.js | 76 + browser/base/content/test/sync/head.js | 34 + .../tabMediaIndicator/almostSilentAudioTrack.webm | Bin 0 -> 1699661 bytes .../base/content/test/tabMediaIndicator/audio.ogg | Bin 0 -> 14293 bytes .../tabMediaIndicator/audioEndedDuringPlaying.webm | Bin 0 -> 109366 bytes .../content/test/tabMediaIndicator/browser.ini | 33 + .../tabMediaIndicator/browser_destroy_iframe.js | 50 + .../tabMediaIndicator/browser_mediaPlayback.js | 42 + .../browser_mediaPlayback_mute.js | 118 ++ .../browser_mediaplayback_audibility_change.js | 258 +++ .../content/test/tabMediaIndicator/browser_mute.js | 19 + .../test/tabMediaIndicator/browser_mute2.js | 32 + .../tabMediaIndicator/browser_mute_webAudio.js | 75 + .../browser_sound_indicator_silent_video.js | 88 + .../browser_webAudio_hideSoundPlayingIcon.js | 60 + .../browser_webAudio_silentData.js | 57 + .../browser_webaudio_audibility_change.js | 172 ++ .../file_almostSilentAudioTrack.html | 18 + .../tabMediaIndicator/file_autoplay_media.html | 9 + .../content/test/tabMediaIndicator/file_empty.html | 8 + .../test/tabMediaIndicator/file_mediaPlayback.html | 9 + .../tabMediaIndicator/file_mediaPlayback2.html | 14 + .../tabMediaIndicator/file_mediaPlaybackFrame.html | 2 + .../file_mediaPlaybackFrame2.html | 2 + .../tabMediaIndicator/file_silentAudioTrack.html | 18 + .../test/tabMediaIndicator/file_webAudio.html | 29 + .../base/content/test/tabMediaIndicator/gizmo.mp4 | Bin 0 -> 455255 bytes .../base/content/test/tabMediaIndicator/head.js | 158 ++ .../content/test/tabMediaIndicator/noaudio.webm | Bin 0 -> 105755 bytes .../test/tabMediaIndicator/silentAudioTrack.webm | Bin 0 -> 224800 bytes .../base/content/test/tabPrompts/auth-route.sjs | 28 + browser/base/content/test/tabPrompts/browser.ini | 30 + .../browser_abort_when_in_modal_state.js | 60 + .../tabPrompts/browser_auth_spoofing_protection.js | 232 +++ .../tabPrompts/browser_auth_spoofing_url_copy.js | 95 + .../browser_auth_spoofing_url_drag_and_drop.js | 93 + .../test/tabPrompts/browser_beforeunload_urlbar.js | 75 + .../tabPrompts/browser_closeTabSpecificPanels.js | 53 + .../test/tabPrompts/browser_confirmFolderUpload.js | 141 ++ .../test/tabPrompts/browser_contentOrigins.js | 217 +++ .../test/tabPrompts/browser_multiplePrompts.js | 171 ++ .../browser_openPromptInBackgroundTab.js | 262 +++ .../content/test/tabPrompts/browser_promptFocus.js | 170 ++ .../tabPrompts/browser_prompt_closed_window.js | 40 + .../browser_switchTabPermissionPrompt.js | 41 + .../test/tabPrompts/browser_windowPrompt.js | 259 +++ .../test/tabPrompts/file_beforeunload_stop.html | 8 + .../test/tabPrompts/openPromptOffTimeout.html | 10 + .../redirect-crossDomain-tabTitle-update.html | 15 + .../test/tabPrompts/redirect-crossDomain.html | 13 + .../test/tabPrompts/redirect-sameDomain.html | 13 + browser/base/content/test/tabcrashed/browser.ini | 21 + .../tabcrashed/browser_aboutRestartRequired.ini | 19 + .../browser_aboutRestartRequired_basic.js | 31 + ..._aboutRestartRequired_buildid_false-positive.js | 35 + ...rowser_aboutRestartRequired_buildid_mismatch.js | 56 + ...aboutRestartRequired_buildid_no-platform-ini.js | 50 + .../test/tabcrashed/browser_autoSubmitRequest.js | 183 ++ .../content/test/tabcrashed/browser_launchFail.js | 59 + .../test/tabcrashed/browser_multipleCrashedTabs.js | 136 ++ .../test/tabcrashed/browser_noPermanentKey.js | 41 + .../test/tabcrashed/browser_printpreview_crash.js | 83 + .../content/test/tabcrashed/browser_showForm.js | 44 + .../base/content/test/tabcrashed/browser_shown.js | 150 ++ .../tabcrashed/browser_shownRestartRequired.js | 121 ++ .../content/test/tabcrashed/browser_withoutDump.js | 42 + .../test/tabcrashed/file_contains_emptyiframe.html | 9 + .../base/content/test/tabcrashed/file_iframe.html | 9 + browser/base/content/test/tabcrashed/head.js | 238 +++ browser/base/content/test/tabdialogs/browser.ini | 19 + .../browser_multiple_dialog_navigation.js | 61 + .../test/tabdialogs/browser_subdialog_esc.js | 122 ++ .../browser_tabdialogbox_content_prompts.js | 179 ++ .../test/tabdialogs/browser_tabdialogbox_focus.js | 212 +++ .../tabdialogs/browser_tabdialogbox_navigation.js | 174 ++ .../content/test/tabdialogs/loadDelayedReply.sjs | 22 + .../base/content/test/tabdialogs/subdialog.xhtml | 46 + .../base/content/test/tabdialogs/test_page.html | 10 + browser/base/content/test/tabs/204.sjs | 3 + browser/base/content/test/tabs/blank.html | 2 + browser/base/content/test/tabs/browser.ini | 211 +++ .../content/test/tabs/browser_addAdjacentNewTab.js | 55 + .../base/content/test/tabs/browser_addTab_index.js | 8 + .../content/test/tabs/browser_adoptTab_failure.js | 107 ++ ...low_process_switches_despite_related_browser.js | 40 + .../base/content/test/tabs/browser_audioTabIcon.js | 676 +++++++ .../tabs/browser_bfcache_exemption_about_pages.js | 176 ++ .../base/content/test/tabs/browser_bug580956.js | 25 + ...1387976_restore_lazy_tab_browser_muted_state.js | 56 + .../test/tabs/browser_close_during_beforeunload.js | 46 + .../test/tabs/browser_close_tab_by_dblclick.js | 35 + ...wser_contextmenu_openlink_after_tabnavigated.js | 60 + .../test/tabs/browser_dont_process_switch_204.js | 56 + .../browser_e10s_about_page_triggeringprincipal.js | 208 +++ .../test/tabs/browser_e10s_about_process.js | 174 ++ .../test/tabs/browser_e10s_chrome_process.js | 136 ++ .../content/test/tabs/browser_e10s_javascript.js | 19 + .../test/tabs/browser_e10s_mozillaweb_process.js | 52 + .../test/tabs/browser_e10s_switchbrowser.js | 490 +++++ .../test/tabs/browser_file_to_http_named_popup.js | 60 + .../tabs/browser_file_to_http_script_closable.js | 43 + .../test/tabs/browser_hiddentab_contextmenu.js | 34 + .../test/tabs/browser_lazy_tab_browser_events.js | 157 ++ ...nk_in_tab_title_and_url_prefilled_blank_page.js | 139 ++ ...nk_in_tab_title_and_url_prefilled_new_window.js | 54 + ...e_and_url_prefilled_normal_page_blank_target.js | 199 ++ ...itle_and_url_prefilled_normal_page_by_script.js | 84 + ...itle_and_url_prefilled_normal_page_no_target.js | 86 + ...e_and_url_prefilled_normal_page_other_target.js | 156 ++ .../tabs/browser_long_data_url_label_truncation.js | 78 + ..._middle_click_new_tab_button_loads_clipboard.js | 255 +++ ...tiselect_tabs_active_tab_selected_by_default.js | 52 + .../test/tabs/browser_multiselect_tabs_bookmark.js | 81 + ...iselect_tabs_clear_selection_when_tab_switch.js | 33 + .../test/tabs/browser_multiselect_tabs_close.js | 192 ++ .../browser_multiselect_tabs_close_other_tabs.js | 122 ++ ...wser_multiselect_tabs_close_tabs_to_the_left.js | 131 ++ ...ser_multiselect_tabs_close_tabs_to_the_right.js | 113 ++ ...owser_multiselect_tabs_close_using_shortcuts.js | 64 + ..._multiselect_tabs_copy_through_drag_and_drop.js | 51 + ...r_multiselect_tabs_drag_to_bookmarks_toolbar.js | 74 + .../tabs/browser_multiselect_tabs_duplicate.js | 136 ++ .../test/tabs/browser_multiselect_tabs_event.js | 220 +++ .../test/tabs/browser_multiselect_tabs_move.js | 192 ++ ...multiselect_tabs_move_to_another_window_drag.js | 118 ++ ...tiselect_tabs_move_to_new_window_contextmenu.js | 129 ++ .../tabs/browser_multiselect_tabs_mute_unmute.js | 336 ++++ .../tabs/browser_multiselect_tabs_open_related.js | 143 ++ .../tabs/browser_multiselect_tabs_pin_unpin.js | 75 + .../test/tabs/browser_multiselect_tabs_play.js | 254 +++ .../test/tabs/browser_multiselect_tabs_reload.js | 82 + ...browser_multiselect_tabs_reopen_in_container.js | 133 ++ .../test/tabs/browser_multiselect_tabs_reorder.js | 65 + .../tabs/browser_multiselect_tabs_using_Ctrl.js | 60 + .../tabs/browser_multiselect_tabs_using_Shift.js | 159 ++ ...rowser_multiselect_tabs_using_Shift_and_Ctrl.js | 75 + .../browser_multiselect_tabs_using_keyboard.js | 147 ++ .../browser_multiselect_tabs_using_selectedTabs.js | 72 + .../content/test/tabs/browser_navigatePinnedTab.js | 71 + .../browser_navigate_home_focuses_addressbar.js | 21 + ...wser_navigate_through_urls_origin_attributes.js | 177 ++ .../tabs/browser_new_file_whitelisted_http_tab.js | 37 + ...wser_new_tab_in_privilegedabout_process_pref.js | 230 +++ .../test/tabs/browser_new_tab_insert_position.js | 288 +++ .../base/content/test/tabs/browser_new_tab_url.js | 29 + .../tabs/browser_newwindow_tabstrip_overflow.js | 41 + ...wser_open_newtab_start_observer_notification.js | 28 + .../browser_opened_file_tab_navigated_to_web.js | 56 + .../tabs/browser_origin_attrs_in_remote_type.js | 106 ++ .../content/test/tabs/browser_origin_attrs_rel.js | 281 +++ .../base/content/test/tabs/browser_originalURI.js | 181 ++ .../content/test/tabs/browser_overflowScroll.js | 111 ++ .../browser_paste_event_at_middle_click_on_link.js | 156 ++ .../base/content/test/tabs/browser_pinnedTabs.js | 97 + .../test/tabs/browser_pinnedTabs_clickOpen.js | 58 + .../tabs/browser_pinnedTabs_closeByKeyboard.js | 72 + .../test/tabs/browser_positional_attributes.js | 60 + .../test/tabs/browser_preloadedBrowser_zoom.js | 89 + .../tabs/browser_privilegedmozilla_process_pref.js | 212 +++ .../browser_progress_keyword_search_handling.js | 91 + .../content/test/tabs/browser_relatedTabs_reset.js | 81 + .../test/tabs/browser_reload_deleted_file.js | 36 + .../test/tabs/browser_removeTabsToTheEnd.js | 30 + .../test/tabs/browser_removeTabsToTheStart.js | 35 + .../content/test/tabs/browser_removeTabs_order.js | 40 + .../tabs/browser_removeTabs_skipPermitUnload.js | 115 ++ .../tabs/browser_replacewithwindow_commands.js | 42 + .../test/tabs/browser_switch_by_scrolling.js | 51 + .../content/test/tabs/browser_tabCloseProbes.js | 112 ++ .../content/test/tabs/browser_tabCloseSpacer.js | 91 + .../test/tabs/browser_tabContextMenu_keyboard.js | 64 + .../base/content/test/tabs/browser_tabReorder.js | 64 + .../test/tabs/browser_tabReorder_overflow.js | 62 + .../content/test/tabs/browser_tabSpinnerProbe.js | 101 + .../content/test/tabs/browser_tabSuccessors.js | 131 ++ .../test/tabs/browser_tab_a11y_description.js | 74 + .../test/tabs/browser_tab_label_during_reload.js | 41 + .../tabs/browser_tab_label_picture_in_picture.js | 30 + .../content/test/tabs/browser_tab_manager_close.js | 84 + .../content/test/tabs/browser_tab_manager_drag.js | 259 +++ .../tabs/browser_tab_manager_keyboard_access.js | 38 + .../test/tabs/browser_tab_manager_visibility.js | 55 + .../tabs/browser_tab_move_to_new_window_reload.js | 51 + browser/base/content/test/tabs/browser_tab_play.js | 216 +++ .../base/content/test/tabs/browser_tab_tooltips.js | 108 ++ .../test/tabs/browser_tabswitch_contextmenu.js | 45 + .../content/test/tabs/browser_tabswitch_select.js | 63 + .../test/tabs/browser_tabswitch_updatecommands.js | 28 + .../test/tabs/browser_tabswitch_window_focus.js | 78 + .../content/test/tabs/browser_undo_close_tabs.js | 171 ++ .../test/tabs/browser_undo_close_tabs_at_start.js | 74 + ...owser_viewsource_of_data_URI_in_file_process.js | 53 + .../tabs/browser_visibleTabs_bookmarkAllTabs.js | 64 + .../test/tabs/browser_visibleTabs_contextMenu.js | 115 ++ .../common_link_in_tab_title_and_url_prefilled.js | 255 +++ browser/base/content/test/tabs/dummy_page.html | 9 + .../base/content/test/tabs/file_about_child.html | 10 + .../base/content/test/tabs/file_about_parent.html | 10 + .../base/content/test/tabs/file_about_srcdoc.html | 9 + .../content/test/tabs/file_anchor_elements.html | 12 + .../base/content/test/tabs/file_mediaPlayback.html | 2 + .../base/content/test/tabs/file_new_tab_page.html | 9 + .../test/tabs/file_rel_opener_noopener.html | 12 + browser/base/content/test/tabs/head.js | 564 ++++++ .../test/tabs/helper_origin_attrs_testing.js | 158 ++ .../tabs/link_in_tab_title_and_url_prefilled.html | 30 + .../content/test/tabs/open_window_in_new_tab.html | 15 + .../base/content/test/tabs/page_with_iframe.html | 12 + .../content/test/tabs/redirect_via_header.html | 9 + .../test/tabs/redirect_via_header.html^headers^ | 2 + .../content/test/tabs/redirect_via_meta_tag.html | 13 + browser/base/content/test/tabs/request-timeout.sjs | 8 + .../base/content/test/tabs/tab_that_closes.html | 15 + .../base/content/test/tabs/test_bug1358314.html | 10 + .../test/tabs/test_process_flags_chrome.html | 10 + browser/base/content/test/tabs/wait-a-bit.sjs | 23 + browser/base/content/test/touch/browser.ini | 4 + .../base/content/test/touch/browser_menu_touch.js | 198 ++ .../base/content/test/utilityOverlay/browser.ini | 2 + .../test/utilityOverlay/browser_openWebLinkIn.js | 185 ++ .../base/content/test/webextensions/.eslintrc.js | 7 + .../base/content/test/webextensions/browser.ini | 33 + .../webextensions/browser_aboutaddons_blanktab.js | 26 + .../webextensions/browser_extension_sideloading.js | 404 ++++ .../browser_extension_update_background.js | 282 +++ ...browser_extension_update_background_noprompt.js | 121 ++ .../test/webextensions/browser_legacy_webext.xpi | Bin 0 -> 4243 bytes .../webextensions/browser_permissions_dismiss.js | 112 ++ .../browser_permissions_installTrigger.js | 26 + .../browser_permissions_local_file.js | 43 + .../browser_permissions_mozAddonManager.js | 18 + .../webextensions/browser_permissions_optional.js | 52 + .../browser_permissions_pointerevent.js | 53 + .../webextensions/browser_permissions_unsigned.js | 63 + .../browser_update_checkForUpdates.js | 17 + .../browser_update_interactive_noprompt.js | 77 + .../webextensions/browser_webext_nopermissions.xpi | Bin 0 -> 4273 bytes .../webextensions/browser_webext_permissions.xpi | Bin 0 -> 16602 bytes .../test/webextensions/browser_webext_unsigned.xpi | Bin 0 -> 12620 bytes .../test/webextensions/browser_webext_update.json | 70 + .../test/webextensions/browser_webext_update1.xpi | Bin 0 -> 4271 bytes .../test/webextensions/browser_webext_update2.xpi | Bin 0 -> 4291 bytes .../webextensions/browser_webext_update_icon1.xpi | Bin 0 -> 16545 bytes .../webextensions/browser_webext_update_icon2.xpi | Bin 0 -> 16564 bytes .../browser_webext_update_origins1.xpi | Bin 0 -> 268 bytes .../browser_webext_update_origins2.xpi | Bin 0 -> 275 bytes .../webextensions/browser_webext_update_perms1.xpi | Bin 0 -> 4273 bytes .../webextensions/browser_webext_update_perms2.xpi | Bin 0 -> 4282 bytes .../webextensions/file_install_extensions.html | 19 + browser/base/content/test/webextensions/head.js | 650 +++++++ browser/base/content/test/webrtc/browser.ini | 118 ++ .../test/webrtc/browser_WebrtcGlobalInformation.js | 484 +++++ .../test/webrtc/browser_device_controls_menus.js | 55 + .../test/webrtc/browser_devices_get_user_media.js | 949 ++++++++++ .../webrtc/browser_devices_get_user_media_anim.js | 106 ++ .../browser_devices_get_user_media_by_device_id.js | 82 + ...r_devices_get_user_media_default_permissions.js | 209 +++ .../webrtc/browser_devices_get_user_media_grace.js | 388 ++++ .../browser_devices_get_user_media_in_frame.js | 775 ++++++++ ...wser_devices_get_user_media_in_xorigin_frame.js | 798 ++++++++ ...evices_get_user_media_in_xorigin_frame_chain.js | 251 +++ ...browser_devices_get_user_media_multi_process.js | 517 ++++++ .../browser_devices_get_user_media_paused.js | 999 ++++++++++ ...browser_devices_get_user_media_queue_request.js | 383 ++++ .../browser_devices_get_user_media_screen.js | 949 ++++++++++ ...wser_devices_get_user_media_screen_tab_close.js | 73 + .../browser_devices_get_user_media_tear_off_tab.js | 100 + ...ser_devices_get_user_media_unprompted_access.js | 666 +++++++ ...es_get_user_media_unprompted_access_in_frame.js | 309 ++++ ...t_user_media_unprompted_access_queue_request.js | 47 + ...et_user_media_unprompted_access_tear_off_tab.js | 108 ++ .../webrtc/browser_devices_select_audio_output.js | 233 +++ .../test/webrtc/browser_global_mute_toggles.js | 293 +++ .../test/webrtc/browser_indicator_popuphiding.js | 50 + .../test/webrtc/browser_notification_silencing.js | 231 +++ .../test/webrtc/browser_stop_sharing_button.js | 175 ++ .../browser_stop_streams_on_indicator_close.js | 215 +++ .../test/webrtc/browser_tab_switch_warning.js | 538 ++++++ .../content/test/webrtc/browser_webrtc_hooks.js | 371 ++++ .../base/content/test/webrtc/get_user_media.html | 124 ++ .../base/content/test/webrtc/get_user_media2.html | 107 ++ .../test/webrtc/get_user_media_in_frame.html | 98 + .../webrtc/get_user_media_in_xorigin_frame.html | 71 + .../get_user_media_in_xorigin_frame_ancestor.html | 12 + .../content/test/webrtc/gracePeriod/browser.ini | 15 + browser/base/content/test/webrtc/head.js | 1338 ++++++++++++++ .../test/webrtc/legacyIndicator/browser.ini | 63 + .../test/webrtc/peerconnection_connect.html | 39 + .../content/test/webrtc/single_peerconnection.html | 23 + browser/base/content/test/zoom/browser.ini | 34 + .../zoom/browser_background_link_zoom_reset.js | 45 + .../content/test/zoom/browser_background_zoom.js | 115 ++ .../base/content/test/zoom/browser_default_zoom.js | 149 ++ .../test/zoom/browser_default_zoom_fission.js | 114 ++ .../test/zoom/browser_default_zoom_multitab.js | 190 ++ .../test/zoom/browser_default_zoom_multitab_002.js | 93 + .../test/zoom/browser_default_zoom_sitespecific.js | 108 ++ .../test/zoom/browser_image_zoom_tabswitch.js | 39 + .../content/test/zoom/browser_mousewheel_zoom.js | 72 + .../zoom/browser_sitespecific_background_pref.js | 35 + .../test/zoom/browser_sitespecific_image_zoom.js | 52 + .../test/zoom/browser_sitespecific_video_zoom.js | 128 ++ .../content/test/zoom/browser_subframe_textzoom.js | 52 + .../test/zoom/browser_tabswitch_zoom_flicker.js | 45 + .../base/content/test/zoom/browser_tooltip_zoom.js | 41 + .../content/test/zoom/browser_zoom_commands.js | 203 ++ browser/base/content/test/zoom/head.js | 223 +++ browser/base/content/test/zoom/zoom_test.html | 14 + 1066 files changed, 115976 insertions(+) create mode 100644 browser/base/content/test/about/POSTSearchEngine.xml create mode 100644 browser/base/content/test/about/browser.ini create mode 100644 browser/base/content/test/about/browser_aboutCertError.js create mode 100644 browser/base/content/test/about/browser_aboutCertError_clockSkew.js create mode 100644 browser/base/content/test/about/browser_aboutCertError_exception.js create mode 100644 browser/base/content/test/about/browser_aboutCertError_mitm.js create mode 100644 browser/base/content/test/about/browser_aboutCertError_noSubjectAltName.js create mode 100644 browser/base/content/test/about/browser_aboutCertError_offlineSupport.js create mode 100644 browser/base/content/test/about/browser_aboutCertError_telemetry.js create mode 100644 browser/base/content/test/about/browser_aboutDialog_distribution.js create mode 100644 browser/base/content/test/about/browser_aboutHome_search_POST.js create mode 100644 browser/base/content/test/about/browser_aboutHome_search_composing.js create mode 100644 browser/base/content/test/about/browser_aboutHome_search_searchbar.js create mode 100644 browser/base/content/test/about/browser_aboutHome_search_suggestion.js create mode 100644 browser/base/content/test/about/browser_aboutHome_search_telemetry.js create mode 100644 browser/base/content/test/about/browser_aboutNetError.js create mode 100644 browser/base/content/test/about/browser_aboutNetError_csp_iframe.js create mode 100644 browser/base/content/test/about/browser_aboutNetError_native_fallback.js create mode 100644 browser/base/content/test/about/browser_aboutNetError_trr.js create mode 100644 browser/base/content/test/about/browser_aboutNetError_xfo_iframe.js create mode 100644 browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbar.js create mode 100644 browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbarEmpty.js create mode 100644 browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbarNewWindow.js create mode 100644 browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbarPrefs.js create mode 100644 browser/base/content/test/about/browser_aboutStopReload.js create mode 100644 browser/base/content/test/about/browser_aboutSupport.js create mode 100644 browser/base/content/test/about/browser_aboutSupport_newtab_security_state.js create mode 100644 browser/base/content/test/about/browser_aboutSupport_places.js create mode 100644 browser/base/content/test/about/browser_bug435325.js create mode 100644 browser/base/content/test/about/browser_bug633691.js create mode 100644 browser/base/content/test/about/csp_iframe.sjs create mode 100644 browser/base/content/test/about/dummy_page.html create mode 100644 browser/base/content/test/about/head.js create mode 100644 browser/base/content/test/about/iframe_page_csp.html create mode 100644 browser/base/content/test/about/iframe_page_xfo.html create mode 100644 browser/base/content/test/about/print_postdata.sjs create mode 100644 browser/base/content/test/about/searchSuggestionEngine.sjs create mode 100644 browser/base/content/test/about/searchSuggestionEngine.xml create mode 100644 browser/base/content/test/about/slow_loading_page.sjs create mode 100644 browser/base/content/test/about/xfo_iframe.sjs create mode 100644 browser/base/content/test/alerts/browser.ini create mode 100644 browser/base/content/test/alerts/browser_notification_close.js create mode 100644 browser/base/content/test/alerts/browser_notification_do_not_disturb.js create mode 100644 browser/base/content/test/alerts/browser_notification_open_settings.js create mode 100644 browser/base/content/test/alerts/browser_notification_remove_permission.js create mode 100644 browser/base/content/test/alerts/browser_notification_replace.js create mode 100644 browser/base/content/test/alerts/browser_notification_tab_switching.js create mode 100644 browser/base/content/test/alerts/file_dom_notifications.html create mode 100644 browser/base/content/test/alerts/head.js create mode 100644 browser/base/content/test/backforward/browser.ini create mode 100644 browser/base/content/test/backforward/browser_history_menu.js create mode 100644 browser/base/content/test/caps/browser.ini create mode 100644 browser/base/content/test/caps/browser_principalSerialization_csp.js create mode 100644 browser/base/content/test/caps/browser_principalSerialization_json.js create mode 100644 browser/base/content/test/caps/browser_principalSerialization_version1.js create mode 100644 browser/base/content/test/captivePortal/browser.ini create mode 100644 browser/base/content/test/captivePortal/browser_CaptivePortalWatcher.js create mode 100644 browser/base/content/test/captivePortal/browser_CaptivePortalWatcher_1.js create mode 100644 browser/base/content/test/captivePortal/browser_captivePortalTabReference.js create mode 100644 browser/base/content/test/captivePortal/browser_captivePortal_certErrorUI.js create mode 100644 browser/base/content/test/captivePortal/browser_captivePortal_https_only.js create mode 100644 browser/base/content/test/captivePortal/browser_closeCapPortalTabCanonicalURL.js create mode 100644 browser/base/content/test/captivePortal/head.js create mode 100644 browser/base/content/test/chrome/chrome.ini create mode 100644 browser/base/content/test/chrome/test_aboutCrashed.xhtml create mode 100644 browser/base/content/test/chrome/test_aboutRestartRequired.xhtml create mode 100644 browser/base/content/test/contentTheme/browser.ini create mode 100644 browser/base/content/test/contentTheme/browser_contentTheme_in_process_tab.js create mode 100644 browser/base/content/test/contextMenu/browser.ini create mode 100644 browser/base/content/test/contextMenu/browser_bug1798178.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_badiframe.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_contenteditable.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_iframe.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_input.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_inspect.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_keyword.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_linkopen.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_loadblobinnewtab.html create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_loadblobinnewtab.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_save_blocked.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_share_macosx.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_share_win.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_shareurl.html create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_spellcheck.js create mode 100644 browser/base/content/test/contextMenu/browser_contextmenu_touch.js create mode 100644 browser/base/content/test/contextMenu/browser_copy_image_link.js create mode 100644 browser/base/content/test/contextMenu/browser_strip_on_share_link.js create mode 100644 browser/base/content/test/contextMenu/browser_utilityOverlay.js create mode 100644 browser/base/content/test/contextMenu/browser_utilityOverlayPrincipal.js create mode 100644 browser/base/content/test/contextMenu/browser_view_image.js create mode 100644 browser/base/content/test/contextMenu/bug1798178.sjs create mode 100644 browser/base/content/test/contextMenu/contextmenu_common.js create mode 100644 browser/base/content/test/contextMenu/ctxmenu-image.png create mode 100644 browser/base/content/test/contextMenu/doggy.png create mode 100644 browser/base/content/test/contextMenu/file_bug1798178.html create mode 100644 browser/base/content/test/contextMenu/firebird.png create mode 100644 browser/base/content/test/contextMenu/firebird.png^headers^ create mode 100644 browser/base/content/test/contextMenu/subtst_contextmenu.html create mode 100644 browser/base/content/test/contextMenu/subtst_contextmenu_input.html create mode 100644 browser/base/content/test/contextMenu/subtst_contextmenu_keyword.html create mode 100644 browser/base/content/test/contextMenu/subtst_contextmenu_webext.html create mode 100644 browser/base/content/test/contextMenu/subtst_contextmenu_xul.xhtml create mode 100644 browser/base/content/test/contextMenu/test_contextmenu_iframe.html create mode 100644 browser/base/content/test/contextMenu/test_contextmenu_links.html create mode 100644 browser/base/content/test/contextMenu/test_view_image_inline_svg.html create mode 100644 browser/base/content/test/contextMenu/test_view_image_revoked_cached_blob.html create mode 100644 browser/base/content/test/favicons/accept.html create mode 100644 browser/base/content/test/favicons/accept.sjs create mode 100644 browser/base/content/test/favicons/auth_test.html create mode 100644 browser/base/content/test/favicons/auth_test.png create mode 100644 browser/base/content/test/favicons/auth_test.png^headers^ create mode 100644 browser/base/content/test/favicons/blank.html create mode 100644 browser/base/content/test/favicons/browser.ini create mode 100644 browser/base/content/test/favicons/browser_bug408415.js create mode 100644 browser/base/content/test/favicons/browser_bug550565.js create mode 100644 browser/base/content/test/favicons/browser_favicon_accept.js create mode 100644 browser/base/content/test/favicons/browser_favicon_auth.js create mode 100644 browser/base/content/test/favicons/browser_favicon_cache.js create mode 100644 browser/base/content/test/favicons/browser_favicon_change.js create mode 100644 browser/base/content/test/favicons/browser_favicon_change_not_in_document.js create mode 100644 browser/base/content/test/favicons/browser_favicon_credentials.js create mode 100644 browser/base/content/test/favicons/browser_favicon_crossorigin.js create mode 100644 browser/base/content/test/favicons/browser_favicon_load.js create mode 100644 browser/base/content/test/favicons/browser_favicon_nostore.js create mode 100644 browser/base/content/test/favicons/browser_favicon_referer.js create mode 100644 browser/base/content/test/favicons/browser_favicon_store.js create mode 100644 browser/base/content/test/favicons/browser_icon_discovery.js create mode 100644 browser/base/content/test/favicons/browser_invalid_href_fallback.js create mode 100644 browser/base/content/test/favicons/browser_missing_favicon.js create mode 100644 browser/base/content/test/favicons/browser_mixed_content.js create mode 100644 browser/base/content/test/favicons/browser_multiple_icons_in_short_timeframe.js create mode 100644 browser/base/content/test/favicons/browser_oversized.js create mode 100644 browser/base/content/test/favicons/browser_preferred_icons.js create mode 100644 browser/base/content/test/favicons/browser_redirect.js create mode 100644 browser/base/content/test/favicons/browser_rich_icons.js create mode 100644 browser/base/content/test/favicons/browser_rooticon.js create mode 100644 browser/base/content/test/favicons/browser_subframe_favicons_not_used.js create mode 100644 browser/base/content/test/favicons/browser_title_flicker.js create mode 100644 browser/base/content/test/favicons/cookie_favicon.html create mode 100644 browser/base/content/test/favicons/cookie_favicon.sjs create mode 100644 browser/base/content/test/favicons/credentials.png create mode 100644 browser/base/content/test/favicons/credentials.png^headers^ create mode 100644 browser/base/content/test/favicons/credentials1.html create mode 100644 browser/base/content/test/favicons/credentials2.html create mode 100644 browser/base/content/test/favicons/crossorigin.html create mode 100644 browser/base/content/test/favicons/crossorigin.png create mode 100644 browser/base/content/test/favicons/crossorigin.png^headers^ create mode 100644 browser/base/content/test/favicons/datauri-favicon.html create mode 100644 browser/base/content/test/favicons/discovery.html create mode 100644 browser/base/content/test/favicons/file_bug970276_favicon1.ico create mode 100644 browser/base/content/test/favicons/file_bug970276_favicon2.ico create mode 100644 browser/base/content/test/favicons/file_bug970276_popup1.html create mode 100644 browser/base/content/test/favicons/file_bug970276_popup2.html create mode 100644 browser/base/content/test/favicons/file_favicon.html create mode 100644 browser/base/content/test/favicons/file_favicon.png create mode 100644 browser/base/content/test/favicons/file_favicon.png^headers^ create mode 100644 browser/base/content/test/favicons/file_favicon_change.html create mode 100644 browser/base/content/test/favicons/file_favicon_change_not_in_document.html create mode 100644 browser/base/content/test/favicons/file_favicon_no_referrer.html create mode 100644 browser/base/content/test/favicons/file_favicon_redirect.html create mode 100644 browser/base/content/test/favicons/file_favicon_redirect.ico create mode 100644 browser/base/content/test/favicons/file_favicon_redirect.ico^headers^ create mode 100644 browser/base/content/test/favicons/file_favicon_thirdParty.html create mode 100644 browser/base/content/test/favicons/file_generic_favicon.ico create mode 100644 browser/base/content/test/favicons/file_insecure_favicon.html create mode 100644 browser/base/content/test/favicons/file_invalid_href.html create mode 100644 browser/base/content/test/favicons/file_mask_icon.html create mode 100644 browser/base/content/test/favicons/file_rich_icon.html create mode 100644 browser/base/content/test/favicons/file_with_favicon.html create mode 100644 browser/base/content/test/favicons/file_with_slow_favicon.html create mode 100644 browser/base/content/test/favicons/head.js create mode 100644 browser/base/content/test/favicons/icon.svg create mode 100644 browser/base/content/test/favicons/large.png create mode 100644 browser/base/content/test/favicons/large_favicon.html create mode 100644 browser/base/content/test/favicons/moz.png create mode 100644 browser/base/content/test/favicons/no-store.html create mode 100644 browser/base/content/test/favicons/no-store.png create mode 100644 browser/base/content/test/favicons/no-store.png^headers^ create mode 100644 browser/base/content/test/favicons/rich_moz_1.png create mode 100644 browser/base/content/test/favicons/rich_moz_2.png create mode 100644 browser/base/content/test/forms/browser.ini create mode 100644 browser/base/content/test/forms/browser_selectpopup.js create mode 100644 browser/base/content/test/forms/browser_selectpopup_colors.js create mode 100644 browser/base/content/test/forms/browser_selectpopup_dir.js create mode 100644 browser/base/content/test/forms/browser_selectpopup_large.js create mode 100644 browser/base/content/test/forms/browser_selectpopup_searchfocus.js create mode 100644 browser/base/content/test/forms/browser_selectpopup_text_transform.js create mode 100644 browser/base/content/test/forms/browser_selectpopup_toplevel.js create mode 100644 browser/base/content/test/forms/browser_selectpopup_user_input.js create mode 100644 browser/base/content/test/forms/browser_selectpopup_width.js create mode 100644 browser/base/content/test/forms/browser_selectpopup_xhtml.js create mode 100644 browser/base/content/test/forms/head.js create mode 100644 browser/base/content/test/fullscreen/FullscreenFrame.sys.mjs create mode 100644 browser/base/content/test/fullscreen/browser.ini create mode 100644 browser/base/content/test/fullscreen/browser_bug1557041.js create mode 100644 browser/base/content/test/fullscreen/browser_bug1620341.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_api_fission.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_context_menu.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_cross_origin.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_enterInUrlbar.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_from_minimize.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_keydown_reservation.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_menus.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_newtab.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_newwindow.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_permissions_prompt.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_warning.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_window_focus.js create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_window_open.js create mode 100644 browser/base/content/test/fullscreen/fullscreen.html create mode 100644 browser/base/content/test/fullscreen/fullscreen_frame.html create mode 100644 browser/base/content/test/fullscreen/head.js create mode 100644 browser/base/content/test/fullscreen/open_and_focus_helper.html create mode 100644 browser/base/content/test/general/alltabslistener.html create mode 100644 browser/base/content/test/general/app_bug575561.html create mode 100644 browser/base/content/test/general/app_subframe_bug575561.html create mode 100644 browser/base/content/test/general/audio.ogg create mode 100644 browser/base/content/test/general/browser.ini create mode 100644 browser/base/content/test/general/browser_accesskeys.js create mode 100644 browser/base/content/test/general/browser_addCertException.js create mode 100644 browser/base/content/test/general/browser_alltabslistener.js create mode 100644 browser/base/content/test/general/browser_backButtonFitts.js create mode 100644 browser/base/content/test/general/browser_beforeunload_duplicate_dialogs.js create mode 100644 browser/base/content/test/general/browser_bug1261299.js create mode 100644 browser/base/content/test/general/browser_bug1297539.js create mode 100644 browser/base/content/test/general/browser_bug1299667.js create mode 100644 browser/base/content/test/general/browser_bug321000.js create mode 100644 browser/base/content/test/general/browser_bug356571.js create mode 100644 browser/base/content/test/general/browser_bug380960.js create mode 100644 browser/base/content/test/general/browser_bug406216.js create mode 100644 browser/base/content/test/general/browser_bug417483.js create mode 100644 browser/base/content/test/general/browser_bug424101.js create mode 100644 browser/base/content/test/general/browser_bug427559.js create mode 100644 browser/base/content/test/general/browser_bug431826.js create mode 100644 browser/base/content/test/general/browser_bug432599.js create mode 100644 browser/base/content/test/general/browser_bug455852.js create mode 100644 browser/base/content/test/general/browser_bug462289.js create mode 100644 browser/base/content/test/general/browser_bug462673.js create mode 100644 browser/base/content/test/general/browser_bug477014.js create mode 100644 browser/base/content/test/general/browser_bug479408.js create mode 100644 browser/base/content/test/general/browser_bug479408_sample.html create mode 100644 browser/base/content/test/general/browser_bug481560.js create mode 100644 browser/base/content/test/general/browser_bug484315.js create mode 100644 browser/base/content/test/general/browser_bug491431.js create mode 100644 browser/base/content/test/general/browser_bug495058.js create mode 100644 browser/base/content/test/general/browser_bug519216.js create mode 100644 browser/base/content/test/general/browser_bug520538.js create mode 100644 browser/base/content/test/general/browser_bug521216.js create mode 100644 browser/base/content/test/general/browser_bug533232.js create mode 100644 browser/base/content/test/general/browser_bug537013.js create mode 100644 browser/base/content/test/general/browser_bug537474.js create mode 100644 browser/base/content/test/general/browser_bug563588.js create mode 100644 browser/base/content/test/general/browser_bug565575.js create mode 100644 browser/base/content/test/general/browser_bug567306.js create mode 100644 browser/base/content/test/general/browser_bug575561.js create mode 100644 browser/base/content/test/general/browser_bug577121.js create mode 100644 browser/base/content/test/general/browser_bug578534.js create mode 100644 browser/base/content/test/general/browser_bug579872.js create mode 100644 browser/base/content/test/general/browser_bug581253.js create mode 100644 browser/base/content/test/general/browser_bug585785.js create mode 100644 browser/base/content/test/general/browser_bug585830.js create mode 100644 browser/base/content/test/general/browser_bug594131.js create mode 100644 browser/base/content/test/general/browser_bug596687.js create mode 100644 browser/base/content/test/general/browser_bug597218.js create mode 100644 browser/base/content/test/general/browser_bug609700.js create mode 100644 browser/base/content/test/general/browser_bug623893.js create mode 100644 browser/base/content/test/general/browser_bug624734.js create mode 100644 browser/base/content/test/general/browser_bug664672.js create mode 100644 browser/base/content/test/general/browser_bug676619.js create mode 100644 browser/base/content/test/general/browser_bug710878.js create mode 100644 browser/base/content/test/general/browser_bug724239.js create mode 100644 browser/base/content/test/general/browser_bug734076.js create mode 100644 browser/base/content/test/general/browser_bug749738.js create mode 100644 browser/base/content/test/general/browser_bug763468_perwindowpb.js create mode 100644 browser/base/content/test/general/browser_bug767836_perwindowpb.js create mode 100644 browser/base/content/test/general/browser_bug817947.js create mode 100644 browser/base/content/test/general/browser_bug832435.js create mode 100644 browser/base/content/test/general/browser_bug882977.js create mode 100644 browser/base/content/test/general/browser_bug963945.js create mode 100644 browser/base/content/test/general/browser_clipboard.js create mode 100644 browser/base/content/test/general/browser_clipboard_pastefile.js create mode 100644 browser/base/content/test/general/browser_contentAltClick.js create mode 100644 browser/base/content/test/general/browser_contentAreaClick.js create mode 100644 browser/base/content/test/general/browser_ctrlTab.js create mode 100644 browser/base/content/test/general/browser_datachoices_notification.js create mode 100644 browser/base/content/test/general/browser_documentnavigation.js create mode 100644 browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js create mode 100644 browser/base/content/test/general/browser_double_close_tab.js create mode 100644 browser/base/content/test/general/browser_drag.js create mode 100644 browser/base/content/test/general/browser_duplicateIDs.js create mode 100644 browser/base/content/test/general/browser_findbarClose.js create mode 100644 browser/base/content/test/general/browser_focusonkeydown.js create mode 100644 browser/base/content/test/general/browser_fullscreen-window-open.js create mode 100644 browser/base/content/test/general/browser_gestureSupport.js create mode 100644 browser/base/content/test/general/browser_hide_removing.js create mode 100644 browser/base/content/test/general/browser_homeDrop.js create mode 100644 browser/base/content/test/general/browser_invalid_uri_back_forward_manipulation.js create mode 100644 browser/base/content/test/general/browser_lastAccessedTab.js create mode 100644 browser/base/content/test/general/browser_menuButtonFitts.js create mode 100644 browser/base/content/test/general/browser_middleMouse_noJSPaste.js create mode 100644 browser/base/content/test/general/browser_minimize.js create mode 100644 browser/base/content/test/general/browser_modifiedclick_inherit_principal.js create mode 100644 browser/base/content/test/general/browser_newTabDrop.js create mode 100644 browser/base/content/test/general/browser_newWindowDrop.js create mode 100644 browser/base/content/test/general/browser_new_http_window_opened_from_file_tab.js create mode 100644 browser/base/content/test/general/browser_newwindow_focus.js create mode 100644 browser/base/content/test/general/browser_plainTextLinks.js create mode 100644 browser/base/content/test/general/browser_printpreview.js create mode 100644 browser/base/content/test/general/browser_private_browsing_window.js create mode 100644 browser/base/content/test/general/browser_private_no_prompt.js create mode 100644 browser/base/content/test/general/browser_refreshBlocker.js create mode 100644 browser/base/content/test/general/browser_relatedTabs.js create mode 100644 browser/base/content/test/general/browser_remoteTroubleshoot.js create mode 100644 browser/base/content/test/general/browser_remoteWebNavigation_postdata.js create mode 100644 browser/base/content/test/general/browser_restore_isAppTab.js create mode 100644 browser/base/content/test/general/browser_save_link-perwindowpb.js create mode 100644 browser/base/content/test/general/browser_save_link_when_window_navigates.js create mode 100644 browser/base/content/test/general/browser_save_private_link_perwindowpb.js create mode 100644 browser/base/content/test/general/browser_save_video.js create mode 100644 browser/base/content/test/general/browser_save_video_frame.js create mode 100644 browser/base/content/test/general/browser_selectTabAtIndex.js create mode 100644 browser/base/content/test/general/browser_star_hsts.js create mode 100644 browser/base/content/test/general/browser_star_hsts.sjs create mode 100644 browser/base/content/test/general/browser_storagePressure_notification.js create mode 100644 browser/base/content/test/general/browser_tabDrop.js create mode 100644 browser/base/content/test/general/browser_tab_close_dependent_window.js create mode 100644 browser/base/content/test/general/browser_tab_detach_restore.js create mode 100644 browser/base/content/test/general/browser_tab_drag_drop_perwindow.js create mode 100644 browser/base/content/test/general/browser_tab_dragdrop.js create mode 100644 browser/base/content/test/general/browser_tab_dragdrop2.js create mode 100644 browser/base/content/test/general/browser_tab_dragdrop2_frame1.xhtml create mode 100644 browser/base/content/test/general/browser_tab_dragdrop_embed.html create mode 100644 browser/base/content/test/general/browser_tabfocus.js create mode 100644 browser/base/content/test/general/browser_tabkeynavigation.js create mode 100644 browser/base/content/test/general/browser_tabs_close_beforeunload.js create mode 100644 browser/base/content/test/general/browser_tabs_isActive.js create mode 100644 browser/base/content/test/general/browser_tabs_owner.js create mode 100644 browser/base/content/test/general/browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js create mode 100644 browser/base/content/test/general/browser_typeAheadFind.js create mode 100644 browser/base/content/test/general/browser_unknownContentType_title.js create mode 100644 browser/base/content/test/general/browser_unloaddialogs.js create mode 100644 browser/base/content/test/general/browser_viewSourceInTabOnViewSource.js create mode 100644 browser/base/content/test/general/browser_visibleFindSelection.js create mode 100644 browser/base/content/test/general/browser_visibleTabs.js create mode 100644 browser/base/content/test/general/browser_visibleTabs_bookmarkAllPages.js create mode 100644 browser/base/content/test/general/browser_visibleTabs_tabPreview.js create mode 100644 browser/base/content/test/general/browser_windowactivation.js create mode 100644 browser/base/content/test/general/browser_zbug569342.js create mode 100644 browser/base/content/test/general/bug792517-2.html create mode 100644 browser/base/content/test/general/bug792517.html create mode 100644 browser/base/content/test/general/bug792517.sjs create mode 100644 browser/base/content/test/general/clipboard_pastefile.html create mode 100644 browser/base/content/test/general/close_beforeunload.html create mode 100644 browser/base/content/test/general/close_beforeunload_opens_second_tab.html create mode 100644 browser/base/content/test/general/download_page.html create mode 100644 browser/base/content/test/general/download_page_1.txt create mode 100644 browser/base/content/test/general/download_page_2.txt create mode 100644 browser/base/content/test/general/download_with_content_disposition_header.sjs create mode 100644 browser/base/content/test/general/dummy.ics create mode 100644 browser/base/content/test/general/dummy.ics^headers^ create mode 100644 browser/base/content/test/general/dummy_page.html create mode 100644 browser/base/content/test/general/file_documentnavigation_frameset.html create mode 100644 browser/base/content/test/general/file_double_close_tab.html create mode 100644 browser/base/content/test/general/file_fullscreen-window-open.html create mode 100644 browser/base/content/test/general/file_window_activation.html create mode 100644 browser/base/content/test/general/file_window_activation2.html create mode 100644 browser/base/content/test/general/file_with_link_to_http.html create mode 100644 browser/base/content/test/general/head.js create mode 100644 browser/base/content/test/general/moz.png create mode 100644 browser/base/content/test/general/navigating_window_with_download.html create mode 100644 browser/base/content/test/general/print_postdata.sjs create mode 100644 browser/base/content/test/general/redirect_download.sjs create mode 100644 browser/base/content/test/general/refresh_header.sjs create mode 100644 browser/base/content/test/general/refresh_meta.sjs create mode 100644 browser/base/content/test/general/test_bug462673.html create mode 100644 browser/base/content/test/general/test_bug628179.html create mode 100644 browser/base/content/test/general/test_remoteTroubleshoot.html create mode 100644 browser/base/content/test/general/title_test.svg create mode 100644 browser/base/content/test/general/unknownContentType_file.pif create mode 100644 browser/base/content/test/general/unknownContentType_file.pif^headers^ create mode 100644 browser/base/content/test/general/video.ogg create mode 100644 browser/base/content/test/general/web_video.html create mode 100644 browser/base/content/test/general/web_video1.ogv create mode 100644 browser/base/content/test/general/web_video1.ogv^headers^ create mode 100644 browser/base/content/test/gesture/browser.ini create mode 100644 browser/base/content/test/gesture/browser_gesture_navigation.js create mode 100644 browser/base/content/test/historySwipeAnimation/browser.ini create mode 100644 browser/base/content/test/historySwipeAnimation/browser_historySwipeAnimation.js create mode 100644 browser/base/content/test/keyboard/browser.ini create mode 100644 browser/base/content/test/keyboard/browser_bookmarks_shortcut.js create mode 100644 browser/base/content/test/keyboard/browser_cancel_caret_browsing_in_content.js create mode 100644 browser/base/content/test/keyboard/browser_popup_keyNav.js create mode 100644 browser/base/content/test/keyboard/browser_toolbarButtonKeyPress.js create mode 100644 browser/base/content/test/keyboard/browser_toolbarKeyNav.js create mode 100644 browser/base/content/test/keyboard/file_empty.html create mode 100644 browser/base/content/test/keyboard/focusableContent.html create mode 100644 browser/base/content/test/keyboard/head.js create mode 100644 browser/base/content/test/menubar/browser.ini create mode 100644 browser/base/content/test/menubar/browser_file_close_tabs.js create mode 100644 browser/base/content/test/menubar/browser_file_menu_import_wizard.js create mode 100644 browser/base/content/test/menubar/browser_file_share.js create mode 100644 browser/base/content/test/menubar/file_shareurl.html create mode 100644 browser/base/content/test/metaTags/bad_meta_tags.html create mode 100644 browser/base/content/test/metaTags/browser.ini create mode 100644 browser/base/content/test/metaTags/browser_bad_meta_tags.js create mode 100644 browser/base/content/test/metaTags/browser_meta_tags.js create mode 100644 browser/base/content/test/metaTags/head.js create mode 100644 browser/base/content/test/metaTags/meta_tags.html create mode 100644 browser/base/content/test/notificationbox/browser.ini create mode 100644 browser/base/content/test/notificationbox/browser_notification_stacking.js create mode 100644 browser/base/content/test/notificationbox/browser_notificationbar_telemetry.js create mode 100644 browser/base/content/test/notificationbox/browser_tabnotificationbox_switch_tabs.js create mode 100644 browser/base/content/test/outOfProcess/browser.ini create mode 100644 browser/base/content/test/outOfProcess/browser_basic_outofprocess.js create mode 100644 browser/base/content/test/outOfProcess/browser_controller.js create mode 100644 browser/base/content/test/outOfProcess/browser_promisefocus.js create mode 100644 browser/base/content/test/outOfProcess/file_base.html create mode 100644 browser/base/content/test/outOfProcess/file_frame1.html create mode 100644 browser/base/content/test/outOfProcess/file_frame2.html create mode 100644 browser/base/content/test/outOfProcess/file_innerframe.html create mode 100644 browser/base/content/test/outOfProcess/head.js create mode 100644 browser/base/content/test/pageActions/browser.ini create mode 100644 browser/base/content/test/pageActions/browser_PageActions_bookmark.js create mode 100644 browser/base/content/test/pageActions/browser_PageActions_overflow.js create mode 100644 browser/base/content/test/pageActions/browser_PageActions_removeExtension.js create mode 100644 browser/base/content/test/pageActions/head.js create mode 100644 browser/base/content/test/pageStyle/browser.ini create mode 100644 browser/base/content/test/pageStyle/browser_disable_author_style_oop.js create mode 100644 browser/base/content/test/pageStyle/browser_page_style_menu.js create mode 100644 browser/base/content/test/pageStyle/browser_page_style_menu_update.js create mode 100644 browser/base/content/test/pageStyle/head.js create mode 100644 browser/base/content/test/pageStyle/page_style.html create mode 100644 browser/base/content/test/pageStyle/page_style_only_alternates.html create mode 100644 browser/base/content/test/pageStyle/page_style_sample.html create mode 100644 browser/base/content/test/pageStyle/style.css create mode 100644 browser/base/content/test/pageinfo/all_images.html create mode 100644 browser/base/content/test/pageinfo/browser.ini create mode 100644 browser/base/content/test/pageinfo/browser_pageinfo_firstPartyIsolation.js create mode 100644 browser/base/content/test/pageinfo/browser_pageinfo_iframe_media.js create mode 100644 browser/base/content/test/pageinfo/browser_pageinfo_image_info.js create mode 100644 browser/base/content/test/pageinfo/browser_pageinfo_images.js create mode 100644 browser/base/content/test/pageinfo/browser_pageinfo_permissions.js create mode 100644 browser/base/content/test/pageinfo/browser_pageinfo_rtl.js create mode 100644 browser/base/content/test/pageinfo/browser_pageinfo_security.js create mode 100644 browser/base/content/test/pageinfo/browser_pageinfo_separate_private.js create mode 100644 browser/base/content/test/pageinfo/browser_pageinfo_svg_image.js create mode 100644 browser/base/content/test/pageinfo/iframes.html create mode 100644 browser/base/content/test/pageinfo/image.html create mode 100644 browser/base/content/test/pageinfo/svg_image.html create mode 100644 browser/base/content/test/performance/PerfTestHelpers.sys.mjs create mode 100644 browser/base/content/test/performance/StartupContentSubframe.sys.mjs create mode 100644 browser/base/content/test/performance/browser.ini create mode 100644 browser/base/content/test/performance/browser_appmenu.js create mode 100644 browser/base/content/test/performance/browser_panel_vsync.js create mode 100644 browser/base/content/test/performance/browser_preferences_usage.js create mode 100644 browser/base/content/test/performance/browser_startup.js create mode 100644 browser/base/content/test/performance/browser_startup_content.js create mode 100644 browser/base/content/test/performance/browser_startup_content_mainthreadio.js create mode 100644 browser/base/content/test/performance/browser_startup_content_subframe.js create mode 100644 browser/base/content/test/performance/browser_startup_flicker.js create mode 100644 browser/base/content/test/performance/browser_startup_hiddenwindow.js create mode 100644 browser/base/content/test/performance/browser_startup_images.js create mode 100644 browser/base/content/test/performance/browser_startup_mainthreadio.js create mode 100644 browser/base/content/test/performance/browser_startup_syncIPC.js create mode 100644 browser/base/content/test/performance/browser_tabclose.js create mode 100644 browser/base/content/test/performance/browser_tabclose_grow.js create mode 100644 browser/base/content/test/performance/browser_tabdetach.js create mode 100644 browser/base/content/test/performance/browser_tabopen.js create mode 100644 browser/base/content/test/performance/browser_tabopen_squeeze.js create mode 100644 browser/base/content/test/performance/browser_tabstrip_overflow_underflow.js create mode 100644 browser/base/content/test/performance/browser_tabswitch.js create mode 100644 browser/base/content/test/performance/browser_toolbariconcolor_restyles.js create mode 100644 browser/base/content/test/performance/browser_urlbar_keyed_search.js create mode 100644 browser/base/content/test/performance/browser_urlbar_search.js create mode 100644 browser/base/content/test/performance/browser_vsync_accessibility.js create mode 100644 browser/base/content/test/performance/browser_window_resize.js create mode 100644 browser/base/content/test/performance/browser_windowclose.js create mode 100644 browser/base/content/test/performance/browser_windowopen.js create mode 100644 browser/base/content/test/performance/file_empty.html create mode 100644 browser/base/content/test/performance/head.js create mode 100644 browser/base/content/test/performance/hidpi/browser.ini create mode 100644 browser/base/content/test/performance/io/browser.ini create mode 100644 browser/base/content/test/performance/lowdpi/browser.ini create mode 100644 browser/base/content/test/performance/moz.build create mode 100644 browser/base/content/test/performance/triage.json create mode 100644 browser/base/content/test/perftest.ini create mode 100644 browser/base/content/test/perftest_browser_xhtml_dom.js create mode 100644 browser/base/content/test/permissions/browser.ini create mode 100644 browser/base/content/test/permissions/browser_autoplay_blocked.html create mode 100644 browser/base/content/test/permissions/browser_autoplay_blocked.js create mode 100644 browser/base/content/test/permissions/browser_autoplay_blocked_slow.sjs create mode 100644 browser/base/content/test/permissions/browser_autoplay_js.html create mode 100644 browser/base/content/test/permissions/browser_autoplay_muted.html create mode 100644 browser/base/content/test/permissions/browser_canvas_fingerprinting_resistance.js create mode 100644 browser/base/content/test/permissions/browser_canvas_rfp_exclusion.js create mode 100644 browser/base/content/test/permissions/browser_permission_delegate_geo.js create mode 100644 browser/base/content/test/permissions/browser_permissions.js create mode 100644 browser/base/content/test/permissions/browser_permissions_delegate_vibrate.js create mode 100644 browser/base/content/test/permissions/browser_permissions_handling_user_input.js create mode 100644 browser/base/content/test/permissions/browser_permissions_postPrompt.js create mode 100644 browser/base/content/test/permissions/browser_reservedkey.js create mode 100644 browser/base/content/test/permissions/browser_site_scoped_permissions.js create mode 100644 browser/base/content/test/permissions/browser_temporary_permissions.js create mode 100644 browser/base/content/test/permissions/browser_temporary_permissions_expiry.js create mode 100644 browser/base/content/test/permissions/browser_temporary_permissions_navigation.js create mode 100644 browser/base/content/test/permissions/browser_temporary_permissions_tabs.js create mode 100644 browser/base/content/test/permissions/dummy.js create mode 100644 browser/base/content/test/permissions/empty.html create mode 100644 browser/base/content/test/permissions/head.js create mode 100644 browser/base/content/test/permissions/permissions.html create mode 100644 browser/base/content/test/permissions/temporary_permissions_frame.html create mode 100644 browser/base/content/test/permissions/temporary_permissions_subframe.html create mode 100644 browser/base/content/test/plugins/browser.ini create mode 100644 browser/base/content/test/plugins/browser_bug797677.js create mode 100644 browser/base/content/test/plugins/browser_enable_DRM_prompt.js create mode 100644 browser/base/content/test/plugins/browser_globalplugin_crashinfobar.js create mode 100644 browser/base/content/test/plugins/browser_private_browsing_eme_persistent_state.js create mode 100644 browser/base/content/test/plugins/empty_file.html create mode 100644 browser/base/content/test/plugins/head.js create mode 100644 browser/base/content/test/plugins/plugin_bug797677.html create mode 100644 browser/base/content/test/plugins/plugin_test.html create mode 100644 browser/base/content/test/popupNotifications/browser.ini create mode 100644 browser/base/content/test/popupNotifications/browser_displayURI.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_2.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_3.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_4.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_5.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_accesskey.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_checkbox.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_hide_after_identity_panel.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_hide_after_protections_panel.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_keyboard.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_learnmore.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_no_anchors.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_security_delay.js create mode 100644 browser/base/content/test/popupNotifications/browser_popupNotification_selection_required.js create mode 100644 browser/base/content/test/popupNotifications/browser_reshow_in_background.js create mode 100644 browser/base/content/test/popupNotifications/head.js create mode 100644 browser/base/content/test/popups/browser.ini create mode 100644 browser/base/content/test/popups/browser_popupUI.js create mode 100644 browser/base/content/test/popups/browser_popup_blocker.js create mode 100644 browser/base/content/test/popups/browser_popup_blocker_frames.js create mode 100644 browser/base/content/test/popups/browser_popup_blocker_identity_block.js create mode 100644 browser/base/content/test/popups/browser_popup_blocker_iframes.js create mode 100644 browser/base/content/test/popups/browser_popup_close_main_window.js create mode 100644 browser/base/content/test/popups/browser_popup_frames.js create mode 100644 browser/base/content/test/popups/browser_popup_inner_outer_size.js create mode 100644 browser/base/content/test/popups/browser_popup_linux_move.js create mode 100644 browser/base/content/test/popups/browser_popup_linux_resize.js create mode 100644 browser/base/content/test/popups/browser_popup_move.js create mode 100644 browser/base/content/test/popups/browser_popup_move_instant.js create mode 100644 browser/base/content/test/popups/browser_popup_new_window_resize.js create mode 100644 browser/base/content/test/popups/browser_popup_new_window_size.js create mode 100644 browser/base/content/test/popups/browser_popup_resize.js create mode 100644 browser/base/content/test/popups/browser_popup_resize_instant.js create mode 100644 browser/base/content/test/popups/browser_popup_resize_repeat.js create mode 100644 browser/base/content/test/popups/browser_popup_resize_repeat_instant.js create mode 100644 browser/base/content/test/popups/browser_popup_resize_revert.js create mode 100644 browser/base/content/test/popups/browser_popup_resize_revert_instant.js create mode 100644 browser/base/content/test/popups/head.js create mode 100644 browser/base/content/test/popups/popup_blocker.html create mode 100644 browser/base/content/test/popups/popup_blocker2.html create mode 100644 browser/base/content/test/popups/popup_blocker_10_popups.html create mode 100644 browser/base/content/test/popups/popup_blocker_a.html create mode 100644 browser/base/content/test/popups/popup_blocker_b.html create mode 100644 browser/base/content/test/popups/popup_blocker_frame.html create mode 100644 browser/base/content/test/popups/popup_size.html create mode 100644 browser/base/content/test/protectionsUI/benignPage.html create mode 100644 browser/base/content/test/protectionsUI/browser.ini create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_3.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_background_tabs.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_categories.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_cookie_banner.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_cookies_subview.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_cryptominers.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_email_trackers_subview.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_fetch.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_fingerprinters.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_icon_state.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_milestones.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_open_preferences.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_pbmode_exceptions.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_report_breakage.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_shield_visibility.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_socialtracking.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_state.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_state_reset.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_subview_shim.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_telemetry.js create mode 100644 browser/base/content/test/protectionsUI/browser_protectionsUI_trackers_subview.js create mode 100644 browser/base/content/test/protectionsUI/containerPage.html create mode 100644 browser/base/content/test/protectionsUI/cookiePage.html create mode 100644 browser/base/content/test/protectionsUI/cookieServer.sjs create mode 100644 browser/base/content/test/protectionsUI/cookieSetterPage.html create mode 100644 browser/base/content/test/protectionsUI/emailTrackingPage.html create mode 100644 browser/base/content/test/protectionsUI/embeddedPage.html create mode 100644 browser/base/content/test/protectionsUI/file_protectionsUI_fetch.html create mode 100644 browser/base/content/test/protectionsUI/file_protectionsUI_fetch.js create mode 100644 browser/base/content/test/protectionsUI/file_protectionsUI_fetch.js^headers^ create mode 100644 browser/base/content/test/protectionsUI/head.js create mode 100644 browser/base/content/test/protectionsUI/sandboxed.html create mode 100644 browser/base/content/test/protectionsUI/sandboxed.html^headers^ create mode 100644 browser/base/content/test/protectionsUI/trackingAPI.js create mode 100644 browser/base/content/test/protectionsUI/trackingPage.html create mode 100644 browser/base/content/test/referrer/browser.ini create mode 100644 browser/base/content/test/referrer/browser_referrer_click_pinned_tab.js create mode 100644 browser/base/content/test/referrer/browser_referrer_middle_click.js create mode 100644 browser/base/content/test/referrer/browser_referrer_middle_click_in_container.js create mode 100644 browser/base/content/test/referrer/browser_referrer_open_link_in_container_tab.js create mode 100644 browser/base/content/test/referrer/browser_referrer_open_link_in_container_tab2.js create mode 100644 browser/base/content/test/referrer/browser_referrer_open_link_in_container_tab3.js create mode 100644 browser/base/content/test/referrer/browser_referrer_open_link_in_private.js create mode 100644 browser/base/content/test/referrer/browser_referrer_open_link_in_tab.js create mode 100644 browser/base/content/test/referrer/browser_referrer_open_link_in_window.js create mode 100644 browser/base/content/test/referrer/browser_referrer_open_link_in_window_in_container.js create mode 100644 browser/base/content/test/referrer/browser_referrer_simple_click.js create mode 100644 browser/base/content/test/referrer/file_referrer_policyserver.sjs create mode 100644 browser/base/content/test/referrer/file_referrer_policyserver_attr.sjs create mode 100644 browser/base/content/test/referrer/file_referrer_testserver.sjs create mode 100644 browser/base/content/test/referrer/head.js create mode 100644 browser/base/content/test/sanitize/browser.ini create mode 100644 browser/base/content/test/sanitize/browser_cookiePermission.js create mode 100644 browser/base/content/test/sanitize/browser_cookiePermission_aboutURL.js create mode 100644 browser/base/content/test/sanitize/browser_cookiePermission_containers.js create mode 100644 browser/base/content/test/sanitize/browser_cookiePermission_subDomains.js create mode 100644 browser/base/content/test/sanitize/browser_purgehistory_clears_sh.js create mode 100644 browser/base/content/test/sanitize/browser_sanitize-cookie-exceptions.js create mode 100644 browser/base/content/test/sanitize/browser_sanitize-formhistory.js create mode 100644 browser/base/content/test/sanitize/browser_sanitize-history.js create mode 100644 browser/base/content/test/sanitize/browser_sanitize-offlineData.js create mode 100644 browser/base/content/test/sanitize/browser_sanitize-passwordDisabledHosts.js create mode 100644 browser/base/content/test/sanitize/browser_sanitize-sitepermissions.js create mode 100644 browser/base/content/test/sanitize/browser_sanitize-timespans.js create mode 100644 browser/base/content/test/sanitize/browser_sanitizeDialog.js create mode 100644 browser/base/content/test/sanitize/dummy.js create mode 100644 browser/base/content/test/sanitize/dummy_page.html create mode 100644 browser/base/content/test/sanitize/head.js create mode 100644 browser/base/content/test/sidebar/browser.ini create mode 100644 browser/base/content/test/sidebar/browser_sidebar_adopt.js create mode 100644 browser/base/content/test/sidebar/browser_sidebar_app_locale_changed.js create mode 100644 browser/base/content/test/sidebar/browser_sidebar_keys.js create mode 100644 browser/base/content/test/sidebar/browser_sidebar_move.js create mode 100644 browser/base/content/test/sidebar/browser_sidebar_persist.js create mode 100644 browser/base/content/test/sidebar/browser_sidebar_switcher.js create mode 100644 browser/base/content/test/siteIdentity/browser.ini create mode 100644 browser/base/content/test/siteIdentity/browser_about_blank_same_document_tabswitch.js create mode 100644 browser/base/content/test/siteIdentity/browser_bug1045809.js create mode 100644 browser/base/content/test/siteIdentity/browser_bug822367.js create mode 100644 browser/base/content/test/siteIdentity/browser_bug902156.js create mode 100644 browser/base/content/test/siteIdentity/browser_bug906190.js create mode 100644 browser/base/content/test/siteIdentity/browser_check_identity_state.js create mode 100644 browser/base/content/test/siteIdentity/browser_check_identity_state_pdf.js create mode 100644 browser/base/content/test/siteIdentity/browser_csp_block_all_mixedcontent.js create mode 100644 browser/base/content/test/siteIdentity/browser_deprecatedTLSVersions.js create mode 100644 browser/base/content/test/siteIdentity/browser_geolocation_indicator.js create mode 100644 browser/base/content/test/siteIdentity/browser_getSecurityInfo.js create mode 100644 browser/base/content/test/siteIdentity/browser_identityBlock_flicker.js create mode 100644 browser/base/content/test/siteIdentity/browser_identityBlock_focus.js create mode 100644 browser/base/content/test/siteIdentity/browser_identityIcon_img_url.js create mode 100644 browser/base/content/test/siteIdentity/browser_identityPopup_HttpsOnlyMode.js create mode 100644 browser/base/content/test/siteIdentity/browser_identityPopup_clearSiteData.js create mode 100644 browser/base/content/test/siteIdentity/browser_identityPopup_clearSiteData_extensions.js create mode 100644 browser/base/content/test/siteIdentity/browser_identityPopup_custom_roots.js create mode 100644 browser/base/content/test/siteIdentity/browser_identityPopup_focus.js create mode 100644 browser/base/content/test/siteIdentity/browser_identity_UI.js create mode 100644 browser/base/content/test/siteIdentity/browser_iframe_navigation.js create mode 100644 browser/base/content/test/siteIdentity/browser_ignore_same_page_navigation.js create mode 100644 browser/base/content/test/siteIdentity/browser_mcb_redirect.js create mode 100644 browser/base/content/test/siteIdentity/browser_mixedContentFramesOnHttp.js create mode 100644 browser/base/content/test/siteIdentity/browser_mixedContentFromOnunload.js create mode 100644 browser/base/content/test/siteIdentity/browser_mixed_content_cert_override.js create mode 100644 browser/base/content/test/siteIdentity/browser_mixed_content_with_navigation.js create mode 100644 browser/base/content/test/siteIdentity/browser_mixed_passive_content_indicator.js create mode 100644 browser/base/content/test/siteIdentity/browser_mixedcontent_securityflags.js create mode 100644 browser/base/content/test/siteIdentity/browser_navigation_failures.js create mode 100644 browser/base/content/test/siteIdentity/browser_no_mcb_for_loopback.js create mode 100644 browser/base/content/test/siteIdentity/browser_no_mcb_for_onions.js create mode 100644 browser/base/content/test/siteIdentity/browser_no_mcb_on_http_site.js create mode 100644 browser/base/content/test/siteIdentity/browser_secure_transport_insecure_scheme.js create mode 100644 browser/base/content/test/siteIdentity/browser_session_store_pageproxystate.js create mode 100644 browser/base/content/test/siteIdentity/browser_tab_sharing_state.js create mode 100644 browser/base/content/test/siteIdentity/dummy_iframe_page.html create mode 100644 browser/base/content/test/siteIdentity/dummy_page.html create mode 100644 browser/base/content/test/siteIdentity/file_bug1045809_1.html create mode 100644 browser/base/content/test/siteIdentity/file_bug1045809_2.html create mode 100644 browser/base/content/test/siteIdentity/file_bug822367_1.html create mode 100644 browser/base/content/test/siteIdentity/file_bug822367_1.js create mode 100644 browser/base/content/test/siteIdentity/file_bug822367_2.html create mode 100644 browser/base/content/test/siteIdentity/file_bug822367_3.html create mode 100644 browser/base/content/test/siteIdentity/file_bug822367_4.html create mode 100644 browser/base/content/test/siteIdentity/file_bug822367_4.js create mode 100644 browser/base/content/test/siteIdentity/file_bug822367_4B.html create mode 100644 browser/base/content/test/siteIdentity/file_bug822367_5.html create mode 100644 browser/base/content/test/siteIdentity/file_bug822367_6.html create mode 100644 browser/base/content/test/siteIdentity/file_bug902156.js create mode 100644 browser/base/content/test/siteIdentity/file_bug902156_1.html create mode 100644 browser/base/content/test/siteIdentity/file_bug902156_2.html create mode 100644 browser/base/content/test/siteIdentity/file_bug902156_3.html create mode 100644 browser/base/content/test/siteIdentity/file_bug906190.js create mode 100644 browser/base/content/test/siteIdentity/file_bug906190.sjs create mode 100644 browser/base/content/test/siteIdentity/file_bug906190_1.html create mode 100644 browser/base/content/test/siteIdentity/file_bug906190_2.html create mode 100644 browser/base/content/test/siteIdentity/file_bug906190_3_4.html create mode 100644 browser/base/content/test/siteIdentity/file_bug906190_redirected.html create mode 100644 browser/base/content/test/siteIdentity/file_csp_block_all_mixedcontent.html create mode 100644 browser/base/content/test/siteIdentity/file_csp_block_all_mixedcontent.js create mode 100644 browser/base/content/test/siteIdentity/file_mixedContentFramesOnHttp.html create mode 100644 browser/base/content/test/siteIdentity/file_mixedContentFromOnunload.html create mode 100644 browser/base/content/test/siteIdentity/file_mixedContentFromOnunload_test1.html create mode 100644 browser/base/content/test/siteIdentity/file_mixedContentFromOnunload_test2.html create mode 100644 browser/base/content/test/siteIdentity/file_mixedPassiveContent.html create mode 100644 browser/base/content/test/siteIdentity/file_pdf.pdf create mode 100644 browser/base/content/test/siteIdentity/file_pdf_blob.html create mode 100644 browser/base/content/test/siteIdentity/head.js create mode 100644 browser/base/content/test/siteIdentity/iframe_navigation.html create mode 100644 browser/base/content/test/siteIdentity/insecure_opener.html create mode 100644 browser/base/content/test/siteIdentity/open-self-from-frame.html create mode 100644 browser/base/content/test/siteIdentity/simple_mixed_passive.html create mode 100644 browser/base/content/test/siteIdentity/test-mixedcontent-securityerrors.html create mode 100644 browser/base/content/test/siteIdentity/test_mcb_double_redirect_image.html create mode 100644 browser/base/content/test/siteIdentity/test_mcb_redirect.html create mode 100644 browser/base/content/test/siteIdentity/test_mcb_redirect.js create mode 100644 browser/base/content/test/siteIdentity/test_mcb_redirect.sjs create mode 100644 browser/base/content/test/siteIdentity/test_mcb_redirect_image.html create mode 100644 browser/base/content/test/siteIdentity/test_no_mcb_for_loopback.html create mode 100644 browser/base/content/test/siteIdentity/test_no_mcb_for_onions.html create mode 100644 browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font.css create mode 100644 browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font.html create mode 100644 browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font2.css create mode 100644 browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font2.html create mode 100644 browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_img.css create mode 100644 browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_img.html create mode 100644 browser/base/content/test/startup/browser.ini create mode 100644 browser/base/content/test/startup/browser_preXULSkeletonUIRegistry.js create mode 100644 browser/base/content/test/static/browser.ini create mode 100644 browser/base/content/test/static/browser_all_files_referenced.js create mode 100644 browser/base/content/test/static/browser_misused_characters_in_strings.js create mode 100644 browser/base/content/test/static/browser_parsable_css.js create mode 100644 browser/base/content/test/static/browser_parsable_script.js create mode 100644 browser/base/content/test/static/browser_sentence_case_strings.js create mode 100644 browser/base/content/test/static/browser_title_case_menus.js create mode 100644 browser/base/content/test/static/bug1262648_string_with_newlines.dtd create mode 100644 browser/base/content/test/static/dummy_page.html create mode 100644 browser/base/content/test/static/head.js create mode 100644 browser/base/content/test/statuspanel/browser.ini create mode 100644 browser/base/content/test/statuspanel/browser_show_statuspanel_idn.js create mode 100644 browser/base/content/test/statuspanel/browser_show_statuspanel_twice.js create mode 100644 browser/base/content/test/statuspanel/head.js create mode 100644 browser/base/content/test/sync/browser.ini create mode 100644 browser/base/content/test/sync/browser_contextmenu_sendpage.js create mode 100644 browser/base/content/test/sync/browser_contextmenu_sendtab.js create mode 100644 browser/base/content/test/sync/browser_fxa_badge.js create mode 100644 browser/base/content/test/sync/browser_fxa_web_channel.html create mode 100644 browser/base/content/test/sync/browser_fxa_web_channel.js create mode 100644 browser/base/content/test/sync/browser_sync.js create mode 100644 browser/base/content/test/sync/browser_synced_tabs_view.js create mode 100644 browser/base/content/test/sync/head.js create mode 100644 browser/base/content/test/tabMediaIndicator/almostSilentAudioTrack.webm create mode 100644 browser/base/content/test/tabMediaIndicator/audio.ogg create mode 100644 browser/base/content/test/tabMediaIndicator/audioEndedDuringPlaying.webm create mode 100644 browser/base/content/test/tabMediaIndicator/browser.ini create mode 100644 browser/base/content/test/tabMediaIndicator/browser_destroy_iframe.js create mode 100644 browser/base/content/test/tabMediaIndicator/browser_mediaPlayback.js create mode 100644 browser/base/content/test/tabMediaIndicator/browser_mediaPlayback_mute.js create mode 100644 browser/base/content/test/tabMediaIndicator/browser_mediaplayback_audibility_change.js create mode 100644 browser/base/content/test/tabMediaIndicator/browser_mute.js create mode 100644 browser/base/content/test/tabMediaIndicator/browser_mute2.js create mode 100644 browser/base/content/test/tabMediaIndicator/browser_mute_webAudio.js create mode 100644 browser/base/content/test/tabMediaIndicator/browser_sound_indicator_silent_video.js create mode 100644 browser/base/content/test/tabMediaIndicator/browser_webAudio_hideSoundPlayingIcon.js create mode 100644 browser/base/content/test/tabMediaIndicator/browser_webAudio_silentData.js create mode 100644 browser/base/content/test/tabMediaIndicator/browser_webaudio_audibility_change.js create mode 100644 browser/base/content/test/tabMediaIndicator/file_almostSilentAudioTrack.html create mode 100644 browser/base/content/test/tabMediaIndicator/file_autoplay_media.html create mode 100644 browser/base/content/test/tabMediaIndicator/file_empty.html create mode 100644 browser/base/content/test/tabMediaIndicator/file_mediaPlayback.html create mode 100644 browser/base/content/test/tabMediaIndicator/file_mediaPlayback2.html create mode 100644 browser/base/content/test/tabMediaIndicator/file_mediaPlaybackFrame.html create mode 100644 browser/base/content/test/tabMediaIndicator/file_mediaPlaybackFrame2.html create mode 100644 browser/base/content/test/tabMediaIndicator/file_silentAudioTrack.html create mode 100644 browser/base/content/test/tabMediaIndicator/file_webAudio.html create mode 100644 browser/base/content/test/tabMediaIndicator/gizmo.mp4 create mode 100644 browser/base/content/test/tabMediaIndicator/head.js create mode 100644 browser/base/content/test/tabMediaIndicator/noaudio.webm create mode 100644 browser/base/content/test/tabMediaIndicator/silentAudioTrack.webm create mode 100644 browser/base/content/test/tabPrompts/auth-route.sjs create mode 100644 browser/base/content/test/tabPrompts/browser.ini create mode 100644 browser/base/content/test/tabPrompts/browser_abort_when_in_modal_state.js create mode 100644 browser/base/content/test/tabPrompts/browser_auth_spoofing_protection.js create mode 100644 browser/base/content/test/tabPrompts/browser_auth_spoofing_url_copy.js create mode 100644 browser/base/content/test/tabPrompts/browser_auth_spoofing_url_drag_and_drop.js create mode 100644 browser/base/content/test/tabPrompts/browser_beforeunload_urlbar.js create mode 100644 browser/base/content/test/tabPrompts/browser_closeTabSpecificPanels.js create mode 100644 browser/base/content/test/tabPrompts/browser_confirmFolderUpload.js create mode 100644 browser/base/content/test/tabPrompts/browser_contentOrigins.js create mode 100644 browser/base/content/test/tabPrompts/browser_multiplePrompts.js create mode 100644 browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js create mode 100644 browser/base/content/test/tabPrompts/browser_promptFocus.js create mode 100644 browser/base/content/test/tabPrompts/browser_prompt_closed_window.js create mode 100644 browser/base/content/test/tabPrompts/browser_switchTabPermissionPrompt.js create mode 100644 browser/base/content/test/tabPrompts/browser_windowPrompt.js create mode 100644 browser/base/content/test/tabPrompts/file_beforeunload_stop.html create mode 100644 browser/base/content/test/tabPrompts/openPromptOffTimeout.html create mode 100644 browser/base/content/test/tabPrompts/redirect-crossDomain-tabTitle-update.html create mode 100644 browser/base/content/test/tabPrompts/redirect-crossDomain.html create mode 100644 browser/base/content/test/tabPrompts/redirect-sameDomain.html create mode 100644 browser/base/content/test/tabcrashed/browser.ini create mode 100644 browser/base/content/test/tabcrashed/browser_aboutRestartRequired.ini create mode 100644 browser/base/content/test/tabcrashed/browser_aboutRestartRequired_basic.js create mode 100644 browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid_false-positive.js create mode 100644 browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid_mismatch.js create mode 100644 browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid_no-platform-ini.js create mode 100644 browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js create mode 100644 browser/base/content/test/tabcrashed/browser_launchFail.js create mode 100644 browser/base/content/test/tabcrashed/browser_multipleCrashedTabs.js create mode 100644 browser/base/content/test/tabcrashed/browser_noPermanentKey.js create mode 100644 browser/base/content/test/tabcrashed/browser_printpreview_crash.js create mode 100644 browser/base/content/test/tabcrashed/browser_showForm.js create mode 100644 browser/base/content/test/tabcrashed/browser_shown.js create mode 100644 browser/base/content/test/tabcrashed/browser_shownRestartRequired.js create mode 100644 browser/base/content/test/tabcrashed/browser_withoutDump.js create mode 100644 browser/base/content/test/tabcrashed/file_contains_emptyiframe.html create mode 100644 browser/base/content/test/tabcrashed/file_iframe.html create mode 100644 browser/base/content/test/tabcrashed/head.js create mode 100644 browser/base/content/test/tabdialogs/browser.ini create mode 100644 browser/base/content/test/tabdialogs/browser_multiple_dialog_navigation.js create mode 100644 browser/base/content/test/tabdialogs/browser_subdialog_esc.js create mode 100644 browser/base/content/test/tabdialogs/browser_tabdialogbox_content_prompts.js create mode 100644 browser/base/content/test/tabdialogs/browser_tabdialogbox_focus.js create mode 100644 browser/base/content/test/tabdialogs/browser_tabdialogbox_navigation.js create mode 100644 browser/base/content/test/tabdialogs/loadDelayedReply.sjs create mode 100644 browser/base/content/test/tabdialogs/subdialog.xhtml create mode 100644 browser/base/content/test/tabdialogs/test_page.html create mode 100644 browser/base/content/test/tabs/204.sjs create mode 100644 browser/base/content/test/tabs/blank.html create mode 100644 browser/base/content/test/tabs/browser.ini create mode 100644 browser/base/content/test/tabs/browser_addAdjacentNewTab.js create mode 100644 browser/base/content/test/tabs/browser_addTab_index.js create mode 100644 browser/base/content/test/tabs/browser_adoptTab_failure.js create mode 100644 browser/base/content/test/tabs/browser_allow_process_switches_despite_related_browser.js create mode 100644 browser/base/content/test/tabs/browser_audioTabIcon.js create mode 100644 browser/base/content/test/tabs/browser_bfcache_exemption_about_pages.js create mode 100644 browser/base/content/test/tabs/browser_bug580956.js create mode 100644 browser/base/content/test/tabs/browser_bug_1387976_restore_lazy_tab_browser_muted_state.js create mode 100644 browser/base/content/test/tabs/browser_close_during_beforeunload.js create mode 100644 browser/base/content/test/tabs/browser_close_tab_by_dblclick.js create mode 100644 browser/base/content/test/tabs/browser_contextmenu_openlink_after_tabnavigated.js create mode 100644 browser/base/content/test/tabs/browser_dont_process_switch_204.js create mode 100644 browser/base/content/test/tabs/browser_e10s_about_page_triggeringprincipal.js create mode 100644 browser/base/content/test/tabs/browser_e10s_about_process.js create mode 100644 browser/base/content/test/tabs/browser_e10s_chrome_process.js create mode 100644 browser/base/content/test/tabs/browser_e10s_javascript.js create mode 100644 browser/base/content/test/tabs/browser_e10s_mozillaweb_process.js create mode 100644 browser/base/content/test/tabs/browser_e10s_switchbrowser.js create mode 100644 browser/base/content/test/tabs/browser_file_to_http_named_popup.js create mode 100644 browser/base/content/test/tabs/browser_file_to_http_script_closable.js create mode 100644 browser/base/content/test/tabs/browser_hiddentab_contextmenu.js create mode 100644 browser/base/content/test/tabs/browser_lazy_tab_browser_events.js create mode 100644 browser/base/content/test/tabs/browser_link_in_tab_title_and_url_prefilled_blank_page.js create mode 100644 browser/base/content/test/tabs/browser_link_in_tab_title_and_url_prefilled_new_window.js create mode 100644 browser/base/content/test/tabs/browser_link_in_tab_title_and_url_prefilled_normal_page_blank_target.js create mode 100644 browser/base/content/test/tabs/browser_link_in_tab_title_and_url_prefilled_normal_page_by_script.js create mode 100644 browser/base/content/test/tabs/browser_link_in_tab_title_and_url_prefilled_normal_page_no_target.js create mode 100644 browser/base/content/test/tabs/browser_link_in_tab_title_and_url_prefilled_normal_page_other_target.js create mode 100644 browser/base/content/test/tabs/browser_long_data_url_label_truncation.js create mode 100644 browser/base/content/test/tabs/browser_middle_click_new_tab_button_loads_clipboard.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_active_tab_selected_by_default.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_bookmark.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_clear_selection_when_tab_switch.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_close.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_close_other_tabs.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_close_tabs_to_the_left.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_close_tabs_to_the_right.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_close_using_shortcuts.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_copy_through_drag_and_drop.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_drag_to_bookmarks_toolbar.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_duplicate.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_event.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_move.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_move_to_another_window_drag.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_move_to_new_window_contextmenu.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_mute_unmute.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_open_related.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_pin_unpin.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_play.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_reload.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_reopen_in_container.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_reorder.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_using_Ctrl.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_using_Shift.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_using_Shift_and_Ctrl.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_using_keyboard.js create mode 100644 browser/base/content/test/tabs/browser_multiselect_tabs_using_selectedTabs.js create mode 100644 browser/base/content/test/tabs/browser_navigatePinnedTab.js create mode 100644 browser/base/content/test/tabs/browser_navigate_home_focuses_addressbar.js create mode 100644 browser/base/content/test/tabs/browser_navigate_through_urls_origin_attributes.js create mode 100644 browser/base/content/test/tabs/browser_new_file_whitelisted_http_tab.js create mode 100644 browser/base/content/test/tabs/browser_new_tab_in_privilegedabout_process_pref.js create mode 100644 browser/base/content/test/tabs/browser_new_tab_insert_position.js create mode 100644 browser/base/content/test/tabs/browser_new_tab_url.js create mode 100644 browser/base/content/test/tabs/browser_newwindow_tabstrip_overflow.js create mode 100644 browser/base/content/test/tabs/browser_open_newtab_start_observer_notification.js create mode 100644 browser/base/content/test/tabs/browser_opened_file_tab_navigated_to_web.js create mode 100644 browser/base/content/test/tabs/browser_origin_attrs_in_remote_type.js create mode 100644 browser/base/content/test/tabs/browser_origin_attrs_rel.js create mode 100644 browser/base/content/test/tabs/browser_originalURI.js create mode 100644 browser/base/content/test/tabs/browser_overflowScroll.js create mode 100644 browser/base/content/test/tabs/browser_paste_event_at_middle_click_on_link.js create mode 100644 browser/base/content/test/tabs/browser_pinnedTabs.js create mode 100644 browser/base/content/test/tabs/browser_pinnedTabs_clickOpen.js create mode 100644 browser/base/content/test/tabs/browser_pinnedTabs_closeByKeyboard.js create mode 100644 browser/base/content/test/tabs/browser_positional_attributes.js create mode 100644 browser/base/content/test/tabs/browser_preloadedBrowser_zoom.js create mode 100644 browser/base/content/test/tabs/browser_privilegedmozilla_process_pref.js create mode 100644 browser/base/content/test/tabs/browser_progress_keyword_search_handling.js create mode 100644 browser/base/content/test/tabs/browser_relatedTabs_reset.js create mode 100644 browser/base/content/test/tabs/browser_reload_deleted_file.js create mode 100644 browser/base/content/test/tabs/browser_removeTabsToTheEnd.js create mode 100644 browser/base/content/test/tabs/browser_removeTabsToTheStart.js create mode 100644 browser/base/content/test/tabs/browser_removeTabs_order.js create mode 100644 browser/base/content/test/tabs/browser_removeTabs_skipPermitUnload.js create mode 100644 browser/base/content/test/tabs/browser_replacewithwindow_commands.js create mode 100644 browser/base/content/test/tabs/browser_switch_by_scrolling.js create mode 100644 browser/base/content/test/tabs/browser_tabCloseProbes.js create mode 100644 browser/base/content/test/tabs/browser_tabCloseSpacer.js create mode 100644 browser/base/content/test/tabs/browser_tabContextMenu_keyboard.js create mode 100644 browser/base/content/test/tabs/browser_tabReorder.js create mode 100644 browser/base/content/test/tabs/browser_tabReorder_overflow.js create mode 100644 browser/base/content/test/tabs/browser_tabSpinnerProbe.js create mode 100644 browser/base/content/test/tabs/browser_tabSuccessors.js create mode 100644 browser/base/content/test/tabs/browser_tab_a11y_description.js create mode 100644 browser/base/content/test/tabs/browser_tab_label_during_reload.js create mode 100644 browser/base/content/test/tabs/browser_tab_label_picture_in_picture.js create mode 100644 browser/base/content/test/tabs/browser_tab_manager_close.js create mode 100644 browser/base/content/test/tabs/browser_tab_manager_drag.js create mode 100644 browser/base/content/test/tabs/browser_tab_manager_keyboard_access.js create mode 100644 browser/base/content/test/tabs/browser_tab_manager_visibility.js create mode 100644 browser/base/content/test/tabs/browser_tab_move_to_new_window_reload.js create mode 100644 browser/base/content/test/tabs/browser_tab_play.js create mode 100644 browser/base/content/test/tabs/browser_tab_tooltips.js create mode 100644 browser/base/content/test/tabs/browser_tabswitch_contextmenu.js create mode 100644 browser/base/content/test/tabs/browser_tabswitch_select.js create mode 100644 browser/base/content/test/tabs/browser_tabswitch_updatecommands.js create mode 100644 browser/base/content/test/tabs/browser_tabswitch_window_focus.js create mode 100644 browser/base/content/test/tabs/browser_undo_close_tabs.js create mode 100644 browser/base/content/test/tabs/browser_undo_close_tabs_at_start.js create mode 100644 browser/base/content/test/tabs/browser_viewsource_of_data_URI_in_file_process.js create mode 100644 browser/base/content/test/tabs/browser_visibleTabs_bookmarkAllTabs.js create mode 100644 browser/base/content/test/tabs/browser_visibleTabs_contextMenu.js create mode 100644 browser/base/content/test/tabs/common_link_in_tab_title_and_url_prefilled.js create mode 100644 browser/base/content/test/tabs/dummy_page.html create mode 100644 browser/base/content/test/tabs/file_about_child.html create mode 100644 browser/base/content/test/tabs/file_about_parent.html create mode 100644 browser/base/content/test/tabs/file_about_srcdoc.html create mode 100644 browser/base/content/test/tabs/file_anchor_elements.html create mode 100644 browser/base/content/test/tabs/file_mediaPlayback.html create mode 100644 browser/base/content/test/tabs/file_new_tab_page.html create mode 100644 browser/base/content/test/tabs/file_rel_opener_noopener.html create mode 100644 browser/base/content/test/tabs/head.js create mode 100644 browser/base/content/test/tabs/helper_origin_attrs_testing.js create mode 100644 browser/base/content/test/tabs/link_in_tab_title_and_url_prefilled.html create mode 100644 browser/base/content/test/tabs/open_window_in_new_tab.html create mode 100644 browser/base/content/test/tabs/page_with_iframe.html create mode 100644 browser/base/content/test/tabs/redirect_via_header.html create mode 100644 browser/base/content/test/tabs/redirect_via_header.html^headers^ create mode 100644 browser/base/content/test/tabs/redirect_via_meta_tag.html create mode 100644 browser/base/content/test/tabs/request-timeout.sjs create mode 100644 browser/base/content/test/tabs/tab_that_closes.html create mode 100644 browser/base/content/test/tabs/test_bug1358314.html create mode 100644 browser/base/content/test/tabs/test_process_flags_chrome.html create mode 100644 browser/base/content/test/tabs/wait-a-bit.sjs create mode 100644 browser/base/content/test/touch/browser.ini create mode 100644 browser/base/content/test/touch/browser_menu_touch.js create mode 100644 browser/base/content/test/utilityOverlay/browser.ini create mode 100644 browser/base/content/test/utilityOverlay/browser_openWebLinkIn.js create mode 100644 browser/base/content/test/webextensions/.eslintrc.js create mode 100644 browser/base/content/test/webextensions/browser.ini create mode 100644 browser/base/content/test/webextensions/browser_aboutaddons_blanktab.js create mode 100644 browser/base/content/test/webextensions/browser_extension_sideloading.js create mode 100644 browser/base/content/test/webextensions/browser_extension_update_background.js create mode 100644 browser/base/content/test/webextensions/browser_extension_update_background_noprompt.js create mode 100644 browser/base/content/test/webextensions/browser_legacy_webext.xpi create mode 100644 browser/base/content/test/webextensions/browser_permissions_dismiss.js create mode 100644 browser/base/content/test/webextensions/browser_permissions_installTrigger.js create mode 100644 browser/base/content/test/webextensions/browser_permissions_local_file.js create mode 100644 browser/base/content/test/webextensions/browser_permissions_mozAddonManager.js create mode 100644 browser/base/content/test/webextensions/browser_permissions_optional.js create mode 100644 browser/base/content/test/webextensions/browser_permissions_pointerevent.js create mode 100644 browser/base/content/test/webextensions/browser_permissions_unsigned.js create mode 100644 browser/base/content/test/webextensions/browser_update_checkForUpdates.js create mode 100644 browser/base/content/test/webextensions/browser_update_interactive_noprompt.js create mode 100644 browser/base/content/test/webextensions/browser_webext_nopermissions.xpi create mode 100644 browser/base/content/test/webextensions/browser_webext_permissions.xpi create mode 100644 browser/base/content/test/webextensions/browser_webext_unsigned.xpi create mode 100644 browser/base/content/test/webextensions/browser_webext_update.json create mode 100644 browser/base/content/test/webextensions/browser_webext_update1.xpi create mode 100644 browser/base/content/test/webextensions/browser_webext_update2.xpi create mode 100644 browser/base/content/test/webextensions/browser_webext_update_icon1.xpi create mode 100644 browser/base/content/test/webextensions/browser_webext_update_icon2.xpi create mode 100644 browser/base/content/test/webextensions/browser_webext_update_origins1.xpi create mode 100644 browser/base/content/test/webextensions/browser_webext_update_origins2.xpi create mode 100644 browser/base/content/test/webextensions/browser_webext_update_perms1.xpi create mode 100644 browser/base/content/test/webextensions/browser_webext_update_perms2.xpi create mode 100644 browser/base/content/test/webextensions/file_install_extensions.html create mode 100644 browser/base/content/test/webextensions/head.js create mode 100644 browser/base/content/test/webrtc/browser.ini create mode 100644 browser/base/content/test/webrtc/browser_WebrtcGlobalInformation.js create mode 100644 browser/base/content/test/webrtc/browser_device_controls_menus.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_anim.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_by_device_id.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_default_permissions.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_grace.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_in_frame.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame_chain.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_multi_process.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_paused.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_queue_request.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_screen.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_screen_tab_close.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_tear_off_tab.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_unprompted_access.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_unprompted_access_in_frame.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_unprompted_access_queue_request.js create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_unprompted_access_tear_off_tab.js create mode 100644 browser/base/content/test/webrtc/browser_devices_select_audio_output.js create mode 100644 browser/base/content/test/webrtc/browser_global_mute_toggles.js create mode 100644 browser/base/content/test/webrtc/browser_indicator_popuphiding.js create mode 100644 browser/base/content/test/webrtc/browser_notification_silencing.js create mode 100644 browser/base/content/test/webrtc/browser_stop_sharing_button.js create mode 100644 browser/base/content/test/webrtc/browser_stop_streams_on_indicator_close.js create mode 100644 browser/base/content/test/webrtc/browser_tab_switch_warning.js create mode 100644 browser/base/content/test/webrtc/browser_webrtc_hooks.js create mode 100644 browser/base/content/test/webrtc/get_user_media.html create mode 100644 browser/base/content/test/webrtc/get_user_media2.html create mode 100644 browser/base/content/test/webrtc/get_user_media_in_frame.html create mode 100644 browser/base/content/test/webrtc/get_user_media_in_xorigin_frame.html create mode 100644 browser/base/content/test/webrtc/get_user_media_in_xorigin_frame_ancestor.html create mode 100644 browser/base/content/test/webrtc/gracePeriod/browser.ini create mode 100644 browser/base/content/test/webrtc/head.js create mode 100644 browser/base/content/test/webrtc/legacyIndicator/browser.ini create mode 100644 browser/base/content/test/webrtc/peerconnection_connect.html create mode 100644 browser/base/content/test/webrtc/single_peerconnection.html create mode 100644 browser/base/content/test/zoom/browser.ini create mode 100644 browser/base/content/test/zoom/browser_background_link_zoom_reset.js create mode 100644 browser/base/content/test/zoom/browser_background_zoom.js create mode 100644 browser/base/content/test/zoom/browser_default_zoom.js create mode 100644 browser/base/content/test/zoom/browser_default_zoom_fission.js create mode 100644 browser/base/content/test/zoom/browser_default_zoom_multitab.js create mode 100644 browser/base/content/test/zoom/browser_default_zoom_multitab_002.js create mode 100644 browser/base/content/test/zoom/browser_default_zoom_sitespecific.js create mode 100644 browser/base/content/test/zoom/browser_image_zoom_tabswitch.js create mode 100644 browser/base/content/test/zoom/browser_mousewheel_zoom.js create mode 100644 browser/base/content/test/zoom/browser_sitespecific_background_pref.js create mode 100644 browser/base/content/test/zoom/browser_sitespecific_image_zoom.js create mode 100644 browser/base/content/test/zoom/browser_sitespecific_video_zoom.js create mode 100644 browser/base/content/test/zoom/browser_subframe_textzoom.js create mode 100644 browser/base/content/test/zoom/browser_tabswitch_zoom_flicker.js create mode 100644 browser/base/content/test/zoom/browser_tooltip_zoom.js create mode 100644 browser/base/content/test/zoom/browser_zoom_commands.js create mode 100644 browser/base/content/test/zoom/head.js create mode 100644 browser/base/content/test/zoom/zoom_test.html (limited to 'browser/base/content/test') diff --git a/browser/base/content/test/about/POSTSearchEngine.xml b/browser/base/content/test/about/POSTSearchEngine.xml new file mode 100644 index 0000000000..f2f884cf51 --- /dev/null +++ b/browser/base/content/test/about/POSTSearchEngine.xml @@ -0,0 +1,6 @@ + + POST Search + + + + diff --git a/browser/base/content/test/about/browser.ini b/browser/base/content/test/about/browser.ini new file mode 100644 index 0000000000..ce82ff8006 --- /dev/null +++ b/browser/base/content/test/about/browser.ini @@ -0,0 +1,59 @@ +[DEFAULT] +support-files = + head.js + print_postdata.sjs + searchSuggestionEngine.sjs + searchSuggestionEngine.xml + slow_loading_page.sjs + POSTSearchEngine.xml + dummy_page.html + +[browser_aboutCertError.js] +[browser_aboutCertError_clockSkew.js] +[browser_aboutCertError_exception.js] +[browser_aboutCertError_mitm.js] +[browser_aboutCertError_noSubjectAltName.js] +[browser_aboutCertError_offlineSupport.js] +[browser_aboutCertError_telemetry.js] +[browser_aboutDialog_distribution.js] +[browser_aboutHome_search_POST.js] +[browser_aboutHome_search_composing.js] +[browser_aboutHome_search_searchbar.js] +[browser_aboutHome_search_suggestion.js] +skip-if = + os == "mac" + os == "linux" && (!debug || bits == 64) + os == 'win' && os_version == '10.0' && bits == 64 && !debug # Bug 1399648, bug 1402502 +[browser_aboutHome_search_telemetry.js] +[browser_aboutNetError.js] +[browser_aboutNetError_csp_iframe.js] +https_first_disabled = true +support-files = + iframe_page_csp.html + csp_iframe.sjs +[browser_aboutNetError_native_fallback.js] +skip-if = + socketprocess_networking +[browser_aboutNetError_trr.js] +skip-if = + socketprocess_networking +[browser_aboutNetError_xfo_iframe.js] +https_first_disabled = true +support-files = + iframe_page_xfo.html + xfo_iframe.sjs +[browser_aboutNewTab_bookmarksToolbar.js] +[browser_aboutNewTab_bookmarksToolbarEmpty.js] +skip-if = tsan # Bug 1676326, highly frequent on TSan +[browser_aboutNewTab_bookmarksToolbarNewWindow.js] +[browser_aboutNewTab_bookmarksToolbarPrefs.js] +[browser_aboutStopReload.js] +[browser_aboutSupport.js] +skip-if = + os == 'linux' && bits == 64 && asan && !debug # Bug 1713368 +[browser_aboutSupport_newtab_security_state.js] +[browser_aboutSupport_places.js] +skip-if = os == 'android' +[browser_bug435325.js] +skip-if = verify && !debug && os == 'mac' +[browser_bug633691.js] diff --git a/browser/base/content/test/about/browser_aboutCertError.js b/browser/base/content/test/about/browser_aboutCertError.js new file mode 100644 index 0000000000..7f1f8149fa --- /dev/null +++ b/browser/base/content/test/about/browser_aboutCertError.js @@ -0,0 +1,548 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// This is testing the aboutCertError page (Bug 1207107). + +const GOOD_PAGE = "https://example.com/"; +const GOOD_PAGE_2 = "https://example.org/"; +const BAD_CERT = "https://expired.example.com/"; +const UNKNOWN_ISSUER = "https://self-signed.example.com "; +const BAD_STS_CERT = + "https://badchain.include-subdomains.pinning.example.com:443"; +const { TabStateFlusher } = ChromeUtils.importESModule( + "resource:///modules/sessionstore/TabStateFlusher.sys.mjs" +); + +add_task(async function checkReturnToAboutHome() { + info( + "Loading a bad cert page directly and making sure 'return to previous page' goes to about:home" + ); + for (let useFrame of [false, true]) { + let tab = await openErrorPage(BAD_CERT, useFrame); + let browser = tab.linkedBrowser; + + is(browser.webNavigation.canGoBack, false, "!webNavigation.canGoBack"); + is( + browser.webNavigation.canGoForward, + false, + "!webNavigation.canGoForward" + ); + + // Populate the shistory entries manually, since it happens asynchronously + // and the following tests will be too soon otherwise. + await TabStateFlusher.flush(browser); + let { entries } = JSON.parse(SessionStore.getTabState(tab)); + is(entries.length, 1, "there is one shistory entry"); + + info("Clicking the go back button on about:certerror"); + let bc = browser.browsingContext; + if (useFrame) { + bc = bc.children[0]; + } + let locationChangePromise = BrowserTestUtils.waitForLocationChange( + gBrowser, + "about:home" + ); + await SpecialPowers.spawn(bc, [useFrame], async function (subFrame) { + let returnButton = content.document.getElementById("returnButton"); + if (!subFrame) { + if (!Services.focus.focusedElement == returnButton) { + await ContentTaskUtils.waitForEvent(returnButton, "focus"); + } + Assert.ok(true, "returnButton has focus"); + } + // Note that going back to about:newtab might cause a process flip, if + // the browser is configured to run about:newtab in its own special + // content process. + returnButton.click(); + }); + + await locationChangePromise; + + is(browser.webNavigation.canGoBack, true, "webNavigation.canGoBack"); + is( + browser.webNavigation.canGoForward, + false, + "!webNavigation.canGoForward" + ); + is(gBrowser.currentURI.spec, "about:home", "Went back"); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } +}); + +add_task(async function checkReturnToPreviousPage() { + info( + "Loading a bad cert page and making sure 'return to previous page' goes back" + ); + for (let useFrame of [false, true]) { + let tab; + let browser; + if (useFrame) { + tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, GOOD_PAGE); + browser = tab.linkedBrowser; + + BrowserTestUtils.loadURIString(browser, GOOD_PAGE_2); + await BrowserTestUtils.browserLoaded(browser, false, GOOD_PAGE_2); + await injectErrorPageFrame(tab, BAD_CERT); + } else { + tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, GOOD_PAGE); + browser = gBrowser.selectedBrowser; + + info("Loading and waiting for the cert error"); + let certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser); + BrowserTestUtils.loadURIString(browser, BAD_CERT); + await certErrorLoaded; + } + + is(browser.webNavigation.canGoBack, true, "webNavigation.canGoBack"); + is( + browser.webNavigation.canGoForward, + false, + "!webNavigation.canGoForward" + ); + + // Populate the shistory entries manually, since it happens asynchronously + // and the following tests will be too soon otherwise. + await TabStateFlusher.flush(browser); + let { entries } = JSON.parse(SessionStore.getTabState(tab)); + is(entries.length, 2, "there are two shistory entries"); + + info("Clicking the go back button on about:certerror"); + let bc = browser.browsingContext; + if (useFrame) { + bc = bc.children[0]; + } + + let pageShownPromise = BrowserTestUtils.waitForContentEvent( + browser, + "pageshow", + true + ); + await SpecialPowers.spawn(bc, [useFrame], async function (subFrame) { + let returnButton = content.document.getElementById("returnButton"); + returnButton.click(); + }); + await pageShownPromise; + + is(browser.webNavigation.canGoBack, false, "!webNavigation.canGoBack"); + is(browser.webNavigation.canGoForward, true, "webNavigation.canGoForward"); + is(gBrowser.currentURI.spec, GOOD_PAGE, "Went back"); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } +}); + +// This checks that the appinfo.appBuildID starts with a date string, +// which is required for the misconfigured system time check. +add_task(async function checkAppBuildIDIsDate() { + let appBuildID = Services.appinfo.appBuildID; + let year = parseInt(appBuildID.substr(0, 4), 10); + let month = parseInt(appBuildID.substr(4, 2), 10); + let day = parseInt(appBuildID.substr(6, 2), 10); + + ok(year >= 2016 && year <= 2100, "appBuildID contains a valid year"); + ok(month >= 1 && month <= 12, "appBuildID contains a valid month"); + ok(day >= 1 && day <= 31, "appBuildID contains a valid day"); +}); + +add_task(async function checkAdvancedDetails() { + info( + "Loading a bad cert page and verifying the main error and advanced details section" + ); + for (let useFrame of [false, true]) { + let tab = await openErrorPage(BAD_CERT, useFrame); + let browser = tab.linkedBrowser; + + let bc = browser.browsingContext; + if (useFrame) { + bc = bc.children[0]; + } + + let message = await SpecialPowers.spawn(bc, [], async function () { + let doc = content.document; + + const shortDesc = doc.getElementById("errorShortDesc"); + const sdArgs = JSON.parse(shortDesc.dataset.l10nArgs); + is( + sdArgs.hostname, + "expired.example.com", + "Should list hostname in error message." + ); + + Assert.ok( + doc.getElementById("certificateErrorDebugInformation").hidden, + "Debug info is initially hidden" + ); + + let exceptionButton = doc.getElementById("exceptionDialogButton"); + Assert.ok( + !exceptionButton.disabled, + "Exception button is not disabled by default." + ); + + let advancedButton = doc.getElementById("advancedButton"); + advancedButton.click(); + + // Wait until fluent sets the errorCode inner text. + let errorCode; + await ContentTaskUtils.waitForCondition(() => { + errorCode = doc.getElementById("errorCode"); + return errorCode && errorCode.textContent != ""; + }, "error code has been set inside the advanced button panel"); + + return { textContent: errorCode.textContent, tagName: errorCode.tagName }; + }); + is( + message.textContent, + "SEC_ERROR_EXPIRED_CERTIFICATE", + "Correct error message found" + ); + is(message.tagName, "a", "Error message is a link"); + + message = await SpecialPowers.spawn(bc, [], async function () { + let doc = content.document; + let errorCode = doc.getElementById("errorCode"); + errorCode.click(); + let div = doc.getElementById("certificateErrorDebugInformation"); + let text = doc.getElementById("certificateErrorText"); + Assert.ok( + content.getComputedStyle(div).display !== "none", + "Debug information is visible" + ); + let failedCertChain = + content.docShell.failedChannel.securityInfo.failedCertChain.map(cert => + cert.getBase64DERString() + ); + return { + divDisplay: content.getComputedStyle(div).display, + text: text.textContent, + failedCertChain, + }; + }); + isnot(message.divDisplay, "none", "Debug information is visible"); + ok(message.text.includes(BAD_CERT), "Correct URL found"); + ok( + message.text.includes("Certificate has expired"), + "Correct error message found" + ); + ok( + message.text.includes("HTTP Strict Transport Security: false"), + "Correct HSTS value found" + ); + ok( + message.text.includes("HTTP Public Key Pinning: false"), + "Correct HPKP value found" + ); + let certChain = getCertChainAsString(message.failedCertChain); + ok(message.text.includes(certChain), "Found certificate chain"); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } +}); + +add_task(async function checkAdvancedDetailsForHSTS() { + info( + "Loading a bad STS cert page and verifying the advanced details section" + ); + for (let useFrame of [false, true]) { + let tab = await openErrorPage(BAD_STS_CERT, useFrame); + let browser = tab.linkedBrowser; + + let bc = browser.browsingContext; + if (useFrame) { + bc = bc.children[0]; + } + + let message = await SpecialPowers.spawn(bc, [], async function () { + let doc = content.document; + let advancedButton = doc.getElementById("advancedButton"); + advancedButton.click(); + + // Wait until fluent sets the errorCode inner text. + let ec; + await ContentTaskUtils.waitForCondition(() => { + ec = doc.getElementById("errorCode"); + return ec.textContent != ""; + }, "error code has been set inside the advanced button panel"); + + let cdl = doc.getElementById("cert_domain_link"); + return { + ecTextContent: ec.textContent, + ecTagName: ec.tagName, + cdlTextContent: cdl.textContent, + cdlTagName: cdl.tagName, + }; + }); + + const badStsUri = Services.io.newURI(BAD_STS_CERT); + is( + message.ecTextContent, + "SSL_ERROR_BAD_CERT_DOMAIN", + "Correct error message found" + ); + is(message.ecTagName, "a", "Error message is a link"); + const url = badStsUri.prePath.slice(badStsUri.prePath.indexOf(".") + 1); + is(message.cdlTextContent, url, "Correct cert_domain_link contents found"); + is(message.cdlTagName, "a", "cert_domain_link is a link"); + + message = await SpecialPowers.spawn(bc, [], async function () { + let doc = content.document; + let errorCode = doc.getElementById("errorCode"); + errorCode.click(); + let div = doc.getElementById("certificateErrorDebugInformation"); + let text = doc.getElementById("certificateErrorText"); + let failedCertChain = + content.docShell.failedChannel.securityInfo.failedCertChain.map(cert => + cert.getBase64DERString() + ); + return { + divDisplay: content.getComputedStyle(div).display, + text: text.textContent, + failedCertChain, + }; + }); + isnot(message.divDisplay, "none", "Debug information is visible"); + ok(message.text.includes(badStsUri.spec), "Correct URL found"); + ok( + message.text.includes( + "requested domain name does not match the server\u2019s certificate" + ), + "Correct error message found" + ); + ok( + message.text.includes("HTTP Strict Transport Security: false"), + "Correct HSTS value found" + ); + ok( + message.text.includes("HTTP Public Key Pinning: true"), + "Correct HPKP value found" + ); + let certChain = getCertChainAsString(message.failedCertChain); + ok(message.text.includes(certChain), "Found certificate chain"); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } +}); + +add_task(async function checkUnknownIssuerLearnMoreLink() { + info( + "Loading a cert error for self-signed pages and checking the correct link is shown" + ); + for (let useFrame of [false, true]) { + let tab = await openErrorPage(UNKNOWN_ISSUER, useFrame); + let browser = tab.linkedBrowser; + + let bc = browser.browsingContext; + if (useFrame) { + bc = bc.children[0]; + } + + let href = await SpecialPowers.spawn(bc, [], async function () { + let learnMoreLink = content.document.getElementById("learnMoreLink"); + return learnMoreLink.href; + }); + ok(href.endsWith("security-error"), "security-error in the Learn More URL"); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } +}); + +add_task(async function checkViewCertificate() { + info("Loading a cert error and checking that the certificate can be shown."); + for (let useFrame of [true, false]) { + if (useFrame) { + // Bug #1573502 + continue; + } + let tab = await openErrorPage(UNKNOWN_ISSUER, useFrame); + let browser = tab.linkedBrowser; + + let bc = browser.browsingContext; + if (useFrame) { + bc = bc.children[0]; + } + + let loaded = BrowserTestUtils.waitForNewTab(gBrowser, null, true); + await SpecialPowers.spawn(bc, [], async function () { + let viewCertificate = content.document.getElementById("viewCertificate"); + viewCertificate.click(); + }); + await loaded; + + let spec = gBrowser.selectedTab.linkedBrowser.documentURI.spec; + Assert.ok( + spec.startsWith("about:certificate"), + "about:certificate is the new opened tab" + ); + + await SpecialPowers.spawn( + gBrowser.selectedTab.linkedBrowser, + [], + async function () { + let doc = content.document; + let certificateSection = await ContentTaskUtils.waitForCondition(() => { + return doc.querySelector("certificate-section"); + }, "Certificate section found"); + + let infoGroup = + certificateSection.shadowRoot.querySelector("info-group"); + Assert.ok(infoGroup, "infoGroup found"); + + let items = infoGroup.shadowRoot.querySelectorAll("info-item"); + let commonnameID = items[items.length - 1].shadowRoot + .querySelector("label") + .getAttribute("data-l10n-id"); + Assert.equal( + commonnameID, + "certificate-viewer-common-name", + "The correct item was selected" + ); + + let commonnameValue = + items[items.length - 1].shadowRoot.querySelector(".info").textContent; + Assert.equal( + commonnameValue, + "self-signed.example.com", + "Shows the correct certificate in the page" + ); + } + ); + BrowserTestUtils.removeTab(gBrowser.selectedTab); // closes about:certificate + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } +}); + +add_task(async function checkBadStsCertHeadline() { + info( + "Loading a bad sts cert error page and checking that the correct headline is shown" + ); + for (let useFrame of [false, true]) { + let tab = await openErrorPage(BAD_CERT, useFrame); + let browser = tab.linkedBrowser; + + let bc = browser.browsingContext; + if (useFrame) { + bc = bc.children[0]; + } + + await SpecialPowers.spawn(bc, [useFrame], async _useFrame => { + const titleText = content.document.querySelector(".title-text"); + is( + titleText.dataset.l10nId, + _useFrame ? "nssBadCert-sts-title" : "nssBadCert-title", + "Error page title is set" + ); + }); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } +}); + +add_task(async function checkSandboxedIframe() { + info( + "Loading a bad sts cert error in a sandboxed iframe and check that the correct headline is shown" + ); + let useFrame = true; + let sandboxed = true; + let tab = await openErrorPage(BAD_CERT, useFrame, sandboxed); + let browser = tab.linkedBrowser; + + let bc = browser.browsingContext.children[0]; + await SpecialPowers.spawn(bc, [], async function () { + let doc = content.document; + + const titleText = doc.querySelector(".title-text"); + is( + titleText.dataset.l10nId, + "nssBadCert-sts-title", + "Title shows Did Not Connect: Potential Security Issue" + ); + + const errorLabel = doc.querySelector( + '[data-l10n-id="cert-error-code-prefix-link"]' + ); + const elArgs = JSON.parse(errorLabel.dataset.l10nArgs); + is( + elArgs.error, + "SEC_ERROR_EXPIRED_CERTIFICATE", + "Correct error message found" + ); + is( + doc.getElementById("errorCode").tagName, + "a", + "Error message contains a link" + ); + }); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +add_task(async function checkViewSource() { + info( + "Loading a bad sts cert error in a sandboxed iframe and check that the correct headline is shown" + ); + let uri = "view-source:" + BAD_CERT; + let tab = await openErrorPage(uri); + let browser = tab.linkedBrowser; + + await SpecialPowers.spawn(browser, [], async function () { + let doc = content.document; + + const errorLabel = doc.querySelector( + '[data-l10n-id="cert-error-code-prefix-link"]' + ); + const elArgs = JSON.parse(errorLabel.dataset.l10nArgs); + is( + elArgs.error, + "SEC_ERROR_EXPIRED_CERTIFICATE", + "Correct error message found" + ); + is( + doc.getElementById("errorCode").tagName, + "a", + "Error message contains a link" + ); + + const titleText = doc.querySelector(".title-text"); + is(titleText.dataset.l10nId, "nssBadCert-title", "Error page title is set"); + + const shortDesc = doc.getElementById("errorShortDesc"); + const sdArgs = JSON.parse(shortDesc.dataset.l10nArgs); + is( + sdArgs.hostname, + "expired.example.com", + "Should list hostname in error message." + ); + }); + + let loaded = BrowserTestUtils.browserLoaded(browser, false, uri); + info("Clicking the exceptionDialogButton in advanced panel"); + await SpecialPowers.spawn(browser, [], async function () { + let doc = content.document; + let exceptionButton = doc.getElementById("exceptionDialogButton"); + exceptionButton.click(); + }); + + info("Loading the url after adding exception"); + await loaded; + + await SpecialPowers.spawn(browser, [], async function () { + let doc = content.document; + ok( + !doc.documentURI.startsWith("about:certerror"), + "Exception has been added" + ); + }); + + let certOverrideService = Cc[ + "@mozilla.org/security/certoverride;1" + ].getService(Ci.nsICertOverrideService); + certOverrideService.clearValidityOverride("expired.example.com", -1, {}); + + loaded = BrowserTestUtils.waitForErrorPage(browser); + BrowserReloadSkipCache(); + await loaded; + + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); diff --git a/browser/base/content/test/about/browser_aboutCertError_clockSkew.js b/browser/base/content/test/about/browser_aboutCertError_clockSkew.js new file mode 100644 index 0000000000..e3b77bd636 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutCertError_clockSkew.js @@ -0,0 +1,153 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS = + "services.settings.clock_skew_seconds"; +const PREF_SERVICES_SETTINGS_LAST_FETCHED = + "services.settings.last_update_seconds"; + +add_task(async function checkWrongSystemTimeWarning() { + async function setUpPage() { + let browser; + let certErrorLoaded; + await BrowserTestUtils.openNewForegroundTab( + gBrowser, + () => { + gBrowser.selectedTab = BrowserTestUtils.addTab( + gBrowser, + "https://expired.example.com/" + ); + browser = gBrowser.selectedBrowser; + certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser); + }, + false + ); + + info("Loading and waiting for the cert error"); + await certErrorLoaded; + + return SpecialPowers.spawn(browser, [], async function () { + let doc = content.document; + let div = doc.getElementById("errorShortDesc"); + let learnMoreLink = doc.getElementById("learnMoreLink"); + + await ContentTaskUtils.waitForCondition( + () => div.textContent.includes("update your computer clock"), + "Correct error message found" + ); + + return { + divDisplay: content.getComputedStyle(div).display, + text: div.textContent, + learnMoreLink: learnMoreLink.href, + }; + }); + } + + // Pretend that we recently updated our kinto clock skew pref + Services.prefs.setIntPref( + PREF_SERVICES_SETTINGS_LAST_FETCHED, + Math.floor(Date.now() / 1000) + ); + + // For this test, we want to trick Firefox into believing that + // the local system time (as returned by Date.now()) is wrong. + // Because we don't want to actually change the local system time, + // we will do the following: + + // Take the validity date of our test page (expired.example.com). + let expiredDate = new Date("2010/01/05 12:00"); + let localDate = Date.now(); + + // Compute the difference between the server date and the correct + // local system date. + let skew = Math.floor((localDate - expiredDate) / 1000); + + // Make it seem like our reference server agrees that the certificate + // date is correct by recording the difference as clock skew. + Services.prefs.setIntPref(PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS, skew); + + let localDateFmt = new Intl.DateTimeFormat("en-US", { + dateStyle: "medium", + }).format(localDate); + + info("Loading a bad cert page with a skewed clock"); + let message = await setUpPage(); + + isnot( + message.divDisplay, + "none", + "Wrong time message information is visible" + ); + ok( + message.text.includes("update your computer clock"), + "Correct error message found" + ); + ok( + message.text.includes("expired.example.com"), + "URL found in error message" + ); + ok(message.text.includes(localDateFmt), "Correct local date displayed"); + ok( + message.learnMoreLink.includes("time-errors"), + "time-errors in the Learn More URL" + ); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + Services.prefs.clearUserPref(PREF_SERVICES_SETTINGS_LAST_FETCHED); + Services.prefs.clearUserPref(PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS); +}); + +add_task(async function checkCertError() { + async function setUpPage() { + let browser; + let certErrorLoaded; + gBrowser.selectedTab = BrowserTestUtils.addTab( + gBrowser, + "https://expired.example.com/" + ); + browser = gBrowser.selectedBrowser; + certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser); + + info("Loading and waiting for the cert error"); + await certErrorLoaded; + + return SpecialPowers.spawn(browser, [], async function () { + let doc = content.document; + let el = doc.getElementById("errorWhatToDoText"); + await ContentTaskUtils.waitForCondition(() => el.textContent); + return el.textContent; + }); + } + + // The particular error message will be displayed only when clock_skew_seconds is + // less or equal to a day and the difference between date.now() and last_fetched is less than + // or equal to 5 days. Setting the prefs accordingly. + + Services.prefs.setIntPref( + PREF_SERVICES_SETTINGS_LAST_FETCHED, + Math.floor(Date.now() / 1000) + ); + + let skew = 60 * 60 * 24; + Services.prefs.setIntPref(PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS, skew); + + info("Loading a bad cert page"); + let message = await setUpPage(); + + ok( + message.includes( + "The issue is most likely with the website, and there is nothing you can do" + + " to resolve it. You can notify the website’s administrator about the problem." + ), + "Correct error message found" + ); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + Services.prefs.clearUserPref(PREF_SERVICES_SETTINGS_LAST_FETCHED); + Services.prefs.clearUserPref(PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS); +}); diff --git a/browser/base/content/test/about/browser_aboutCertError_exception.js b/browser/base/content/test/about/browser_aboutCertError_exception.js new file mode 100644 index 0000000000..7ee1bdde45 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutCertError_exception.js @@ -0,0 +1,221 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const BAD_CERT = "https://expired.example.com/"; +const BAD_STS_CERT = + "https://badchain.include-subdomains.pinning.example.com:443"; +const PREF_PERMANENT_OVERRIDE = "security.certerrors.permanentOverride"; + +add_task(async function checkExceptionDialogButton() { + info( + "Loading a bad cert page and making sure the exceptionDialogButton directly adds an exception" + ); + let tab = await openErrorPage(BAD_CERT); + let browser = tab.linkedBrowser; + let loaded = BrowserTestUtils.browserLoaded(browser, false, BAD_CERT); + info("Clicking the exceptionDialogButton in advanced panel"); + await SpecialPowers.spawn(browser, [], async function () { + let doc = content.document; + let exceptionButton = doc.getElementById("exceptionDialogButton"); + exceptionButton.click(); + }); + + info("Loading the url after adding exception"); + await loaded; + + await SpecialPowers.spawn(browser, [], async function () { + let doc = content.document; + ok( + !doc.documentURI.startsWith("about:certerror"), + "Exception has been added" + ); + }); + + let certOverrideService = Cc[ + "@mozilla.org/security/certoverride;1" + ].getService(Ci.nsICertOverrideService); + certOverrideService.clearValidityOverride("expired.example.com", -1, {}); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +add_task(async function checkPermanentExceptionPref() { + info( + "Loading a bad cert page and making sure the permanent state of exceptions can be controlled via pref" + ); + + for (let permanentOverride of [false, true]) { + Services.prefs.setBoolPref(PREF_PERMANENT_OVERRIDE, permanentOverride); + + let tab = await openErrorPage(BAD_CERT); + let browser = tab.linkedBrowser; + let loaded = BrowserTestUtils.browserLoaded(browser, false, BAD_CERT); + info("Clicking the exceptionDialogButton in advanced panel"); + let serverCertBytes = await SpecialPowers.spawn( + browser, + [], + async function () { + let doc = content.document; + let exceptionButton = doc.getElementById("exceptionDialogButton"); + exceptionButton.click(); + return content.docShell.failedChannel.securityInfo.serverCert.getRawDER(); + } + ); + + info("Loading the url after adding exception"); + await loaded; + + await SpecialPowers.spawn(browser, [], async function () { + let doc = content.document; + ok( + !doc.documentURI.startsWith("about:certerror"), + "Exception has been added" + ); + }); + + let certOverrideService = Cc[ + "@mozilla.org/security/certoverride;1" + ].getService(Ci.nsICertOverrideService); + + let isTemporary = {}; + let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( + Ci.nsIX509CertDB + ); + let cert = certdb.constructX509(serverCertBytes); + let hasException = certOverrideService.hasMatchingOverride( + "expired.example.com", + -1, + {}, + cert, + isTemporary + ); + ok(hasException, "Has stored an exception for the page."); + is( + isTemporary.value, + !permanentOverride, + `Has stored a ${ + permanentOverride ? "permanent" : "temporary" + } exception for the page.` + ); + + certOverrideService.clearValidityOverride("expired.example.com", -1, {}); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } + + Services.prefs.clearUserPref(PREF_PERMANENT_OVERRIDE); +}); + +add_task(async function checkBadStsCert() { + info("Loading a badStsCert and making sure exception button doesn't show up"); + + for (let useFrame of [false, true]) { + let tab = await openErrorPage(BAD_STS_CERT, useFrame); + let browser = tab.linkedBrowser; + + await SpecialPowers.spawn( + browser, + [{ frame: useFrame }], + async function ({ frame }) { + let doc = frame + ? content.document.querySelector("iframe").contentDocument + : content.document; + let exceptionButton = doc.getElementById("exceptionDialogButton"); + ok( + ContentTaskUtils.is_hidden(exceptionButton), + "Exception button is hidden." + ); + } + ); + + let message = await SpecialPowers.spawn( + browser, + [{ frame: useFrame }], + async function ({ frame }) { + let doc = frame + ? content.document.querySelector("iframe").contentDocument + : content.document; + let advancedButton = doc.getElementById("advancedButton"); + advancedButton.click(); + + // aboutNetError.mjs is using async localization to format several + // messages and in result the translation may be applied later. + // We want to return the textContent of the element only after + // the translation completes, so let's wait for it here. + let elements = [doc.getElementById("badCertTechnicalInfo")]; + await ContentTaskUtils.waitForCondition(() => { + return elements.every(elem => !!elem.textContent.trim().length); + }); + + return doc.getElementById("badCertTechnicalInfo").textContent; + } + ); + ok( + message.includes("SSL_ERROR_BAD_CERT_DOMAIN"), + "Didn't find SSL_ERROR_BAD_CERT_DOMAIN." + ); + ok( + message.includes("The certificate is only valid for"), + "Didn't find error message." + ); + ok( + message.includes("a certificate that is not valid for"), + "Didn't find error message." + ); + ok( + message.includes("badchain.include-subdomains.pinning.example.com"), + "Didn't find domain in error message." + ); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } +}); + +add_task(async function checkhideAddExceptionButtonViaPref() { + info( + "Loading a bad cert page and verifying the pref security.certerror.hideAddException" + ); + Services.prefs.setBoolPref("security.certerror.hideAddException", true); + + for (let useFrame of [false, true]) { + let tab = await openErrorPage(BAD_CERT, useFrame); + let browser = tab.linkedBrowser; + + await SpecialPowers.spawn( + browser, + [{ frame: useFrame }], + async function ({ frame }) { + let doc = frame + ? content.document.querySelector("iframe").contentDocument + : content.document; + + let exceptionButton = doc.getElementById("exceptionDialogButton"); + ok( + ContentTaskUtils.is_hidden(exceptionButton), + "Exception button is hidden." + ); + } + ); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } + + Services.prefs.clearUserPref("security.certerror.hideAddException"); +}); + +add_task(async function checkhideAddExceptionButtonInFrames() { + info("Loading a bad cert page in a frame and verifying it's hidden."); + let tab = await openErrorPage(BAD_CERT, true); + let browser = tab.linkedBrowser; + + await SpecialPowers.spawn(browser, [], async function () { + let doc = content.document.querySelector("iframe").contentDocument; + let exceptionButton = doc.getElementById("exceptionDialogButton"); + ok( + ContentTaskUtils.is_hidden(exceptionButton), + "Exception button is hidden." + ); + }); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); diff --git a/browser/base/content/test/about/browser_aboutCertError_mitm.js b/browser/base/content/test/about/browser_aboutCertError_mitm.js new file mode 100644 index 0000000000..5c9b5e8144 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutCertError_mitm.js @@ -0,0 +1,158 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const PREF_MITM_PRIMING = "security.certerrors.mitm.priming.enabled"; +const PREF_MITM_PRIMING_ENDPOINT = "security.certerrors.mitm.priming.endpoint"; +const PREF_MITM_CANARY_ISSUER = "security.pki.mitm_canary_issuer"; +const PREF_MITM_AUTO_ENABLE_ENTERPRISE_ROOTS = + "security.certerrors.mitm.auto_enable_enterprise_roots"; +const PREF_ENTERPRISE_ROOTS = "security.enterprise_roots.enabled"; + +const UNKNOWN_ISSUER = "https://untrusted.example.com"; + +// Check that basic MitM priming works and the MitM error page is displayed successfully. +add_task(async function checkMitmPriming() { + await SpecialPowers.pushPrefEnv({ + set: [ + [PREF_MITM_PRIMING, true], + [PREF_MITM_PRIMING_ENDPOINT, UNKNOWN_ISSUER], + ], + }); + + let browser; + let certErrorLoaded; + await BrowserTestUtils.openNewForegroundTab( + gBrowser, + () => { + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, UNKNOWN_ISSUER); + browser = gBrowser.selectedBrowser; + // The page will reload by itself after the initial canary request, so we wait + // until the AboutNetErrorLoad event has happened twice. + certErrorLoaded = new Promise(resolve => { + let loaded = 0; + let removeEventListener = BrowserTestUtils.addContentEventListener( + browser, + "AboutNetErrorLoad", + () => { + if (++loaded == 2) { + removeEventListener(); + resolve(); + } + }, + { capture: false, wantUntrusted: true } + ); + }); + }, + false + ); + + await certErrorLoaded; + + await SpecialPowers.spawn(browser, [], () => { + is( + content.document.body.getAttribute("code"), + "MOZILLA_PKIX_ERROR_MITM_DETECTED", + "MitM error page has loaded." + ); + }); + + ok(true, "Successfully loaded the MitM error page."); + + is( + Services.prefs.getStringPref(PREF_MITM_CANARY_ISSUER), + "CN=Unknown CA", + "Stored the correct issuer" + ); + + await SpecialPowers.spawn(browser, [], async () => { + const shortDesc = content.document.querySelector("#errorShortDesc"); + const whatToDo = content.document.querySelector("#errorWhatToDoText"); + + await ContentTaskUtils.waitForCondition( + () => shortDesc.textContent != "" && whatToDo.textContent != "", + "DOM localization has been updated" + ); + + ok( + shortDesc.textContent.includes("Unknown CA"), + "Shows the name of the issuer." + ); + + ok( + whatToDo.textContent.includes("Unknown CA"), + "Shows the name of the issuer." + ); + }); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + Services.prefs.clearUserPref(PREF_MITM_CANARY_ISSUER); +}); + +// Check that we set the enterprise roots pref correctly on MitM +add_task(async function checkMitmAutoEnableEnterpriseRoots() { + await SpecialPowers.pushPrefEnv({ + set: [ + [PREF_MITM_PRIMING, true], + [PREF_MITM_PRIMING_ENDPOINT, UNKNOWN_ISSUER], + [PREF_MITM_AUTO_ENABLE_ENTERPRISE_ROOTS, true], + [PREF_ENTERPRISE_ROOTS, false], + ], + }); + + let browser; + let certErrorLoaded; + + let prefChanged = TestUtils.waitForPrefChange( + PREF_ENTERPRISE_ROOTS, + value => value === true + ); + await BrowserTestUtils.openNewForegroundTab( + gBrowser, + () => { + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, UNKNOWN_ISSUER); + browser = gBrowser.selectedBrowser; + // The page will reload by itself after the initial canary request, so we wait + // until the AboutNetErrorLoad event has happened twice. + certErrorLoaded = new Promise(resolve => { + let loaded = 0; + let removeEventListener = BrowserTestUtils.addContentEventListener( + browser, + "AboutNetErrorLoad", + () => { + if (++loaded == 2) { + removeEventListener(); + resolve(); + } + }, + { capture: false, wantUntrusted: true } + ); + }); + }, + false + ); + + await certErrorLoaded; + await prefChanged; + + await SpecialPowers.spawn(browser, [], () => { + is( + content.document.body.getAttribute("code"), + "MOZILLA_PKIX_ERROR_MITM_DETECTED", + "MitM error page has loaded." + ); + }); + + ok(true, "Successfully loaded the MitM error page."); + + ok( + !Services.prefs.prefHasUserValue(PREF_ENTERPRISE_ROOTS), + "Flipped the enterprise roots pref back" + ); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + Services.prefs.clearUserPref(PREF_MITM_CANARY_ISSUER); +}); diff --git a/browser/base/content/test/about/browser_aboutCertError_noSubjectAltName.js b/browser/base/content/test/about/browser_aboutCertError_noSubjectAltName.js new file mode 100644 index 0000000000..1a2add1c96 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutCertError_noSubjectAltName.js @@ -0,0 +1,67 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const BROWSER_NAME = document + .getElementById("bundle_brand") + .getString("brandShortName"); +const UNKNOWN_ISSUER = "https://no-subject-alt-name.example.com:443"; + +const checkAdvancedAndGetTechnicalInfoText = async () => { + let doc = content.document; + + let advancedButton = doc.getElementById("advancedButton"); + ok(advancedButton, "advancedButton found"); + is( + advancedButton.hasAttribute("disabled"), + false, + "advancedButton should be clickable" + ); + advancedButton.click(); + + let badCertAdvancedPanel = doc.getElementById("badCertAdvancedPanel"); + ok(badCertAdvancedPanel, "badCertAdvancedPanel found"); + + let badCertTechnicalInfo = doc.getElementById("badCertTechnicalInfo"); + ok(badCertTechnicalInfo, "badCertTechnicalInfo found"); + + // Wait until fluent sets the errorCode inner text. + await ContentTaskUtils.waitForCondition(() => { + let errorCode = doc.getElementById("errorCode"); + return errorCode.textContent == "SSL_ERROR_BAD_CERT_DOMAIN"; + }, "correct error code has been set inside the advanced button panel"); + + let viewCertificate = doc.getElementById("viewCertificate"); + ok(viewCertificate, "viewCertificate found"); + + return badCertTechnicalInfo.innerHTML; +}; + +const checkCorrectMessages = message => { + let isCorrectMessage = message.includes( + "Websites prove their identity via certificates. " + + BROWSER_NAME + + " does not trust this site because it uses a certificate that is" + + " not valid for no-subject-alt-name.example.com" + ); + is(isCorrectMessage, true, "That message should appear"); + let isWrongMessage = message.includes("The certificate is only valid for "); + is(isWrongMessage, false, "That message shouldn't appear"); +}; + +add_task(async function checkUntrustedCertError() { + info( + `Loading ${UNKNOWN_ISSUER} which does not have a subject specified in the certificate` + ); + let tab = await openErrorPage(UNKNOWN_ISSUER); + let browser = tab.linkedBrowser; + info("Clicking the exceptionDialogButton in advanced panel"); + let badCertTechnicalInfoText = await SpecialPowers.spawn( + browser, + [], + checkAdvancedAndGetTechnicalInfoText + ); + checkCorrectMessages(badCertTechnicalInfoText, browser); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); diff --git a/browser/base/content/test/about/browser_aboutCertError_offlineSupport.js b/browser/base/content/test/about/browser_aboutCertError_offlineSupport.js new file mode 100644 index 0000000000..5b717a683a --- /dev/null +++ b/browser/base/content/test/about/browser_aboutCertError_offlineSupport.js @@ -0,0 +1,51 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const BAD_CERT_PAGE = "https://expired.example.com"; +const DUMMY_SUPPORT_BASE_PATH = "/1/firefox/fxVersion/OSVersion/language/"; +const DUMMY_SUPPORT_URL = BAD_CERT_PAGE + DUMMY_SUPPORT_BASE_PATH; +const OFFLINE_SUPPORT_PAGE = + "chrome://global/content/neterror/supportpages/time-errors.html"; + +add_task(async function testOfflineSupportPage() { + // Cache the original value of app.support.baseURL pref to reset later + let originalBaseURL = Services.prefs.getCharPref("app.support.baseURL"); + + Services.prefs.setCharPref("app.support.baseURL", DUMMY_SUPPORT_URL); + let errorTab = await openErrorPage(BAD_CERT_PAGE); + + let offlineSupportPromise = BrowserTestUtils.waitForNewTab( + gBrowser, + DUMMY_SUPPORT_URL + "time-errors" + ); + await SpecialPowers.spawn( + errorTab.linkedBrowser, + [DUMMY_SUPPORT_URL], + async expectedURL => { + let doc = content.document; + + let learnMoreLink = doc.getElementById("learnMoreLink"); + let supportPageURL = learnMoreLink.getAttribute("href"); + ok( + supportPageURL == expectedURL + "time-errors", + "Correct support page URL has been set" + ); + await EventUtils.synthesizeMouseAtCenter(learnMoreLink, {}, content); + } + ); + let offlineSupportTab = await offlineSupportPromise; + await BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser, + false, + OFFLINE_SUPPORT_PAGE + ); + + // Reset this pref instead of clearing it to maintain globally set + // custom value for testing purposes. + Services.prefs.setCharPref("app.support.baseURL", originalBaseURL); + + await BrowserTestUtils.removeTab(offlineSupportTab); + await BrowserTestUtils.removeTab(errorTab); +}); diff --git a/browser/base/content/test/about/browser_aboutCertError_telemetry.js b/browser/base/content/test/about/browser_aboutCertError_telemetry.js new file mode 100644 index 0000000000..61ec8afcbf --- /dev/null +++ b/browser/base/content/test/about/browser_aboutCertError_telemetry.js @@ -0,0 +1,164 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +const BAD_CERT = "https://expired.example.com/"; +const BAD_STS_CERT = + "https://badchain.include-subdomains.pinning.example.com:443"; + +add_task(async function checkTelemetryClickEvents() { + info("Loading a bad cert page and verifying telemetry click events arrive."); + + let oldCanRecord = Services.telemetry.canRecordExtended; + Services.telemetry.canRecordExtended = true; + + registerCleanupFunction(() => { + Services.telemetry.canRecordExtended = oldCanRecord; + }); + + // For obvious reasons event telemetry in the content processes updates with + // the main processs asynchronously, so we need to wait for the main process + // to catch up through the entire test. + + // There's an arbitrary interval of 2 seconds in which the content + // processes sync their event data with the parent process, we wait + // this out to ensure that we clear everything that is left over from + // previous tests and don't receive random events in the middle of our tests. + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(c => setTimeout(c, 2000)); + + // Clear everything. + Services.telemetry.clearEvents(); + await TestUtils.waitForCondition(() => { + let events = Services.telemetry.snapshotEvents( + Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, + true + ).content; + return !events || !events.length; + }); + + // Now enable recording our telemetry. Even if this is disabled, content + // processes will send event telemetry to the parent, thus we needed to ensure + // we waited and cleared first. Sigh. + Services.telemetry.setEventRecordingEnabled("security.ui.certerror", true); + + for (let useFrame of [false, true]) { + let recordedObjects = [ + "advanced_button", + "learn_more_link", + "error_code_link", + "clipboard_button_top", + "clipboard_button_bot", + "return_button_top", + ]; + + recordedObjects.push("return_button_adv"); + if (!useFrame) { + recordedObjects.push("exception_button"); + } + + for (let object of recordedObjects) { + let tab = await openErrorPage(BAD_CERT, useFrame); + let browser = tab.linkedBrowser; + + let loadEvents = await TestUtils.waitForCondition(() => { + let events = Services.telemetry.snapshotEvents( + Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, + true + ).content; + if (events && events.length) { + events = events.filter( + e => e[1] == "security.ui.certerror" && e[2] == "load" + ); + if ( + events.length == 1 && + events[0][5].is_frame == useFrame.toString() + ) { + return events; + } + } + return null; + }, "recorded telemetry for the load"); + + is( + loadEvents.length, + 1, + `recorded telemetry for the load testing ${object}, useFrame: ${useFrame}` + ); + + let bc = browser.browsingContext; + if (useFrame) { + bc = bc.children[0]; + } + + await SpecialPowers.spawn(bc, [object], async function (objectId) { + let doc = content.document; + + await ContentTaskUtils.waitForCondition( + () => doc.body.classList.contains("certerror"), + "Wait for certerror to be loaded" + ); + + let domElement = doc.querySelector(`[data-telemetry-id='${objectId}']`); + domElement.click(); + }); + + let clickEvents = await TestUtils.waitForCondition(() => { + let events = Services.telemetry.snapshotEvents( + Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, + true + ).content; + if (events && events.length) { + events = events.filter( + e => + e[1] == "security.ui.certerror" && + e[2] == "click" && + e[3] == object + ); + if ( + events.length == 1 && + events[0][5].is_frame == useFrame.toString() + ) { + return events; + } + } + return null; + }, "Has captured telemetry events."); + + is( + clickEvents.length, + 1, + `recorded telemetry for the click on ${object}, useFrame: ${useFrame}` + ); + + // We opened an extra tab for the SUMO page, need to close it. + if (object == "learn_more_link") { + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } + + if (object == "exception_button") { + let certOverrideService = Cc[ + "@mozilla.org/security/certoverride;1" + ].getService(Ci.nsICertOverrideService); + certOverrideService.clearValidityOverride( + "expired.example.com", + -1, + {} + ); + } + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } + } + + let enableCertErrorUITelemetry = Services.prefs.getBoolPref( + "security.certerrors.recordEventTelemetry" + ); + Services.telemetry.setEventRecordingEnabled( + "security.ui.certerror", + enableCertErrorUITelemetry + ); +}); diff --git a/browser/base/content/test/about/browser_aboutDialog_distribution.js b/browser/base/content/test/about/browser_aboutDialog_distribution.js new file mode 100644 index 0000000000..8f52533bbc --- /dev/null +++ b/browser/base/content/test/about/browser_aboutDialog_distribution.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/toolkit/mozapps/update/tests/browser/head.js", + this +); + +add_task(async function verify_distribution_info_hides() { + let defaultBranch = Services.prefs.getDefaultBranch(null); + + defaultBranch.setCharPref("distribution.id", "mozilla-test-distribution-id"); + defaultBranch.setCharPref("distribution.version", "1.0"); + + let aboutDialog = await waitForAboutDialog(); + + let distroIdField = aboutDialog.document.getElementById("distributionId"); + let distroField = aboutDialog.document.getElementById("distribution"); + + if ( + AppConstants.platform === "win" && + Services.sysinfo.getProperty("hasWinPackageId") + ) { + is(distroIdField.value, "mozilla-test-distribution-id - 1.0"); + is(distroIdField.style.display, "block"); + is(distroField.style.display, "block"); + } else { + is(distroIdField.value, ""); + isnot(distroIdField.style.display, "block"); + isnot(distroField.style.display, "block"); + } + + aboutDialog.close(); +}); + +add_task(async function verify_distribution_info_displays() { + let defaultBranch = Services.prefs.getDefaultBranch(null); + + defaultBranch.setCharPref("distribution.id", "test-distribution-id"); + defaultBranch.setCharPref("distribution.version", "1.0"); + defaultBranch.setCharPref("distribution.about", "About Text"); + + let aboutDialog = await waitForAboutDialog(); + + let distroIdField = aboutDialog.document.getElementById("distributionId"); + + is(distroIdField.value, "test-distribution-id - 1.0"); + is(distroIdField.style.display, "block"); + + let distroField = aboutDialog.document.getElementById("distribution"); + is(distroField.value, "About Text"); + is(distroField.style.display, "block"); + + aboutDialog.close(); +}); + +add_task(async function cleanup() { + let defaultBranch = Services.prefs.getDefaultBranch(null); + + // This is the best we can do since we can't remove default prefs + defaultBranch.setCharPref("distribution.id", ""); + defaultBranch.setCharPref("distribution.version", ""); + defaultBranch.setCharPref("distribution.about", ""); +}); diff --git a/browser/base/content/test/about/browser_aboutHome_search_POST.js b/browser/base/content/test/about/browser_aboutHome_search_POST.js new file mode 100644 index 0000000000..c892198207 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutHome_search_POST.js @@ -0,0 +1,104 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +ignoreAllUncaughtExceptions(); + +add_task(async function () { + info("Check POST search engine support"); + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "browser.newtabpage.activity-stream.improvesearch.handoffToAwesomebar", + false, + ], + ], + }); + + let currEngine = await Services.search.getDefault(); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:home" }, + async browser => { + let observerPromise = new Promise(resolve => { + let searchObserver = async function search_observer( + subject, + topic, + data + ) { + let engine = subject.QueryInterface(Ci.nsISearchEngine); + info("Observer: " + data + " for " + engine.name); + + if (data != "engine-added") { + return; + } + + if (engine.name != "POST Search") { + return; + } + + Services.obs.removeObserver( + searchObserver, + "browser-search-engine-modified" + ); + + resolve(engine); + }; + + Services.obs.addObserver( + searchObserver, + "browser-search-engine-modified" + ); + }); + + let engine; + await promiseContentSearchChange(browser, async () => { + Services.search.addOpenSearchEngine( + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://test:80/browser/browser/base/content/test/about/POSTSearchEngine.xml", + null + ); + + engine = await observerPromise; + Services.search.setDefault( + engine, + Ci.nsISearchService.CHANGE_REASON_UNKNOWN + ); + return engine.name; + }); + + // Ready to execute the tests! + let needle = "Search for something awesome."; + + let promise = BrowserTestUtils.browserLoaded(browser); + await SpecialPowers.spawn(browser, [{ needle }], async function (args) { + let doc = content.document; + let el = doc.querySelector(["#searchText", "#newtab-search-text"]); + el.value = args.needle; + doc.getElementById("searchSubmit").click(); + }); + + await promise; + + // When the search results load, check them for correctness. + await SpecialPowers.spawn(browser, [{ needle }], async function (args) { + let loadedText = content.document.body.textContent; + ok(loadedText, "search page loaded"); + is( + loadedText, + "searchterms=" + escape(args.needle.replace(/\s/g, "+")), + "Search text should arrive correctly" + ); + }); + + await Services.search.setDefault( + currEngine, + Ci.nsISearchService.CHANGE_REASON_UNKNOWN + ); + try { + await Services.search.removeEngine(engine); + } catch (ex) {} + } + ); + await SpecialPowers.popPrefEnv(); +}); diff --git a/browser/base/content/test/about/browser_aboutHome_search_composing.js b/browser/base/content/test/about/browser_aboutHome_search_composing.js new file mode 100644 index 0000000000..309f1f674a --- /dev/null +++ b/browser/base/content/test/about/browser_aboutHome_search_composing.js @@ -0,0 +1,110 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +ignoreAllUncaughtExceptions(); + +add_task(async function () { + info("Clicking suggestion list while composing"); + + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "browser.newtabpage.activity-stream.improvesearch.handoffToAwesomebar", + false, + ], + ], + }); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:home" }, + async function (browser) { + // Add a test engine that provides suggestions and switch to it. + let engine; + await promiseContentSearchChange(browser, async () => { + engine = await SearchTestUtils.promiseNewSearchEngine({ + url: getRootDirectory(gTestPath) + "searchSuggestionEngine.xml", + setAsDefault: true, + }); + return engine.name; + }); + + // Clear any search history results + await FormHistory.update({ op: "remove" }); + + await SpecialPowers.spawn(browser, [], async function () { + // Start composition and type "x" + let input = content.document.querySelector([ + "#searchText", + "#newtab-search-text", + ]); + input.focus(); + }); + + info("Setting up the mutation observer before synthesizing composition"); + let mutationPromise = SpecialPowers.spawn(browser, [], async function () { + let searchController = content.wrappedJSObject.gContentSearchController; + + // Wait for the search suggestions to become visible. + let table = searchController._suggestionsList; + let input = content.document.querySelector([ + "#searchText", + "#newtab-search-text", + ]); + + await ContentTaskUtils.waitForMutationCondition( + input, + { attributeFilter: ["aria-expanded"] }, + () => input.getAttribute("aria-expanded") == "true" + ); + ok(!table.hidden, "Search suggestion table unhidden"); + + let row = table.children[1]; + row.setAttribute("id", "TEMPID"); + + // ContentSearchUIController looks at the current selectedIndex when + // performing a search. Synthesizing the mouse event on the suggestion + // doesn't actually mouseover the suggestion and trigger it to be flagged + // as selected, so we manually select it first. + searchController.selectedIndex = 1; + }); + + // FYI: "compositionstart" will be dispatched automatically. + await BrowserTestUtils.synthesizeCompositionChange( + { + composition: { + string: "x", + clauses: [ + { length: 1, attr: Ci.nsITextInputProcessor.ATTR_RAW_CLAUSE }, + ], + }, + caret: { start: 1, length: 0 }, + }, + browser + ); + + info("Waiting for search suggestion table unhidden"); + await mutationPromise; + + // Click the second suggestion. + let expectedURL = (await Services.search.getDefault()).getSubmission( + "xbar", + null, + "homepage" + ).uri.spec; + let loadPromise = BrowserTestUtils.waitForDocLoadAndStopIt( + expectedURL, + gBrowser.selectedBrowser + ); + await BrowserTestUtils.synthesizeMouseAtCenter( + "#TEMPID", + { + button: 0, + }, + browser + ); + await loadPromise; + } + ); + await SpecialPowers.popPrefEnv(); +}); diff --git a/browser/base/content/test/about/browser_aboutHome_search_searchbar.js b/browser/base/content/test/about/browser_aboutHome_search_searchbar.js new file mode 100644 index 0000000000..7b08d2ae34 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutHome_search_searchbar.js @@ -0,0 +1,44 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +const { CustomizableUITestUtils } = ChromeUtils.importESModule( + "resource://testing-common/CustomizableUITestUtils.sys.mjs" +); +let gCUITestUtils = new CustomizableUITestUtils(window); + +ignoreAllUncaughtExceptions(); + +add_task(async function test_setup() { + await gCUITestUtils.addSearchBar(); + registerCleanupFunction(() => { + gCUITestUtils.removeSearchBar(); + }); +}); + +add_task(async function () { + info("Cmd+k should focus the search box in the toolbar when it's present"); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:home" }, + async function (browser) { + await BrowserTestUtils.synthesizeMouseAtCenter("#brandLogo", {}, browser); + + let doc = window.document; + let searchInput = BrowserSearch.searchBar.textbox; + isnot( + searchInput, + doc.activeElement, + "Search bar should not be the active element." + ); + + EventUtils.synthesizeKey("k", { accelKey: true }); + await TestUtils.waitForCondition(() => doc.activeElement === searchInput); + is( + searchInput, + doc.activeElement, + "Search bar should be the active element." + ); + } + ); +}); diff --git a/browser/base/content/test/about/browser_aboutHome_search_suggestion.js b/browser/base/content/test/about/browser_aboutHome_search_suggestion.js new file mode 100644 index 0000000000..4e1da9fe3e --- /dev/null +++ b/browser/base/content/test/about/browser_aboutHome_search_suggestion.js @@ -0,0 +1,78 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +ignoreAllUncaughtExceptions(); + +add_task(async function () { + // See browser_contentSearchUI.js for comprehensive content search UI tests. + info("Search suggestion smoke test"); + + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "browser.newtabpage.activity-stream.improvesearch.handoffToAwesomebar", + false, + ], + ], + }); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:home" }, + async function (browser) { + // Add a test engine that provides suggestions and switch to it. + let engine; + await promiseContentSearchChange(browser, async () => { + engine = await SearchTestUtils.promiseNewSearchEngine({ + url: getRootDirectory(gTestPath) + "searchSuggestionEngine.xml", + setAsDefault: true, + }); + await Services.search.setDefault( + engine, + Ci.nsISearchService.CHANGE_REASON_UNKNOWN + ); + return engine.name; + }); + + await SpecialPowers.spawn(browser, [], async function () { + // Type an X in the search input. + let input = content.document.querySelector([ + "#searchText", + "#newtab-search-text", + ]); + input.focus(); + }); + + await BrowserTestUtils.synthesizeKey("x", {}, browser); + + await SpecialPowers.spawn(browser, [], async function () { + // Wait for the search suggestions to become visible. + let table = content.document.getElementById("searchSuggestionTable"); + let input = content.document.querySelector([ + "#searchText", + "#newtab-search-text", + ]); + + await ContentTaskUtils.waitForMutationCondition( + input, + { attributeFilter: ["aria-expanded"] }, + () => input.getAttribute("aria-expanded") == "true" + ); + ok(!table.hidden, "Search suggestion table unhidden"); + }); + + // Empty the search input, causing the suggestions to be hidden. + await BrowserTestUtils.synthesizeKey("a", { accelKey: true }, browser); + await BrowserTestUtils.synthesizeKey("VK_DELETE", {}, browser); + + await SpecialPowers.spawn(browser, [], async function () { + let table = content.document.getElementById("searchSuggestionTable"); + await ContentTaskUtils.waitForCondition( + () => table.hidden, + "Search suggestion table hidden" + ); + }); + } + ); + await SpecialPowers.popPrefEnv(); +}); diff --git a/browser/base/content/test/about/browser_aboutHome_search_telemetry.js b/browser/base/content/test/about/browser_aboutHome_search_telemetry.js new file mode 100644 index 0000000000..e23d07aa38 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutHome_search_telemetry.js @@ -0,0 +1,101 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +ignoreAllUncaughtExceptions(); + +add_task(async function () { + info( + "Check that performing a search fires a search event and records to Telemetry." + ); + + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "browser.newtabpage.activity-stream.improvesearch.handoffToAwesomebar", + false, + ], + ], + }); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:home" }, + async function (browser) { + let engine; + await promiseContentSearchChange(browser, async () => { + engine = await SearchTestUtils.promiseNewSearchEngine({ + url: getRootDirectory(gTestPath) + "searchSuggestionEngine.xml", + setAsDefault: true, + }); + return engine.name; + }); + + await SpecialPowers.spawn( + browser, + [{ expectedName: engine.name }], + async function (args) { + let engineName = + content.wrappedJSObject.gContentSearchController.defaultEngine.name; + is( + engineName, + args.expectedName, + "Engine name in DOM should match engine we just added" + ); + } + ); + + let numSearchesBefore = 0; + // Get the current number of recorded searches. + let histogramKey = `other-${engine.name}.abouthome`; + try { + let hs = Services.telemetry + .getKeyedHistogramById("SEARCH_COUNTS") + .snapshot(); + if (histogramKey in hs) { + numSearchesBefore = hs[histogramKey].sum; + } + } catch (ex) { + // No searches performed yet, not a problem, |numSearchesBefore| is 0. + } + + let searchStr = "a search"; + + let expectedURL = (await Services.search.getDefault()).getSubmission( + searchStr, + null, + "homepage" + ).uri.spec; + let promise = BrowserTestUtils.waitForDocLoadAndStopIt( + expectedURL, + browser + ); + + // Perform a search to increase the SEARCH_COUNT histogram. + await SpecialPowers.spawn( + browser, + [{ searchStr }], + async function (args) { + let doc = content.document; + info("Perform a search."); + let el = doc.querySelector(["#searchText", "#newtab-search-text"]); + el.value = args.searchStr; + doc.getElementById("searchSubmit").click(); + } + ); + + await promise; + + // Make sure the SEARCH_COUNTS histogram has the right key and count. + let hs = Services.telemetry + .getKeyedHistogramById("SEARCH_COUNTS") + .snapshot(); + Assert.ok(histogramKey in hs, "histogram with key should be recorded"); + Assert.equal( + hs[histogramKey].sum, + numSearchesBefore + 1, + "histogram sum should be incremented" + ); + } + ); + await SpecialPowers.popPrefEnv(); +}); diff --git a/browser/base/content/test/about/browser_aboutNetError.js b/browser/base/content/test/about/browser_aboutNetError.js new file mode 100644 index 0000000000..0f98413f33 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutNetError.js @@ -0,0 +1,245 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const SSL3_PAGE = "https://ssl3.example.com/"; +const TLS10_PAGE = "https://tls1.example.com/"; +const TLS12_PAGE = "https://tls12.example.com/"; +const TRIPLEDES_PAGE = "https://3des.example.com/"; + +const lazy = {}; + +XPCOMUtils.defineLazyServiceGetter( + lazy, + "gDNSOverride", + "@mozilla.org/network/native-dns-override;1", + "nsINativeDNSResolverOverride" +); + +// This includes all the cipher suite prefs we have. +function resetPrefs() { + Services.prefs.clearUserPref("security.tls.version.min"); + Services.prefs.clearUserPref("security.tls.version.max"); + Services.prefs.clearUserPref("security.tls.version.enable-deprecated"); + Services.prefs.clearUserPref("browser.fixup.alternate.enabled"); +} + +add_task(async function resetToDefaultConfig() { + info( + "Change TLS config to cause page load to fail, check that reset button is shown and that it works" + ); + + // Set ourselves up for a TLS error. + Services.prefs.setIntPref("security.tls.version.min", 1); // TLS 1.0 + Services.prefs.setIntPref("security.tls.version.max", 1); + + let browser; + let pageLoaded; + await BrowserTestUtils.openNewForegroundTab( + gBrowser, + () => { + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, TLS12_PAGE); + browser = gBrowser.selectedBrowser; + pageLoaded = BrowserTestUtils.waitForErrorPage(browser); + }, + false + ); + + info("Loading and waiting for the net error"); + await pageLoaded; + + // Setup an observer for the target page. + const finalLoadComplete = BrowserTestUtils.browserLoaded( + browser, + false, + TLS12_PAGE + ); + + await SpecialPowers.spawn(browser, [], async function () { + const doc = content.document; + ok( + doc.documentURI.startsWith("about:neterror"), + "Should be showing error page" + ); + + const prefResetButton = doc.getElementById("prefResetButton"); + await ContentTaskUtils.waitForCondition( + () => ContentTaskUtils.is_visible(prefResetButton), + "prefResetButton is visible" + ); + + if (!Services.focus.focusedElement == prefResetButton) { + await ContentTaskUtils.waitForEvent(prefResetButton, "focus"); + } + + Assert.ok(true, "prefResetButton has focus"); + + prefResetButton.click(); + }); + + info("Waiting for the page to load after the click"); + await finalLoadComplete; + + resetPrefs(); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +add_task(async function checkLearnMoreLink() { + info("Load an unsupported TLS page and check for a learn more link"); + + // Set ourselves up for TLS error + Services.prefs.setIntPref("security.tls.version.min", 3); + Services.prefs.setIntPref("security.tls.version.max", 4); + + let browser; + let pageLoaded; + await BrowserTestUtils.openNewForegroundTab( + gBrowser, + () => { + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, TLS10_PAGE); + browser = gBrowser.selectedBrowser; + pageLoaded = BrowserTestUtils.waitForErrorPage(browser); + }, + false + ); + + info("Loading and waiting for the net error"); + await pageLoaded; + + const baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL"); + + await SpecialPowers.spawn(browser, [baseURL], function (_baseURL) { + const doc = content.document; + ok( + doc.documentURI.startsWith("about:neterror"), + "Should be showing error page" + ); + + const tlsVersionNotice = doc.getElementById("tlsVersionNotice"); + ok( + ContentTaskUtils.is_visible(tlsVersionNotice), + "TLS version notice is visible" + ); + + const learnMoreLink = doc.getElementById("learnMoreLink"); + ok( + ContentTaskUtils.is_visible(learnMoreLink), + "Learn More link is visible" + ); + is(learnMoreLink.getAttribute("href"), _baseURL + "connection-not-secure"); + + const titleEl = doc.querySelector(".title-text"); + const actualDataL10nID = titleEl.getAttribute("data-l10n-id"); + is( + actualDataL10nID, + "nssFailure2-title", + "Correct error page title is set" + ); + + const errorCodeEl = doc.querySelector("#errorShortDesc2"); + const actualDataL10Args = errorCodeEl.getAttribute("data-l10n-args"); + ok( + actualDataL10Args.includes("SSL_ERROR_PROTOCOL_VERSION_ALERT"), + "Correct error code is set" + ); + }); + + resetPrefs(); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +// When a user tries going to a host without a suffix +// and the term doesn't match a host and we are able to suggest a +// valid correction, the page should show the correction. +// e.g. http://example/example2 -> https://www.example.com/example2 +add_task(async function checkDomainCorrection() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.fixup.alternate.enabled", false]], + }); + lazy.gDNSOverride.addIPOverride("www.example.com", "::1"); + + info("Try loading a URI that should result in an error page"); + BrowserTestUtils.openNewForegroundTab( + gBrowser, + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example/example2/", + false + ); + + info("Loading and waiting for the net error"); + let browser = gBrowser.selectedBrowser; + let pageLoaded = BrowserTestUtils.waitForErrorPage(browser); + await pageLoaded; + + const baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL"); + + await SpecialPowers.spawn(browser, [baseURL], async function (_baseURL) { + const doc = content.document; + ok( + doc.documentURI.startsWith("about:neterror"), + "Should be showing error page" + ); + + const errorNotice = doc.getElementById("errorShortDesc"); + ok(ContentTaskUtils.is_visible(errorNotice), "Error text is visible"); + + // Wait for the domain suggestion to be resolved and for the text to update + let link; + await ContentTaskUtils.waitForCondition(() => { + link = errorNotice.querySelector("a"); + return link && link.textContent != ""; + }, "Helper link has been set"); + + is( + link.getAttribute("href"), + "https://www.example.com/example2/", + "Link was corrected" + ); + + const actualDataL10nID = link.getAttribute("data-l10n-name"); + is(actualDataL10nID, "website", "Correct name is set"); + }); + + lazy.gDNSOverride.clearHostOverride("www.example.com"); + resetPrefs(); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +// Test that ciphersuites that use 3DES (namely, TLS_RSA_WITH_3DES_EDE_CBC_SHA) +// can only be enabled when deprecated TLS is enabled. +add_task(async function onlyAllow3DESWithDeprecatedTLS() { + // By default, connecting to a server that only uses 3DES should fail. + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:blank" }, + async browser => { + BrowserTestUtils.loadURIString(browser, TRIPLEDES_PAGE); + await BrowserTestUtils.waitForErrorPage(browser); + } + ); + + // Enabling deprecated TLS should also enable 3DES. + Services.prefs.setBoolPref("security.tls.version.enable-deprecated", true); + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:blank" }, + async browser => { + BrowserTestUtils.loadURIString(browser, TRIPLEDES_PAGE); + await BrowserTestUtils.browserLoaded(browser, false, TRIPLEDES_PAGE); + } + ); + + // 3DES can be disabled separately. + Services.prefs.setBoolPref( + "security.ssl3.deprecated.rsa_des_ede3_sha", + false + ); + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:blank" }, + async browser => { + BrowserTestUtils.loadURIString(browser, TRIPLEDES_PAGE); + await BrowserTestUtils.waitForErrorPage(browser); + } + ); + + resetPrefs(); +}); diff --git a/browser/base/content/test/about/browser_aboutNetError_csp_iframe.js b/browser/base/content/test/about/browser_aboutNetError_csp_iframe.js new file mode 100644 index 0000000000..21e2ba7b51 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutNetError_csp_iframe.js @@ -0,0 +1,153 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const BLOCKED_PAGE = + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.org:8000/browser/browser/base/content/test/about/csp_iframe.sjs"; + +add_task(async function test_csp() { + let { iframePageTab, blockedPageTab } = await setupPage( + "iframe_page_csp.html", + BLOCKED_PAGE + ); + + let cspBrowser = gBrowser.selectedTab.linkedBrowser; + + // The blocked page opened in a new window/tab + await SpecialPowers.spawn( + cspBrowser, + [BLOCKED_PAGE], + async function (cspBlockedPage) { + let cookieHeader = content.document.getElementById("strictCookie"); + let location = content.document.location.href; + + Assert.ok( + cookieHeader.textContent.includes("No same site strict cookie header"), + "Same site strict cookie has not been set" + ); + Assert.equal( + location, + cspBlockedPage, + "Location of new page is correct!" + ); + } + ); + + Services.cookies.removeAll(); + BrowserTestUtils.removeTab(iframePageTab); + BrowserTestUtils.removeTab(blockedPageTab); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +async function setupPage(htmlPageName, blockedPage) { + let iFramePage = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com" + ) + htmlPageName; + + // Opening the blocked page once in a new tab + let blockedPageTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + blockedPage + ); + let blockedPageBrowser = blockedPageTab.linkedBrowser; + + let cookies = Services.cookies.getCookiesFromHost( + "example.org", + blockedPageBrowser.contentPrincipal.originAttributes + ); + let strictCookie = cookies[0]; + + is( + strictCookie.value, + "green", + "Same site strict cookie has the expected value" + ); + + is(strictCookie.sameSite, 2, "The cookie is a same site strict cookie"); + + // Opening the page that contains the iframe + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + let browser = tab.linkedBrowser; + let browserLoaded = BrowserTestUtils.browserLoaded( + browser, + true, + blockedPage, + true + ); + + BrowserTestUtils.loadURIString(browser, iFramePage); + await browserLoaded; + info("The error page has loaded!"); + + await SpecialPowers.spawn(browser, [], async function () { + let iframe = content.document.getElementById("theIframe"); + + await ContentTaskUtils.waitForCondition(() => + SpecialPowers.spawn(iframe, [], () => + content.document.body.classList.contains("neterror") + ) + ); + }); + + let iframe = browser.browsingContext.children[0]; + + let newTabLoaded = BrowserTestUtils.waitForNewTab(gBrowser, null, true); + + // In the iframe, we see the correct error page and click on the button + // to open the blocked page in a new window/tab + await SpecialPowers.spawn(iframe, [], async function () { + let doc = content.document; + + // aboutNetError.mjs is using async localization to format several + // messages and in result the translation may be applied later. + // We want to return the textContent of the element only after + // the translation completes, so let's wait for it here. + let elements = [ + doc.getElementById("errorLongDesc"), + doc.getElementById("openInNewWindowButton"), + ]; + await ContentTaskUtils.waitForCondition(() => { + return elements.every(elem => !!elem.textContent.trim().length); + }); + + let textLongDescription = doc.getElementById("errorLongDesc").textContent; + let learnMoreLinkLocation = doc.getElementById("learnMoreLink").href; + + Assert.ok( + textLongDescription.includes( + "To see this page, you need to open it in a new window." + ), + "Correct error message found" + ); + + let button = doc.getElementById("openInNewWindowButton"); + Assert.ok( + button.textContent.includes("Open Site in New Window"), + "We see the correct button to open the site in a new window" + ); + + Assert.ok( + learnMoreLinkLocation.includes("xframe-neterror-page"), + "Correct Learn More URL for CSP error page" + ); + + // We click on the button + await EventUtils.synthesizeMouseAtCenter(button, {}, content); + }); + info("Button was clicked!"); + + // We wait for the new tab to load + await newTabLoaded; + info("The new tab has loaded!"); + + let iframePageTab = tab; + return { + iframePageTab, + blockedPageTab, + }; +} diff --git a/browser/base/content/test/about/browser_aboutNetError_native_fallback.js b/browser/base/content/test/about/browser_aboutNetError_native_fallback.js new file mode 100644 index 0000000000..4a87ad5cce --- /dev/null +++ b/browser/base/content/test/about/browser_aboutNetError_native_fallback.js @@ -0,0 +1,174 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +let oldProxyType = Services.prefs.getIntPref("network.proxy.type"); + +function reset() { + Services.prefs.clearUserPref("network.trr.display_fallback_warning"); + Services.prefs.clearUserPref("network.trr.mode"); + Services.prefs.clearUserPref("network.dns.native-is-localhost"); + Services.prefs.clearUserPref("doh-rollout.disable-heuristics"); + Services.prefs.setIntPref("network.proxy.type", oldProxyType); + Services.prefs.clearUserPref("network.trr.uri"); + + Services.dns.setHeuristicDetectionResult(Ci.nsITRRSkipReason.TRR_OK); +} + +// This helper verifies that the given url loads correctly +async function verifyLoad(url, testName) { + let browser; + await BrowserTestUtils.openNewForegroundTab( + gBrowser, + () => { + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, url); + browser = gBrowser.selectedBrowser; + }, + true + ); + + await SpecialPowers.spawn(browser, [{ url, testName }], function (args) { + const doc = content.document; + ok( + doc.documentURI == args.url, + "Should have loaded page: " + args.testName + ); + }); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +} + +// This helper verifies that loading the given url will lead to an error -- the fallback warning if the parameter is true +async function verifyError(url, fallbackWarning, testName) { + // Clear everything. + Services.telemetry.clearEvents(); + await TestUtils.waitForCondition(() => { + let events = Services.telemetry.snapshotEvents( + Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, + true + ).content; + return !events || !events.length; + }); + Services.telemetry.setEventRecordingEnabled("security.doh.neterror", true); + + let browser; + let pageLoaded; + await BrowserTestUtils.openNewForegroundTab( + gBrowser, + () => { + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, url); + browser = gBrowser.selectedBrowser; + pageLoaded = BrowserTestUtils.waitForErrorPage(browser); + }, + false + ); + + info("Loading and waiting for the net error"); + await pageLoaded; + + await SpecialPowers.spawn( + browser, + [{ url, fallbackWarning, testName }], + function (args) { + const doc = content.document; + + ok(doc.documentURI.startsWith("about:neterror")); + "Should be showing error page: " + args.testName; + + const titleEl = doc.querySelector(".title-text"); + const actualDataL10nID = titleEl.getAttribute("data-l10n-id"); + if (args.fallbackWarning) { + is( + actualDataL10nID, + "dns-not-found-native-fallback-title2", + "Correct fallback warning error page title is set: " + args.testName + ); + } else { + ok( + actualDataL10nID != "dns-not-found-native-fallback-title2", + "Should not show fallback warning: " + args.testName + ); + } + } + ); + + if (fallbackWarning) { + let loadEvent = await TestUtils.waitForCondition(() => { + let events = Services.telemetry.snapshotEvents( + Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, + true + ).content; + return events?.find( + e => e[1] == "security.doh.neterror" && e[2] == "load" + ); + }, "recorded telemetry for the load"); + loadEvent.shift(); + Assert.deepEqual(loadEvent, [ + "security.doh.neterror", + "load", + "dohwarning", + "NativeFallbackWarning", + { + mode: "0", + provider_key: "0.0.0.0", + skip_reason: "TRR_HEURISTIC_TRIPPED_CANARY", + }, + ]); + } + BrowserTestUtils.removeTab(gBrowser.selectedTab); +} + +// This test verifies that the native fallback warning appears in the desired scenarios, and only in those scenarios +add_task(async function nativeFallbackWarnings() { + Services.prefs.setBoolPref("network.dns.native-is-localhost", true); + + // Disable heuristics since they will attempt to connect to external servers + Services.prefs.setBoolPref("doh-rollout.disable-heuristics", true); + + // Set a local TRR to prevent external connections + Services.prefs.setCharPref("network.trr.uri", "https://0.0.0.0/dns-query"); + + registerCleanupFunction(reset); + + // Test without DoH + Services.prefs.setIntPref( + "network.trr.mode", + Ci.nsIDNSService.MODE_NATIVEONLY + ); + + Services.dns.clearCache(true); + await verifyLoad("https://www.example.com/", "valid url, no error"); + + // Should not trigger the native fallback warning + await verifyError("https://does-not-exist.test", false, "non existent url"); + + // We need to disable proxy, otherwise TRR isn't used for name resolution. + Services.prefs.setIntPref("network.proxy.type", 0); + + // Switch to TRR first + Services.prefs.setIntPref( + "network.trr.mode", + Ci.nsIDNSService.MODE_NATIVEONLY + ); + Services.prefs.setBoolPref("network.trr.display_fallback_warning", true); + + // Simulate a tripped canary network + Services.dns.setHeuristicDetectionResult( + Ci.nsITRRSkipReason.TRR_HEURISTIC_TRIPPED_CANARY + ); + + // We should see the fallback warning displayed in both of these scenarios + Services.dns.clearCache(true); + await verifyError( + "https://www.example.com", + true, + "canary heuristic tripped" + ); + await verifyError( + "https://does-not-exist.test", + true, + "canary heuristic tripped - non existent url" + ); + + reset(); +}); diff --git a/browser/base/content/test/about/browser_aboutNetError_trr.js b/browser/base/content/test/about/browser_aboutNetError_trr.js new file mode 100644 index 0000000000..bfee686e7c --- /dev/null +++ b/browser/base/content/test/about/browser_aboutNetError_trr.js @@ -0,0 +1,189 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// See bug 1831731. This test should not actually try to create a connection to +// the real DoH endpoint. But that may happen when clearing the proxy type, and +// sometimes even in the next test. +// To prevent that we override the IP to a local address. +Cc["@mozilla.org/network/native-dns-override;1"] + .getService(Ci.nsINativeDNSResolverOverride) + .addIPOverride("mozilla.cloudflare-dns.com", "127.0.0.1"); + +let oldProxyType = Services.prefs.getIntPref("network.proxy.type"); +function resetPrefs() { + Services.prefs.clearUserPref("network.trr.mode"); + Services.prefs.clearUserPref("network.dns.native-is-localhost"); + Services.prefs.setIntPref("network.proxy.type", oldProxyType); +} + +async function loadErrorPage() { + Services.prefs.setBoolPref("network.dns.native-is-localhost", true); + Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRONLY); + // We need to disable proxy, otherwise TRR isn't used for name resolution. + Services.prefs.setIntPref("network.proxy.type", 0); + registerCleanupFunction(resetPrefs); + + let browser; + let pageLoaded; + await BrowserTestUtils.openNewForegroundTab( + gBrowser, + () => { + gBrowser.selectedTab = BrowserTestUtils.addTab( + gBrowser, + "https://does-not-exist.test" + ); + browser = gBrowser.selectedBrowser; + pageLoaded = BrowserTestUtils.waitForErrorPage(browser); + }, + false + ); + + info("Loading and waiting for the net error"); + await pageLoaded; + return browser; +} + +// This test makes sure that the Add exception button only shows up +// when the skipReason indicates that the domain could not be resolved. +// If instead there is a problem with the TRR connection, then we don't +// show the exception button. +add_task(async function exceptionButtonTRROnly() { + let browser = await loadErrorPage(); + + await SpecialPowers.spawn(browser, [], function () { + const doc = content.document; + ok( + doc.documentURI.startsWith("about:neterror"), + "Should be showing error page" + ); + + const titleEl = doc.querySelector(".title-text"); + const actualDataL10nID = titleEl.getAttribute("data-l10n-id"); + is( + actualDataL10nID, + "dns-not-found-trr-only-title2", + "Correct error page title is set" + ); + + let trrExceptionButton = doc.getElementById("trrExceptionButton"); + Assert.equal( + trrExceptionButton.hidden, + true, + "Exception button should be hidden for TRR service failures" + ); + }); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + resetPrefs(); +}); + +add_task(async function TRROnlyExceptionButtonTelemetry() { + // Clear everything. + Services.telemetry.clearEvents(); + await TestUtils.waitForCondition(() => { + let events = Services.telemetry.snapshotEvents( + Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, + true + ).content; + return !events || !events.length; + }); + Services.telemetry.setEventRecordingEnabled("security.doh.neterror", true); + + let browser = await loadErrorPage(); + + await SpecialPowers.spawn(browser, [], function () { + const doc = content.document; + ok( + doc.documentURI.startsWith("about:neterror"), + "Should be showing error page" + ); + }); + + let loadEvent = await TestUtils.waitForCondition(() => { + let events = Services.telemetry.snapshotEvents( + Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, + true + ).content; + return events?.find(e => e[1] == "security.doh.neterror" && e[2] == "load"); + }, "recorded telemetry for the load"); + + loadEvent.shift(); + Assert.deepEqual(loadEvent, [ + "security.doh.neterror", + "load", + "dohwarning", + "TRROnlyFailure", + { + mode: "3", + provider_key: "mozilla.cloudflare-dns.com", + skip_reason: "TRR_UNKNOWN_CHANNEL_FAILURE", + }, + ]); + + await SpecialPowers.spawn(browser, [], function () { + const doc = content.document; + let buttons = ["neterrorTryAgainButton", "trrSettingsButton"]; + for (let buttonId of buttons) { + let button = doc.getElementById(buttonId); + button.click(); + } + }); + + // Since we click TryAgain, make sure the error page is loaded again. + await BrowserTestUtils.waitForErrorPage(browser); + + is( + gBrowser.tabs.length, + 3, + "Should open about:preferences#privacy-doh in another tab" + ); + + let clickEvents = await TestUtils.waitForCondition( + () => { + let events = Services.telemetry.snapshotEvents( + Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, + true + ).content; + return events?.filter( + e => e[1] == "security.doh.neterror" && e[2] == "click" + ); + }, + "recorded telemetry for clicking buttons", + 500, + 100 + ); + + let firstEvent = clickEvents[0]; + firstEvent.shift(); // remove timestamp + Assert.deepEqual(firstEvent, [ + "security.doh.neterror", + "click", + "try_again_button", + "TRROnlyFailure", + { + mode: "3", + provider_key: "mozilla.cloudflare-dns.com", + skip_reason: "TRR_UNKNOWN_CHANNEL_FAILURE", + }, + ]); + + let secondEvent = clickEvents[1]; + secondEvent.shift(); // remove timestamp + Assert.deepEqual(secondEvent, [ + "security.doh.neterror", + "click", + "settings_button", + "TRROnlyFailure", + { + mode: "3", + provider_key: "mozilla.cloudflare-dns.com", + skip_reason: "TRR_UNKNOWN_CHANNEL_FAILURE", + }, + ]); + + BrowserTestUtils.removeTab(gBrowser.tabs[2]); + BrowserTestUtils.removeTab(gBrowser.tabs[1]); + resetPrefs(); +}); diff --git a/browser/base/content/test/about/browser_aboutNetError_xfo_iframe.js b/browser/base/content/test/about/browser_aboutNetError_xfo_iframe.js new file mode 100644 index 0000000000..ae4d5c22a2 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutNetError_xfo_iframe.js @@ -0,0 +1,139 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const BLOCKED_PAGE = + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.org:8000/browser/browser/base/content/test/about/xfo_iframe.sjs"; + +add_task(async function test_xfo_iframe() { + let { iframePageTab, blockedPageTab } = await setupPage( + "iframe_page_xfo.html", + BLOCKED_PAGE + ); + + let xfoBrowser = gBrowser.selectedTab.linkedBrowser; + + // The blocked page opened in a new window/tab + await SpecialPowers.spawn( + xfoBrowser, + [BLOCKED_PAGE], + async function (xfoBlockedPage) { + let cookieHeader = content.document.getElementById("strictCookie"); + let location = content.document.location.href; + + Assert.ok( + cookieHeader.textContent.includes("No same site strict cookie header"), + "Same site strict cookie has not been set" + ); + Assert.equal( + location, + xfoBlockedPage, + "Location of new page is correct!" + ); + } + ); + + Services.cookies.removeAll(); + BrowserTestUtils.removeTab(iframePageTab); + BrowserTestUtils.removeTab(blockedPageTab); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +async function setupPage(htmlPageName, blockedPage) { + let iFramePage = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com" + ) + htmlPageName; + + // Opening the blocked page once in a new tab + let blockedPageTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + blockedPage + ); + let blockedPageBrowser = blockedPageTab.linkedBrowser; + + let cookies = Services.cookies.getCookiesFromHost( + "example.org", + blockedPageBrowser.contentPrincipal.originAttributes + ); + let strictCookie = cookies[0]; + + is( + strictCookie.value, + "creamy", + "Same site strict cookie has the expected value" + ); + + is(strictCookie.sameSite, 2, "The cookie is a same site strict cookie"); + + // Opening the page that contains the iframe + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + let browser = tab.linkedBrowser; + let browserLoaded = BrowserTestUtils.browserLoaded( + browser, + true, + blockedPage, + true + ); + + BrowserTestUtils.loadURIString(browser, iFramePage); + await browserLoaded; + info("The error page has loaded!"); + + await SpecialPowers.spawn(browser, [], async function () { + let iframe = content.document.getElementById("theIframe"); + + await ContentTaskUtils.waitForCondition(() => + SpecialPowers.spawn(iframe, [], () => + content.document.body.classList.contains("neterror") + ) + ); + }); + + let frameContext = browser.browsingContext.children[0]; + let newTabLoaded = BrowserTestUtils.waitForNewTab(gBrowser, null, true); + + // In the iframe, we see the correct error page and click on the button + // to open the blocked page in a new window/tab + await SpecialPowers.spawn(frameContext, [], async function () { + let doc = content.document; + let textLongDescription = doc.getElementById("errorLongDesc").textContent; + let learnMoreLinkLocation = doc.getElementById("learnMoreLink").href; + + Assert.ok( + textLongDescription.includes( + "To see this page, you need to open it in a new window." + ), + "Correct error message found" + ); + + let button = doc.getElementById("openInNewWindowButton"); + Assert.ok( + button.textContent.includes("Open Site in New Window"), + "We see the correct button to open the site in a new window" + ); + + Assert.ok( + learnMoreLinkLocation.includes("xframe-neterror-page"), + "Correct Learn More URL for XFO error page" + ); + + // We click on the button + await EventUtils.synthesizeMouseAtCenter(button, {}, content); + }); + info("Button was clicked!"); + + // We wait for the new tab to load + await newTabLoaded; + info("The new tab has loaded!"); + + let iframePageTab = tab; + return { + iframePageTab, + blockedPageTab, + }; +} diff --git a/browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbar.js b/browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbar.js new file mode 100644 index 0000000000..c566276d9f --- /dev/null +++ b/browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbar.js @@ -0,0 +1,311 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async function bookmarks_toolbar_shown_on_newtab() { + let newtab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:newtab", + waitForLoad: false, + }); + + // 1: Test that the toolbar is shown in a newly opened foreground about:newtab + await waitForBookmarksToolbarVisibility({ + visible: true, + message: "Toolbar should be visible on newtab", + }); + ok(isBookmarksToolbarVisible(), "Toolbar should be visible on newtab"); + + // 2: Test that the toolbar is hidden when the browser is navigated away from newtab + BrowserTestUtils.loadURIString(newtab.linkedBrowser, "https://example.com"); + await BrowserTestUtils.browserLoaded(newtab.linkedBrowser); + await waitForBookmarksToolbarVisibility({ + visible: false, + message: + "Toolbar should not be visible on newtab after example.com is loaded within", + }); + ok( + !isBookmarksToolbarVisible(), + "Toolbar should not be visible on newtab after example.com is loaded within" + ); + + // 3: Re-load about:newtab in the browser for the following tests and confirm toolbar reappears + BrowserTestUtils.loadURIString(newtab.linkedBrowser, "about:newtab"); + await BrowserTestUtils.browserLoaded(newtab.linkedBrowser); + await waitForBookmarksToolbarVisibility({ + visible: true, + message: "Toolbar should be visible on newtab", + }); + ok(isBookmarksToolbarVisible(), "Toolbar should be visible on newtab"); + + // 4: Toolbar should get hidden when opening a new tab to example.com + let example = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "https://example.com", + }); + await waitForBookmarksToolbarVisibility({ + visible: false, + message: "Toolbar should be hidden on example.com", + }); + + // 5: Toolbar should become visible when switching tabs to newtab + await BrowserTestUtils.switchTab(gBrowser, newtab); + await waitForBookmarksToolbarVisibility({ + visible: true, + message: "Toolbar is visible with switch to newtab", + }); + ok(isBookmarksToolbarVisible(), "Toolbar is visible with switch to newtab"); + + // 6: Toolbar should become hidden when switching tabs to example.com + await BrowserTestUtils.switchTab(gBrowser, example); + await waitForBookmarksToolbarVisibility({ + visible: false, + message: "Toolbar is hidden with switch to example", + }); + + // 7: Similar to #3 above, loading about:newtab in example should show toolbar + BrowserTestUtils.loadURIString(example.linkedBrowser, "about:newtab"); + await BrowserTestUtils.browserLoaded(example.linkedBrowser); + await waitForBookmarksToolbarVisibility({ + visible: true, + message: "Toolbar is visible with newtab load", + }); + ok(isBookmarksToolbarVisible(), "Toolbar is visible with newtab load"); + + // 8: Switching back and forth between two browsers showing about:newtab will still show the toolbar + await BrowserTestUtils.switchTab(gBrowser, newtab); + ok(isBookmarksToolbarVisible(), "Toolbar is visible with switch to newtab"); + await BrowserTestUtils.switchTab(gBrowser, example); + ok( + isBookmarksToolbarVisible(), + "Toolbar is visible with switch to example(newtab)" + ); + + // 9: With custom newtab URL, toolbar isn't shown on about:newtab but is shown on custom URL + let oldNewTab = AboutNewTab.newTabURL; + AboutNewTab.newTabURL = "https://example.com/2"; + await BrowserTestUtils.switchTab(gBrowser, newtab); + await waitForBookmarksToolbarVisibility({ visible: false }); + ok(!isBookmarksToolbarVisible(), "Toolbar should hide with custom newtab"); + BrowserTestUtils.loadURIString(example.linkedBrowser, AboutNewTab.newTabURL); + await BrowserTestUtils.browserLoaded(example.linkedBrowser); + await BrowserTestUtils.switchTab(gBrowser, example); + await waitForBookmarksToolbarVisibility({ visible: true }); + ok( + isBookmarksToolbarVisible(), + "Toolbar is visible with switch to custom newtab" + ); + + await BrowserTestUtils.removeTab(newtab); + await BrowserTestUtils.removeTab(example); + AboutNewTab.newTabURL = oldNewTab; +}); + +add_task(async function bookmarks_toolbar_open_persisted() { + let newtab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:newtab", + waitForLoad: false, + }); + let example = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "https://example.com", + }); + let isToolbarPersistedOpen = () => + Services.prefs.getCharPref("browser.toolbars.bookmarks.visibility") == + "always"; + + ok(!isBookmarksToolbarVisible(), "Toolbar is hidden"); + await BrowserTestUtils.switchTab(gBrowser, newtab); + await waitForBookmarksToolbarVisibility({ visible: true }); + ok(isBookmarksToolbarVisible(), "Toolbar is visible"); + await BrowserTestUtils.switchTab(gBrowser, example); + await waitForBookmarksToolbarVisibility({ visible: false }); + ok(!isBookmarksToolbarVisible(), "Toolbar is hidden"); + ok(!isToolbarPersistedOpen(), "Toolbar is not persisted open"); + + let contextMenu = document.querySelector("#toolbar-context-menu"); + let popupShown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown"); + let menuButton = document.getElementById("PanelUI-menu-button"); + EventUtils.synthesizeMouseAtCenter( + menuButton, + { type: "contextmenu" }, + window + ); + await popupShown; + let bookmarksToolbarMenu = document.querySelector("#toggle_PersonalToolbar"); + let subMenu = bookmarksToolbarMenu.querySelector("menupopup"); + popupShown = BrowserTestUtils.waitForEvent(subMenu, "popupshown"); + bookmarksToolbarMenu.openMenu(true); + await popupShown; + let alwaysMenuItem = document.querySelector( + 'menuitem[data-visibility-enum="always"]' + ); + let neverMenuItem = document.querySelector( + 'menuitem[data-visibility-enum="never"]' + ); + let newTabMenuItem = document.querySelector( + 'menuitem[data-visibility-enum="newtab"]' + ); + is(alwaysMenuItem.getAttribute("checked"), "false", "Menuitem isn't checked"); + is(neverMenuItem.getAttribute("checked"), "false", "Menuitem isn't checked"); + is(newTabMenuItem.getAttribute("checked"), "true", "Menuitem is checked"); + + subMenu.activateItem(alwaysMenuItem); + + await waitForBookmarksToolbarVisibility({ visible: true }); + popupShown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown"); + EventUtils.synthesizeMouseAtCenter( + menuButton, + { type: "contextmenu" }, + window + ); + await popupShown; + bookmarksToolbarMenu = document.querySelector("#toggle_PersonalToolbar"); + subMenu = bookmarksToolbarMenu.querySelector("menupopup"); + popupShown = BrowserTestUtils.waitForEvent(subMenu, "popupshown"); + bookmarksToolbarMenu.openMenu(true); + await popupShown; + alwaysMenuItem = document.querySelector( + 'menuitem[data-visibility-enum="always"]' + ); + neverMenuItem = document.querySelector( + 'menuitem[data-visibility-enum="never"]' + ); + newTabMenuItem = document.querySelector( + 'menuitem[data-visibility-enum="newtab"]' + ); + is(alwaysMenuItem.getAttribute("checked"), "true", "Menuitem is checked"); + is(neverMenuItem.getAttribute("checked"), "false", "Menuitem isn't checked"); + is(newTabMenuItem.getAttribute("checked"), "false", "Menuitem isn't checked"); + contextMenu.hidePopup(); + ok(isBookmarksToolbarVisible(), "Toolbar is visible"); + ok(isToolbarPersistedOpen(), "Toolbar is persisted open"); + await BrowserTestUtils.switchTab(gBrowser, newtab); + ok(isBookmarksToolbarVisible(), "Toolbar is visible"); + await BrowserTestUtils.switchTab(gBrowser, example); + ok(isBookmarksToolbarVisible(), "Toolbar is visible"); + + popupShown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown"); + EventUtils.synthesizeMouseAtCenter( + menuButton, + { type: "contextmenu" }, + window + ); + await popupShown; + bookmarksToolbarMenu = document.querySelector("#toggle_PersonalToolbar"); + subMenu = bookmarksToolbarMenu.querySelector("menupopup"); + popupShown = BrowserTestUtils.waitForEvent(subMenu, "popupshown"); + bookmarksToolbarMenu.openMenu(true); + await popupShown; + alwaysMenuItem = document.querySelector( + 'menuitem[data-visibility-enum="always"]' + ); + neverMenuItem = document.querySelector( + 'menuitem[data-visibility-enum="never"]' + ); + newTabMenuItem = document.querySelector( + 'menuitem[data-visibility-enum="newtab"]' + ); + is(alwaysMenuItem.getAttribute("checked"), "true", "Menuitem is checked"); + is(neverMenuItem.getAttribute("checked"), "false", "Menuitem isn't checked"); + is(newTabMenuItem.getAttribute("checked"), "false", "Menuitem isn't checked"); + subMenu.activateItem(newTabMenuItem); + await waitForBookmarksToolbarVisibility({ + visible: false, + message: "Toolbar is hidden", + }); + await BrowserTestUtils.switchTab(gBrowser, newtab); + await waitForBookmarksToolbarVisibility({ + visible: true, + message: "Toolbar is visible", + }); + await BrowserTestUtils.switchTab(gBrowser, example); + await waitForBookmarksToolbarVisibility({ + visible: false, + message: "Toolbar is hidden", + }); + + await BrowserTestUtils.removeTab(newtab); + await BrowserTestUtils.removeTab(example); +}); + +add_task(async function test_with_newtabpage_disabled() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.newtabpage.enabled", true]], + }); + + let tabCount = gBrowser.tabs.length; + document.getElementById("cmd_newNavigatorTab").doCommand(); + // Can't use BrowserTestUtils.waitForNewTab since onLocationChange will not + // fire due to preloaded new tabs. + await TestUtils.waitForCondition(() => gBrowser.tabs.length == tabCount + 1); + let newtab = gBrowser.selectedTab; + is(newtab.linkedBrowser.currentURI.spec, "about:newtab", "newtab is loaded"); + await waitForBookmarksToolbarVisibility({ + visible: true, + message: "Toolbar is visible with NTP enabled", + }); + let firstid = await SpecialPowers.spawn(newtab.linkedBrowser, [], () => { + return content.document.body.firstElementChild?.id; + }); + is(firstid, "root", "new tab page contains content"); + await BrowserTestUtils.removeTab(newtab); + + await SpecialPowers.pushPrefEnv({ + set: [["browser.newtabpage.enabled", false]], + }); + + document.getElementById("cmd_newNavigatorTab").doCommand(); + await TestUtils.waitForCondition(() => gBrowser.tabs.length == tabCount + 1); + newtab = gBrowser.selectedTab; + + await waitForBookmarksToolbarVisibility({ + visible: true, + message: "Toolbar is visible with NTP disabled", + }); + + is( + newtab.linkedBrowser.currentURI.spec, + "about:newtab", + "blank new tab is loaded" + ); + firstid = await SpecialPowers.spawn(newtab.linkedBrowser, [], () => { + return content.document.body.firstElementChild; + }); + ok(!firstid, "blank new tab page contains no content"); + + await BrowserTestUtils.removeTab(newtab); + + await SpecialPowers.pushPrefEnv({ + set: [["browser.newtabpage.enabled", true]], + }); +}); + +add_task(async function test_history_pushstate() { + await BrowserTestUtils.withNewTab("https://example.com/", async browser => { + await waitForBookmarksToolbarVisibility({ visible: false }); + ok(!isBookmarksToolbarVisible(), "Toolbar should be hidden"); + + // Temporarily show the toolbar: + setToolbarVisibility( + document.querySelector("#PersonalToolbar"), + true, + false, + false + ); + ok(isBookmarksToolbarVisible(), "Toolbar should now be visible"); + + // Now "navigate" + await SpecialPowers.spawn(browser, [], () => { + content.location.href += "#foo"; + }); + + await TestUtils.waitForCondition( + () => gURLBar.value.endsWith("#foo"), + "URL bar should update" + ); + ok(isBookmarksToolbarVisible(), "Toolbar should still be visible"); + }); +}); diff --git a/browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbarEmpty.js b/browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbarEmpty.js new file mode 100644 index 0000000000..8e9ef8d163 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbarEmpty.js @@ -0,0 +1,158 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const bookmarksInfo = [ + { + title: "firefox", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + url: "http://example.com", + }, + { + title: "rules", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + url: "http://example.com/2", + }, + { + title: "yo", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + url: "http://example.com/2", + }, +]; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + // Ensure we can wait for about:newtab to load. + set: [["browser.newtab.preload", false]], + }); + // Move all existing bookmarks in the Bookmarks Toolbar and + // Other Bookmarks to the Bookmarks Menu so they don't affect + // the visibility of the Bookmarks Toolbar. Restore them at + // the end of the test. + let Bookmarks = PlacesUtils.bookmarks; + let toolbarBookmarks = []; + let unfiledBookmarks = []; + let guidBookmarkTuples = [ + [Bookmarks.toolbarGuid, toolbarBookmarks], + [Bookmarks.unfiledGuid, unfiledBookmarks], + ]; + for (let [parentGuid, arr] of guidBookmarkTuples) { + await Bookmarks.fetch({ parentGuid }, bookmark => arr.push(bookmark)); + } + await Promise.all( + [...toolbarBookmarks, ...unfiledBookmarks].map(async bookmark => { + bookmark.parentGuid = Bookmarks.menuGuid; + return Bookmarks.update(bookmark); + }) + ); + registerCleanupFunction(async () => { + for (let [parentGuid, arr] of guidBookmarkTuples) { + await Promise.all( + arr.map(async bookmark => { + bookmark.parentGuid = parentGuid; + return Bookmarks.update(bookmark); + }) + ); + } + }); +}); + +add_task(async function bookmarks_toolbar_not_shown_when_empty() { + let bookmarks = await PlacesUtils.bookmarks.insertTree({ + guid: PlacesUtils.bookmarks.toolbarGuid, + children: bookmarksInfo, + }); + let example = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "https://example.com", + }); + let newtab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:newtab", + }); + let emptyMessage = document.getElementById("personal-toolbar-empty"); + + // 1: Test that the toolbar is shown in a newly opened foreground about:newtab + await waitForBookmarksToolbarVisibility({ + visible: true, + message: "Toolbar should be visible on newtab", + }); + ok(emptyMessage.hidden, "Empty message is hidden with toolbar populated"); + + // 2: Toolbar should get hidden when switching tab to example.com + await BrowserTestUtils.switchTab(gBrowser, example); + await waitForBookmarksToolbarVisibility({ + visible: false, + message: "Toolbar should be hidden on example.com", + }); + + // 3: Remove all children of the Bookmarks Toolbar and confirm that + // the toolbar should not become visible when switching to newtab + CustomizableUI.addWidgetToArea( + "personal-bookmarks", + CustomizableUI.AREA_TABSTRIP + ); + CustomizableUI.removeWidgetFromArea("import-button"); + await BrowserTestUtils.switchTab(gBrowser, newtab); + await waitForBookmarksToolbarVisibility({ + visible: true, + message: "Toolbar is visible when there are no items in the toolbar area", + }); + ok(!emptyMessage.hidden, "Empty message is shown with toolbar empty"); + // Click the link and check we open the library: + let winPromise = BrowserTestUtils.domWindowOpenedAndLoaded(); + EventUtils.synthesizeMouseAtCenter( + emptyMessage.querySelector(".text-link"), + {} + ); + let libraryWin = await winPromise; + is( + libraryWin.document.location.href, + "chrome://browser/content/places/places.xhtml", + "Should have opened library." + ); + await BrowserTestUtils.closeWindow(libraryWin); + + // 4: Put personal-bookmarks back in the toolbar and confirm the toolbar is visible now + CustomizableUI.addWidgetToArea( + "personal-bookmarks", + CustomizableUI.AREA_BOOKMARKS + ); + await BrowserTestUtils.switchTab(gBrowser, example); + await BrowserTestUtils.switchTab(gBrowser, newtab); + await waitForBookmarksToolbarVisibility({ + visible: true, + message: "Toolbar should be visible with Bookmarks Toolbar Items restored", + }); + ok(emptyMessage.hidden, "Empty message is hidden with toolbar populated"); + + // 5: Remove all the bookmarks in the toolbar and confirm that the toolbar + // is hidden on the New Tab now + await PlacesUtils.bookmarks.remove(bookmarks); + await BrowserTestUtils.switchTab(gBrowser, example); + await BrowserTestUtils.switchTab(gBrowser, newtab); + await waitForBookmarksToolbarVisibility({ + visible: true, + message: + "Toolbar is visible when there are no items or nested bookmarks in the toolbar area", + }); + ok(!emptyMessage.hidden, "Empty message is shown with toolbar empty"); + + // 6: Add a toolbarbutton and make sure that the toolbar appears when the button is visible + CustomizableUI.addWidgetToArea( + "characterencoding-button", + CustomizableUI.AREA_BOOKMARKS + ); + await BrowserTestUtils.switchTab(gBrowser, example); + await BrowserTestUtils.switchTab(gBrowser, newtab); + await waitForBookmarksToolbarVisibility({ + visible: true, + message: "Toolbar is visible when there is a visible button in the toolbar", + }); + ok(emptyMessage.hidden, "Empty message is hidden with button in toolbar"); + + await BrowserTestUtils.removeTab(newtab); + await BrowserTestUtils.removeTab(example); + CustomizableUI.reset(); +}); diff --git a/browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbarNewWindow.js b/browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbarNewWindow.js new file mode 100644 index 0000000000..19c990bbbc --- /dev/null +++ b/browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbarNewWindow.js @@ -0,0 +1,82 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +const testCases = [ + { + name: "bookmarks_toolbar_shown_on_newtab_newTabEnabled", + newTabEnabled: true, + }, + { + name: "bookmarks_toolbar_shown_on_newtab", + newTabEnabled: false, + }, +]; + +async function test_bookmarks_toolbar_visibility({ newTabEnabled }) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.newtabpage.enabled", newTabEnabled]], + }); + + // Ensure the toolbar doesnt become visible at any point before the tab finishes loading + + let url = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "slow_loading_page.sjs"; + + let startTime = Date.now(); + let newWindowOpened = BrowserTestUtils.domWindowOpened(); + let beforeShown = TestUtils.topicObserved("browser-window-before-show"); + + openTrustedLinkIn(url, "window"); + + let newWin = await newWindowOpened; + let slowSiteLoaded = BrowserTestUtils.firstBrowserLoaded(newWin, false); + + function checkToolbarIsCollapsed(win, message) { + let toolbar = win.document.getElementById("PersonalToolbar"); + ok(toolbar && toolbar.collapsed, message); + } + + await beforeShown; + checkToolbarIsCollapsed( + newWin, + "Toolbar is initially hidden on the new window" + ); + + function onToolbarMutation() { + checkToolbarIsCollapsed(newWin, "Toolbar should remain collapsed"); + } + let toolbarMutationObserver = new newWin.MutationObserver(onToolbarMutation); + toolbarMutationObserver.observe( + newWin.document.getElementById("PersonalToolbar"), + { + attributeFilter: ["collapsed"], + } + ); + + info("Waiting for the slow site to load"); + await slowSiteLoaded; + info(`Window opened and slow site loaded in: ${Date.now() - startTime}ms`); + + checkToolbarIsCollapsed(newWin, "Finally, the toolbar is still hidden"); + + toolbarMutationObserver.disconnect(); + await BrowserTestUtils.closeWindow(newWin); +} + +// Make separate tasks for each test case, so we get more useful stack traces on failure +for (let testData of testCases) { + let tmp = { + async [testData.name]() { + info("testing with: " + JSON.stringify(testData)); + await test_bookmarks_toolbar_visibility(testData); + }, + }; + add_task(tmp[testData.name]); +} diff --git a/browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbarPrefs.js b/browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbarPrefs.js new file mode 100644 index 0000000000..e9f7768beb --- /dev/null +++ b/browser/base/content/test/about/browser_aboutNewTab_bookmarksToolbarPrefs.js @@ -0,0 +1,74 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(3); + +add_task(async function test_with_different_pref_states() { + // [prefName, prefValue, toolbarVisibleExampleCom, toolbarVisibleNewTab] + let bookmarksToolbarVisibilityStates = [ + ["browser.toolbars.bookmarks.visibility", "newtab"], + ["browser.toolbars.bookmarks.visibility", "always"], + ["browser.toolbars.bookmarks.visibility", "never"], + ]; + for (let visibilityState of bookmarksToolbarVisibilityStates) { + await SpecialPowers.pushPrefEnv({ + set: [visibilityState], + }); + + for (let privateWin of [true, false]) { + info( + `Testing with ${visibilityState} in a ${ + privateWin ? "private" : "non-private" + } window` + ); + let win = await BrowserTestUtils.openNewBrowserWindow({ + private: privateWin, + }); + is( + win.gBrowser.currentURI.spec, + privateWin ? "about:privatebrowsing" : "about:blank", + "Expecting about:privatebrowsing or about:blank as URI of new window" + ); + + if (!privateWin) { + await waitForBookmarksToolbarVisibility({ + win, + visible: visibilityState[1] == "always", + message: + "Toolbar should be visible only if visibilityState is 'always'. State: " + + visibilityState[1], + }); + await BrowserTestUtils.openNewForegroundTab({ + gBrowser: win.gBrowser, + opening: "about:newtab", + waitForLoad: false, + }); + } + + await waitForBookmarksToolbarVisibility({ + win, + visible: + visibilityState[1] == "newtab" || visibilityState[1] == "always", + message: + "Toolbar should be visible as long as visibilityState isn't set to 'never'. State: " + + visibilityState[1], + }); + + await BrowserTestUtils.openNewForegroundTab({ + gBrowser: win.gBrowser, + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + opening: "http://example.com", + }); + await waitForBookmarksToolbarVisibility({ + win, + visible: visibilityState[1] == "always", + message: + "Toolbar should be visible only if visibilityState is 'always'. State: " + + visibilityState[1], + }); + await BrowserTestUtils.closeWindow(win); + } + } +}); diff --git a/browser/base/content/test/about/browser_aboutStopReload.js b/browser/base/content/test/about/browser_aboutStopReload.js new file mode 100644 index 0000000000..66c11a3de3 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutStopReload.js @@ -0,0 +1,169 @@ +async function waitForNoAnimation(elt) { + return TestUtils.waitForCondition(() => !elt.hasAttribute("animate")); +} + +async function getAnimatePromise(elt) { + return BrowserTestUtils.waitForAttribute("animate", elt).then(() => + Assert.ok(true, `${elt.id} should animate`) + ); +} + +function stopReloadMutationCallback() { + Assert.ok( + false, + "stop-reload's animate attribute should not have been mutated" + ); +} + +// Force-enable the animation +gReduceMotionOverride = false; + +add_task(async function checkDontShowStopOnNewTab() { + let stopReloadContainer = document.getElementById("stop-reload-button"); + let stopReloadContainerObserver = new MutationObserver( + stopReloadMutationCallback + ); + + await waitForNoAnimation(stopReloadContainer); + stopReloadContainerObserver.observe(stopReloadContainer, { + attributeFilter: ["animate"], + }); + let tab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:robots", + waitForStateStop: true, + }); + BrowserTestUtils.removeTab(tab); + + Assert.ok( + true, + "Test finished: stop-reload does not animate when navigating to local URI on new tab" + ); + stopReloadContainerObserver.disconnect(); +}); + +add_task(async function checkDontShowStopFromLocalURI() { + let stopReloadContainer = document.getElementById("stop-reload-button"); + let stopReloadContainerObserver = new MutationObserver( + stopReloadMutationCallback + ); + + let tab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:robots", + waitForStateStop: true, + }); + await waitForNoAnimation(stopReloadContainer); + stopReloadContainerObserver.observe(stopReloadContainer, { + attributeFilter: ["animate"], + }); + BrowserTestUtils.loadURIString(tab.linkedBrowser, "about:mozilla"); + BrowserTestUtils.removeTab(tab); + + Assert.ok( + true, + "Test finished: stop-reload does not animate when navigating between local URIs" + ); + stopReloadContainerObserver.disconnect(); +}); + +add_task(async function checkDontShowStopFromNonLocalURI() { + let stopReloadContainer = document.getElementById("stop-reload-button"); + let stopReloadContainerObserver = new MutationObserver( + stopReloadMutationCallback + ); + + let tab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "https://example.com", + waitForStateStop: true, + }); + await waitForNoAnimation(stopReloadContainer); + stopReloadContainerObserver.observe(stopReloadContainer, { + attributeFilter: ["animate"], + }); + BrowserTestUtils.loadURIString(tab.linkedBrowser, "about:mozilla"); + BrowserTestUtils.removeTab(tab); + + Assert.ok( + true, + "Test finished: stop-reload does not animate when navigating to local URI from non-local URI" + ); + stopReloadContainerObserver.disconnect(); +}); + +add_task(async function checkDoShowStopOnNewTab() { + let stopReloadContainer = document.getElementById("stop-reload-button"); + let reloadButton = document.getElementById("reload-button"); + let stopPromise = BrowserTestUtils.waitForAttribute( + "displaystop", + reloadButton + ); + + await waitForNoAnimation(stopReloadContainer); + + let tab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "https://example.com", + waitForStateStop: true, + }); + await stopPromise; + await waitForNoAnimation(stopReloadContainer); + BrowserTestUtils.removeTab(tab); + + info( + "Test finished: stop-reload shows stop when navigating to non-local URI during tab opening" + ); +}); + +add_task(async function checkAnimateStopOnTabAfterTabFinishesOpening() { + let stopReloadContainer = document.getElementById("stop-reload-button"); + + await waitForNoAnimation(stopReloadContainer); + let tab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + waitForStateStop: true, + }); + await TestUtils.waitForCondition(() => { + info( + "Waiting for tabAnimationsInProgress to equal 0, currently " + + gBrowser.tabAnimationsInProgress + ); + return !gBrowser.tabAnimationsInProgress; + }); + let animatePromise = getAnimatePromise(stopReloadContainer); + BrowserTestUtils.loadURIString(tab.linkedBrowser, "https://example.com"); + await animatePromise; + BrowserTestUtils.removeTab(tab); + + info( + "Test finished: stop-reload animates when navigating to non-local URI on new tab after tab has opened" + ); +}); + +add_task(async function checkDoShowStopFromLocalURI() { + let stopReloadContainer = document.getElementById("stop-reload-button"); + + await waitForNoAnimation(stopReloadContainer); + let tab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:robots", + waitForStateStop: true, + }); + await TestUtils.waitForCondition(() => { + info( + "Waiting for tabAnimationsInProgress to equal 0, currently " + + gBrowser.tabAnimationsInProgress + ); + return !gBrowser.tabAnimationsInProgress; + }); + let animatePromise = getAnimatePromise(stopReloadContainer); + BrowserTestUtils.loadURIString(tab.linkedBrowser, "https://example.com"); + await animatePromise; + await waitForNoAnimation(stopReloadContainer); + BrowserTestUtils.removeTab(tab); + + info( + "Test finished: stop-reload animates when navigating to non-local URI from local URI" + ); +}); diff --git a/browser/base/content/test/about/browser_aboutSupport.js b/browser/base/content/test/about/browser_aboutSupport.js new file mode 100644 index 0000000000..e846a2b493 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutSupport.js @@ -0,0 +1,146 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { ExperimentAPI } = ChromeUtils.importESModule( + "resource://nimbus/ExperimentAPI.sys.mjs" +); +const { ExperimentFakes } = ChromeUtils.importESModule( + "resource://testing-common/NimbusTestUtils.sys.mjs" +); + +add_task(async function () { + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:support" }, + async function (browser) { + let keyLocationServiceGoogleStatus = await SpecialPowers.spawn( + browser, + [], + async function () { + let textBox = content.document.getElementById( + "key-location-service-google-box" + ); + await ContentTaskUtils.waitForCondition( + () => content.document.l10n.getAttributes(textBox).id, + "Google location service API key status loaded" + ); + return content.document.l10n.getAttributes(textBox).id; + } + ); + ok( + keyLocationServiceGoogleStatus, + "Google location service API key status shown" + ); + + let keySafebrowsingGoogleStatus = await SpecialPowers.spawn( + browser, + [], + async function () { + let textBox = content.document.getElementById( + "key-safebrowsing-google-box" + ); + await ContentTaskUtils.waitForCondition( + () => content.document.l10n.getAttributes(textBox).id, + "Google Safebrowsing API key status loaded" + ); + return content.document.l10n.getAttributes(textBox).id; + } + ); + ok( + keySafebrowsingGoogleStatus, + "Google Safebrowsing API key status shown" + ); + + let keyMozillaStatus = await SpecialPowers.spawn( + browser, + [], + async function () { + let textBox = content.document.getElementById("key-mozilla-box"); + await ContentTaskUtils.waitForCondition( + () => content.document.l10n.getAttributes(textBox).id, + "Mozilla API key status loaded" + ); + return content.document.l10n.getAttributes(textBox).id; + } + ); + ok(keyMozillaStatus, "Mozilla API key status shown"); + } + ); +}); + +add_task(async function test_nimbus_experiments() { + await ExperimentAPI.ready(); + let doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({ + featureId: "aboutwelcome", + value: { enabled: true }, + }); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:support" }, + async function (browser) { + let experimentName = await SpecialPowers.spawn( + browser, + [], + async function () { + await ContentTaskUtils.waitForCondition( + () => + content.document.querySelector( + "#remote-experiments-tbody tr:first-child td" + )?.innerText + ); + return content.document.querySelector( + "#remote-experiments-tbody tr:first-child td" + ).innerText; + } + ); + ok( + experimentName.match("Nimbus"), + "Rendered the expected experiment slug" + ); + } + ); + + await doExperimentCleanup(); +}); + +add_task(async function test_remote_configuration() { + await ExperimentAPI.ready(); + let doCleanup = await ExperimentFakes.enrollWithRollout({ + featureId: NimbusFeatures.aboutwelcome.featureId, + value: { enabled: true }, + }); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:support" }, + async function (browser) { + let [userFacingName, branch] = await SpecialPowers.spawn( + browser, + [], + async function () { + await ContentTaskUtils.waitForCondition( + () => + content.document.querySelector( + "#remote-features-tbody tr:first-child td" + )?.innerText + ); + let rolloutName = content.document.querySelector( + "#remote-features-tbody tr:first-child td" + ).innerText; + let branchName = content.document.querySelector( + "#remote-features-tbody tr:first-child td:nth-child(2)" + ).innerText; + + return [rolloutName, branchName]; + } + ); + ok( + userFacingName.match("NimbusTestUtils"), + "Rendered the expected rollout" + ); + ok(branch.match("aboutwelcome"), "Rendered the expected rollout branch"); + } + ); + + await doCleanup(); +}); diff --git a/browser/base/content/test/about/browser_aboutSupport_newtab_security_state.js b/browser/base/content/test/about/browser_aboutSupport_newtab_security_state.js new file mode 100644 index 0000000000..caa45a1af5 --- /dev/null +++ b/browser/base/content/test/about/browser_aboutSupport_newtab_security_state.js @@ -0,0 +1,19 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +add_task(async function checkIdentityOfAboutSupport() { + let tab = gBrowser.addTab("about:support", { + referrerURI: null, + inBackground: false, + allowThirdPartyFixup: false, + relatedToCurrent: false, + skipAnimation: true, + allowMixedContent: false, + triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(), + }); + + await promiseTabLoaded(tab); + let identityBox = document.getElementById("identity-box"); + is(identityBox.className, "chromeUI", "Should know that we're chrome."); + gBrowser.removeTab(tab); +}); diff --git a/browser/base/content/test/about/browser_aboutSupport_places.js b/browser/base/content/test/about/browser_aboutSupport_places.js new file mode 100644 index 0000000000..e971de7f0e --- /dev/null +++ b/browser/base/content/test/about/browser_aboutSupport_places.js @@ -0,0 +1,45 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async function test_places_db_stats_table() { + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:support" }, + async function (browser) { + const [initialToggleText, toggleTextAfterShow, toggleTextAfterHide] = + await SpecialPowers.spawn(browser, [], async function () { + const toggleButton = content.document.getElementById( + "place-database-stats-toggle" + ); + const getToggleText = () => + content.document.l10n.getAttributes(toggleButton).id; + const toggleTexts = []; + const table = content.document.getElementById( + "place-database-stats-tbody" + ); + await ContentTaskUtils.waitForCondition( + () => table.style.display === "none", + "Stats table is hidden initially" + ); + toggleTexts.push(getToggleText()); + toggleButton.click(); + await ContentTaskUtils.waitForCondition( + () => table.style.display === "", + "Stats table is shown after first toggle" + ); + toggleTexts.push(getToggleText()); + toggleButton.click(); + await ContentTaskUtils.waitForCondition( + () => table.style.display === "none", + "Stats table is hidden after second toggle" + ); + toggleTexts.push(getToggleText()); + return toggleTexts; + }); + Assert.equal(initialToggleText, "place-database-stats-show"); + Assert.equal(toggleTextAfterShow, "place-database-stats-hide"); + Assert.equal(toggleTextAfterHide, "place-database-stats-show"); + } + ); +}); diff --git a/browser/base/content/test/about/browser_bug435325.js b/browser/base/content/test/about/browser_bug435325.js new file mode 100644 index 0000000000..70a3b272a9 --- /dev/null +++ b/browser/base/content/test/about/browser_bug435325.js @@ -0,0 +1,58 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Ensure that clicking the button in the Offline mode neterror page makes the browser go online. See bug 435325. */ + +add_task(async function checkSwitchPageToOnlineMode() { + // Go offline and disable the proxy and cache, then try to load the test URL. + Services.io.offline = true; + + // Tests always connect to localhost, and per bug 87717, localhost is now + // reachable in offline mode. To avoid this, disable any proxy. + let proxyPrefValue = SpecialPowers.getIntPref("network.proxy.type"); + await SpecialPowers.pushPrefEnv({ + set: [ + ["network.proxy.type", 0], + ["browser.cache.disk.enable", false], + ["browser.cache.memory.enable", false], + ], + }); + + await BrowserTestUtils.withNewTab("about:blank", async function (browser) { + let netErrorLoaded = BrowserTestUtils.waitForErrorPage(browser); + + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + BrowserTestUtils.loadURIString(browser, "http://example.com/"); + await netErrorLoaded; + + // Re-enable the proxy so example.com is resolved to localhost, rather than + // the actual example.com. + await SpecialPowers.pushPrefEnv({ + set: [["network.proxy.type", proxyPrefValue]], + }); + let changeObserved = TestUtils.topicObserved( + "network:offline-status-changed" + ); + + // Click on the 'Try again' button. + await SpecialPowers.spawn(browser, [], async function () { + ok( + content.document.documentURI.startsWith("about:neterror?e=netOffline"), + "Should be showing error page" + ); + content.document + .querySelector("#netErrorButtonContainer > .try-again") + .click(); + }); + + await changeObserved; + ok( + !Services.io.offline, + "After clicking the 'Try Again' button, we're back online." + ); + }); +}); + +registerCleanupFunction(function () { + Services.io.offline = false; +}); diff --git a/browser/base/content/test/about/browser_bug633691.js b/browser/base/content/test/about/browser_bug633691.js new file mode 100644 index 0000000000..33d58475f6 --- /dev/null +++ b/browser/base/content/test/about/browser_bug633691.js @@ -0,0 +1,32 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +add_task(async function test() { + const URL = "data:text/html,"; + await BrowserTestUtils.withNewTab( + { gBrowser, url: URL }, + async function (browser) { + let context = await SpecialPowers.spawn(browser, [], function () { + let iframe = content.document.querySelector("iframe"); + iframe.src = "https://expired.example.com/"; + return BrowsingContext.getFromWindow(iframe.contentWindow); + }); + await TestUtils.waitForCondition(() => { + let frame = context.currentWindowGlobal; + return frame && frame.documentURI.spec.startsWith("about:certerror"); + }); + await SpecialPowers.spawn(context, [], async function () { + await ContentTaskUtils.waitForCondition( + () => content.document.readyState == "interactive" + ); + let aP = content.document.getElementById("badCertAdvancedPanel"); + Assert.ok(aP, "Advanced content should exist"); + Assert.ok( + ContentTaskUtils.is_hidden(aP), + "Advanced content should not be visible by default" + ); + }); + } + ); +}); diff --git a/browser/base/content/test/about/csp_iframe.sjs b/browser/base/content/test/about/csp_iframe.sjs new file mode 100644 index 0000000000..f53ed8498f --- /dev/null +++ b/browser/base/content/test/about/csp_iframe.sjs @@ -0,0 +1,33 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function handleRequest(request, response) { + // let's enjoy the amazing CSP setting + response.setHeader( + "Content-Security-Policy", + "frame-ancestors 'self'", + false + ); + + // let's avoid caching issues + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache", false); + + // everything is fine - no needs to worry :) + response.setStatusLine(request.httpVersion, 200); + response.setHeader("Content-Type", "text/html", false); + let txt = "

CSP Page opened in new window!

"; + response.write(txt); + + let cookie = request.hasHeader("Cookie") + ? request.getHeader("Cookie") + : "" + + "

No same site strict cookie header

" + + ""; + response.write(cookie); + + if (!request.hasHeader("Cookie")) { + let strictCookie = `matchaCookie=green; Domain=.example.org; SameSite=Strict`; + response.setHeader("Set-Cookie", strictCookie); + } +} diff --git a/browser/base/content/test/about/dummy_page.html b/browser/base/content/test/about/dummy_page.html new file mode 100644 index 0000000000..1a87e28408 --- /dev/null +++ b/browser/base/content/test/about/dummy_page.html @@ -0,0 +1,9 @@ + + +Dummy test page + + + +

Dummy test page

+ + diff --git a/browser/base/content/test/about/head.js b/browser/base/content/test/about/head.js new file mode 100644 index 0000000000..c723fbee33 --- /dev/null +++ b/browser/base/content/test/about/head.js @@ -0,0 +1,220 @@ +ChromeUtils.defineESModuleGetters(this, { + FormHistory: "resource://gre/modules/FormHistory.sys.mjs", + SearchTestUtils: "resource://testing-common/SearchTestUtils.sys.mjs", +}); + +SearchTestUtils.init(this); + +function getCertChainAsString(certBase64Array) { + let certChain = ""; + for (let cert of certBase64Array) { + certChain += getPEMString(cert); + } + return certChain; +} + +function getPEMString(derb64) { + // Wrap the Base64 string into lines of 64 characters, + // with CRLF line breaks (as specified in RFC 1421). + var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n"); + return ( + "-----BEGIN CERTIFICATE-----\r\n" + + wrapped + + "\r\n-----END CERTIFICATE-----\r\n" + ); +} + +async function injectErrorPageFrame(tab, src, sandboxed) { + let loadedPromise = BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + true, + null, + true + ); + + await SpecialPowers.spawn( + tab.linkedBrowser, + [src, sandboxed], + async function (frameSrc, frameSandboxed) { + let iframe = content.document.createElement("iframe"); + iframe.src = frameSrc; + if (frameSandboxed) { + iframe.setAttribute("sandbox", "allow-scripts"); + } + content.document.body.appendChild(iframe); + } + ); + + await loadedPromise; +} + +async function openErrorPage(src, useFrame, sandboxed) { + let dummyPage = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "dummy_page.html"; + + let tab; + if (useFrame) { + info("Loading cert error page in an iframe"); + tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, dummyPage); + await injectErrorPageFrame(tab, src, sandboxed); + } else { + let certErrorLoaded; + tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + () => { + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, src); + let browser = gBrowser.selectedBrowser; + certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser); + }, + false + ); + info("Loading and waiting for the cert error"); + await certErrorLoaded; + } + + return tab; +} + +function waitForCondition(condition, nextTest, errorMsg, retryTimes) { + retryTimes = typeof retryTimes !== "undefined" ? retryTimes : 30; + var tries = 0; + var interval = setInterval(function () { + if (tries >= retryTimes) { + ok(false, errorMsg); + moveOn(); + } + var conditionPassed; + try { + conditionPassed = condition(); + } catch (e) { + ok(false, e + "\n" + e.stack); + conditionPassed = false; + } + if (conditionPassed) { + moveOn(); + } + tries++; + }, 100); + var moveOn = function () { + clearInterval(interval); + nextTest(); + }; +} + +function whenTabLoaded(aTab, aCallback) { + promiseTabLoadEvent(aTab).then(aCallback); +} + +function promiseTabLoaded(aTab) { + return new Promise(resolve => { + whenTabLoaded(aTab, resolve); + }); +} + +/** + * Waits for a load (or custom) event to finish in a given tab. If provided + * load an uri into the tab. + * + * @param tab + * The tab to load into. + * @param [optional] url + * The url to load, or the current url. + * @return {Promise} resolved when the event is handled. + * @resolves to the received event + * @rejects if a valid load event is not received within a meaningful interval + */ +function promiseTabLoadEvent(tab, url) { + info("Wait tab event: load"); + + function handle(loadedUrl) { + if (loadedUrl === "about:blank" || (url && loadedUrl !== url)) { + info(`Skipping spurious load event for ${loadedUrl}`); + return false; + } + + info("Tab event received: load"); + return true; + } + + let loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, handle); + + if (url) { + BrowserTestUtils.loadURIString(tab.linkedBrowser, url); + } + + return loaded; +} + +/** + * Wait for the search engine to change. searchEngineChangeFn is a function + * that will be called to change the search engine. + */ +async function promiseContentSearchChange(browser, searchEngineChangeFn) { + // Add an event listener manually then perform the action, rather than using + // BrowserTestUtils.addContentEventListener as that doesn't add the listener + // early enough. + await SpecialPowers.spawn(browser, [], async () => { + // Store the results in a temporary place. + content._searchDetails = { + defaultEnginesList: [], + listener: event => { + if (event.detail.type == "CurrentState") { + content._searchDetails.defaultEnginesList.push( + content.wrappedJSObject.gContentSearchController.defaultEngine.name + ); + } + }, + }; + + // Listen using the system group to ensure that it fires after + // the default behaviour. + content.addEventListener( + "ContentSearchService", + content._searchDetails.listener, + { mozSystemGroup: true } + ); + }); + + let expectedEngineName = await searchEngineChangeFn(); + + await SpecialPowers.spawn( + browser, + [expectedEngineName], + async expectedEngineNameChild => { + await ContentTaskUtils.waitForCondition( + () => + content._searchDetails.defaultEnginesList && + content._searchDetails.defaultEnginesList[ + content._searchDetails.defaultEnginesList.length - 1 + ] == expectedEngineNameChild + ); + content.removeEventListener( + "ContentSearchService", + content._searchDetails.listener, + { mozSystemGroup: true } + ); + delete content._searchDetails; + } + ); +} + +async function waitForBookmarksToolbarVisibility({ + win = window, + visible, + message, +}) { + let result = await TestUtils.waitForCondition(() => { + let toolbar = win.document.getElementById("PersonalToolbar"); + return toolbar && (visible ? !toolbar.collapsed : toolbar.collapsed); + }, message || "waiting for toolbar to become " + (visible ? "visible" : "hidden")); + ok(result, message); + return result; +} + +function isBookmarksToolbarVisible(win = window) { + let toolbar = win.document.getElementById("PersonalToolbar"); + return !toolbar.collapsed; +} diff --git a/browser/base/content/test/about/iframe_page_csp.html b/browser/base/content/test/about/iframe_page_csp.html new file mode 100644 index 0000000000..93a23de15d --- /dev/null +++ b/browser/base/content/test/about/iframe_page_csp.html @@ -0,0 +1,16 @@ + + + + + Dummy iFrame page + + +

iFrame CSP test

+ + + diff --git a/browser/base/content/test/about/iframe_page_xfo.html b/browser/base/content/test/about/iframe_page_xfo.html new file mode 100644 index 0000000000..34e7f5cc52 --- /dev/null +++ b/browser/base/content/test/about/iframe_page_xfo.html @@ -0,0 +1,16 @@ + + + + + Dummy iFrame page + + +

iFrame XFO test

+ + + diff --git a/browser/base/content/test/about/print_postdata.sjs b/browser/base/content/test/about/print_postdata.sjs new file mode 100644 index 0000000000..0e3ef38419 --- /dev/null +++ b/browser/base/content/test/about/print_postdata.sjs @@ -0,0 +1,25 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); + +function handleRequest(request, response) { + response.setHeader("Content-Type", "text/plain", false); + if (request.method == "GET") { + response.write(request.queryString); + } else { + var body = new BinaryInputStream(request.bodyInputStream); + + var avail; + var bytes = []; + + while ((avail = body.available()) > 0) { + Array.prototype.push.apply(bytes, body.readByteArray(avail)); + } + + var data = String.fromCharCode.apply(null, bytes); + response.bodyOutputStream.write(data, data.length); + } +} diff --git a/browser/base/content/test/about/searchSuggestionEngine.sjs b/browser/base/content/test/about/searchSuggestionEngine.sjs new file mode 100644 index 0000000000..1978b4f665 --- /dev/null +++ b/browser/base/content/test/about/searchSuggestionEngine.sjs @@ -0,0 +1,9 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function handleRequest(req, resp) { + let suffixes = ["foo", "bar"]; + let data = [req.queryString, suffixes.map(s => req.queryString + s)]; + resp.setHeader("Content-Type", "application/json", false); + resp.write(JSON.stringify(data)); +} diff --git a/browser/base/content/test/about/searchSuggestionEngine.xml b/browser/base/content/test/about/searchSuggestionEngine.xml new file mode 100644 index 0000000000..409d0b4084 --- /dev/null +++ b/browser/base/content/test/about/searchSuggestionEngine.xml @@ -0,0 +1,11 @@ + + + + +browser_searchSuggestionEngine searchSuggestionEngine.xml + + + + + diff --git a/browser/base/content/test/about/slow_loading_page.sjs b/browser/base/content/test/about/slow_loading_page.sjs new file mode 100644 index 0000000000..747390cdf7 --- /dev/null +++ b/browser/base/content/test/about/slow_loading_page.sjs @@ -0,0 +1,29 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +const DELAY_MS = 400; + +const HTML = ` + + + + + hi mom! + +`; + +function handleRequest(req, resp) { + resp.processAsync(); + + let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + timer.init( + () => { + resp.setHeader("Cache-Control", "no-cache", false); + resp.setHeader("Content-Type", "text/html;charset=utf-8", false); + resp.write(HTML); + resp.finish(); + }, + DELAY_MS, + Ci.nsITimer.TYPE_ONE_SHOT + ); +} diff --git a/browser/base/content/test/about/xfo_iframe.sjs b/browser/base/content/test/about/xfo_iframe.sjs new file mode 100644 index 0000000000..e8a6352ce0 --- /dev/null +++ b/browser/base/content/test/about/xfo_iframe.sjs @@ -0,0 +1,34 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function handleRequest(request, response) { + // let's enjoy the amazing XFO setting + response.setHeader("X-Frame-Options", "SAMEORIGIN"); + + // let's avoid caching issues + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache", false); + + // everything is fine - no needs to worry :) + response.setStatusLine(request.httpVersion, 200); + + response.setHeader("Content-Type", "text/html", false); + let txt = + "XFO page" + + "

" + + "XFO blocked page opened in new window!" + + "

"; + response.write(txt); + + let cookie = request.hasHeader("Cookie") + ? request.getHeader("Cookie") + : "" + + "

No same site strict cookie header

" + + ""; + response.write(cookie); + + if (!request.hasHeader("Cookie")) { + let strictCookie = `matchaCookie=creamy; Domain=.example.org; SameSite=Strict`; + response.setHeader("Set-Cookie", strictCookie); + } +} diff --git a/browser/base/content/test/alerts/browser.ini b/browser/base/content/test/alerts/browser.ini new file mode 100644 index 0000000000..c06f0d03d9 --- /dev/null +++ b/browser/base/content/test/alerts/browser.ini @@ -0,0 +1,22 @@ +[DEFAULT] +support-files = + head.js + file_dom_notifications.html + +[browser_notification_close.js] +https_first_disabled = true +skip-if = os == 'win' # Bug 1227785 +[browser_notification_do_not_disturb.js] +https_first_disabled = true +[browser_notification_open_settings.js] +https_first_disabled = true +skip-if = os == 'win' # Bug 1411118 +[browser_notification_remove_permission.js] +https_first_disabled = true +skip-if = os == 'win' # Bug 1411118 +[browser_notification_replace.js] +https_first_disabled = true +skip-if = os == 'win' # Bug 1422928 +[browser_notification_tab_switching.js] +https_first_disabled = true +skip-if = os == 'win' # Bug 1243263 diff --git a/browser/base/content/test/alerts/browser_notification_close.js b/browser/base/content/test/alerts/browser_notification_close.js new file mode 100644 index 0000000000..2d71db31a0 --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_close.js @@ -0,0 +1,107 @@ +"use strict"; + +const { PlacesTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PlacesTestUtils.sys.mjs" +); + +const { PermissionTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PermissionTestUtils.sys.mjs" +); + +let notificationURL = + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; +let oldShowFavicons; + +add_task(async function test_notificationClose() { + let notificationURI = makeURI(notificationURL); + await addNotificationPermission(notificationURL); + + oldShowFavicons = Services.prefs.getBoolPref("alerts.showFavicons"); + Services.prefs.setBoolPref("alerts.showFavicons", true); + + await PlacesTestUtils.addVisits(notificationURI); + let faviconURI = await new Promise(resolve => { + let uri = makeURI( + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC" + ); + PlacesUtils.favicons.setAndFetchFaviconForPage( + notificationURI, + uri, + true, + PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, + uriResult => resolve(uriResult), + Services.scriptSecurityManager.getSystemPrincipal() + ); + }); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: notificationURL, + }, + async function dummyTabTask(aBrowser) { + await openNotification(aBrowser, "showNotification2"); + + info("Notification alert showing"); + + let alertWindow = Services.wm.getMostRecentWindow("alert:alert"); + if (!alertWindow) { + ok(true, "Notifications don't use XUL windows on all platforms."); + await closeNotification(aBrowser); + return; + } + + let alertTitleLabel = + alertWindow.document.getElementById("alertTitleLabel"); + is( + alertTitleLabel.value, + "Test title", + "Title text of notification should be present" + ); + let alertTextLabel = + alertWindow.document.getElementById("alertTextLabel"); + is( + alertTextLabel.textContent, + "Test body 2", + "Body text of notification should be present" + ); + let alertIcon = alertWindow.document.getElementById("alertIcon"); + is( + alertIcon.src, + faviconURI.spec, + "Icon of notification should be present" + ); + + let alertCloseButton = alertWindow.document.querySelector(".close-icon"); + is(alertCloseButton.localName, "toolbarbutton", "close button found"); + let promiseBeforeUnloadEvent = BrowserTestUtils.waitForEvent( + alertWindow, + "beforeunload" + ); + let closedTime = alertWindow.Date.now(); + alertCloseButton.click(); + info("Clicked on close button"); + await promiseBeforeUnloadEvent; + + ok(true, "Alert should close when the close button is clicked"); + let currentTime = alertWindow.Date.now(); + // The notification will self-close at 12 seconds, so this checks + // that the notification closed before the timeout. + ok( + currentTime - closedTime < 5000, + "Close requested at " + + closedTime + + ", actually closed at " + + currentTime + ); + } + ); +}); + +add_task(async function cleanup() { + PermissionTestUtils.remove(notificationURL, "desktop-notification"); + if (typeof oldShowFavicons == "boolean") { + Services.prefs.setBoolPref("alerts.showFavicons", oldShowFavicons); + } +}); diff --git a/browser/base/content/test/alerts/browser_notification_do_not_disturb.js b/browser/base/content/test/alerts/browser_notification_do_not_disturb.js new file mode 100644 index 0000000000..8fb5a8a52b --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_do_not_disturb.js @@ -0,0 +1,160 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests that notifications can be silenced using nsIAlertsDoNotDisturb + * on systems where that interface and its methods are implemented for + * the nsIAlertService. + */ + +const ALERT_SERVICE = Cc["@mozilla.org/alerts-service;1"] + .getService(Ci.nsIAlertsService) + .QueryInterface(Ci.nsIAlertsDoNotDisturb); + +const PAGE = + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; + +// The amount of time in seconds that we will wait for a notification +// to show up before we decide that it's not coming. +const NOTIFICATION_TIMEOUT_SECS = 2000; + +add_setup(async function () { + await addNotificationPermission(PAGE); +}); + +/** + * Test that the manualDoNotDisturb attribute can prevent + * notifications from appearing. + */ +add_task(async function test_manualDoNotDisturb() { + try { + // Only run the test if the do-not-disturb + // interface has been implemented. + ALERT_SERVICE.manualDoNotDisturb; + ok(true, "Alert service implements do-not-disturb interface"); + } catch (e) { + ok( + true, + "Alert service doesn't implement do-not-disturb interface, exiting test" + ); + return; + } + + // In the event that something goes wrong during this test, make sure + // we put the attribute back to the default setting when this test file + // exits. + registerCleanupFunction(() => { + ALERT_SERVICE.manualDoNotDisturb = false; + }); + + // Make sure that do-not-disturb is not enabled before we start. + ok( + !ALERT_SERVICE.manualDoNotDisturb, + "Alert service should not be disabled when test starts" + ); + + await BrowserTestUtils.withNewTab(PAGE, async browser => { + await openNotification(browser, "showNotification2"); + + info("Notification alert showing"); + + let alertWindow = Services.wm.getMostRecentWindow("alert:alert"); + + // For now, only the XUL alert backend implements the manualDoNotDisturb + // method for nsIAlertsDoNotDisturb, so we expect there to be a XUL alert + // window. If the method gets implemented by native backends in the future, + // we'll probably want to branch here and set the manualDoNotDisturb + // attribute manually. + ok(alertWindow, "Expected a XUL alert window."); + + // We're using the XUL notification backend. This means that there's + // a menuitem for enabling manualDoNotDisturb. We exercise that + // menuitem here. + let doNotDisturbMenuItem = alertWindow.document.getElementById( + "doNotDisturbMenuItem" + ); + is(doNotDisturbMenuItem.localName, "menuitem", "menuitem found"); + + let unloadPromise = BrowserTestUtils.waitForEvent( + alertWindow, + "beforeunload" + ); + + doNotDisturbMenuItem.click(); + info("Clicked on do-not-disturb menuitem"); + await unloadPromise; + + // At this point, we should be configured to not display notifications + // to the user. + ok( + ALERT_SERVICE.manualDoNotDisturb, + "Alert service should be disabled after clicking menuitem" + ); + + // The notification should not appear, but there is no way from the + // client-side to know that it was blocked, except for waiting some time + // and realizing that the "onshow" event never fired. + await Assert.rejects( + openNotification(browser, "showNotification2", NOTIFICATION_TIMEOUT_SECS), + /timed out/, + "The notification should never display." + ); + + ALERT_SERVICE.manualDoNotDisturb = false; + }); +}); + +/** + * Test that the suppressForScreenSharing attribute can prevent + * notifications from appearing. + */ +add_task(async function test_suppressForScreenSharing() { + try { + // Only run the test if the do-not-disturb + // interface has been implemented. + ALERT_SERVICE.suppressForScreenSharing; + ok(true, "Alert service implements do-not-disturb interface"); + } catch (e) { + ok( + true, + "Alert service doesn't implement do-not-disturb interface, exiting test" + ); + return; + } + + // In the event that something goes wrong during this test, make sure + // we put the attribute back to the default setting when this test file + // exits. + registerCleanupFunction(() => { + ALERT_SERVICE.suppressForScreenSharing = false; + }); + + // Make sure that do-not-disturb is not enabled before we start. + ok( + !ALERT_SERVICE.suppressForScreenSharing, + "Alert service should not be suppressing for screen sharing when test " + + "starts" + ); + + await BrowserTestUtils.withNewTab(PAGE, async browser => { + await openNotification(browser, "showNotification2"); + + info("Notification alert showing"); + await closeNotification(browser); + ALERT_SERVICE.suppressForScreenSharing = true; + + // The notification should not appear, but there is no way from the + // client-side to know that it was blocked, except for waiting some time + // and realizing that the "onshow" event never fired. + await Assert.rejects( + openNotification(browser, "showNotification2", NOTIFICATION_TIMEOUT_SECS), + /timed out/, + "The notification should never display." + ); + }); + + ALERT_SERVICE.suppressForScreenSharing = false; +}); diff --git a/browser/base/content/test/alerts/browser_notification_open_settings.js b/browser/base/content/test/alerts/browser_notification_open_settings.js new file mode 100644 index 0000000000..ed51cd782b --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_open_settings.js @@ -0,0 +1,80 @@ +"use strict"; + +var notificationURL = + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; +var expectedURL = "about:preferences#privacy"; + +add_task(async function test_settingsOpen_observer() { + info( + "Opening a dummy tab so openPreferences=>switchToTabHavingURI doesn't use the blank tab." + ); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "about:robots", + }, + async function dummyTabTask(aBrowser) { + // Ensure preferences is loaded before removing the tab. + let syncPaneLoadedPromise = TestUtils.topicObserved( + "sync-pane-loaded", + () => true + ); + let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, expectedURL); + info("simulate a notifications-open-settings notification"); + let uri = NetUtil.newURI("https://example.com"); + let principal = Services.scriptSecurityManager.createContentPrincipal( + uri, + {} + ); + Services.obs.notifyObservers(principal, "notifications-open-settings"); + let tab = await tabPromise; + ok(tab, "The notification settings tab opened"); + await syncPaneLoadedPromise; + BrowserTestUtils.removeTab(tab); + } + ); +}); + +add_task(async function test_settingsOpen_button() { + info("Adding notification permission"); + await addNotificationPermission(notificationURL); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: notificationURL, + }, + async function tabTask(aBrowser) { + info("Waiting for notification"); + await openNotification(aBrowser, "showNotification2"); + + let alertWindow = Services.wm.getMostRecentWindow("alert:alert"); + if (!alertWindow) { + ok(true, "Notifications don't use XUL windows on all platforms."); + await closeNotification(aBrowser); + return; + } + + // Ensure preferences is loaded before removing the tab. + let syncPaneLoadedPromise = TestUtils.topicObserved( + "sync-pane-loaded", + () => true + ); + let closePromise = promiseWindowClosed(alertWindow); + let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, expectedURL); + let openSettingsMenuItem = alertWindow.document.getElementById( + "openSettingsMenuItem" + ); + openSettingsMenuItem.click(); + + info("Waiting for notification settings tab"); + let tab = await tabPromise; + ok(tab, "The notification settings tab opened"); + + await syncPaneLoadedPromise; + await closePromise; + BrowserTestUtils.removeTab(tab); + } + ); +}); diff --git a/browser/base/content/test/alerts/browser_notification_remove_permission.js b/browser/base/content/test/alerts/browser_notification_remove_permission.js new file mode 100644 index 0000000000..ba198870a3 --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_remove_permission.js @@ -0,0 +1,86 @@ +"use strict"; + +const { PermissionTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PermissionTestUtils.sys.mjs" +); + +var tab; +var notificationURL = + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; +var alertWindowClosed = false; +var permRemoved = false; + +function test() { + waitForExplicitFinish(); + + registerCleanupFunction(function () { + gBrowser.removeTab(tab); + window.restore(); + }); + + addNotificationPermission(notificationURL).then(function openTab() { + tab = BrowserTestUtils.addTab(gBrowser, notificationURL); + gBrowser.selectedTab = tab; + BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => onLoad()); + }); +} + +function onLoad() { + openNotification(tab.linkedBrowser, "showNotification2").then(onAlertShowing); +} + +function onAlertShowing() { + info("Notification alert showing"); + + let alertWindow = Services.wm.getMostRecentWindow("alert:alert"); + if (!alertWindow) { + ok(true, "Notifications don't use XUL windows on all platforms."); + closeNotification(tab.linkedBrowser).then(finish); + return; + } + ok( + PermissionTestUtils.testExactPermission( + notificationURL, + "desktop-notification" + ), + "Permission should exist prior to removal" + ); + let disableForOriginMenuItem = alertWindow.document.getElementById( + "disableForOriginMenuItem" + ); + is(disableForOriginMenuItem.localName, "menuitem", "menuitem found"); + Services.obs.addObserver(permObserver, "perm-changed"); + alertWindow.addEventListener("beforeunload", onAlertClosing); + disableForOriginMenuItem.click(); + info("Clicked on disable-for-origin menuitem"); +} + +function permObserver(subject, topic, data) { + if (topic != "perm-changed") { + return; + } + + let permission = subject.QueryInterface(Ci.nsIPermission); + is( + permission.type, + "desktop-notification", + "desktop-notification permission changed" + ); + is(data, "deleted", "desktop-notification permission deleted"); + + Services.obs.removeObserver(permObserver, "perm-changed"); + permRemoved = true; + if (alertWindowClosed) { + finish(); + } +} + +function onAlertClosing(event) { + event.target.removeEventListener("beforeunload", onAlertClosing); + + alertWindowClosed = true; + if (permRemoved) { + finish(); + } +} diff --git a/browser/base/content/test/alerts/browser_notification_replace.js b/browser/base/content/test/alerts/browser_notification_replace.js new file mode 100644 index 0000000000..9c72e90ab1 --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_replace.js @@ -0,0 +1,66 @@ +"use strict"; + +let notificationURL = + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; + +add_task(async function test_notificationReplace() { + await addNotificationPermission(notificationURL); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: notificationURL, + }, + async function dummyTabTask(aBrowser) { + await SpecialPowers.spawn(aBrowser, [], async function () { + let win = content.window.wrappedJSObject; + let notification = win.showNotification1(); + let promiseCloseEvent = ContentTaskUtils.waitForEvent( + notification, + "close" + ); + + let showEvent = await ContentTaskUtils.waitForEvent( + notification, + "show" + ); + Assert.equal( + showEvent.target.body, + "Test body 1", + "Showed tagged notification" + ); + + let newNotification = win.showNotification2(); + let newShowEvent = await ContentTaskUtils.waitForEvent( + newNotification, + "show" + ); + Assert.equal( + newShowEvent.target.body, + "Test body 2", + "Showed new notification with same tag" + ); + + let closeEvent = await promiseCloseEvent; + Assert.equal( + closeEvent.target.body, + "Test body 1", + "Closed previous tagged notification" + ); + + let promiseNewCloseEvent = ContentTaskUtils.waitForEvent( + newNotification, + "close" + ); + newNotification.close(); + let newCloseEvent = await promiseNewCloseEvent; + Assert.equal( + newCloseEvent.target.body, + "Test body 2", + "Closed new notification" + ); + }); + } + ); +}); diff --git a/browser/base/content/test/alerts/browser_notification_tab_switching.js b/browser/base/content/test/alerts/browser_notification_tab_switching.js new file mode 100644 index 0000000000..ee675670cb --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_tab_switching.js @@ -0,0 +1,117 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +"use strict"; + +const { PermissionTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PermissionTestUtils.sys.mjs" +); + +var tab; +var notification; +var notificationURL = + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; +var newWindowOpenedFromTab; + +add_task(async function test_notificationPreventDefaultAndSwitchTabs() { + await addNotificationPermission(notificationURL); + + let originalTab = gBrowser.selectedTab; + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: notificationURL, + }, + async function dummyTabTask(aBrowser) { + // Put new tab in background so it is obvious when it is re-focused. + await BrowserTestUtils.switchTab(gBrowser, originalTab); + isnot( + gBrowser.selectedBrowser, + aBrowser, + "Notification page loaded as a background tab" + ); + + // First, show a notification that will be have the tab-switching prevented. + function promiseNotificationEvent(evt) { + return SpecialPowers.spawn( + aBrowser, + [evt], + async function (contentEvt) { + return new Promise(resolve => { + let contentNotification = content.wrappedJSObject._notification; + contentNotification.addEventListener( + contentEvt, + function (event) { + resolve({ defaultPrevented: event.defaultPrevented }); + }, + { once: true } + ); + }); + } + ); + } + await openNotification(aBrowser, "showNotification1"); + info("Notification alert showing"); + let alertWindow = Services.wm.getMostRecentWindow("alert:alert"); + if (!alertWindow) { + ok(true, "Notifications don't use XUL windows on all platforms."); + await closeNotification(aBrowser); + return; + } + info("Clicking on notification"); + let promiseClickEvent = promiseNotificationEvent("click"); + + // NB: This executeSoon is needed to allow the non-e10s runs of this test + // a chance to set the event listener on the page. Otherwise, we + // synchronously fire the click event before we listen for the event. + executeSoon(() => { + EventUtils.synthesizeMouseAtCenter( + alertWindow.document.getElementById("alertTitleLabel"), + {}, + alertWindow + ); + }); + let clickEvent = await promiseClickEvent; + ok( + clickEvent.defaultPrevented, + "The event handler for the first notification cancels the event" + ); + isnot( + gBrowser.selectedBrowser, + aBrowser, + "Notification page still a background tab" + ); + let notificationClosed = promiseNotificationEvent("close"); + await closeNotification(aBrowser); + await notificationClosed; + + // Second, show a notification that will cause the tab to get switched. + await openNotification(aBrowser, "showNotification2"); + alertWindow = Services.wm.getMostRecentWindow("alert:alert"); + let promiseTabSelect = BrowserTestUtils.waitForEvent( + gBrowser.tabContainer, + "TabSelect" + ); + EventUtils.synthesizeMouseAtCenter( + alertWindow.document.getElementById("alertTitleLabel"), + {}, + alertWindow + ); + await promiseTabSelect; + is( + gBrowser.selectedBrowser.currentURI.spec, + notificationURL, + "Clicking on the second notification should select its originating tab" + ); + notificationClosed = promiseNotificationEvent("close"); + await closeNotification(aBrowser); + await notificationClosed; + } + ); +}); + +add_task(async function cleanup() { + PermissionTestUtils.remove(notificationURL, "desktop-notification"); +}); diff --git a/browser/base/content/test/alerts/file_dom_notifications.html b/browser/base/content/test/alerts/file_dom_notifications.html new file mode 100644 index 0000000000..6deede8fcf --- /dev/null +++ b/browser/base/content/test/alerts/file_dom_notifications.html @@ -0,0 +1,39 @@ + + + + + + +
+ +
+ + diff --git a/browser/base/content/test/alerts/head.js b/browser/base/content/test/alerts/head.js new file mode 100644 index 0000000000..4be18f6c41 --- /dev/null +++ b/browser/base/content/test/alerts/head.js @@ -0,0 +1,73 @@ +// Platforms may default to reducing motion. We override this to ensure the +// alert slide animation is enabled in tests. +SpecialPowers.pushPrefEnv({ + set: [["ui.prefersReducedMotion", 0]], +}); + +async function addNotificationPermission(originString) { + return SpecialPowers.pushPermissions([ + { + type: "desktop-notification", + allow: true, + context: originString, + }, + ]); +} + +/** + * Similar to `BrowserTestUtils.closeWindow`, but + * doesn't call `window.close()`. + */ +function promiseWindowClosed(window) { + return new Promise(function (resolve) { + Services.ww.registerNotification(function observer(subject, topic, data) { + if (topic == "domwindowclosed" && subject == window) { + Services.ww.unregisterNotification(observer); + resolve(); + } + }); + }); +} + +/** + * These two functions work with file_dom_notifications.html to open the + * notification and close it. + * + * |fn| can be showNotification1 or showNotification2. + * if |timeout| is passed, then the promise returned from this function is + * rejected after the requested number of miliseconds. + */ +function openNotification(aBrowser, fn, timeout) { + info(`openNotification: ${fn}`); + return SpecialPowers.spawn( + aBrowser, + [[fn, timeout]], + async function ([contentFn, contentTimeout]) { + await new Promise((resolve, reject) => { + let win = content.wrappedJSObject; + let notification = win[contentFn](); + win._notification = notification; + + function listener() { + notification.removeEventListener("show", listener); + resolve(); + } + + notification.addEventListener("show", listener); + + if (contentTimeout) { + content.setTimeout(() => { + notification.removeEventListener("show", listener); + reject("timed out"); + }, contentTimeout); + } + }); + } + ); +} + +function closeNotification(aBrowser) { + return SpecialPowers.spawn(aBrowser, [], function () { + content.wrappedJSObject._notification.close(); + }); +} diff --git a/browser/base/content/test/backforward/browser.ini b/browser/base/content/test/backforward/browser.ini new file mode 100644 index 0000000000..2bfb071ee4 --- /dev/null +++ b/browser/base/content/test/backforward/browser.ini @@ -0,0 +1,2 @@ +[browser_history_menu.js] +https_first_disabled = true diff --git a/browser/base/content/test/backforward/browser_history_menu.js b/browser/base/content/test/backforward/browser_history_menu.js new file mode 100644 index 0000000000..b812a6ae24 --- /dev/null +++ b/browser/base/content/test/backforward/browser_history_menu.js @@ -0,0 +1,175 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// This test verifies that the back forward button long-press menu and context menu +// shows the correct history items. + +add_task(async function mousedown_back() { + await testBackForwardMenu(false); +}); + +add_task(async function contextmenu_back() { + await testBackForwardMenu(true); +}); + +async function openHistoryMenu(useContextMenu) { + let backButton = document.getElementById("back-button"); + let rect = backButton.getBoundingClientRect(); + + info("waiting for the history menu to open"); + + let popupShownPromise = BrowserTestUtils.waitForEvent( + useContextMenu ? document.getElementById("backForwardMenu") : backButton, + "popupshown" + ); + if (useContextMenu) { + EventUtils.synthesizeMouseAtCenter(backButton, { + type: "contextmenu", + button: 2, + }); + } else { + EventUtils.synthesizeMouseAtCenter(backButton, { type: "mousedown" }); + } + + EventUtils.synthesizeMouse(backButton, rect.width / 2, rect.height, { + type: "mouseup", + }); + let popupEvent = await popupShownPromise; + + ok(true, "history menu opened"); + + return popupEvent; +} + +async function testBackForwardMenu(useContextMenu) { + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com" + ); + + for (let iter = 2; iter <= 4; iter++) { + // Iterate three times. For the first two times through the loop, add a new history item. + // But for the last iteration, go back in the history instead. + await SpecialPowers.spawn( + gBrowser.selectedBrowser, + [iter], + async function (iterChild) { + if (iterChild == 4) { + let popStatePromise = new Promise(function (resolve) { + content.onpopstate = resolve; + }); + content.history.back(); + await popStatePromise; + } else { + content.history.pushState({}, "" + iterChild, iterChild + ".html"); + } + } + ); + + // Wait for the session data to be flushed before continuing the test + await new Promise(resolve => + SessionStore.getSessionHistory(gBrowser.selectedTab, resolve) + ); + + let popupEvent = await openHistoryMenu(useContextMenu); + + // Wait for the session data to be flushed before continuing the test + await new Promise(resolve => + SessionStore.getSessionHistory(gBrowser.selectedTab, resolve) + ); + + is( + popupEvent.target.children.length, + iter > 3 ? 3 : iter, + "Correct number of history items" + ); + + let node = popupEvent.target.lastElementChild; + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + is(node.getAttribute("uri"), "http://example.com/", "'1' item uri"); + is(node.getAttribute("index"), "0", "'1' item index"); + is( + node.getAttribute("historyindex"), + iter == 3 ? "-2" : "-1", + "'1' item historyindex" + ); + + node = node.previousElementSibling; + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + is(node.getAttribute("uri"), "http://example.com/2.html", "'2' item uri"); + is(node.getAttribute("index"), "1", "'2' item index"); + is( + node.getAttribute("historyindex"), + iter == 3 ? "-1" : "0", + "'2' item historyindex" + ); + + if (iter >= 3) { + node = node.previousElementSibling; + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + is(node.getAttribute("uri"), "http://example.com/3.html", "'3' item uri"); + is(node.getAttribute("index"), "2", "'3' item index"); + is( + node.getAttribute("historyindex"), + iter == 4 ? "1" : "0", + "'3' item historyindex" + ); + } + + // Close the popup, but on the last iteration, click on one of the history items + // to ensure it opens in a new tab. + let popupHiddenPromise = BrowserTestUtils.waitForEvent( + popupEvent.target, + "popuphidden" + ); + + if (iter < 4) { + popupEvent.target.hidePopup(); + } else { + let newTabPromise = BrowserTestUtils.waitForNewTab( + gBrowser, + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + url => url == "http://example.com/" + ); + + popupEvent.target.activateItem(popupEvent.target.children[2], { + button: 1, + }); + + let newtab = await newTabPromise; + gBrowser.removeTab(newtab); + } + + await popupHiddenPromise; + } + + gBrowser.removeTab(tab); +} + +// Make sure that the history popup appears after navigating around in a preferences page. +add_task(async function test_preferences_page() { + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:preferences" + ); + + openPreferences("search"); + let popupEvent = await openHistoryMenu(true); + + // Wait for the session data to be flushed before continuing the test + await new Promise(resolve => + SessionStore.getSessionHistory(gBrowser.selectedTab, resolve) + ); + + is(popupEvent.target.children.length, 2, "Correct number of history items"); + + let popupHiddenPromise = BrowserTestUtils.waitForEvent( + popupEvent.target, + "popuphidden" + ); + popupEvent.target.hidePopup(); + await popupHiddenPromise; + + gBrowser.removeTab(tab); +}); diff --git a/browser/base/content/test/caps/browser.ini b/browser/base/content/test/caps/browser.ini new file mode 100644 index 0000000000..18464cdf77 --- /dev/null +++ b/browser/base/content/test/caps/browser.ini @@ -0,0 +1,6 @@ +[DEFAULT] + +[browser_principalSerialization_csp.js] +[browser_principalSerialization_json.js] +skip-if = debug # deliberately bypass assertions when deserializing. Bug 965637 removed the CSP from Principals, but the remaining bits in such Principals should deserialize correctly. +[browser_principalSerialization_version1.js] diff --git a/browser/base/content/test/caps/browser_principalSerialization_csp.js b/browser/base/content/test/caps/browser_principalSerialization_csp.js new file mode 100644 index 0000000000..909e728794 --- /dev/null +++ b/browser/base/content/test/caps/browser_principalSerialization_csp.js @@ -0,0 +1,106 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* + * Within Bug 965637 we move the CSP away from the Principal. Serialized Principals however + * might still have CSPs serialized within them. This tests ensures that we do not + * encounter a memory corruption when deserializing. It's fine that the deserialized + * CSP is null, but the Principal itself should deserialize correctly. + */ + +add_task(async function test_deserialize_principal_with_csp() { + /* + This test should be resilient to changes in principal serialization, if these are failing then it's likely the code will break session storage. + To recreate this for another version, copy the function into the browser console, browse some pages and printHistory. + + Generated with: + function printHistory() { + let tests = []; + let entries = SessionStore.getSessionHistory(gBrowser.selectedTab).entries.map((entry) => { return entry.triggeringPrincipal_base64 }); + entries.push(E10SUtils.serializePrincipal(gBrowser.selectedTab.linkedBrowser._contentPrincipal)); + for (let entry of entries) { + console.log(entry); + let testData = {}; + testData.input = entry; + let principal = E10SUtils.deserializePrincipal(testData.input); + testData.output = {}; + if (principal.URI === null) { + testData.output.URI = false; + } else { + testData.output.URISpec = principal.URI.spec; + } + testData.output.originAttributes = principal.originAttributes; + testData.output.cspJSON = principal.cspJSON; + + tests.push(testData); + } + return tests; + } + printHistory(); // Copy this into: serializedPrincipalsFromFirefox + */ + + let serializedPrincipalsFromFirefox = [ + { + input: + "ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAHmh0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTLwAAAAAAAAAFAAAACAAAAA8AAAAA/////wAAAAD/////AAAACAAAAA8AAAAXAAAABwAAABcAAAAHAAAAFwAAAAcAAAAeAAAAAAAAAAD/////AAAAAP////8AAAAA/////wAAAAD/////AQAAAAAAAAAAAAAAAQnZ7Rrl1EAEv+Anzrkj2ayzxMCuvV5MrYfgjSENuz+fAd6UctCANBHTk5kAEEug/UCSBzpUbXhPMJE6uHGBMgjGAAAAAv////8AAAG7AQAAAB5odHRwczovL3d3dy5tb3ppbGxhLm9yZy9lbi1VUy8AAAAAAAAABQAAAAgAAAAPAAAAAP////8AAAAA/////wAAAAgAAAAPAAAAFwAAAAcAAAAXAAAABwAAABcAAAAHAAAAHgAAAAAAAAAA/////wAAAAD/////AAAAAP////8AAAAA/////wEAAAAAAAAAAAABAAAFtgBzAGMAcgBpAHAAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIAAnAHUAbgBzAGEAZgBlAC0AaQBuAGwAaQBuAGUAJwAgACcAdQBuAHMAYQBmAGUALQBlAHYAYQBsACcAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdABhAGcAbQBhAG4AYQBnAGUAcgAuAGcAbwBvAGcAbABlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AcwAuAHkAdABpAG0AZwAuAGMAbwBtADsAIABpAG0AZwAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIABkAGEAdABhADoAIABoAHQAdABwAHMAOgAvAC8AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAZABzAGUAcgB2AGkAYwBlAC4AZwBvAG8AZwBsAGUALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AZABlACAAaAB0AHQAcABzADoALwAvAGEAZABzAGUAcgB2AGkAYwBlAC4AZwBvAG8AZwBsAGUALgBkAGsAIABoAHQAdABwAHMAOgAvAC8AYwByAGUAYQB0AGkAdgBlAGMAbwBtAG0AbwBuAHMALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwBhAGQALgBkAG8AdQBiAGwAZQBjAGwAaQBjAGsALgBuAGUAdAA7ACAAZABlAGYAYQB1AGwAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AOwAgAGYAcgBhAG0AZQAtAHMAcgBjACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAtAG4AbwBjAG8AbwBrAGkAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAcgBhAGMAawBlAHIAdABlAHMAdAAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AcwB1AHIAdgBlAHkAZwBpAHoAbQBvAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAuAGMAbgAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALgBjAG8AbQA7ACAAcwB0AHkAbABlAC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG4AZQB0ACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBjAG8AbQAgACcAdQBuAHMAYQBmAGUALQBpAG4AbABpAG4AZQAnADsAIABjAG8AbgBuAGUAYwB0AC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG4AZQB0ACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALwAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALgBjAG4ALwA7ACAAYwBoAGkAbABkAC0AcwByAGMAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC0AbgBvAGMAbwBvAGsAaQBlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdAByAGEAYwBrAGUAcgB0AGUAcwB0AC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBzAHUAcgB2AGUAeQBnAGkAegBtAG8ALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC4AYwBuACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAuAGMAbwBtAAA=", + output: { + // Within Bug 965637 we removed CSP from Principals. Already serialized Principals however should still deserialize correctly (just without the CSP). + // "cspJSON": "{\"csp-policies\":[{\"child-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"connect-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://accounts.firefox.com/\",\"https://accounts.firefox.com.cn/\"],\"default-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\"],\"frame-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"img-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"data:\",\"https://mozilla.org\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://adservice.google.com\",\"https://adservice.google.de\",\"https://adservice.google.dk\",\"https://creativecommons.org\",\"https://ad.doubleclick.net\"],\"report-only\":false,\"script-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\",\"'unsafe-eval'\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://tagmanager.google.com\",\"https://www.youtube.com\",\"https://s.ytimg.com\"],\"style-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\"]}]}", + URISpec: "https://www.mozilla.org/en-US/", + originAttributes: { + firstPartyDomain: "", + inIsolatedMozBrowser: false, + privateBrowsingId: 0, + userContextId: 0, + geckoViewSessionContextId: "", + partitionKey: "", + }, + }, + }, + { + input: + "ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAL2h0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTL2ZpcmVmb3gvYWNjb3VudHMvAAAAAAAAAAUAAAAIAAAADwAAAAj/////AAAACP////8AAAAIAAAADwAAABcAAAAYAAAAFwAAABgAAAAXAAAAGAAAAC8AAAAAAAAAL/////8AAAAA/////wAAABf/////AAAAF/////8BAAAAAAAAAAAAAAABCdntGuXUQAS/4CfOuSPZrLPEwK69Xkyth+CNIQ27P58B3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAL2h0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTL2ZpcmVmb3gvYWNjb3VudHMvAAAAAAAAAAUAAAAIAAAADwAAAAj/////AAAACP////8AAAAIAAAADwAAABcAAAAYAAAAFwAAABgAAAAXAAAAGAAAAC8AAAAAAAAAL/////8AAAAA/////wAAABf/////AAAAF/////8BAAAAAAAAAAAAAQAABbYAcwBjAHIAaQBwAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtACAAJwB1AG4AcwBhAGYAZQAtAGkAbgBsAGkAbgBlACcAIAAnAHUAbgBzAGEAZgBlAC0AZQB2AGEAbAAnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBnAG8AbwBnAGwAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHMALgB5AHQAaQBtAGcALgBjAG8AbQA7ACAAaQBtAGcALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtACAAZABhAHQAYQA6ACAAaAB0AHQAcABzADoALwAvAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBkAHMAZQByAHYAaQBjAGUALgBnAG8AbwBnAGwAZQAuAGQAZQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AZABrACAAaAB0AHQAcABzADoALwAvAGMAcgBlAGEAdABpAHYAZQBjAG8AbQBtAG8AbgBzAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AYQBkAC4AZABvAHUAYgBsAGUAYwBsAGkAYwBrAC4AbgBlAHQAOwAgAGQAZQBmAGEAdQBsAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtADsAIABmAHIAYQBtAGUALQBzAHIAYwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALQBuAG8AYwBvAG8AawBpAGUALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB0AHIAYQBjAGsAZQByAHQAZQBzAHQALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHMAdQByAHYAZQB5AGcAaQB6AG0AbwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALgBjAG4AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC4AYwBvAG0AOwAgAHMAdAB5AGwAZQAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIAAnAHUAbgBzAGEAZgBlAC0AaQBuAGwAaQBuAGUAJwA7ACAAYwBvAG4AbgBlAGMAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC8AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC4AYwBuAC8AOwAgAGMAaABpAGwAZAAtAHMAcgBjACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAtAG4AbwBjAG8AbwBrAGkAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAcgBhAGMAawBlAHIAdABlAHMAdAAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AcwB1AHIAdgBlAHkAZwBpAHoAbQBvAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAuAGMAbgAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALgBjAG8AbQAA", + output: { + URISpec: "https://www.mozilla.org/en-US/firefox/accounts/", + originAttributes: { + firstPartyDomain: "", + inIsolatedMozBrowser: false, + privateBrowsingId: 0, + userContextId: 0, + geckoViewSessionContextId: "", + partitionKey: "", + }, + // Within Bug 965637 we removed CSP from Principals. Already serialized Principals however should still deserialize correctly (just without the CSP). + // "cspJSON": "{\"csp-policies\":[{\"child-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"connect-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://accounts.firefox.com/\",\"https://accounts.firefox.com.cn/\"],\"default-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\"],\"frame-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"img-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"data:\",\"https://mozilla.org\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://adservice.google.com\",\"https://adservice.google.de\",\"https://adservice.google.dk\",\"https://creativecommons.org\",\"https://ad.doubleclick.net\"],\"report-only\":false,\"script-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\",\"'unsafe-eval'\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://tagmanager.google.com\",\"https://www.youtube.com\",\"https://s.ytimg.com\"],\"style-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\"]}]}", + }, + }, + ]; + + for (let test of serializedPrincipalsFromFirefox) { + let principal = E10SUtils.deserializePrincipal(test.input); + + for (let key in principal.originAttributes) { + is( + principal.originAttributes[key], + test.output.originAttributes[key], + `Ensure value of ${key} is ${test.output.originAttributes[key]}` + ); + } + + if ("URI" in test.output && test.output.URI === false) { + is( + principal.isContentPrincipal, + false, + "Should have not have a URI for system" + ); + } else { + is( + principal.spec, + test.output.URISpec, + `Should have spec ${test.output.URISpec}` + ); + } + } +}); diff --git a/browser/base/content/test/caps/browser_principalSerialization_json.js b/browser/base/content/test/caps/browser_principalSerialization_json.js new file mode 100644 index 0000000000..f79f269fd7 --- /dev/null +++ b/browser/base/content/test/caps/browser_principalSerialization_json.js @@ -0,0 +1,161 @@ +"use strict"; + +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + This test file exists to ensure whenever changes to principal serialization happens, + we guarantee that the data can be restored and generated into a new principal. + + The tests are written to be brittle so we encode all versions of the changes into the tests. +*/ + +add_task(async function test_nullPrincipal() { + const nullId = "0"; + // fields + const uri = 0; + const suffix = 1; + + const nullReplaceRegex = + /moz-nullprincipal:{[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}}/; + const NULL_REPLACE = "NULL_PRINCIPAL_URL"; + + /* + This test should NOT be resilient to changes in versioning, + however it exists purely to verify the code doesn't unintentionally change without updating versioning and migration code. + */ + let tests = [ + { + input: { OA: {} }, + expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}"}}`, + }, + { + input: { OA: {} }, + expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}"}}`, + }, + { + input: { OA: { userContextId: 0 } }, + expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}"}}`, + }, + { + input: { OA: { userContextId: 2 } }, + expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}","${suffix}":"^userContextId=2"}}`, + }, + { + input: { OA: { privateBrowsingId: 1 } }, + expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}","${suffix}":"^privateBrowsingId=1"}}`, + }, + { + input: { OA: { privateBrowsingId: 0 } }, + expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}"}}`, + }, + ]; + + for (let test of tests) { + let p = Services.scriptSecurityManager.createNullPrincipal(test.input.OA); + let sp = E10SUtils.serializePrincipal(p); + // Not sure why cppjson is adding a \n here + let spr = sp.replace(nullReplaceRegex, NULL_REPLACE); + is( + test.expected, + spr, + "Expected serialized object for " + JSON.stringify(test.input) + ); + let dp = E10SUtils.deserializePrincipal(sp); + + // Check all the origin attributes + for (let key in test.input.OA) { + is( + dp.originAttributes[key], + test.input.OA[key], + "Ensure value of " + key + " is " + test.input.OA[key] + ); + } + } +}); + +add_task(async function test_contentPrincipal() { + const contentId = "1"; + // fields + const content = 0; + // const domain = 1; + const suffix = 2; + // const csp = 3; + + /* + This test should NOT be resilient to changes in versioning, + however it exists purely to verify the code doesn't unintentionally change without updating versioning and migration code. + */ + let tests = [ + { + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + input: { uri: "http://example.com/", OA: {} }, + expected: `{"${contentId}":{"${content}":"http://example.com/"}}`, + }, + { + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + input: { uri: "http://mozilla1.com/", OA: {} }, + expected: `{"${contentId}":{"${content}":"http://mozilla1.com/"}}`, + }, + { + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + input: { uri: "http://mozilla2.com/", OA: { userContextId: 0 } }, + expected: `{"${contentId}":{"${content}":"http://mozilla2.com/"}}`, + }, + { + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + input: { uri: "http://mozilla3.com/", OA: { userContextId: 2 } }, + expected: `{"${contentId}":{"${content}":"http://mozilla3.com/","${suffix}":"^userContextId=2"}}`, + }, + { + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + input: { uri: "http://mozilla4.com/", OA: { privateBrowsingId: 1 } }, + expected: `{"${contentId}":{"${content}":"http://mozilla4.com/","${suffix}":"^privateBrowsingId=1"}}`, + }, + { + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + input: { uri: "http://mozilla5.com/", OA: { privateBrowsingId: 0 } }, + expected: `{"${contentId}":{"${content}":"http://mozilla5.com/"}}`, + }, + ]; + + for (let test of tests) { + let uri = Services.io.newURI(test.input.uri); + let p = Services.scriptSecurityManager.createContentPrincipal( + uri, + test.input.OA + ); + let sp = E10SUtils.serializePrincipal(p); + is(test.expected, sp, "Expected serialized object for " + test.input.uri); + let dp = E10SUtils.deserializePrincipal(sp); + is(dp.URI.spec, test.input.uri, "Ensure spec is the same"); + + // Check all the origin attributes + for (let key in test.input.OA) { + is( + dp.originAttributes[key], + test.input.OA[key], + "Ensure value of " + key + " is " + test.input.OA[key] + ); + } + } +}); + +add_task(async function test_systemPrincipal() { + const systemId = "3"; + /* + This test should NOT be resilient to changes in versioning, + however it exists purely to verify the code doesn't unintentionally change without updating versioning and migration code. + */ + const expected = `{"${systemId}":{}}`; + + let p = Services.scriptSecurityManager.getSystemPrincipal(); + let sp = E10SUtils.serializePrincipal(p); + is(expected, sp, "Expected serialized object for system principal"); + let dp = E10SUtils.deserializePrincipal(sp); + is( + dp, + Services.scriptSecurityManager.getSystemPrincipal(), + "Deserialized the system principal" + ); +}); diff --git a/browser/base/content/test/caps/browser_principalSerialization_version1.js b/browser/base/content/test/caps/browser_principalSerialization_version1.js new file mode 100644 index 0000000000..6c4a41e911 --- /dev/null +++ b/browser/base/content/test/caps/browser_principalSerialization_version1.js @@ -0,0 +1,159 @@ +"use strict"; + +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + This test file exists to ensure whenever changes to principal serialization happens, + we guarantee that the data can be restored and generated into a new principal. + + The tests are written to be brittle so we encode all versions of the changes into the tests. +*/ + +add_task(function test_nullPrincipal() { + /* + As Null principals are designed to be non deterministic we just need to ensure that + a previous serialized version matches what it was generated as. + + This test should be resilient to changes in versioning, however it should also be duplicated for a new serialization change. + */ + // Principal created with: E10SUtils.serializePrincipal(Services.scriptSecurityManager.createNullPrincipal({ })); + let p = E10SUtils.deserializePrincipal( + "vQZuXxRvRHKDMXv9BbHtkAAAAAAAAAAAwAAAAAAAAEYAAAA4bW96LW51bGxwcmluY2lwYWw6ezU2Y2FjNTQwLTg2NGQtNDdlNy04ZTI1LTE2MTRlYWI1MTU1ZX0AAAAA" + ); + is( + "moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}", + p.URI.spec, + "Deserialized principal doesn't have the correct URI" + ); + + // Principal created with: E10SUtils.serializePrincipal(Services.scriptSecurityManager.createNullPrincipal({ userContextId: 2 })); + let p2 = E10SUtils.deserializePrincipal( + "vQZuXxRvRHKDMXv9BbHtkAAAAAAAAAAAwAAAAAAAAEYAAAA4bW96LW51bGxwcmluY2lwYWw6ezA1ZjllN2JhLWIwODMtNDJhMi1iNDdkLTZiODRmNmYwYTM3OX0AAAAQXnVzZXJDb250ZXh0SWQ9Mg==" + ); + is( + "moz-nullprincipal:{05f9e7ba-b083-42a2-b47d-6b84f6f0a379}", + p2.URI.spec, + "Deserialized principal doesn't have the correct URI" + ); + is(p2.originAttributes.userContextId, 2, "Expected a userContextId of 2"); +}); + +add_task(async function test_realHistoryCheck() { + /* + This test should be resilient to changes in principal serialization, if these are failing then it's likely the code will break session storage. + To recreate this for another version, copy the function into the browser console, browse some pages and printHistory. + + Generated with: + function printHistory() { + let tests = []; + let entries = SessionStore.getSessionHistory(gBrowser.selectedTab).entries.map((entry) => { return entry.triggeringPrincipal_base64 }); + entries.push(E10SUtils.serializePrincipal(gBrowser.selectedTab.linkedBrowser._contentPrincipal)); + for (let entry of entries) { + console.log(entry); + let testData = {}; + testData.input = entry; + let principal = E10SUtils.deserializePrincipal(testData.input); + testData.output = {}; + if (principal.URI === null) { + testData.output.URI = false; + } else { + testData.output.URISpec = principal.URI.spec; + } + testData.output.originAttributes = principal.originAttributes; + + tests.push(testData); + } + return tests; + } + printHistory(); // Copy this into: serializedPrincipalsFromFirefox + */ + + let serializedPrincipalsFromFirefox = [ + { + input: "SmIS26zLEdO3ZQBgsLbOywAAAAAAAAAAwAAAAAAAAEY=", + output: { + URI: false, + originAttributes: { + firstPartyDomain: "", + inIsolatedMozBrowser: false, + privateBrowsingId: 0, + userContextId: 0, + geckoViewSessionContextId: "", + partitionKey: "", + }, + }, + }, + { + input: + "ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAe2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTLz91dG1fc291cmNlPXd3dy5tb3ppbGxhLm9yZyZ1dG1fbWVkaXVtPXJlZmVycmFsJnV0bV9jYW1wYWlnbj1uYXYmdXRtX2NvbnRlbnQ9ZGV2ZWxvcGVycwAAAAAAAAAFAAAACAAAABUAAAAA/////wAAAAD/////AAAACAAAABUAAAAdAAAAXgAAAB0AAAAHAAAAHQAAAAcAAAAkAAAAAAAAAAD/////AAAAAP////8AAAAlAAAAVgAAAAD/////AQAAAAAAAAAAAAAAAA==", + output: { + URISpec: + "https://developer.mozilla.org/en-US/?utm_source=www.mozilla.org&utm_medium=referral&utm_campaign=nav&utm_content=developers", + originAttributes: { + firstPartyDomain: "", + inIsolatedMozBrowser: false, + privateBrowsingId: 0, + userContextId: 0, + geckoViewSessionContextId: "", + partitionKey: "", + }, + }, + }, + { + input: "SmIS26zLEdO3ZQBgsLbOywAAAAAAAAAAwAAAAAAAAEY=", + output: { + URI: false, + originAttributes: { + firstPartyDomain: "", + inIsolatedMozBrowser: false, + privateBrowsingId: 0, + userContextId: 0, + geckoViewSessionContextId: "", + partitionKey: "", + }, + }, + }, + { + input: + "vQZuXxRvRHKDMXv9BbHtkAAAAAAAAAAAwAAAAAAAAEYAAAA4bW96LW51bGxwcmluY2lwYWw6ezA0NWNhMThkLTQzNmMtNDc0NC1iYmI2LWIxYTE1MzY2ZGY3OX0AAAAA", + output: { + URISpec: "moz-nullprincipal:{045ca18d-436c-4744-bbb6-b1a15366df79}", + originAttributes: { + firstPartyDomain: "", + inIsolatedMozBrowser: false, + privateBrowsingId: 0, + userContextId: 0, + geckoViewSessionContextId: "", + partitionKey: "", + }, + }, + }, + ]; + + for (let test of serializedPrincipalsFromFirefox) { + let principal = E10SUtils.deserializePrincipal(test.input); + + for (let key in principal.originAttributes) { + is( + principal.originAttributes[key], + test.output.originAttributes[key], + `Ensure value of ${key} is ${test.output.originAttributes[key]}` + ); + } + + if ("URI" in test.output && test.output.URI === false) { + is( + principal.isContentPrincipal, + false, + "Should have not have a URI for system" + ); + } else { + is( + principal.spec, + test.output.URISpec, + `Should have spec ${test.output.URISpec}` + ); + } + } +}); diff --git a/browser/base/content/test/captivePortal/browser.ini b/browser/base/content/test/captivePortal/browser.ini new file mode 100644 index 0000000000..37b72ab758 --- /dev/null +++ b/browser/base/content/test/captivePortal/browser.ini @@ -0,0 +1,12 @@ +[DEFAULT] +support-files = + head.js + +[browser_CaptivePortalWatcher.js] +skip-if = os == "win" # Bug 1313894 +[browser_CaptivePortalWatcher_1.js] +skip-if = os == "win" # Bug 1313894 +[browser_captivePortalTabReference.js] +[browser_captivePortal_certErrorUI.js] +[browser_captivePortal_https_only.js] +[browser_closeCapPortalTabCanonicalURL.js] diff --git a/browser/base/content/test/captivePortal/browser_CaptivePortalWatcher.js b/browser/base/content/test/captivePortal/browser_CaptivePortalWatcher.js new file mode 100644 index 0000000000..aeafae21d8 --- /dev/null +++ b/browser/base/content/test/captivePortal/browser_CaptivePortalWatcher.js @@ -0,0 +1,125 @@ +/* eslint-disable mozilla/no-arbitrary-setTimeout */ +"use strict"; + +// Bug 1318389 - This test does a lot of window and tab manipulation, +// causing it to take a long time on debug. +requestLongerTimeout(2); + +add_task(setupPrefsAndRecentWindowBehavior); + +// Each of the test cases below is run twice: once for login-success and once +// for login-abort (aSuccess set to true and false respectively). +let testCasesForBothSuccessAndAbort = [ + /** + * A portal is detected when there's no browser window, then a browser + * window is opened, then the portal is freed. + * The portal tab should be added and focused when the window is + * opened, and closed automatically when the success event is fired. + * The captive portal notification should be shown when the window is + * opened, and closed automatically when the success event is fired. + */ + async function test_detectedWithNoBrowserWindow_Open(aSuccess) { + await portalDetected(); + let win = await focusWindowAndWaitForPortalUI(); + await freePortal(aSuccess); + ensureNoPortalTab(win); + ensureNoPortalNotification(win); + await closeWindowAndWaitForWindowActivate(win); + }, + + /** + * A portal is detected when multiple browser windows are open but none + * have focus. A browser window is focused, then the portal is freed. + * The portal tab should be added and focused when the window is + * focused, and closed automatically when the success event is fired. + * The captive portal notification should be shown in all windows upon + * detection, and closed automatically when the success event is fired. + */ + async function test_detectedWithNoBrowserWindow_Focused(aSuccess) { + let win1 = await openWindowAndWaitForFocus(); + let win2 = await openWindowAndWaitForFocus(); + // Defocus both windows. + await SimpleTest.promiseFocus(window); + + await portalDetected(); + + // Notification should be shown in both windows. + ensurePortalNotification(win1); + ensureNoPortalTab(win1); + ensurePortalNotification(win2); + ensureNoPortalTab(win2); + + await focusWindowAndWaitForPortalUI(false, win2); + + await freePortal(aSuccess); + + ensureNoPortalNotification(win1); + ensureNoPortalTab(win2); + ensureNoPortalNotification(win2); + + await closeWindowAndWaitForWindowActivate(win2); + // No need to wait for xul-window-visible: after win2 is closed, focus + // is restored to the default window and win1 remains in the background. + await BrowserTestUtils.closeWindow(win1); + }, + + /** + * A portal is detected when there's no browser window, then a browser + * window is opened, then the portal is freed. + * The recheck triggered when the browser window is opened takes a + * long time. No portal tab should be added. + * The captive portal notification should be shown when the window is + * opened, and closed automatically when the success event is fired. + */ + async function test_detectedWithNoBrowserWindow_LongRecheck(aSuccess) { + await portalDetected(); + let win = await focusWindowAndWaitForPortalUI(true); + await freePortal(aSuccess); + ensureNoPortalTab(win); + ensureNoPortalNotification(win); + await closeWindowAndWaitForWindowActivate(win); + }, + + /** + * A portal is detected when there's no browser window, and the + * portal is freed before a browser window is opened. No portal + * UI should be shown when a browser window is opened. + */ + async function test_detectedWithNoBrowserWindow_GoneBeforeOpen(aSuccess) { + await portalDetected(); + await freePortal(aSuccess); + let win = await openWindowAndWaitForFocus(); + // Wait for a while to make sure no UI is shown. + await new Promise(resolve => { + setTimeout(resolve, 1000); + }); + ensureNoPortalTab(win); + ensureNoPortalNotification(win); + await closeWindowAndWaitForWindowActivate(win); + }, + + /** + * A portal is detected when a browser window has focus. No portal tab should + * be opened. A notification bar should be displayed in all browser windows. + */ + async function test_detectedWithFocus(aSuccess) { + let win1 = await openWindowAndWaitForFocus(); + let win2 = await openWindowAndWaitForFocus(); + await portalDetected(); + ensureNoPortalTab(win1); + ensureNoPortalTab(win2); + ensurePortalNotification(win1); + ensurePortalNotification(win2); + await freePortal(aSuccess); + ensureNoPortalNotification(win1); + ensureNoPortalNotification(win2); + await BrowserTestUtils.closeWindow(win2); + await BrowserTestUtils.closeWindow(win1); + await waitForBrowserWindowActive(window); + }, +]; + +for (let testcase of testCasesForBothSuccessAndAbort) { + add_task(testcase.bind(null, true)); + add_task(testcase.bind(null, false)); +} diff --git a/browser/base/content/test/captivePortal/browser_CaptivePortalWatcher_1.js b/browser/base/content/test/captivePortal/browser_CaptivePortalWatcher_1.js new file mode 100644 index 0000000000..6c6cc5f438 --- /dev/null +++ b/browser/base/content/test/captivePortal/browser_CaptivePortalWatcher_1.js @@ -0,0 +1,108 @@ +"use strict"; + +add_task(setupPrefsAndRecentWindowBehavior); + +let testcases = [ + /** + * A portal is detected when there's no browser window, + * then a browser window is opened, and the portal is logged into + * and redirects to a different page. The portal tab should be added + * and focused when the window is opened, and left open after login + * since it redirected. + */ + async function test_detectedWithNoBrowserWindow_Redirect() { + await portalDetected(); + let win = await focusWindowAndWaitForPortalUI(); + let browser = win.gBrowser.selectedTab.linkedBrowser; + let loadPromise = BrowserTestUtils.browserLoaded( + browser, + false, + CANONICAL_URL_REDIRECTED + ); + BrowserTestUtils.loadURIString(browser, CANONICAL_URL_REDIRECTED); + await loadPromise; + await freePortal(true); + ensurePortalTab(win); + ensureNoPortalNotification(win); + await closeWindowAndWaitForWindowActivate(win); + }, + + /** + * Test the various expected behaviors of the "Show Login Page" button + * in the captive portal notification. The button should be visible for + * all tabs except the captive portal tab, and when clicked, should + * ensure a captive portal tab is open and select it. + */ + async function test_showLoginPageButton() { + let win = await openWindowAndWaitForFocus(); + await portalDetected(); + let notification = ensurePortalNotification(win); + testShowLoginPageButtonVisibility(notification, "visible"); + + function testPortalTabSelectedAndButtonNotVisible() { + is( + win.gBrowser.selectedTab, + tab, + "The captive portal tab should be selected." + ); + testShowLoginPageButtonVisibility(notification, "hidden"); + } + + let button = notification.buttonContainer.querySelector( + "button.notification-button" + ); + async function clickButtonAndExpectNewPortalTab() { + let p = BrowserTestUtils.waitForNewTab(win.gBrowser, CANONICAL_URL); + button.click(); + let tab = await p; + is( + win.gBrowser.selectedTab, + tab, + "The captive portal tab should be selected." + ); + return tab; + } + + // Simulate clicking the button. The portal tab should be opened and + // selected and the button should hide. + let tab = await clickButtonAndExpectNewPortalTab(); + testPortalTabSelectedAndButtonNotVisible(); + + // Close the tab. The button should become visible. + BrowserTestUtils.removeTab(tab); + ensureNoPortalTab(win); + testShowLoginPageButtonVisibility(notification, "visible"); + + // When the button is clicked, a new portal tab should be opened and + // selected. + tab = await clickButtonAndExpectNewPortalTab(); + + // Open another arbitrary tab. The button should become visible. When it's clicked, + // the portal tab should be selected. + let anotherTab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser); + testShowLoginPageButtonVisibility(notification, "visible"); + button.click(); + is( + win.gBrowser.selectedTab, + tab, + "The captive portal tab should be selected." + ); + + // Close the portal tab and select the arbitrary tab. The button should become + // visible and when it's clicked, a new portal tab should be opened. + BrowserTestUtils.removeTab(tab); + win.gBrowser.selectedTab = anotherTab; + testShowLoginPageButtonVisibility(notification, "visible"); + tab = await clickButtonAndExpectNewPortalTab(); + + BrowserTestUtils.removeTab(anotherTab); + await freePortal(true); + ensureNoPortalTab(win); + ensureNoPortalNotification(win); + await closeWindowAndWaitForWindowActivate(win); + }, +]; + +for (let testcase of testcases) { + add_task(testcase); +} diff --git a/browser/base/content/test/captivePortal/browser_captivePortalTabReference.js b/browser/base/content/test/captivePortal/browser_captivePortalTabReference.js new file mode 100644 index 0000000000..b630f35149 --- /dev/null +++ b/browser/base/content/test/captivePortal/browser_captivePortalTabReference.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const CPS = Cc["@mozilla.org/network/captive-portal-service;1"].getService( + Ci.nsICaptivePortalService +); + +async function checkCaptivePortalTabReference(evt, currState) { + await portalDetected(); + let errorTab = await openCaptivePortalErrorTab(); + let portalTab = await openCaptivePortalLoginTab(errorTab); + + // Release the reference held to the portal tab by sending success/abort events. + Services.obs.notifyObservers(null, evt); + await TestUtils.waitForCondition( + () => CPS.state == currState, + "Captive portal has been released" + ); + gBrowser.removeTab(errorTab); + + await portalDetected(); + ok(CPS.state == CPS.LOCKED_PORTAL, "Captive portal is locked again"); + errorTab = await openCaptivePortalErrorTab(); + let portalTab2 = await openCaptivePortalLoginTab(errorTab); + ok( + portalTab != portalTab2, + "waitForNewTab in openCaptivePortalLoginTab should not have completed at this point if references were held to the old captive portal tab after login/abort." + ); + gBrowser.removeTab(portalTab); + gBrowser.removeTab(portalTab2); + + let errorTabReloaded = BrowserTestUtils.waitForErrorPage( + errorTab.linkedBrowser + ); + Services.obs.notifyObservers(null, "captive-portal-login-success"); + await errorTabReloaded; + + gBrowser.removeTab(errorTab); +} + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["captivedetect.canonicalURL", CANONICAL_URL], + ["captivedetect.canonicalContent", CANONICAL_CONTENT], + ], + }); +}); + +let capPortalStates = [ + { + evt: "captive-portal-login-success", + state: CPS.UNLOCKED_PORTAL, + }, + { + evt: "captive-portal-login-abort", + state: CPS.UNKNOWN, + }, +]; + +for (let elem of capPortalStates) { + add_task(checkCaptivePortalTabReference.bind(null, elem.evt, elem.state)); +} diff --git a/browser/base/content/test/captivePortal/browser_captivePortal_certErrorUI.js b/browser/base/content/test/captivePortal/browser_captivePortal_certErrorUI.js new file mode 100644 index 0000000000..d23125a627 --- /dev/null +++ b/browser/base/content/test/captivePortal/browser_captivePortal_certErrorUI.js @@ -0,0 +1,221 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["captivedetect.canonicalURL", CANONICAL_URL], + ["captivedetect.canonicalContent", CANONICAL_CONTENT], + ], + }); +}); + +// This tests the alternate cert error UI when we are behind a captive portal. +add_task(async function checkCaptivePortalCertErrorUI() { + info( + "Checking that the alternate cert error UI is shown when we are behind a captive portal" + ); + + // Open a second window in the background. Later, we'll check that + // when we click the button to open the captive portal tab, the tab + // only opens in the active window and not in the background one. + let secondWindow = await openWindowAndWaitForFocus(); + await SimpleTest.promiseFocus(window); + + await portalDetected(); + + // Check that we didn't open anything in the background window. + ensureNoPortalTab(secondWindow); + + let tab = await openCaptivePortalErrorTab(); + let browser = tab.linkedBrowser; + let portalTabPromise = BrowserTestUtils.waitForNewTab( + gBrowser, + CANONICAL_URL + ); + + await SpecialPowers.spawn(browser, [], async () => { + let doc = content.document; + let loginButton = doc.getElementById("openPortalLoginPageButton"); + await ContentTaskUtils.waitForCondition( + () => ContentTaskUtils.is_visible(loginButton), + "Captive portal error page UI is visible" + ); + + if (!Services.focus.focusedElement == loginButton) { + await ContentTaskUtils.waitForEvent(loginButton, "focus"); + } + + Assert.ok(true, "openPortalLoginPageButton has focus"); + info("Clicking the Open Login Page button"); + await EventUtils.synthesizeMouseAtCenter(loginButton, {}, content); + }); + + let portalTab = await portalTabPromise; + is( + gBrowser.selectedTab, + portalTab, + "Login page should be open in a new foreground tab." + ); + + // Check that we didn't open anything in the background window. + ensureNoPortalTab(secondWindow); + + // Make sure clicking the "Open Login Page" button again focuses the existing portal tab. + await BrowserTestUtils.switchTab(gBrowser, tab); + // Passing an empty function to BrowserTestUtils.switchTab lets us wait for an arbitrary + // tab switch. + portalTabPromise = BrowserTestUtils.switchTab(gBrowser, () => {}); + await SpecialPowers.spawn(browser, [], async () => { + info("Clicking the Open Login Page button."); + let loginButton = content.document.getElementById( + "openPortalLoginPageButton" + ); + await EventUtils.synthesizeMouseAtCenter(loginButton, {}, content); + }); + + info("Opening captive portal login page"); + let portalTab2 = await portalTabPromise; + is(portalTab2, portalTab, "The existing portal tab should be focused."); + + // Check that we didn't open anything in the background window. + ensureNoPortalTab(secondWindow); + + let portalTabClosing = BrowserTestUtils.waitForTabClosing(portalTab); + let errorTabReloaded = BrowserTestUtils.waitForErrorPage(browser); + + Services.obs.notifyObservers(null, "captive-portal-login-success"); + await portalTabClosing; + + info( + "Waiting for error tab to be reloaded after the captive portal was freed." + ); + await errorTabReloaded; + await SpecialPowers.spawn(browser, [], () => { + let doc = content.document; + ok( + !doc.body.classList.contains("captiveportal"), + "Captive portal error page UI is not visible." + ); + }); + + await BrowserTestUtils.removeTab(tab); + await BrowserTestUtils.closeWindow(secondWindow); +}); + +add_task(async function testCaptivePortalAdvancedPanel() { + info( + "Checking that the advanced section of the about:certerror UI is shown when we are behind a captive portal." + ); + await portalDetected(); + let tab = await openCaptivePortalErrorTab(); + let browser = tab.linkedBrowser; + + const waitForLocationChange = (async () => { + await BrowserTestUtils.waitForLocationChange(gBrowser, BAD_CERT_PAGE); + info("(waitForLocationChange resolved)"); + })(); + await SpecialPowers.spawn(browser, [BAD_CERT_PAGE], async expectedURL => { + const doc = content.document; + let advancedButton = doc.getElementById("advancedButton"); + await ContentTaskUtils.waitForCondition( + () => ContentTaskUtils.is_visible(advancedButton), + "Captive portal UI is visible" + ); + + info("Clicking on the advanced button"); + const advPanel = doc.getElementById("badCertAdvancedPanel"); + ok( + !ContentTaskUtils.is_visible(advPanel), + "Advanced panel is not yet visible" + ); + await EventUtils.synthesizeMouseAtCenter(advancedButton, {}, content); + ok(ContentTaskUtils.is_visible(advPanel), "Advanced panel is now visible"); + + let advPanelContent = doc.getElementById("badCertTechnicalInfo"); + ok( + ContentTaskUtils.is_visible(advPanelContent) && + advPanelContent.textContent.includes("expired.example.com"), + "Advanced panel text content is visible" + ); + + let advPanelErrorCode = doc.getElementById("errorCode"); + ok( + advPanelErrorCode.textContent, + "Cert error code is visible in the advanced panel" + ); + + // - + + const advPanelExceptionButton = doc.getElementById("exceptionDialogButton"); + + function isOnCertErrorPage() { + return ContentTaskUtils.is_visible(advPanel); + } + + ok(isOnCertErrorPage(), "On cert error page before adding exception"); + ok( + advPanelExceptionButton.disabled, + "Exception button should start disabled" + ); + await EventUtils.synthesizeMouseAtCenter( + advPanelExceptionButton, + {}, + content + ); // Click + const clickTime = content.performance.now(); + ok( + isOnCertErrorPage(), + "Still on cert error page because clicked too early" + ); + + // Now waitForCondition now that it's possible. + try { + await ContentTaskUtils.waitForCondition( + () => !advPanelExceptionButton.disabled, + "Wait for exception button enabled" + ); + } catch (rejected) { + ok(false, rejected); + return; + } + ok( + !advPanelExceptionButton.disabled, + "Exception button should be enabled after waiting" + ); + const msSinceClick = content.performance.now() - clickTime; + const expr = `${msSinceClick} > 1000`; + /* eslint-disable no-eval */ + ok(eval(expr), `Exception button should stay disabled for ${expr} ms`); + + await EventUtils.synthesizeMouseAtCenter( + advPanelExceptionButton, + {}, + content + ); // Click + info("Clicked"); + }); + await waitForLocationChange; + info("Page reloaded after adding cert exception"); + + // Clear the certificate exception. + let certOverrideService = Cc[ + "@mozilla.org/security/certoverride;1" + ].getService(Ci.nsICertOverrideService); + certOverrideService.clearValidityOverride("expired.example.com", -1, {}); + + info("After clearing cert override, asking for reload..."); + const waitForErrorPage = BrowserTestUtils.waitForErrorPage(browser); + await SpecialPowers.spawn(browser, [], async () => { + info("reload..."); + content.location.reload(); + }); + info("waitForErrorPage..."); + await waitForErrorPage; + + info("removeTab..."); + await BrowserTestUtils.removeTab(tab); + info("Done!"); +}); diff --git a/browser/base/content/test/captivePortal/browser_captivePortal_https_only.js b/browser/base/content/test/captivePortal/browser_captivePortal_https_only.js new file mode 100644 index 0000000000..789d392107 --- /dev/null +++ b/browser/base/content/test/captivePortal/browser_captivePortal_https_only.js @@ -0,0 +1,73 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; +const { PermissionTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PermissionTestUtils.sys.mjs" +); +const testPath = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com" +); +const CANONICAL_URI = Services.io.newURI(testPath); +const PERMISSION_NAME = "https-only-load-insecure"; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + // That changes the canoncicalURL from "http://{server}/captive-detect/success.txt" + // to http://example.com + set: [ + ["captivedetect.canonicalURL", testPath], + ["dom.security.https_only_mode", true], + ], + }); +}); + +// This test checks if https-only exempts the canoncial uri. +add_task(async function checkCaptivePortalExempt() { + await portalDetected(); + info("Checking that the canonical uri is exempt by https-only mode"); + let tab = await openCaptivePortalErrorTab(); + let browser = tab.linkedBrowser; + let portalTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, testPath); + + await SpecialPowers.spawn(browser, [], async () => { + let doc = content.document; + let loginButton = doc.getElementById("openPortalLoginPageButton"); + await ContentTaskUtils.waitForCondition( + () => ContentTaskUtils.is_visible(loginButton), + "Captive portal error page UI is visible" + ); + + if (!Services.focus.focusedElement == loginButton) { + await ContentTaskUtils.waitForEvent(loginButton, "focus"); + } + + Assert.ok(true, "openPortalLoginPageButton has focus"); + info("Clicking the Open Login Page button"); + await EventUtils.synthesizeMouseAtCenter(loginButton, {}, content); + }); + is( + PermissionTestUtils.testPermission(CANONICAL_URI, PERMISSION_NAME), + Services.perms.ALLOW_ACTION, + "Check permission in perm. manager if canoncial uri is set as exempt." + ); + let portalTab = await portalTabPromise; + is( + gBrowser.selectedTab, + portalTab, + "Login page should be open in a new foreground tab." + ); + is( + gBrowser.currentURI.spec, + testPath, + "Opened the right URL without upgrading it." + ); + // Close all tabs + await BrowserTestUtils.removeTab(portalTab); + let tabReloaded = BrowserTestUtils.waitForErrorPage(tab.linkedBrowser); + Services.obs.notifyObservers(null, "captive-portal-login-success"); + await tabReloaded; + await BrowserTestUtils.removeTab(tab); +}); diff --git a/browser/base/content/test/captivePortal/browser_closeCapPortalTabCanonicalURL.js b/browser/base/content/test/captivePortal/browser_closeCapPortalTabCanonicalURL.js new file mode 100644 index 0000000000..0457dab1c0 --- /dev/null +++ b/browser/base/content/test/captivePortal/browser_closeCapPortalTabCanonicalURL.js @@ -0,0 +1,152 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js"); +const LOGIN_LINK = `login`; +const LOGIN_URL = "http://localhost:8080/login"; +const CANONICAL_SUCCESS_URL = "http://localhost:8080/success"; +const CPS = Cc["@mozilla.org/network/captive-portal-service;1"].getService( + Ci.nsICaptivePortalService +); + +let server; +let loginPageShown = false; + +function redirectHandler(request, response) { + if (loginPageShown) { + return; + } + response.setStatusLine(request.httpVersion, 302, "captive"); + response.setHeader("Content-Type", "text/html"); + response.setHeader("Location", LOGIN_URL); +} + +function loginHandler(request, response) { + response.setHeader("Content-Type", "text/html"); + response.bodyOutputStream.write(LOGIN_LINK, LOGIN_LINK.length); + loginPageShown = true; +} + +function unlockHandler(request, response) { + response.setStatusLine(request.httpVersion, 302, "login complete"); + response.setHeader("Content-Type", "text/html"); + response.setHeader("Location", CANONICAL_SUCCESS_URL); +} + +add_setup(async function () { + // Set up a mock server for handling captive portal redirect. + server = new HttpServer(); + server.registerPathHandler("/success", redirectHandler); + server.registerPathHandler("/login", loginHandler); + server.registerPathHandler("/unlock", unlockHandler); + server.start(8080); + info("Mock server is now set up for captive portal redirect"); + + await SpecialPowers.pushPrefEnv({ + set: [ + ["captivedetect.canonicalURL", CANONICAL_SUCCESS_URL], + ["captivedetect.canonicalContent", CANONICAL_CONTENT], + ], + }); +}); + +// This test checks if the captive portal tab is removed after the +// sucess/abort events are fired, assuming the tab has already redirected +// to the canonical URL before they are fired. +add_task(async function checkCaptivePortalTabCloseOnCanonicalURL_one() { + await portalDetected(); + let errorTab = await openCaptivePortalErrorTab(); + let tab = await openCaptivePortalLoginTab(errorTab, LOGIN_URL); + let browser = tab.linkedBrowser; + + let redirectedToCanonicalURL = BrowserTestUtils.browserLoaded( + browser, + false, + CANONICAL_SUCCESS_URL + ); + let errorPageReloaded = BrowserTestUtils.waitForErrorPage( + errorTab.linkedBrowser + ); + + await SpecialPowers.spawn(browser, [], async () => { + let doc = content.document; + let loginButton = doc.querySelector("a"); + await ContentTaskUtils.waitForCondition( + () => loginButton, + "Login button on the captive portal tab is visible" + ); + info("Clicking the login button on the captive portal tab page"); + await EventUtils.synthesizeMouseAtCenter(loginButton, {}, content); + }); + + await redirectedToCanonicalURL; + info( + "Re-direct to canonical URL in the captive portal tab was succcessful after login" + ); + + let tabClosed = BrowserTestUtils.waitForTabClosing(tab); + Services.obs.notifyObservers(null, "captive-portal-login-success"); + await tabClosed; + info( + "Captive portal tab was closed on re-direct to canonical URL after login as expected" + ); + + await errorPageReloaded; + info("Captive portal error page was reloaded"); + gBrowser.removeTab(errorTab); +}); + +// This test checks if the captive portal tab is removed on location change +// i.e. when it is re-directed to the canonical URL long after success/abort +// event handlers are executed. +add_task(async function checkCaptivePortalTabCloseOnCanonicalURL_two() { + loginPageShown = false; + await portalDetected(); + let errorTab = await openCaptivePortalErrorTab(); + let tab = await openCaptivePortalLoginTab(errorTab, LOGIN_URL); + let browser = tab.linkedBrowser; + + let redirectedToCanonicalURL = BrowserTestUtils.waitForLocationChange( + gBrowser, + CANONICAL_SUCCESS_URL + ); + let errorPageReloaded = BrowserTestUtils.waitForErrorPage( + errorTab.linkedBrowser + ); + + Services.obs.notifyObservers(null, "captive-portal-login-success"); + await TestUtils.waitForCondition( + () => CPS.state == CPS.UNLOCKED_PORTAL, + "Captive portal is released" + ); + + let tabClosed = BrowserTestUtils.waitForTabClosing(tab); + await SpecialPowers.spawn(browser, [], async () => { + let doc = content.document; + let loginButton = doc.querySelector("a"); + await ContentTaskUtils.waitForCondition( + () => loginButton, + "Login button on the captive portal tab is visible" + ); + info("Clicking the login button on the captive portal tab page"); + await EventUtils.synthesizeMouseAtCenter(loginButton, {}, content); + }); + + await redirectedToCanonicalURL; + info( + "Re-direct to canonical URL in the captive portal tab was succcessful after login" + ); + await tabClosed; + info( + "Captive portal tab was closed on re-direct to canonical URL after login as expected" + ); + + await errorPageReloaded; + info("Captive portal error page was reloaded"); + gBrowser.removeTab(errorTab); + + // Stop the server. + await new Promise(r => server.stop(r)); +}); diff --git a/browser/base/content/test/captivePortal/head.js b/browser/base/content/test/captivePortal/head.js new file mode 100644 index 0000000000..4e47c3012a --- /dev/null +++ b/browser/base/content/test/captivePortal/head.js @@ -0,0 +1,260 @@ +XPCOMUtils.defineLazyServiceGetter( + this, + "cps", + "@mozilla.org/network/captive-portal-service;1", + "nsICaptivePortalService" +); + +const CANONICAL_CONTENT = "success"; +const CANONICAL_URL = "data:text/plain;charset=utf-8," + CANONICAL_CONTENT; +const CANONICAL_URL_REDIRECTED = "data:text/plain;charset=utf-8,redirected"; +const PORTAL_NOTIFICATION_VALUE = "captive-portal-detected"; +const BAD_CERT_PAGE = "https://expired.example.com/"; + +async function setupPrefsAndRecentWindowBehavior() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["captivedetect.canonicalURL", CANONICAL_URL], + ["captivedetect.canonicalContent", CANONICAL_CONTENT], + ], + }); + // We need to test behavior when a portal is detected when there is no browser + // window, but we can't close the default window opened by the test harness. + // Instead, we deactivate CaptivePortalWatcher in the default window and + // exclude it using an attribute to mask its presence. + window.CaptivePortalWatcher.uninit(); + window.document.documentElement.setAttribute("ignorecaptiveportal", "true"); + + registerCleanupFunction(function cleanUp() { + window.CaptivePortalWatcher.init(); + window.document.documentElement.removeAttribute("ignorecaptiveportal"); + }); +} + +async function portalDetected() { + Services.obs.notifyObservers(null, "captive-portal-login"); + await TestUtils.waitForCondition(() => { + return cps.state == cps.LOCKED_PORTAL; + }, "Waiting for Captive Portal Service to update state after portal detected."); +} + +async function freePortal(aSuccess) { + Services.obs.notifyObservers( + null, + "captive-portal-login-" + (aSuccess ? "success" : "abort") + ); + await TestUtils.waitForCondition(() => { + return cps.state != cps.LOCKED_PORTAL; + }, "Waiting for Captive Portal Service to update state after portal freed."); +} + +// If a window is provided, it will be focused. Otherwise, a new window +// will be opened and focused. +async function focusWindowAndWaitForPortalUI(aLongRecheck, win) { + // CaptivePortalWatcher triggers a recheck when a window gains focus. If + // the time taken for the check to complete is under PORTAL_RECHECK_DELAY_MS, + // a tab with the login page is opened and selected. If it took longer, + // no tab is opened. It's not reliable to time things in an async test, + // so use a delay threshold of -1 to simulate a long recheck (so that any + // amount of time is considered excessive), and a very large threshold to + // simulate a short recheck. + Services.prefs.setIntPref( + "captivedetect.portalRecheckDelayMS", + aLongRecheck ? -1 : 1000000 + ); + + if (!win) { + win = await BrowserTestUtils.openNewBrowserWindow(); + } + let windowActivePromise = waitForBrowserWindowActive(win); + win.focus(); + await windowActivePromise; + + // After a new window is opened, CaptivePortalWatcher asks for a recheck, and + // waits for it to complete. We need to manually tell it a recheck completed. + await TestUtils.waitForCondition(() => { + return win.CaptivePortalWatcher._waitingForRecheck; + }, "Waiting for CaptivePortalWatcher to trigger a recheck."); + Services.obs.notifyObservers(null, "captive-portal-check-complete"); + + let notification = ensurePortalNotification(win); + + if (aLongRecheck) { + ensureNoPortalTab(win); + testShowLoginPageButtonVisibility(notification, "visible"); + return win; + } + + let tab = win.gBrowser.tabs[1]; + if (tab.linkedBrowser.currentURI.spec != CANONICAL_URL) { + // The tab should load the canonical URL, wait for it. + await BrowserTestUtils.waitForLocationChange(win.gBrowser, CANONICAL_URL); + } + is( + win.gBrowser.selectedTab, + tab, + "The captive portal tab should be open and selected in the new window." + ); + testShowLoginPageButtonVisibility(notification, "hidden"); + return win; +} + +function ensurePortalTab(win) { + // For the tests that call this function, it's enough to ensure there + // are two tabs in the window - the default tab and the portal tab. + is( + win.gBrowser.tabs.length, + 2, + "There should be a captive portal tab in the window." + ); +} + +function ensurePortalNotification(win) { + let notification = win.gNotificationBox.getNotificationWithValue( + PORTAL_NOTIFICATION_VALUE + ); + isnot( + notification, + null, + "There should be a captive portal notification in the window." + ); + return notification; +} + +// Helper to test whether the "Show Login Page" is visible in the captive portal +// notification (it should be hidden when the portal tab is selected). +function testShowLoginPageButtonVisibility(notification, visibility) { + let showLoginPageButton = notification.buttonContainer.querySelector( + "button.notification-button" + ); + // If the visibility property was never changed from default, it will be + // an empty string, so we pretend it's "visible" (effectively the same). + is( + showLoginPageButton.style.visibility || "visible", + visibility, + 'The "Show Login Page" button should be ' + visibility + "." + ); +} + +function ensureNoPortalTab(win) { + is( + win.gBrowser.tabs.length, + 1, + "There should be no captive portal tab in the window." + ); +} + +function ensureNoPortalNotification(win) { + is( + win.gNotificationBox.getNotificationWithValue(PORTAL_NOTIFICATION_VALUE), + null, + "There should be no captive portal notification in the window." + ); +} + +/** + * Some tests open a new window and close it later. When the window is closed, + * the original window opened by mochitest gains focus, generating an + * activate event. If the next test also opens a new window + * before this event has a chance to fire, CaptivePortalWatcher picks + * up the first one instead of the one from the new window. To avoid this + * unfortunate intermittent timing issue, we wait for the event from + * the original window every time we close a window that we opened. + */ +function waitForBrowserWindowActive(win) { + return new Promise(resolve => { + if (Services.focus.activeWindow == win) { + resolve(); + } else { + win.addEventListener( + "activate", + () => { + resolve(); + }, + { once: true } + ); + } + }); +} + +async function closeWindowAndWaitForWindowActivate(win) { + let activationPromises = []; + for (let w of BrowserWindowTracker.orderedWindows) { + if ( + w != win && + !win.document.documentElement.getAttribute("ignorecaptiveportal") + ) { + activationPromises.push(waitForBrowserWindowActive(win)); + } + } + await BrowserTestUtils.closeWindow(win); + await Promise.race(activationPromises); +} + +/** + * BrowserTestUtils.openNewBrowserWindow() does not guarantee the newly + * opened window has received focus when the promise resolves, so we + * have to manually wait every time. + */ +async function openWindowAndWaitForFocus() { + let win = await BrowserTestUtils.openNewBrowserWindow(); + await waitForBrowserWindowActive(win); + return win; +} + +async function openCaptivePortalErrorTab() { + // Open a page with a cert error. + let browser; + let certErrorLoaded; + let errorTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + () => { + let tab = BrowserTestUtils.addTab(gBrowser, BAD_CERT_PAGE); + gBrowser.selectedTab = tab; + browser = gBrowser.selectedBrowser; + certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser); + return tab; + }, + false + ); + await certErrorLoaded; + info("A cert error page was opened"); + await SpecialPowers.spawn(errorTab.linkedBrowser, [], async () => { + let doc = content.document; + let loginButton = doc.getElementById("openPortalLoginPageButton"); + await ContentTaskUtils.waitForCondition( + () => loginButton && doc.body.className == "captiveportal", + "Captive portal error page UI is visible" + ); + }); + info("Captive portal error page UI is visible"); + + return errorTab; +} + +async function openCaptivePortalLoginTab( + errorTab, + LOGIN_PAGE_URL = CANONICAL_URL +) { + let portalTabPromise = BrowserTestUtils.waitForNewTab( + gBrowser, + LOGIN_PAGE_URL, + true + ); + + await SpecialPowers.spawn(errorTab.linkedBrowser, [], async () => { + let doc = content.document; + let loginButton = doc.getElementById("openPortalLoginPageButton"); + info("Click on the login button on the captive portal error page"); + await EventUtils.synthesizeMouseAtCenter(loginButton, {}, content); + }); + + let portalTab = await portalTabPromise; + is( + gBrowser.selectedTab, + portalTab, + "Captive Portal login page is now open in a new foreground tab." + ); + + return portalTab; +} diff --git a/browser/base/content/test/chrome/chrome.ini b/browser/base/content/test/chrome/chrome.ini new file mode 100644 index 0000000000..9882f4b647 --- /dev/null +++ b/browser/base/content/test/chrome/chrome.ini @@ -0,0 +1,4 @@ +[DEFAULT] + +[test_aboutCrashed.xhtml] +[test_aboutRestartRequired.xhtml] diff --git a/browser/base/content/test/chrome/test_aboutCrashed.xhtml b/browser/base/content/test/chrome/test_aboutCrashed.xhtml new file mode 100644 index 0000000000..0e2ef64f9b --- /dev/null +++ b/browser/base/content/test/chrome/test_aboutCrashed.xhtml @@ -0,0 +1,77 @@ + + + + + + + + + + + diff --git a/browser/base/content/test/chrome/test_aboutRestartRequired.xhtml b/browser/base/content/test/chrome/test_aboutRestartRequired.xhtml new file mode 100644 index 0000000000..9745e8e935 --- /dev/null +++ b/browser/base/content/test/chrome/test_aboutRestartRequired.xhtml @@ -0,0 +1,76 @@ + + + + + + + + + + + diff --git a/browser/base/content/test/contentTheme/browser.ini b/browser/base/content/test/contentTheme/browser.ini new file mode 100644 index 0000000000..a7c859a1b3 --- /dev/null +++ b/browser/base/content/test/contentTheme/browser.ini @@ -0,0 +1,3 @@ +[DEFAULT] + +[browser_contentTheme_in_process_tab.js] diff --git a/browser/base/content/test/contentTheme/browser_contentTheme_in_process_tab.js b/browser/base/content/test/contentTheme/browser_contentTheme_in_process_tab.js new file mode 100644 index 0000000000..c53e178bc5 --- /dev/null +++ b/browser/base/content/test/contentTheme/browser_contentTheme_in_process_tab.js @@ -0,0 +1,80 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests that tabs running in the parent process can hear about updates + * to lightweight themes via contentTheme.js. + * + * The test loads the History Sidebar document in a tab to avoid having + * to create a special parent-process page for the LightweightTheme + * JSWindow actors. + */ +add_task(async function test_in_process_tab() { + let win = await BrowserTestUtils.openNewBrowserWindow(); + const IN_PROCESS_URI = "chrome://browser/content/places/historySidebar.xhtml"; + const SIDEBAR_BGCOLOR = "rgb(255, 0, 0)"; + // contentTheme.js will always convert the sidebar text color to rgba, so + // we need to compare against that. + const SIDEBAR_TEXT_COLOR = "rgba(0, 255, 0, 1)"; + + await BrowserTestUtils.withNewTab( + { + gBrowser: win.gBrowser, + url: IN_PROCESS_URI, + }, + async browser => { + await SpecialPowers.spawn( + browser, + [SIDEBAR_BGCOLOR, SIDEBAR_TEXT_COLOR], + async (bgColor, textColor) => { + let style = content.document.documentElement.style; + Assert.notEqual( + style.getPropertyValue("--lwt-sidebar-background-color"), + bgColor + ); + Assert.notEqual( + style.getPropertyValue("--lwt-sidebar-text-color"), + textColor + ); + } + ); + + // Now cobble together a very simple theme that sets the sidebar background + // and text color. + let lwtData = { + theme: { + sidebar: SIDEBAR_BGCOLOR, + sidebar_text: SIDEBAR_TEXT_COLOR, + }, + darkTheme: null, + window: win.docShell.outerWindowID, + }; + + Services.obs.notifyObservers(lwtData, "lightweight-theme-styling-update"); + + await SpecialPowers.spawn( + browser, + [SIDEBAR_BGCOLOR, SIDEBAR_TEXT_COLOR], + async (bgColor, textColor) => { + let style = content.document.documentElement.style; + Assert.equal( + style.getPropertyValue("--lwt-sidebar-background-color"), + bgColor, + "The sidebar background text color should have been set by " + + "contentTheme.js" + ); + Assert.equal( + style.getPropertyValue("--lwt-sidebar-text-color"), + textColor, + "The sidebar background text color should have been set by " + + "contentTheme.js" + ); + } + ); + } + ); + + await BrowserTestUtils.closeWindow(win); +}); diff --git a/browser/base/content/test/contextMenu/browser.ini b/browser/base/content/test/contextMenu/browser.ini new file mode 100644 index 0000000000..df0a013059 --- /dev/null +++ b/browser/base/content/test/contextMenu/browser.ini @@ -0,0 +1,91 @@ +[DEFAULT] +support-files = + subtst_contextmenu_webext.html + test_contextmenu_links.html + subtst_contextmenu.html + subtst_contextmenu_input.html + subtst_contextmenu_keyword.html + subtst_contextmenu_xul.xhtml + ctxmenu-image.png + ../general/head.js + ../general/video.ogg + ../general/audio.ogg + ../../../../../toolkit/components/pdfjs/test/file_pdfjs_test.pdf + contextmenu_common.js + file_bug1798178.html + bug1798178.sjs + +[browser_bug1798178.js] +[browser_contextmenu.js] +tags = fullscreen +skip-if = + os == "linux" + verify +[browser_contextmenu_badiframe.js] +https_first_disabled = true +skip-if = + os == "win" # Bug 1719856 + os == "linux" && socketprocess_networking +[browser_contextmenu_contenteditable.js] +[browser_contextmenu_iframe.js] +support-files = + test_contextmenu_iframe.html +skip-if = + os == "linux" && socketprocess_networking +[browser_contextmenu_input.js] +skip-if = + os == "linux" +[browser_contextmenu_inspect.js] +skip-if = + os == "linux" && socketprocess_networking +[browser_contextmenu_keyword.js] +skip-if = + os == "linux" # disabled on Linux due to bug 513558 +[browser_contextmenu_linkopen.js] +skip-if = + os == "linux" && socketprocess_networking +[browser_contextmenu_loadblobinnewtab.js] +support-files = browser_contextmenu_loadblobinnewtab.html +skip-if = + os == "linux" && socketprocess_networking +[browser_contextmenu_save_blocked.js] +skip-if = + os == "linux" && socketprocess_networking +[browser_contextmenu_share_macosx.js] +support-files = + browser_contextmenu_shareurl.html +run-if = + os == "mac" +[browser_contextmenu_share_win.js] +https_first_disabled = true +support-files = + browser_contextmenu_shareurl.html +run-if = + os == "win" +[browser_contextmenu_spellcheck.js] +https_first_disabled = true +skip-if = + os == "linux" + debug # bug 1798233 - this trips assertions that seem harmless in opt and unlikely to occur in practical use. +[browser_contextmenu_touch.js] +skip-if = true # Bug 1424433, disable due to very high frequency failure rate also on Windows 10 +[browser_copy_image_link.js] +support-files = + doggy.png + firebird.png + firebird.png^headers^ +skip-if = + os == "linux" && socketprocess_networking +[browser_strip_on_share_link.js] +[browser_utilityOverlay.js] +https_first_disabled = true +skip-if = + os == "linux" && socketprocess_networking +[browser_utilityOverlayPrincipal.js] +https_first_disabled = true +[browser_view_image.js] +support-files = + test_view_image_revoked_cached_blob.html + test_view_image_inline_svg.html +skip-if = + os == "linux" && socketprocess_networking diff --git a/browser/base/content/test/contextMenu/browser_bug1798178.js b/browser/base/content/test/contextMenu/browser_bug1798178.js new file mode 100644 index 0000000000..529665a6f9 --- /dev/null +++ b/browser/base/content/test/contextMenu/browser_bug1798178.js @@ -0,0 +1,89 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockTransfer.js", + this +); + +const TEST_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "file_bug1798178.html"; + +let MockFilePicker = SpecialPowers.MockFilePicker; +MockFilePicker.init(window); + +function createTemporarySaveDirectory() { + let saveDir = Services.dirsvc.get("TmpD", Ci.nsIFile); + saveDir.append("testsavedir"); + if (!saveDir.exists()) { + info("create testsavedir!"); + saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755); + } + info("return from createTempSaveDir: " + saveDir.path); + return saveDir; +} + +add_task(async function test_save_link_cross_origin() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.opaqueResponseBlocking", true]], + }); + await BrowserTestUtils.withNewTab(TEST_URL, async browser => { + let menu = document.getElementById("contentAreaContextMenu"); + let popupShown = BrowserTestUtils.waitForEvent(menu, "popupshown"); + BrowserTestUtils.synthesizeMouseAtCenter( + "a[href]", + { type: "contextmenu", button: 2 }, + browser + ); + await popupShown; + + let filePickerShow = new Promise(r => { + MockFilePicker.showCallback = function (fp) { + ok(true, "filepicker should be shown"); + info("MockFilePicker showCallback"); + + let fileName = fp.defaultString; + destFile = tempDir.clone(); + destFile.append(fileName); + + MockFilePicker.setFiles([destFile]); + MockFilePicker.filterIndex = 1; // kSaveAsType_URL + + info("MockFilePicker showCallback done"); + r(); + }; + }); + + info("Let's create a temporary dir"); + let tempDir = createTemporarySaveDirectory(); + let destFile; + + MockFilePicker.displayDirectory = tempDir; + + let transferCompletePromise = new Promise(resolve => { + function onTransferComplete(downloadSuccess) { + ok(downloadSuccess, "File should have been downloaded successfully"); + resolve(); + } + mockTransferCallback = onTransferComplete; + mockTransferRegisterer.register(); + }); + + let saveLinkCommand = document.getElementById("context-savelink"); + info("saveLinkCommand: " + saveLinkCommand); + saveLinkCommand.doCommand(); + + await filePickerShow; + + let popupHiddenPromise = BrowserTestUtils.waitForEvent(menu, "popuphidden"); + menu.hidePopup(); + await popupHiddenPromise; + + await transferCompletePromise; + }); +}); diff --git a/browser/base/content/test/contextMenu/browser_contextmenu.js b/browser/base/content/test/contextMenu/browser_contextmenu.js new file mode 100644 index 0000000000..03a848f26d --- /dev/null +++ b/browser/base/content/test/contextMenu/browser_contextmenu.js @@ -0,0 +1,1943 @@ +"use strict"; + +let contextMenu; +let LOGIN_FILL_ITEMS = ["---", null, "manage-saved-logins", true]; +let NAVIGATION_ITEMS = + AppConstants.platform == "macosx" + ? [ + "context-back", + false, + "context-forward", + false, + "context-reload", + true, + "---", + null, + "context-bookmarkpage", + true, + ] + : [ + "context-navigation", + null, + [ + "context-back", + false, + "context-forward", + false, + "context-reload", + true, + "context-bookmarkpage", + true, + ], + null, + "---", + null, + ]; +let hasPocket = Services.prefs.getBoolPref("extensions.pocket.enabled"); +let hasContainers = + Services.prefs.getBoolPref("privacy.userContext.enabled") && + ContextualIdentityService.getPublicIdentities().length; + +const example_base = + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com/browser/browser/base/content/test/contextMenu/"; +const chrome_base = + "chrome://mochitests/content/browser/browser/base/content/test/contextMenu/"; +const head_base = + "chrome://mochitests/content/browser/browser/base/content/test/contextMenu/"; + +/* import-globals-from contextmenu_common.js */ +Services.scriptloader.loadSubScript( + chrome_base + "contextmenu_common.js", + this +); + +function getThisFrameSubMenu(base_menu) { + if (AppConstants.NIGHTLY_BUILD) { + let osPidItem = ["context-frameOsPid", false]; + base_menu = base_menu.concat(osPidItem); + } + return base_menu; +} + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.search.separatePrivateDefault.ui.enabled", true], + ["extensions.screenshots.disabled", false], + ["layout.forms.reveal-password-context-menu.enabled", true], + ], + }); +}); + +// Below are test cases for XUL element +add_task(async function test_xul_text_link_label() { + let url = chrome_base + "subtst_contextmenu_xul.xhtml"; + + await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + url, + waitForLoad: true, + waitForStateStop: true, + }); + + await test_contextmenu("#test-xul-text-link-label", [ + "context-openlinkintab", + true, + ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []), + // We need a blank entry here because the containers submenu is + // dynamically generated with no ids. + ...(hasContainers ? ["", null] : []), + "context-openlink", + true, + "context-openlinkprivate", + true, + "---", + null, + "context-bookmarklink", + true, + "context-savelink", + true, + ...(hasPocket ? ["context-savelinktopocket", true] : []), + "context-copylink", + true, + "---", + null, + "context-searchselect", + true, + "context-searchselect-private", + true, + ]); + + // Clean up so won't affect HTML element test cases. + lastElementSelector = null; + gBrowser.removeCurrentTab(); +}); + +// Below are test cases for HTML element. + +add_task(async function test_setup_html() { + let url = example_base + "subtst_contextmenu.html"; + + await BrowserTestUtils.openNewForegroundTab(gBrowser, url); + + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () { + let doc = content.document; + let audioIframe = doc.querySelector("#test-audio-in-iframe"); + // media documents always use a