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 --- .../preferences/tests/addons/pl-dictionary.xpi | Bin 0 -> 793 bytes .../preferences/tests/addons/set_homepage.xpi | Bin 0 -> 5156 bytes .../preferences/tests/addons/set_newtab.xpi | Bin 0 -> 5210 bytes browser/components/preferences/tests/browser.ini | 152 ++ .../preferences/tests/browser_advanced_update.js | 185 +++ .../browser_application_xml_handle_internally.js | 49 + .../tests/browser_applications_selection.js | 403 ++++++ .../tests/browser_basic_rebuild_fonts_test.js | 235 ++++ .../tests/browser_browser_languages_subdialog.js | 1058 ++++++++++++++ .../browser_bug1018066_resetScrollPosition.js | 30 + ...er_bug1020245_openPreferences_to_paneContent.js | 163 +++ ...9_prevent_scrolling_when_preferences_flipped.js | 116 ++ ...revent_scrolling_when_preferences_flipped.xhtml | 26 + .../tests/browser_bug1547020_lockedDownloadDir.js | 24 + .../preferences/tests/browser_bug1579418.js | 55 + .../preferences/tests/browser_bug410900.js | 47 + .../preferences/tests/browser_bug731866.js | 95 ++ .../tests/browser_bug795764_cachedisabled.js | 62 + .../preferences/tests/browser_cert_export.js | 161 +++ .../tests/browser_change_app_handler.js | 155 +++ .../preferences/tests/browser_checkspelling.js | 34 + .../preferences/tests/browser_connection.js | 145 ++ .../tests/browser_connection_bug1445991.js | 31 + .../tests/browser_connection_bug1505330.js | 31 + .../tests/browser_connection_bug388287.js | 124 ++ .../tests/browser_containers_name_input.js | 72 + .../preferences/tests/browser_contentblocking.js | 1382 +++++++++++++++++++ .../tests/browser_contentblocking_categories.js | 487 +++++++ ...browser_contentblocking_standard_tcp_section.js | 148 ++ .../tests/browser_cookie_exceptions_addRemove.js | 299 ++++ .../tests/browser_cookies_exceptions.js | 568 ++++++++ .../tests/browser_defaultbrowser_alwayscheck.js | 185 +++ .../preferences/tests/browser_engines.js | 141 ++ .../tests/browser_etp_exceptions_dialog.js | 96 ++ .../tests/browser_experimental_features.js | 74 + .../tests/browser_experimental_features_filter.js | 183 +++ ...experimental_features_hidden_when_not_public.js | 86 ++ .../browser_experimental_features_resetall.js | 112 ++ .../tests/browser_extension_controlled.js | 1447 ++++++++++++++++++++ .../preferences/tests/browser_filetype_dialog.js | 189 +++ .../components/preferences/tests/browser_fluent.js | 40 + .../preferences/tests/browser_homepage_default.js | 31 + .../browser_homepages_filter_aboutpreferences.js | 33 + .../tests/browser_homepages_use_bookmark.js | 94 ++ .../tests/browser_hometab_restore_defaults.js | 220 +++ .../tests/browser_https_only_exceptions.js | 279 ++++ .../tests/browser_https_only_section.js | 74 + .../tests/browser_ignore_invalid_capability.js | 40 + .../tests/browser_languages_subdialog.js | 139 ++ .../tests/browser_layersacceleration.js | 36 + .../tests/browser_localSearchShortcuts.js | 309 +++++ .../preferences/tests/browser_moreFromMozilla.js | 380 +++++ .../tests/browser_moreFromMozilla_locales.js | 331 +++++ .../preferences/tests/browser_newtab_menu.js | 38 + .../tests/browser_notifications_do_not_disturb.js | 57 + .../tests/browser_open_download_preferences.js | 288 ++++ .../tests/browser_open_migration_wizard.js | 54 + .../tests/browser_password_management.js | 43 + .../preferences/tests/browser_pdf_disabled.js | 49 + .../preferences/tests/browser_performance.js | 300 ++++ .../browser_performance_content_process_limit.js | 52 + .../tests/browser_performance_e10srollout.js | 164 +++ .../tests/browser_performance_non_e10s.js | 210 +++ ...rowser_permissions_checkPermissionsWereAdded.js | 127 ++ .../tests/browser_permissions_dialog.js | 642 +++++++++ .../browser_permissions_dialog_default_perm.js | 145 ++ .../tests/browser_permissions_urlFieldHidden.js | 38 + .../preferences/tests/browser_primaryPassword.js | 130 ++ .../tests/browser_privacy_cookieBannerHandling.js | 210 +++ .../tests/browser_privacy_dnsoverhttps.js | 844 ++++++++++++ .../tests/browser_privacy_firefoxSuggest.js | 855 ++++++++++++ ...rowser_privacy_passwordGenerationAndAutofill.js | 199 +++ .../tests/browser_privacy_quickactions.js | 110 ++ .../tests/browser_privacy_relayIntegration.js | 251 ++++ .../tests/browser_privacy_segmentation_pref.js | 131 ++ .../tests/browser_privacy_syncDataClearing.js | 287 ++++ .../preferences/tests/browser_privacypane_2.js | 19 + .../preferences/tests/browser_privacypane_3.js | 21 + .../preferences/tests/browser_proxy_backup.js | 84 ++ .../tests/browser_sanitizeOnShutdown_prefLocked.js | 47 + .../tests/browser_searchChangedEngine.js | 90 ++ .../tests/browser_searchDefaultEngine.js | 372 +++++ .../tests/browser_searchFindMoreLink.js | 36 + .../tests/browser_searchRestoreDefaults.js | 259 ++++ .../preferences/tests/browser_searchScroll.js | 66 + .../tests/browser_searchShowSuggestionsFirst.js | 240 ++++ .../browser_search_no_results_change_category.js | 44 + .../tests/browser_search_searchTerms.js | 201 +++ ...ser_search_subdialog_tooltip_saved_addresses.js | 39 + ...owser_search_subdialogs_within_preferences_1.js | 48 + ...owser_search_subdialogs_within_preferences_2.js | 36 + ...owser_search_subdialogs_within_preferences_3.js | 35 + ...owser_search_subdialogs_within_preferences_4.js | 39 + ...owser_search_subdialogs_within_preferences_5.js | 46 + ...owser_search_subdialogs_within_preferences_6.js | 35 + ...owser_search_subdialogs_within_preferences_7.js | 34 + ...owser_search_subdialogs_within_preferences_8.js | 45 + ...arch_subdialogs_within_preferences_site_data.js | 45 + .../tests/browser_search_within_preferences_1.js | 344 +++++ .../tests/browser_search_within_preferences_2.js | 180 +++ .../browser_search_within_preferences_command.js | 45 + .../preferences/tests/browser_searchsuggestions.js | 128 ++ .../preferences/tests/browser_security-1.js | 106 ++ .../preferences/tests/browser_security-2.js | 177 +++ .../preferences/tests/browser_security-3.js | 130 ++ .../tests/browser_site_login_exceptions.js | 101 ++ .../tests/browser_site_login_exceptions_policy.js | 65 + .../preferences/tests/browser_spotlight.js | 72 + .../tests/browser_statePartitioning_PBM_strings.js | 124 ++ .../tests/browser_statePartitioning_strings.js | 79 ++ .../preferences/tests/browser_subdialogs.js | 639 +++++++++ .../tests/browser_sync_chooseWhatToSync.js | 178 +++ .../preferences/tests/browser_sync_disabled.js | 26 + .../preferences/tests/browser_sync_pairing.js | 149 ++ .../browser_warning_permanent_private_browsing.js | 57 + .../preferences/tests/empty_pdf_file.pdf | 0 .../preferences/tests/engine1/manifest.json | 27 + .../preferences/tests/engine2/manifest.json | 27 + browser/components/preferences/tests/head.js | 334 +++++ .../tests/privacypane_tests_perwindow.js | 388 ++++++ .../preferences/tests/siteData/browser.ini | 22 + .../tests/siteData/browser_clearSiteData.js | 219 +++ .../preferences/tests/siteData/browser_siteData.js | 400 ++++++ .../tests/siteData/browser_siteData2.js | 475 +++++++ .../tests/siteData/browser_siteData3.js | 327 +++++ .../siteData/browser_siteData_multi_select.js | 119 ++ .../components/preferences/tests/siteData/head.js | 280 ++++ .../tests/siteData/offline/manifest.appcache | 3 + .../tests/siteData/offline/offline.html | 13 + .../tests/siteData/service_worker_test.html | 19 + .../tests/siteData/service_worker_test.js | 1 + .../preferences/tests/siteData/site_data_test.html | 29 + .../components/preferences/tests/subdialog.xhtml | 29 + .../components/preferences/tests/subdialog2.xhtml | 29 + 134 files changed, 23302 insertions(+) create mode 100644 browser/components/preferences/tests/addons/pl-dictionary.xpi create mode 100644 browser/components/preferences/tests/addons/set_homepage.xpi create mode 100644 browser/components/preferences/tests/addons/set_newtab.xpi create mode 100644 browser/components/preferences/tests/browser.ini create mode 100644 browser/components/preferences/tests/browser_advanced_update.js create mode 100644 browser/components/preferences/tests/browser_application_xml_handle_internally.js create mode 100644 browser/components/preferences/tests/browser_applications_selection.js create mode 100644 browser/components/preferences/tests/browser_basic_rebuild_fonts_test.js create mode 100644 browser/components/preferences/tests/browser_browser_languages_subdialog.js create mode 100644 browser/components/preferences/tests/browser_bug1018066_resetScrollPosition.js create mode 100644 browser/components/preferences/tests/browser_bug1020245_openPreferences_to_paneContent.js create mode 100644 browser/components/preferences/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.js create mode 100644 browser/components/preferences/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.xhtml create mode 100644 browser/components/preferences/tests/browser_bug1547020_lockedDownloadDir.js create mode 100644 browser/components/preferences/tests/browser_bug1579418.js create mode 100644 browser/components/preferences/tests/browser_bug410900.js create mode 100644 browser/components/preferences/tests/browser_bug731866.js create mode 100644 browser/components/preferences/tests/browser_bug795764_cachedisabled.js create mode 100644 browser/components/preferences/tests/browser_cert_export.js create mode 100644 browser/components/preferences/tests/browser_change_app_handler.js create mode 100644 browser/components/preferences/tests/browser_checkspelling.js create mode 100644 browser/components/preferences/tests/browser_connection.js create mode 100644 browser/components/preferences/tests/browser_connection_bug1445991.js create mode 100644 browser/components/preferences/tests/browser_connection_bug1505330.js create mode 100644 browser/components/preferences/tests/browser_connection_bug388287.js create mode 100644 browser/components/preferences/tests/browser_containers_name_input.js create mode 100644 browser/components/preferences/tests/browser_contentblocking.js create mode 100644 browser/components/preferences/tests/browser_contentblocking_categories.js create mode 100644 browser/components/preferences/tests/browser_contentblocking_standard_tcp_section.js create mode 100644 browser/components/preferences/tests/browser_cookie_exceptions_addRemove.js create mode 100644 browser/components/preferences/tests/browser_cookies_exceptions.js create mode 100644 browser/components/preferences/tests/browser_defaultbrowser_alwayscheck.js create mode 100644 browser/components/preferences/tests/browser_engines.js create mode 100644 browser/components/preferences/tests/browser_etp_exceptions_dialog.js create mode 100644 browser/components/preferences/tests/browser_experimental_features.js create mode 100644 browser/components/preferences/tests/browser_experimental_features_filter.js create mode 100644 browser/components/preferences/tests/browser_experimental_features_hidden_when_not_public.js create mode 100644 browser/components/preferences/tests/browser_experimental_features_resetall.js create mode 100644 browser/components/preferences/tests/browser_extension_controlled.js create mode 100644 browser/components/preferences/tests/browser_filetype_dialog.js create mode 100644 browser/components/preferences/tests/browser_fluent.js create mode 100644 browser/components/preferences/tests/browser_homepage_default.js create mode 100644 browser/components/preferences/tests/browser_homepages_filter_aboutpreferences.js create mode 100644 browser/components/preferences/tests/browser_homepages_use_bookmark.js create mode 100644 browser/components/preferences/tests/browser_hometab_restore_defaults.js create mode 100644 browser/components/preferences/tests/browser_https_only_exceptions.js create mode 100644 browser/components/preferences/tests/browser_https_only_section.js create mode 100644 browser/components/preferences/tests/browser_ignore_invalid_capability.js create mode 100644 browser/components/preferences/tests/browser_languages_subdialog.js create mode 100644 browser/components/preferences/tests/browser_layersacceleration.js create mode 100644 browser/components/preferences/tests/browser_localSearchShortcuts.js create mode 100644 browser/components/preferences/tests/browser_moreFromMozilla.js create mode 100644 browser/components/preferences/tests/browser_moreFromMozilla_locales.js create mode 100644 browser/components/preferences/tests/browser_newtab_menu.js create mode 100644 browser/components/preferences/tests/browser_notifications_do_not_disturb.js create mode 100644 browser/components/preferences/tests/browser_open_download_preferences.js create mode 100644 browser/components/preferences/tests/browser_open_migration_wizard.js create mode 100644 browser/components/preferences/tests/browser_password_management.js create mode 100644 browser/components/preferences/tests/browser_pdf_disabled.js create mode 100644 browser/components/preferences/tests/browser_performance.js create mode 100644 browser/components/preferences/tests/browser_performance_content_process_limit.js create mode 100644 browser/components/preferences/tests/browser_performance_e10srollout.js create mode 100644 browser/components/preferences/tests/browser_performance_non_e10s.js create mode 100644 browser/components/preferences/tests/browser_permissions_checkPermissionsWereAdded.js create mode 100644 browser/components/preferences/tests/browser_permissions_dialog.js create mode 100644 browser/components/preferences/tests/browser_permissions_dialog_default_perm.js create mode 100644 browser/components/preferences/tests/browser_permissions_urlFieldHidden.js create mode 100644 browser/components/preferences/tests/browser_primaryPassword.js create mode 100644 browser/components/preferences/tests/browser_privacy_cookieBannerHandling.js create mode 100644 browser/components/preferences/tests/browser_privacy_dnsoverhttps.js create mode 100644 browser/components/preferences/tests/browser_privacy_firefoxSuggest.js create mode 100644 browser/components/preferences/tests/browser_privacy_passwordGenerationAndAutofill.js create mode 100644 browser/components/preferences/tests/browser_privacy_quickactions.js create mode 100644 browser/components/preferences/tests/browser_privacy_relayIntegration.js create mode 100644 browser/components/preferences/tests/browser_privacy_segmentation_pref.js create mode 100644 browser/components/preferences/tests/browser_privacy_syncDataClearing.js create mode 100644 browser/components/preferences/tests/browser_privacypane_2.js create mode 100644 browser/components/preferences/tests/browser_privacypane_3.js create mode 100644 browser/components/preferences/tests/browser_proxy_backup.js create mode 100644 browser/components/preferences/tests/browser_sanitizeOnShutdown_prefLocked.js create mode 100644 browser/components/preferences/tests/browser_searchChangedEngine.js create mode 100644 browser/components/preferences/tests/browser_searchDefaultEngine.js create mode 100644 browser/components/preferences/tests/browser_searchFindMoreLink.js create mode 100644 browser/components/preferences/tests/browser_searchRestoreDefaults.js create mode 100644 browser/components/preferences/tests/browser_searchScroll.js create mode 100644 browser/components/preferences/tests/browser_searchShowSuggestionsFirst.js create mode 100644 browser/components/preferences/tests/browser_search_no_results_change_category.js create mode 100644 browser/components/preferences/tests/browser_search_searchTerms.js create mode 100644 browser/components/preferences/tests/browser_search_subdialog_tooltip_saved_addresses.js create mode 100644 browser/components/preferences/tests/browser_search_subdialogs_within_preferences_1.js create mode 100644 browser/components/preferences/tests/browser_search_subdialogs_within_preferences_2.js create mode 100644 browser/components/preferences/tests/browser_search_subdialogs_within_preferences_3.js create mode 100644 browser/components/preferences/tests/browser_search_subdialogs_within_preferences_4.js create mode 100644 browser/components/preferences/tests/browser_search_subdialogs_within_preferences_5.js create mode 100644 browser/components/preferences/tests/browser_search_subdialogs_within_preferences_6.js create mode 100644 browser/components/preferences/tests/browser_search_subdialogs_within_preferences_7.js create mode 100644 browser/components/preferences/tests/browser_search_subdialogs_within_preferences_8.js create mode 100644 browser/components/preferences/tests/browser_search_subdialogs_within_preferences_site_data.js create mode 100644 browser/components/preferences/tests/browser_search_within_preferences_1.js create mode 100644 browser/components/preferences/tests/browser_search_within_preferences_2.js create mode 100644 browser/components/preferences/tests/browser_search_within_preferences_command.js create mode 100644 browser/components/preferences/tests/browser_searchsuggestions.js create mode 100644 browser/components/preferences/tests/browser_security-1.js create mode 100644 browser/components/preferences/tests/browser_security-2.js create mode 100644 browser/components/preferences/tests/browser_security-3.js create mode 100644 browser/components/preferences/tests/browser_site_login_exceptions.js create mode 100644 browser/components/preferences/tests/browser_site_login_exceptions_policy.js create mode 100644 browser/components/preferences/tests/browser_spotlight.js create mode 100644 browser/components/preferences/tests/browser_statePartitioning_PBM_strings.js create mode 100644 browser/components/preferences/tests/browser_statePartitioning_strings.js create mode 100644 browser/components/preferences/tests/browser_subdialogs.js create mode 100644 browser/components/preferences/tests/browser_sync_chooseWhatToSync.js create mode 100644 browser/components/preferences/tests/browser_sync_disabled.js create mode 100644 browser/components/preferences/tests/browser_sync_pairing.js create mode 100644 browser/components/preferences/tests/browser_warning_permanent_private_browsing.js create mode 100644 browser/components/preferences/tests/empty_pdf_file.pdf create mode 100644 browser/components/preferences/tests/engine1/manifest.json create mode 100644 browser/components/preferences/tests/engine2/manifest.json create mode 100644 browser/components/preferences/tests/head.js create mode 100644 browser/components/preferences/tests/privacypane_tests_perwindow.js create mode 100644 browser/components/preferences/tests/siteData/browser.ini create mode 100644 browser/components/preferences/tests/siteData/browser_clearSiteData.js create mode 100644 browser/components/preferences/tests/siteData/browser_siteData.js create mode 100644 browser/components/preferences/tests/siteData/browser_siteData2.js create mode 100644 browser/components/preferences/tests/siteData/browser_siteData3.js create mode 100644 browser/components/preferences/tests/siteData/browser_siteData_multi_select.js create mode 100644 browser/components/preferences/tests/siteData/head.js create mode 100644 browser/components/preferences/tests/siteData/offline/manifest.appcache create mode 100644 browser/components/preferences/tests/siteData/offline/offline.html create mode 100644 browser/components/preferences/tests/siteData/service_worker_test.html create mode 100644 browser/components/preferences/tests/siteData/service_worker_test.js create mode 100644 browser/components/preferences/tests/siteData/site_data_test.html create mode 100644 browser/components/preferences/tests/subdialog.xhtml create mode 100644 browser/components/preferences/tests/subdialog2.xhtml (limited to 'browser/components/preferences/tests') diff --git a/browser/components/preferences/tests/addons/pl-dictionary.xpi b/browser/components/preferences/tests/addons/pl-dictionary.xpi new file mode 100644 index 0000000000..cc4da1fa83 Binary files /dev/null and b/browser/components/preferences/tests/addons/pl-dictionary.xpi differ diff --git a/browser/components/preferences/tests/addons/set_homepage.xpi b/browser/components/preferences/tests/addons/set_homepage.xpi new file mode 100644 index 0000000000..9aff671021 Binary files /dev/null and b/browser/components/preferences/tests/addons/set_homepage.xpi differ diff --git a/browser/components/preferences/tests/addons/set_newtab.xpi b/browser/components/preferences/tests/addons/set_newtab.xpi new file mode 100644 index 0000000000..f11db0b6a8 Binary files /dev/null and b/browser/components/preferences/tests/addons/set_newtab.xpi differ diff --git a/browser/components/preferences/tests/browser.ini b/browser/components/preferences/tests/browser.ini new file mode 100644 index 0000000000..8203bceb90 --- /dev/null +++ b/browser/components/preferences/tests/browser.ini @@ -0,0 +1,152 @@ +[DEFAULT] +prefs = + extensions.formautofill.addresses.available='on' + extensions.formautofill.creditCards.available='on' + signon.management.page.os-auth.enabled=true +support-files = + head.js + privacypane_tests_perwindow.js + addons/pl-dictionary.xpi + addons/set_homepage.xpi + addons/set_newtab.xpi + +[browser_advanced_update.js] +skip-if = !updater +[browser_application_xml_handle_internally.js] +[browser_applications_selection.js] +[browser_basic_rebuild_fonts_test.js] +[browser_browser_languages_subdialog.js] +skip-if = + tsan + (!debug && os == 'win') # Bug 1518370 +[browser_bug1018066_resetScrollPosition.js] +[browser_bug1020245_openPreferences_to_paneContent.js] +[browser_bug1184989_prevent_scrolling_when_preferences_flipped.js] +skip-if = os == "mac" # 1664576 + os == "win" && os_version == "6.1" # Skip on Azure - frequent failure +support-files = + browser_bug1184989_prevent_scrolling_when_preferences_flipped.xhtml +[browser_bug1547020_lockedDownloadDir.js] +[browser_bug1579418.js] +[browser_bug410900.js] +[browser_bug731866.js] +[browser_bug795764_cachedisabled.js] +[browser_cert_export.js] +[browser_change_app_handler.js] +skip-if = os != "win" # Windows-specific handler application selection dialog +[browser_checkspelling.js] +[browser_connection.js] +[browser_connection_bug1445991.js] +[browser_connection_bug1505330.js] +skip-if = (verify && debug && (os == 'linux' || os == 'mac')) +[browser_connection_bug388287.js] +[browser_containers_name_input.js] +[browser_contentblocking.js] +skip-if = socketprocess_networking +[browser_contentblocking_categories.js] +[browser_contentblocking_standard_tcp_section.js] +[browser_cookie_exceptions_addRemove.js] +[browser_cookies_exceptions.js] +[browser_defaultbrowser_alwayscheck.js] +[browser_engines.js] +[browser_etp_exceptions_dialog.js] +[browser_experimental_features.js] +[browser_experimental_features_filter.js] +[browser_experimental_features_hidden_when_not_public.js] +skip-if = + os == "mac" && debug # Bug 1723854 + os == "linux" && os_version == "18.04" && debug # Bug 1723854 +[browser_experimental_features_resetall.js] +[browser_extension_controlled.js] +skip-if = + tsan + ccov && (os == 'linux' || os == 'win') # Linux: bug 1613530, Windows: bug 1437051 +[browser_filetype_dialog.js] +[browser_fluent.js] +[browser_homepage_default.js] +[browser_homepages_filter_aboutpreferences.js] +[browser_homepages_use_bookmark.js] +[browser_hometab_restore_defaults.js] +https_first_disabled = true +[browser_https_only_exceptions.js] +[browser_https_only_section.js] +[browser_ignore_invalid_capability.js] +[browser_languages_subdialog.js] +[browser_layersacceleration.js] +[browser_localSearchShortcuts.js] +[browser_moreFromMozilla.js] +[browser_moreFromMozilla_locales.js] +[browser_newtab_menu.js] +[browser_notifications_do_not_disturb.js] +[browser_open_download_preferences.js] +support-files = empty_pdf_file.pdf +[browser_open_migration_wizard.js] +[browser_password_management.js] +[browser_pdf_disabled.js] +[browser_performance.js] +[browser_performance_content_process_limit.js] +[browser_performance_e10srollout.js] +[browser_performance_non_e10s.js] +skip-if = true +[browser_permissions_checkPermissionsWereAdded.js] +[browser_permissions_dialog.js] +[browser_permissions_dialog_default_perm.js] +[browser_permissions_urlFieldHidden.js] +[browser_primaryPassword.js] +[browser_privacy_cookieBannerHandling.js] +[browser_privacy_dnsoverhttps.js] +[browser_privacy_firefoxSuggest.js] +[browser_privacy_passwordGenerationAndAutofill.js] +[browser_privacy_quickactions.js] +[browser_privacy_relayIntegration.js] +[browser_privacy_segmentation_pref.js] +[browser_privacy_syncDataClearing.js] +[browser_privacypane_2.js] +[browser_privacypane_3.js] +[browser_proxy_backup.js] +[browser_sanitizeOnShutdown_prefLocked.js] +[browser_searchChangedEngine.js] +[browser_searchDefaultEngine.js] +support-files = + engine1/manifest.json + engine2/manifest.json +[browser_searchFindMoreLink.js] +[browser_searchRestoreDefaults.js] +[browser_searchScroll.js] +support-files = + !/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js +[browser_searchShowSuggestionsFirst.js] +[browser_search_no_results_change_category.js] +[browser_search_searchTerms.js] +[browser_search_subdialog_tooltip_saved_addresses.js] +[browser_search_subdialogs_within_preferences_1.js] +skip-if = tsan # Bug 1678829 +[browser_search_subdialogs_within_preferences_2.js] +[browser_search_subdialogs_within_preferences_3.js] +[browser_search_subdialogs_within_preferences_4.js] +[browser_search_subdialogs_within_preferences_5.js] +[browser_search_subdialogs_within_preferences_6.js] +[browser_search_subdialogs_within_preferences_7.js] +[browser_search_subdialogs_within_preferences_8.js] +[browser_search_subdialogs_within_preferences_site_data.js] +[browser_search_within_preferences_1.js] +skip-if = (os == 'win' && processor == "aarch64") # Bug 1536560 +[browser_search_within_preferences_2.js] +[browser_search_within_preferences_command.js] +[browser_searchsuggestions.js] +[browser_security-1.js] +[browser_security-2.js] +[browser_security-3.js] +[browser_site_login_exceptions.js] +[browser_site_login_exceptions_policy.js] +[browser_spotlight.js] +[browser_statePartitioning_PBM_strings.js] +[browser_statePartitioning_strings.js] +[browser_subdialogs.js] +support-files = + subdialog.xhtml + subdialog2.xhtml +[browser_sync_chooseWhatToSync.js] +[browser_sync_disabled.js] +[browser_sync_pairing.js] +[browser_warning_permanent_private_browsing.js] diff --git a/browser/components/preferences/tests/browser_advanced_update.js b/browser/components/preferences/tests/browser_advanced_update.js new file mode 100644 index 0000000000..95da7a1c7a --- /dev/null +++ b/browser/components/preferences/tests/browser_advanced_update.js @@ -0,0 +1,185 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const Cm = Components.manager; + +const uuidGenerator = Services.uuid; + +const mockUpdateManager = { + contractId: "@mozilla.org/updates/update-manager;1", + + _mockClassId: uuidGenerator.generateUUID(), + + _originalClassId: "", + + QueryInterface: ChromeUtils.generateQI(["nsIUpdateManager"]), + + createInstance(iiD) { + return this.QueryInterface(iiD); + }, + + register() { + let registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); + if (!registrar.isCIDRegistered(this._mockClassId)) { + this._originalClassId = registrar.contractIDToCID(this.contractId); + registrar.registerFactory( + this._mockClassId, + "Unregister after testing", + this.contractId, + this + ); + } + }, + + unregister() { + let registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); + registrar.unregisterFactory(this._mockClassId, this); + registrar.registerFactory(this._originalClassId, "", this.contractId, null); + }, + + getUpdateCount() { + return this._updates.length; + }, + + getUpdateAt(index) { + return this._updates[index]; + }, + + _updates: [ + { + name: "Firefox Developer Edition 49.0a2", + statusText: "The Update was successfully installed", + buildID: "20160728004010", + installDate: 1469763105156, + detailsURL: "https://www.mozilla.org/firefox/aurora/", + }, + { + name: "Firefox Developer Edition 43.0a2", + statusText: "The Update was successfully installed", + buildID: "20150929004011", + installDate: 1443585886224, + detailsURL: "https://www.mozilla.org/firefox/aurora/", + }, + { + name: "Firefox Developer Edition 42.0a2", + statusText: "The Update was successfully installed", + buildID: "20150920004018", + installDate: 1442818147544, + detailsURL: "https://www.mozilla.org/firefox/aurora/", + }, + ], +}; + +function formatInstallDate(sec) { + var date = new Date(sec); + const dtOptions = { + year: "numeric", + month: "long", + day: "numeric", + hour: "numeric", + minute: "numeric", + second: "numeric", + }; + return date.toLocaleString(undefined, dtOptions); +} + +add_task(async function () { + await openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true }); + let doc = gBrowser.selectedBrowser.contentDocument; + + let showBtn = doc.getElementById("showUpdateHistory"); + let dialogOverlay = content.gSubDialog._preloadDialog._overlay; + + // XXX: For unknown reasons, this mock cannot be loaded by + // XPCOMUtils.defineLazyServiceGetter() called in aboutDialog-appUpdater.js. + // It is registered here so that we could assert update history subdialog + // without stopping the preferences advanced pane from loading. + // See bug 1361929. + mockUpdateManager.register(); + + // Test the dialog window opens + ok( + BrowserTestUtils.is_hidden(dialogOverlay), + "The dialog should be invisible" + ); + let promiseSubDialogLoaded = promiseLoadSubDialog( + "chrome://mozapps/content/update/history.xhtml" + ); + showBtn.doCommand(); + await promiseSubDialogLoaded; + ok( + !BrowserTestUtils.is_hidden(dialogOverlay), + "The dialog should be visible" + ); + + let dialogFrame = dialogOverlay.querySelector(".dialogFrame"); + let frameDoc = dialogFrame.contentDocument; + let updates = frameDoc.querySelectorAll("richlistitem.update"); + + // Test the update history numbers are correct + is( + updates.length, + mockUpdateManager.getUpdateCount(), + "The update count is incorrect." + ); + + // Test the updates are displayed correctly + let update = null; + let updateData = null; + for (let i = 0; i < updates.length; ++i) { + update = updates[i]; + updateData = mockUpdateManager.getUpdateAt(i); + + let testcases = [ + { + selector: ".update-name", + id: "update-full-build-name", + args: { name: updateData.name, buildID: updateData.buildID }, + }, + { + selector: ".update-installedOn-label", + id: "update-installed-on", + args: { date: formatInstallDate(updateData.installDate) }, + }, + { + selector: ".update-status-label", + id: "update-status", + args: { status: updateData.statusText }, + }, + ]; + + for (let { selector, id, args } of testcases) { + const element = update.querySelector(selector); + const l10nAttrs = frameDoc.l10n.getAttributes(element); + Assert.deepEqual( + l10nAttrs, + { + id, + args, + }, + "Wrong " + id + ); + } + + if (update.detailsURL) { + is( + update.detailsURL, + update.querySelector(".text-link").href, + "Wrong detailsURL" + ); + } + } + + // Test the dialog window closes + let closeBtn = dialogOverlay.querySelector(".dialogClose"); + closeBtn.doCommand(); + ok( + BrowserTestUtils.is_hidden(dialogOverlay), + "The dialog should be invisible" + ); + + mockUpdateManager.unregister(); + gBrowser.removeCurrentTab(); +}); diff --git a/browser/components/preferences/tests/browser_application_xml_handle_internally.js b/browser/components/preferences/tests/browser_application_xml_handle_internally.js new file mode 100644 index 0000000000..edb4a4c0ec --- /dev/null +++ b/browser/components/preferences/tests/browser_application_xml_handle_internally.js @@ -0,0 +1,49 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const HandlerService = Cc[ + "@mozilla.org/uriloader/handler-service;1" +].getService(Ci.nsIHandlerService); + +const MIMEService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService); + +// This test checks that application/xml has the handle internally option. +add_task(async function applicationXmlHandleInternally() { + const mimeInfo = MIMEService.getFromTypeAndExtension( + "application/xml", + "xml" + ); + HandlerService.store(mimeInfo); + registerCleanupFunction(() => { + HandlerService.remove(mimeInfo); + }); + + await openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true }); + + let win = gBrowser.selectedBrowser.contentWindow; + + let container = win.document.getElementById("handlersView"); + + // First, find the application/xml item. + let xmlItem = container.querySelector("richlistitem[type='application/xml']"); + Assert.ok(xmlItem, "application/xml is present in handlersView"); + if (xmlItem) { + xmlItem.scrollIntoView({ block: "center" }); + xmlItem.closest("richlistbox").selectItem(xmlItem); + + // Open its menu + let list = xmlItem.querySelector(".actionsMenu"); + let popup = list.menupopup; + let popupShown = BrowserTestUtils.waitForEvent(popup, "popupshown"); + EventUtils.synthesizeMouseAtCenter(list, {}, win); + await popupShown; + + let handleInternallyItem = list.querySelector( + `menuitem[action='${Ci.nsIHandlerInfo.handleInternally}']` + ); + + ok(!!handleInternallyItem, "handle internally is present"); + } + + gBrowser.removeCurrentTab(); +}); diff --git a/browser/components/preferences/tests/browser_applications_selection.js b/browser/components/preferences/tests/browser_applications_selection.js new file mode 100644 index 0000000000..683ce76a89 --- /dev/null +++ b/browser/components/preferences/tests/browser_applications_selection.js @@ -0,0 +1,403 @@ +SimpleTest.requestCompleteLog(); +const { HandlerServiceTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/HandlerServiceTestUtils.sys.mjs" +); + +let gHandlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService( + Ci.nsIHandlerService +); + +let gOldMailHandlers = []; +let gDummyHandlers = []; +let gOriginalPreferredMailHandler; +let gOriginalPreferredPDFHandler; + +registerCleanupFunction(function () { + function removeDummyHandlers(handlers) { + // Remove any of the dummy handlers we created. + for (let i = handlers.Count() - 1; i >= 0; i--) { + try { + if ( + gDummyHandlers.some( + h => + h.uriTemplate == + handlers.queryElementAt(i, Ci.nsIWebHandlerApp).uriTemplate + ) + ) { + handlers.removeElementAt(i); + } + } catch (ex) { + /* ignore non-web-app handlers */ + } + } + } + // Re-add the original protocol handlers: + let mailHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("mailto"); + let mailHandlers = mailHandlerInfo.possibleApplicationHandlers; + for (let h of gOldMailHandlers) { + mailHandlers.appendElement(h); + } + removeDummyHandlers(mailHandlers); + mailHandlerInfo.preferredApplicationHandler = gOriginalPreferredMailHandler; + gHandlerService.store(mailHandlerInfo); + + let pdfHandlerInfo = + HandlerServiceTestUtils.getHandlerInfo("application/pdf"); + removeDummyHandlers(pdfHandlerInfo.possibleApplicationHandlers); + pdfHandlerInfo.preferredApplicationHandler = gOriginalPreferredPDFHandler; + gHandlerService.store(pdfHandlerInfo); + + gBrowser.removeCurrentTab(); +}); + +function scrubMailtoHandlers(handlerInfo) { + // Remove extant web handlers because they have icons that + // we fetch from the web, which isn't allowed in tests. + let handlers = handlerInfo.possibleApplicationHandlers; + for (let i = handlers.Count() - 1; i >= 0; i--) { + try { + let handler = handlers.queryElementAt(i, Ci.nsIWebHandlerApp); + gOldMailHandlers.push(handler); + // If we get here, this is a web handler app. Remove it: + handlers.removeElementAt(i); + } catch (ex) {} + } +} + +add_setup(async function () { + // Create our dummy handlers + let handler1 = Cc["@mozilla.org/uriloader/web-handler-app;1"].createInstance( + Ci.nsIWebHandlerApp + ); + handler1.name = "Handler 1"; + handler1.uriTemplate = "https://example.com/first/%s"; + + let handler2 = Cc["@mozilla.org/uriloader/web-handler-app;1"].createInstance( + Ci.nsIWebHandlerApp + ); + handler2.name = "Handler 2"; + handler2.uriTemplate = "http://example.org/second/%s"; + gDummyHandlers.push(handler1, handler2); + + function substituteWebHandlers(handlerInfo) { + // Append the dummy handlers to replace them: + let handlers = handlerInfo.possibleApplicationHandlers; + handlers.appendElement(handler1); + handlers.appendElement(handler2); + gHandlerService.store(handlerInfo); + } + // Set up our mailto handler test infrastructure. + let mailtoHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("mailto"); + scrubMailtoHandlers(mailtoHandlerInfo); + gOriginalPreferredMailHandler = mailtoHandlerInfo.preferredApplicationHandler; + substituteWebHandlers(mailtoHandlerInfo); + + // Now do the same for pdf handler: + let pdfHandlerInfo = + HandlerServiceTestUtils.getHandlerInfo("application/pdf"); + // PDF doesn't have built-in web handlers, so no need to scrub. + gOriginalPreferredPDFHandler = pdfHandlerInfo.preferredApplicationHandler; + substituteWebHandlers(pdfHandlerInfo); + + await openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true }); + info("Preferences page opened on the general pane."); + + await gBrowser.selectedBrowser.contentWindow.promiseLoadHandlersList; + info("Apps list loaded."); +}); + +async function selectStandardOptions(itemToUse) { + async function selectItemInPopup(item) { + let popupShown = BrowserTestUtils.waitForEvent(popup, "popupshown"); + // Synthesizing the mouse on the .actionsMenu menulist somehow just selects + // the top row. Probably something to do with the multiple layers of anon + // content - workaround by using the `.open` setter instead. + list.open = true; + await popupShown; + let popupHidden = BrowserTestUtils.waitForEvent(popup, "popuphidden"); + if (typeof item == "function") { + item = item(); + } + popup.activateItem(item); + await popupHidden; + return item; + } + + let itemType = itemToUse.getAttribute("type"); + // Center the item. Center rather than top so it doesn't get blocked by + // the search header. + itemToUse.scrollIntoView({ block: "center" }); + itemToUse.closest("richlistbox").selectItem(itemToUse); + Assert.ok(itemToUse.selected, "Should be able to select our item."); + // Force reflow to make sure it's visible and the container dropdown isn't + // hidden. + itemToUse.getBoundingClientRect().top; + let list = itemToUse.querySelector(".actionsMenu"); + let popup = list.menupopup; + + // select one of our test cases: + let handlerItem = list.querySelector("menuitem[data-l10n-args*='Handler 1']"); + await selectItemInPopup(handlerItem); + let { preferredAction, alwaysAskBeforeHandling } = + HandlerServiceTestUtils.getHandlerInfo(itemType); + Assert.notEqual( + preferredAction, + Ci.nsIHandlerInfo.alwaysAsk, + "Should have selected something other than 'always ask' (" + itemType + ")" + ); + Assert.ok( + !alwaysAskBeforeHandling, + "Should have turned off asking before handling (" + itemType + ")" + ); + + // Test the alwaysAsk option + let alwaysAskItem = list.getElementsByAttribute( + "action", + Ci.nsIHandlerInfo.alwaysAsk + )[0]; + await selectItemInPopup(alwaysAskItem); + Assert.equal( + list.selectedItem, + alwaysAskItem, + "Should have selected always ask item (" + itemType + ")" + ); + alwaysAskBeforeHandling = + HandlerServiceTestUtils.getHandlerInfo(itemType).alwaysAskBeforeHandling; + Assert.ok( + alwaysAskBeforeHandling, + "Should have turned on asking before handling (" + itemType + ")" + ); + + let useDefaultItem = list.getElementsByAttribute( + "action", + Ci.nsIHandlerInfo.useSystemDefault + ); + useDefaultItem = useDefaultItem && useDefaultItem[0]; + if (useDefaultItem) { + await selectItemInPopup(useDefaultItem); + Assert.equal( + list.selectedItem, + useDefaultItem, + "Should have selected 'use default' item (" + itemType + ")" + ); + preferredAction = + HandlerServiceTestUtils.getHandlerInfo(itemType).preferredAction; + Assert.equal( + preferredAction, + Ci.nsIHandlerInfo.useSystemDefault, + "Should have selected 'use default' (" + itemType + ")" + ); + } else { + // Whether there's a "use default" item depends on the OS, so it's not + // possible to rely on it being the case or not. + info("No 'Use default' item, so not testing (" + itemType + ")"); + } + + // Select a web app item. + let webAppItems = Array.from( + popup.getElementsByAttribute("action", Ci.nsIHandlerInfo.useHelperApp) + ); + webAppItems = webAppItems.filter( + item => item.handlerApp instanceof Ci.nsIWebHandlerApp + ); + Assert.equal( + webAppItems.length, + 2, + "Should have 2 web application handler. (" + itemType + ")" + ); + Assert.notEqual( + webAppItems[0].label, + webAppItems[1].label, + "Should have 2 different web app handlers" + ); + let selectedItem = await selectItemInPopup(webAppItems[0]); + + // Test that the selected item label is the same as the label + // of the menu item. + let win = gBrowser.selectedBrowser.contentWindow; + await win.document.l10n.translateFragment(selectedItem); + await win.document.l10n.translateFragment(itemToUse); + Assert.equal( + selectedItem.label, + itemToUse.querySelector(".actionContainer label").value, + "Should have selected correct item (" + itemType + ")" + ); + let { preferredApplicationHandler } = + HandlerServiceTestUtils.getHandlerInfo(itemType); + preferredApplicationHandler.QueryInterface(Ci.nsIWebHandlerApp); + Assert.equal( + selectedItem.handlerApp.uriTemplate, + preferredApplicationHandler.uriTemplate, + "App should actually be selected in the backend. (" + itemType + ")" + ); + + // select the other web app item + selectedItem = await selectItemInPopup(webAppItems[1]); + + // Test that the selected item label is the same as the label + // of the menu item + await win.document.l10n.translateFragment(selectedItem); + await win.document.l10n.translateFragment(itemToUse); + Assert.equal( + selectedItem.label, + itemToUse.querySelector(".actionContainer label").value, + "Should have selected correct item (" + itemType + ")" + ); + preferredApplicationHandler = + HandlerServiceTestUtils.getHandlerInfo( + itemType + ).preferredApplicationHandler; + preferredApplicationHandler.QueryInterface(Ci.nsIWebHandlerApp); + Assert.equal( + selectedItem.handlerApp.uriTemplate, + preferredApplicationHandler.uriTemplate, + "App should actually be selected in the backend. (" + itemType + ")" + ); +} + +add_task(async function checkDropdownBehavior() { + let win = gBrowser.selectedBrowser.contentWindow; + + let container = win.document.getElementById("handlersView"); + + // First check a protocol handler item. + let mailItem = container.querySelector("richlistitem[type='mailto']"); + Assert.ok(mailItem, "mailItem is present in handlersView."); + await selectStandardOptions(mailItem); + + // Then check a content menu item. + let pdfItem = container.querySelector("richlistitem[type='application/pdf']"); + Assert.ok(pdfItem, "pdfItem is present in handlersView."); + await selectStandardOptions(pdfItem); +}); + +add_task(async function sortingCheck() { + let win = gBrowser.selectedBrowser.contentWindow; + const handlerView = win.document.getElementById("handlersView"); + const typeColumn = win.document.getElementById("typeColumn"); + Assert.ok(typeColumn, "typeColumn is present in handlersView."); + + let expectedNumberOfItems = + handlerView.querySelectorAll("richlistitem").length; + + // Test default sorting + assertSortByType("ascending"); + + const oldDir = typeColumn.getAttribute("sortDirection"); + + // click on an item and sort again: + let itemToUse = handlerView.querySelector("richlistitem[type=mailto]"); + itemToUse.scrollIntoView({ block: "center" }); + itemToUse.closest("richlistbox").selectItem(itemToUse); + + // Test sorting on the type column + typeColumn.click(); + assertSortByType("descending"); + Assert.notEqual( + oldDir, + typeColumn.getAttribute("sortDirection"), + "Sort direction should change" + ); + + typeColumn.click(); + assertSortByType("ascending"); + + const actionColumn = win.document.getElementById("actionColumn"); + Assert.ok(actionColumn, "actionColumn is present in handlersView."); + + // Test sorting on the action column + const oldActionDir = actionColumn.getAttribute("sortDirection"); + actionColumn.click(); + assertSortByAction("ascending"); + Assert.notEqual( + oldActionDir, + actionColumn.getAttribute("sortDirection"), + "Sort direction should change" + ); + + actionColumn.click(); + assertSortByAction("descending"); + + // Restore the default sort order + typeColumn.click(); + assertSortByType("ascending"); + + function assertSortByAction(order) { + Assert.equal( + actionColumn.getAttribute("sortDirection"), + order, + `Sort direction should be ${order}` + ); + let siteItems = handlerView.getElementsByTagName("richlistitem"); + Assert.equal( + siteItems.length, + expectedNumberOfItems, + "Number of items should not change." + ); + for (let i = 0; i < siteItems.length - 1; ++i) { + let aType = siteItems[i].getAttribute("actionDescription").toLowerCase(); + let bType = siteItems[i + 1] + .getAttribute("actionDescription") + .toLowerCase(); + let result = 0; + if (aType > bType) { + result = 1; + } else if (bType > aType) { + result = -1; + } + if (order == "ascending") { + Assert.lessOrEqual( + result, + 0, + "Should sort applications in the ascending order by action" + ); + } else { + Assert.greaterOrEqual( + result, + 0, + "Should sort applications in the descending order by action" + ); + } + } + } + + function assertSortByType(order) { + Assert.equal( + typeColumn.getAttribute("sortDirection"), + order, + `Sort direction should be ${order}` + ); + + let siteItems = handlerView.getElementsByTagName("richlistitem"); + Assert.equal( + siteItems.length, + expectedNumberOfItems, + "Number of items should not change." + ); + for (let i = 0; i < siteItems.length - 1; ++i) { + let aType = siteItems[i].getAttribute("typeDescription").toLowerCase(); + let bType = siteItems[i + 1] + .getAttribute("typeDescription") + .toLowerCase(); + let result = 0; + if (aType > bType) { + result = 1; + } else if (bType > aType) { + result = -1; + } + if (order == "ascending") { + Assert.lessOrEqual( + result, + 0, + "Should sort applications in the ascending order by type" + ); + } else { + Assert.greaterOrEqual( + result, + 0, + "Should sort applications in the descending order by type" + ); + } + } + } +}); diff --git a/browser/components/preferences/tests/browser_basic_rebuild_fonts_test.js b/browser/components/preferences/tests/browser_basic_rebuild_fonts_test.js new file mode 100644 index 0000000000..bacda8a6b4 --- /dev/null +++ b/browser/components/preferences/tests/browser_basic_rebuild_fonts_test.js @@ -0,0 +1,235 @@ +add_task(async function () { + await openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true }); + await gBrowser.contentWindow.gMainPane._selectDefaultLanguageGroupPromise; + await TestUtils.waitForCondition( + () => !gBrowser.contentWindow.Preferences.updateQueued + ); + + let doc = gBrowser.contentDocument; + let contentWindow = gBrowser.contentWindow; + var langGroup = Services.prefs.getComplexValue( + "font.language.group", + Ci.nsIPrefLocalizedString + ).data; + is( + contentWindow.Preferences.get("font.language.group").value, + langGroup, + "Language group should be set correctly." + ); + + let defaultFontType = Services.prefs.getCharPref("font.default." + langGroup); + let fontFamilyPref = "font.name." + defaultFontType + "." + langGroup; + let fontFamily = Services.prefs.getCharPref(fontFamilyPref); + let fontFamilyField = doc.getElementById("defaultFont"); + is(fontFamilyField.value, fontFamily, "Font family should be set correctly."); + + function dispatchMenuItemCommand(menuItem) { + const cmdEvent = doc.createEvent("xulcommandevent"); + cmdEvent.initCommandEvent( + "command", + true, + true, + contentWindow, + 0, + false, + false, + false, + false, + 0, + null, + 0 + ); + menuItem.dispatchEvent(cmdEvent); + } + + /** + * Return a promise that resolves when the fontFamilyPref changes. + * + * Font prefs are the only ones whose form controls set "delayprefsave", + * which delays the pref change when a user specifies a new value + * for the pref. Thus, in order to confirm that the pref gets changed + * when the test selects a new value in a font field, we need to await + * the change. Awaiting this function does so for fontFamilyPref. + */ + function fontFamilyPrefChanged() { + return new Promise(resolve => { + const observer = { + observe(aSubject, aTopic, aData) { + // Check for an exact match to avoid the ambiguity of nsIPrefBranch's + // prefix-matching algorithm for notifying pref observers. + if (aData == fontFamilyPref) { + Services.prefs.removeObserver(fontFamilyPref, observer); + resolve(); + } + }, + }; + Services.prefs.addObserver(fontFamilyPref, observer); + }); + } + + const menuItems = fontFamilyField.querySelectorAll("menuitem"); + ok(menuItems.length > 1, "There are multiple font menuitems."); + ok(menuItems[0].selected, "The first (default) font menuitem is selected."); + + dispatchMenuItemCommand(menuItems[1]); + ok(menuItems[1].selected, "The second font menuitem is selected."); + + await fontFamilyPrefChanged(); + fontFamily = Services.prefs.getCharPref(fontFamilyPref); + is(fontFamilyField.value, fontFamily, "The font family has been updated."); + + dispatchMenuItemCommand(menuItems[0]); + ok( + menuItems[0].selected, + "The first (default) font menuitem is selected again." + ); + + await fontFamilyPrefChanged(); + fontFamily = Services.prefs.getCharPref(fontFamilyPref); + is(fontFamilyField.value, fontFamily, "The font family has been updated."); + + let defaultFontSize = Services.prefs.getIntPref( + "font.size.variable." + langGroup + ); + let fontSizeField = doc.getElementById("defaultFontSize"); + is( + fontSizeField.value, + "" + defaultFontSize, + "Font size should be set correctly." + ); + + let promiseSubDialogLoaded = promiseLoadSubDialog( + "chrome://browser/content/preferences/dialogs/fonts.xhtml" + ); + doc.getElementById("advancedFonts").click(); + let win = await promiseSubDialogLoaded; + doc = win.document; + + // Simulate a dumb font backend. + win.FontBuilder._enumerator = { + _list: ["MockedFont1", "MockedFont2", "MockedFont3"], + _defaultFont: null, + EnumerateFontsAsync(lang, type) { + return Promise.resolve(this._list); + }, + EnumerateAllFontsAsync() { + return Promise.resolve(this._list); + }, + getDefaultFont() { + return this._defaultFont; + }, + getStandardFamilyName(name) { + return name; + }, + }; + win.FontBuilder._allFonts = null; + win.FontBuilder._langGroupSupported = false; + + let langGroupElement = win.Preferences.get("font.language.group"); + let selectLangsField = doc.getElementById("selectLangs"); + let serifField = doc.getElementById("serif"); + let armenian = "x-armn"; + let western = "x-western"; + + // Await rebuilding of the font lists, which happens asynchronously in + // gFontsDialog._selectLanguageGroup. Testing code needs to call this + // function and await its resolution after changing langGroupElement's value + // (or doing anything else that triggers a call to _selectLanguageGroup). + function fontListsRebuilt() { + return win.gFontsDialog._selectLanguageGroupPromise; + } + + langGroupElement.value = armenian; + await fontListsRebuilt(); + selectLangsField.value = armenian; + is(serifField.value, "", "Font family should not be set."); + + let armenianSerifElement = win.Preferences.get("font.name.serif.x-armn"); + + langGroupElement.value = western; + await fontListsRebuilt(); + selectLangsField.value = western; + + // Simulate a font backend supporting language-specific enumeration. + // NB: FontBuilder has cached the return value from EnumerateAllFonts(), + // so _allFonts will always have 3 elements regardless of subsequent + // _list changes. + win.FontBuilder._enumerator._list = ["MockedFont2"]; + + langGroupElement.value = armenian; + await fontListsRebuilt(); + selectLangsField.value = armenian; + is( + serifField.value, + "", + "Font family should still be empty for indicating using 'default' font." + ); + + langGroupElement.value = western; + await fontListsRebuilt(); + selectLangsField.value = western; + + // Simulate a system that has no fonts for the specified language. + win.FontBuilder._enumerator._list = []; + + langGroupElement.value = armenian; + await fontListsRebuilt(); + selectLangsField.value = armenian; + is(serifField.value, "", "Font family should not be set."); + + // Setting default font to "MockedFont3". Then, when serifField.value is + // empty, it should indicate using "MockedFont3" but it shouldn't be saved + // to "MockedFont3" in the pref. It should be resolved at runtime. + win.FontBuilder._enumerator._list = [ + "MockedFont1", + "MockedFont2", + "MockedFont3", + ]; + win.FontBuilder._enumerator._defaultFont = "MockedFont3"; + langGroupElement.value = armenian; + await fontListsRebuilt(); + selectLangsField.value = armenian; + is( + serifField.value, + "", + "Font family should be empty even if there is a default font." + ); + + armenianSerifElement.value = "MockedFont2"; + serifField.value = "MockedFont2"; + is( + serifField.value, + "MockedFont2", + 'Font family should be "MockedFont2" for now.' + ); + + langGroupElement.value = western; + await fontListsRebuilt(); + selectLangsField.value = western; + is(serifField.value, "", "Font family of other language should not be set."); + + langGroupElement.value = armenian; + await fontListsRebuilt(); + selectLangsField.value = armenian; + is( + serifField.value, + "MockedFont2", + "Font family should not be changed even after switching the language." + ); + + // If MochedFont2 is removed from the system, the value should be treated + // as empty (i.e., 'default' font) after rebuilding the font list. + win.FontBuilder._enumerator._list = ["MockedFont1", "MockedFont3"]; + win.FontBuilder._enumerator._allFonts = ["MockedFont1", "MockedFont3"]; + serifField.removeAllItems(); // This will cause rebuilding the font list from available fonts. + langGroupElement.value = armenian; + await fontListsRebuilt(); + selectLangsField.value = armenian; + is( + serifField.value, + "", + "Font family should become empty due to the font uninstalled." + ); + + gBrowser.removeCurrentTab(); +}); diff --git a/browser/components/preferences/tests/browser_browser_languages_subdialog.js b/browser/components/preferences/tests/browser_browser_languages_subdialog.js new file mode 100644 index 0000000000..8b57bf08a8 --- /dev/null +++ b/browser/components/preferences/tests/browser_browser_languages_subdialog.js @@ -0,0 +1,1058 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { AddonTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/AddonTestUtils.sys.mjs" +); + +AddonTestUtils.initMochitest(this); + +const BROWSER_LANGUAGES_URL = + "chrome://browser/content/preferences/dialogs/browserLanguages.xhtml"; +const DICTIONARY_ID_PL = "pl@dictionaries.addons.mozilla.org"; +const TELEMETRY_CATEGORY = "intl.ui.browserLanguage"; + +function langpackId(locale) { + return `langpack-${locale}@firefox.mozilla.org`; +} + +function getManifestData(locale, version = "2.0") { + return { + langpack_id: locale, + name: `${locale} Language Pack`, + description: `${locale} Language pack`, + languages: { + [locale]: { + chrome_resources: { + branding: `browser/chrome/${locale}/locale/branding/`, + }, + version: "1", + }, + }, + browser_specific_settings: { + gecko: { + id: langpackId(locale), + strict_min_version: AppConstants.MOZ_APP_VERSION, + strict_max_version: AppConstants.MOZ_APP_VERSION, + }, + }, + version, + manifest_version: 2, + sources: { + browser: { + base_path: "browser/", + }, + }, + author: "Mozilla", + }; +} + +let testLocales = ["fr", "pl", "he"]; +let testLangpacks; + +function createLangpack(locale, version) { + return AddonTestUtils.createTempXPIFile({ + "manifest.json": getManifestData(locale, version), + [`browser/${locale}/branding/brand.ftl`]: "-brand-short-name = Firefox", + }); +} + +function createTestLangpacks() { + if (!testLangpacks) { + testLangpacks = Promise.all( + testLocales.map(async locale => [locale, await createLangpack(locale)]) + ); + } + return testLangpacks; +} + +function createLocaleResult(target_locale, url) { + return { + guid: langpackId(target_locale), + type: "language", + target_locale, + current_compatible_version: { + files: [ + { + platform: "all", + url, + }, + ], + }, + }; +} + +async function createLanguageToolsFile() { + let langpacks = await createTestLangpacks(); + let results = langpacks.map(([locale, file]) => + createLocaleResult(locale, Services.io.newFileURI(file).spec) + ); + + let filename = "language-tools.json"; + let files = { [filename]: { results } }; + let tempdir = AddonTestUtils.tempDir.clone(); + let dir = await AddonTestUtils.promiseWriteFilesToDir(tempdir.path, files); + dir.append(filename); + + return dir; +} + +async function createDictionaryBrowseResults() { + let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/")); + let dictionaryPath = testDir + "/addons/pl-dictionary.xpi"; + let filename = "dictionaries.json"; + let response = { + page_size: 25, + page_count: 1, + count: 1, + results: [ + { + current_version: { + id: 1823648, + compatibility: { + firefox: { max: "9999", min: "4.0" }, + }, + files: [ + { + platform: "all", + url: dictionaryPath, + }, + ], + version: "1.0.20160228", + }, + default_locale: "pl", + description: "Polish spell-check", + guid: DICTIONARY_ID_PL, + name: "Polish Dictionary", + slug: "polish-spellchecker-dictionary", + status: "public", + summary: "Polish dictionary", + type: "dictionary", + }, + ], + }; + + let files = { [filename]: response }; + let dir = await AddonTestUtils.promiseWriteFilesToDir( + AddonTestUtils.tempDir.path, + files + ); + dir.append(filename); + + return dir; +} + +function assertLocaleOrder(list, locales) { + is( + list.itemCount, + locales.split(",").length, + "The right number of locales are selected" + ); + is( + Array.from(list.children) + .map(child => child.value) + .join(","), + locales, + "The selected locales are in order" + ); +} + +function assertAvailableLocales(list, locales) { + let items = Array.from(list.menupopup.children); + let listLocales = items.filter(item => item.value && item.value != "search"); + is( + listLocales.length, + locales.length, + "The right number of locales are available" + ); + is( + listLocales + .map(item => item.value) + .sort() + .join(","), + locales.sort().join(","), + "The available locales match" + ); + is(items[0].getAttribute("class"), "label-item", "The first row is a label"); +} + +function getDialogId(dialogDoc) { + return dialogDoc.ownerGlobal.arguments[0].telemetryId; +} + +function assertTelemetryRecorded(events) { + let snapshot = Services.telemetry.snapshotEvents( + Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, + true + ); + + // Make sure we got some data. + ok( + snapshot.parent && !!snapshot.parent.length, + "Got parent telemetry events in the snapshot" + ); + + // Only look at the related events after stripping the timestamp and category. + let relatedEvents = snapshot.parent + .filter(([timestamp, category]) => category == TELEMETRY_CATEGORY) + .map(relatedEvent => relatedEvent.slice(2, 6)); + + // Events are now an array of: method, object[, value[, extra]] as expected. + Assert.deepEqual(relatedEvents, events, "The events are recorded correctly"); +} + +async function selectLocale(localeCode, available, selected, dialogDoc) { + let [locale] = Array.from(available.menupopup.children).filter( + item => item.value == localeCode + ); + available.selectedItem = locale; + + // Get ready for the selected list to change. + let added = waitForMutation(selected, { childList: true }, target => + Array.from(target.children).some(el => el.value == localeCode) + ); + + // Add the locale. + dialogDoc.getElementById("add").doCommand(); + + // Wait for the list to update. + await added; +} + +async function openDialog(doc, search = false) { + let dialogLoaded = promiseLoadSubDialog(BROWSER_LANGUAGES_URL); + if (search) { + doc.getElementById("primaryBrowserLocaleSearch").doCommand(); + doc.getElementById("primaryBrowserLocale").menupopup.hidePopup(); + } else { + doc.getElementById("manageBrowserLanguagesButton").doCommand(); + } + let dialogWin = await dialogLoaded; + let dialogDoc = dialogWin.document; + return { + dialog: dialogDoc.getElementById("BrowserLanguagesDialog"), + dialogDoc, + available: dialogDoc.getElementById("availableLocales"), + selected: dialogDoc.getElementById("selectedLocales"), + }; +} + +add_task(async function testDisabledBrowserLanguages() { + let langpacksFile = await createLanguageToolsFile(); + let langpacksUrl = Services.io.newFileURI(langpacksFile).spec; + + await SpecialPowers.pushPrefEnv({ + set: [ + ["intl.multilingual.enabled", true], + ["intl.multilingual.downloadEnabled", true], + ["intl.multilingual.liveReload", false], + ["intl.multilingual.liveReloadBidirectional", false], + ["intl.locale.requested", "en-US,pl,he,de"], + ["extensions.langpacks.signatures.required", false], + ["extensions.getAddons.langpacks.url", langpacksUrl], + ], + }); + + // Install an old pl langpack. + let oldLangpack = await createLangpack("pl", "1.0"); + await AddonTestUtils.promiseInstallFile(oldLangpack); + + // Install all the other available langpacks. + let pl; + let langpacks = await createTestLangpacks(); + let addons = await Promise.all( + langpacks.map(async ([locale, file]) => { + if (locale == "pl") { + pl = await AddonManager.getAddonByID(langpackId("pl")); + // Disable pl so it's removed from selected. + await pl.disable(); + return pl; + } + let install = await AddonTestUtils.promiseInstallFile(file); + return install.addon; + }) + ); + + await openPreferencesViaOpenPreferencesAPI("paneGeneral", { + leaveOpen: true, + }); + + let doc = gBrowser.contentDocument; + let { dialogDoc, available, selected } = await openDialog(doc); + + // pl is not selected since it's disabled. + is(pl.userDisabled, true, "pl is disabled"); + is(pl.version, "1.0", "pl is the old 1.0 version"); + assertLocaleOrder(selected, "en-US,he"); + + // Wait for the children menu to be populated. + await BrowserTestUtils.waitForCondition( + () => !!available.children.length, + "Children list populated" + ); + + // Only fr is enabled and not selected, so it's the only locale available. + assertAvailableLocales(available, ["fr"]); + + // Search for more languages. + available.menupopup.lastElementChild.doCommand(); + available.menupopup.hidePopup(); + await waitForMutation(available.menupopup, { childList: true }, target => + Array.from(available.menupopup.children).some( + locale => locale.value == "pl" + ) + ); + + // pl is now available since it is available remotely. + assertAvailableLocales(available, ["fr", "pl"]); + + let installId = null; + AddonTestUtils.promiseInstallEvent("onInstallEnded").then(([install]) => { + installId = install.installId; + }); + + // Add pl. + await selectLocale("pl", available, selected, dialogDoc); + assertLocaleOrder(selected, "pl,en-US,he"); + + // Find pl again since it's been upgraded. + pl = await AddonManager.getAddonByID(langpackId("pl")); + is(pl.userDisabled, false, "pl is now enabled"); + is(pl.version, "2.0", "pl is upgraded to version 2.0"); + + let dialogId = getDialogId(dialogDoc); + ok(dialogId, "There's a dialogId"); + ok(installId, "There's an installId"); + + await Promise.all(addons.map(addon => addon.uninstall())); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + assertTelemetryRecorded([ + ["manage", "main", dialogId], + ["search", "dialog", dialogId], + ["add", "dialog", dialogId, { installId }], + + // Cancel is recorded when the tab is closed. + ["cancel", "dialog", dialogId], + ]); +}); + +add_task(async function testReorderingBrowserLanguages() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["intl.multilingual.enabled", true], + ["intl.multilingual.downloadEnabled", true], + ["intl.multilingual.liveReload", false], + ["intl.multilingual.liveReloadBidirectional", false], + ["intl.locale.requested", "en-US,pl,he,de"], + ["extensions.langpacks.signatures.required", false], + ], + }); + + // Install all the available langpacks. + let langpacks = await createTestLangpacks(); + let addons = await Promise.all( + langpacks.map(async ([locale, file]) => { + let install = await AddonTestUtils.promiseInstallFile(file); + return install.addon; + }) + ); + + await openPreferencesViaOpenPreferencesAPI("paneGeneral", { + leaveOpen: true, + }); + + let doc = gBrowser.contentDocument; + let messageBar = doc.getElementById("confirmBrowserLanguage"); + is(messageBar.hidden, true, "The message bar is hidden at first"); + + // Open the dialog. + let { dialog, dialogDoc, selected } = await openDialog(doc); + let firstDialogId = getDialogId(dialogDoc); + + // The initial order is set by the pref, filtered by available. + assertLocaleOrder(selected, "en-US,pl,he"); + + // Moving pl down changes the order. + selected.selectedItem = selected.querySelector("[value='pl']"); + dialogDoc.getElementById("down").doCommand(); + assertLocaleOrder(selected, "en-US,he,pl"); + + // Accepting the change shows the confirm message bar. + let dialogClosed = BrowserTestUtils.waitForEvent(dialog, "dialogclosing"); + dialog.acceptDialog(); + await dialogClosed; + + // The message bar uses async `formatValues` and that may resolve + // after the dialog is closed. + await BrowserTestUtils.waitForMutationCondition( + messageBar, + { attributes: true }, + () => !messageBar.hidden + ); + is( + messageBar.querySelector("button").getAttribute("locales"), + "en-US,he,pl", + "The locales are set on the message bar button" + ); + + // Open the dialog again. + let newDialog = await openDialog(doc); + dialog = newDialog.dialog; + dialogDoc = newDialog.dialogDoc; + let secondDialogId = getDialogId(dialogDoc); + selected = newDialog.selected; + + // The initial order comes from the previous settings. + assertLocaleOrder(selected, "en-US,he,pl"); + + // Select pl in the list. + selected.selectedItem = selected.querySelector("[value='pl']"); + // Move pl back up. + dialogDoc.getElementById("up").doCommand(); + assertLocaleOrder(selected, "en-US,pl,he"); + + // Accepting the change hides the confirm message bar. + dialogClosed = BrowserTestUtils.waitForEvent(dialog, "dialogclosing"); + dialog.acceptDialog(); + await dialogClosed; + is(messageBar.hidden, true, "The message bar is hidden again"); + + ok(firstDialogId, "There was an id on the first dialog"); + ok(secondDialogId, "There was an id on the second dialog"); + ok(firstDialogId != secondDialogId, "The dialog ids are different"); + ok( + parseInt(firstDialogId) < parseInt(secondDialogId), + "The second dialog id is larger than the first" + ); + + await Promise.all(addons.map(addon => addon.uninstall())); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + assertTelemetryRecorded([ + ["manage", "main", firstDialogId], + ["reorder", "dialog", firstDialogId], + ["accept", "dialog", firstDialogId], + ["manage", "main", secondDialogId], + ["reorder", "dialog", secondDialogId], + ["accept", "dialog", secondDialogId], + ]); +}); + +add_task(async function testAddAndRemoveSelectedLanguages() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["intl.multilingual.enabled", true], + ["intl.multilingual.downloadEnabled", true], + ["intl.multilingual.liveReload", false], + ["intl.multilingual.liveReloadBidirectional", false], + ["intl.locale.requested", "en-US"], + ["extensions.langpacks.signatures.required", false], + ], + }); + + let langpacks = await createTestLangpacks(); + let addons = await Promise.all( + langpacks.map(async ([locale, file]) => { + let install = await AddonTestUtils.promiseInstallFile(file); + return install.addon; + }) + ); + + await openPreferencesViaOpenPreferencesAPI("paneGeneral", { + leaveOpen: true, + }); + + let doc = gBrowser.contentDocument; + let messageBar = doc.getElementById("confirmBrowserLanguage"); + is(messageBar.hidden, true, "The message bar is hidden at first"); + + // Open the dialog. + let { dialog, dialogDoc, available, selected } = await openDialog(doc); + let dialogId = getDialogId(dialogDoc); + + // loadLocalesFromAMO is async but `initAvailableLocales` doesn't wait + // for it to be resolved, so we have to wait for the list to be populated + // before we test for its values. + await BrowserTestUtils.waitForMutationCondition( + available.menupopup, + { attributes: true, childList: true }, + () => { + let listLocales = Array.from(available.menupopup.children).filter( + item => item.value && item.value != "search" + ); + return listLocales.length == 3; + } + ); + // The initial order is set by the pref. + assertLocaleOrder(selected, "en-US"); + assertAvailableLocales(available, ["fr", "pl", "he"]); + + // Add pl and fr to selected. + await selectLocale("pl", available, selected, dialogDoc); + await selectLocale("fr", available, selected, dialogDoc); + + assertLocaleOrder(selected, "fr,pl,en-US"); + assertAvailableLocales(available, ["he"]); + + // Remove pl and fr from selected. + dialogDoc.getElementById("remove").doCommand(); + dialogDoc.getElementById("remove").doCommand(); + assertLocaleOrder(selected, "en-US"); + assertAvailableLocales(available, ["fr", "pl", "he"]); + + // Add he to selected. + await selectLocale("he", available, selected, dialogDoc); + assertLocaleOrder(selected, "he,en-US"); + assertAvailableLocales(available, ["pl", "fr"]); + + // Accepting the change shows the confirm message bar. + let dialogClosed = BrowserTestUtils.waitForEvent(dialog, "dialogclosing"); + dialog.acceptDialog(); + await dialogClosed; + + await waitForMutation( + messageBar, + { attributes: true, attributeFilter: ["hidden"] }, + target => !target.hidden + ); + + is(messageBar.hidden, false, "The message bar is now visible"); + is( + messageBar.querySelector("button").getAttribute("locales"), + "he,en-US", + "The locales are set on the message bar button" + ); + + await Promise.all(addons.map(addon => addon.uninstall())); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + assertTelemetryRecorded([ + ["manage", "main", dialogId], + + // Install id is not recorded since it was already installed. + ["add", "dialog", dialogId], + ["add", "dialog", dialogId], + + ["remove", "dialog", dialogId], + ["remove", "dialog", dialogId], + + ["add", "dialog", dialogId], + ["accept", "dialog", dialogId], + ]); +}); + +add_task(async function testInstallFromAMO() { + let langpacks = await AddonManager.getAddonsByTypes(["locale"]); + is(langpacks.length, 0, "There are no langpacks installed"); + + let langpacksFile = await createLanguageToolsFile(); + let langpacksUrl = Services.io.newFileURI(langpacksFile).spec; + let dictionaryBrowseFile = await createDictionaryBrowseResults(); + let browseApiEndpoint = Services.io.newFileURI(dictionaryBrowseFile).spec; + + await SpecialPowers.pushPrefEnv({ + set: [ + ["intl.multilingual.enabled", true], + ["intl.multilingual.downloadEnabled", true], + ["intl.multilingual.liveReload", false], + ["intl.multilingual.liveReloadBidirectional", false], + ["intl.locale.requested", "en-US"], + ["extensions.getAddons.langpacks.url", langpacksUrl], + ["extensions.langpacks.signatures.required", false], + ["extensions.getAddons.get.url", browseApiEndpoint], + ], + }); + + await openPreferencesViaOpenPreferencesAPI("paneGeneral", { + leaveOpen: true, + }); + + let doc = gBrowser.contentDocument; + let messageBar = doc.getElementById("confirmBrowserLanguage"); + is(messageBar.hidden, true, "The message bar is hidden at first"); + + // Verify only en-US is listed on the main pane. + let getMainPaneLocales = () => { + let available = doc.getElementById("primaryBrowserLocale"); + let availableLocales = Array.from(available.menupopup.children); + return availableLocales + .map(item => item.value) + .sort() + .join(","); + }; + is(getMainPaneLocales(), "en-US,search", "Only en-US installed to start"); + + // Open the dialog. + let { dialog, dialogDoc, available, selected } = await openDialog(doc, true); + let firstDialogId = getDialogId(dialogDoc); + + // Make sure the message bar is still hidden. + is( + messageBar.hidden, + true, + "The message bar is still hidden after searching" + ); + + if (available.itemCount == 1) { + await waitForMutation( + available.menupopup, + { childList: true }, + target => available.itemCount > 1 + ); + } + + // The initial order is set by the pref. + assertLocaleOrder(selected, "en-US"); + assertAvailableLocales(available, ["fr", "he", "pl"]); + is( + Services.locale.availableLocales.join(","), + "en-US", + "There is only one installed locale" + ); + + // Verify that there are no extra dictionaries. + let dicts = await AddonManager.getAddonsByTypes(["dictionary"]); + is(dicts.length, 0, "There are no installed dictionaries"); + + let installId = null; + AddonTestUtils.promiseInstallEvent("onInstallEnded").then(([install]) => { + installId = install.installId; + }); + + // Add Polish, this will install the langpack. + await selectLocale("pl", available, selected, dialogDoc); + + ok(installId, "We got an installId for the langpack installation"); + + let langpack = await AddonManager.getAddonByID(langpackId("pl")); + Assert.deepEqual( + langpack.installTelemetryInfo, + { source: "about:preferences" }, + "The source is set to preferences" + ); + + // Verify the list is correct. + assertLocaleOrder(selected, "pl,en-US"); + assertAvailableLocales(available, ["fr", "he"]); + is( + Services.locale.availableLocales.sort().join(","), + "en-US,pl", + "Polish is now installed" + ); + + await BrowserTestUtils.waitForCondition(async () => { + let newDicts = await AddonManager.getAddonsByTypes(["dictionary"]); + let done = !!newDicts.length; + + if (done) { + is( + newDicts[0].id, + DICTIONARY_ID_PL, + "The polish dictionary was installed" + ); + } + + return done; + }); + + // Move pl down the list, which prevents an error since it isn't valid. + dialogDoc.getElementById("down").doCommand(); + assertLocaleOrder(selected, "en-US,pl"); + + // Test that disabling the langpack removes it from the list. + let dialogClosed = BrowserTestUtils.waitForEvent(dialog, "dialogclosing"); + dialog.acceptDialog(); + await dialogClosed; + + // Verify pl is now available to select. + is(getMainPaneLocales(), "en-US,pl,search", "en-US and pl now available"); + + // Disable the Polish langpack. + langpack = await AddonManager.getAddonByID("langpack-pl@firefox.mozilla.org"); + await langpack.disable(); + + ({ dialogDoc, available, selected } = await openDialog(doc, true)); + let secondDialogId = getDialogId(dialogDoc); + + // Wait for the available langpacks to load. + if (available.itemCount == 1) { + await waitForMutation( + available.menupopup, + { childList: true }, + target => available.itemCount > 1 + ); + } + assertLocaleOrder(selected, "en-US"); + assertAvailableLocales(available, ["fr", "he", "pl"]); + + // Uninstall the langpack and dictionary. + let installs = await AddonManager.getAddonsByTypes(["locale", "dictionary"]); + is(installs.length, 2, "There is one langpack and one dictionary installed"); + await Promise.all(installs.map(item => item.uninstall())); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + assertTelemetryRecorded([ + // First dialog installs a locale and accepts. + ["search", "main", firstDialogId], + // It has an installId since it was downloaded. + ["add", "dialog", firstDialogId, { installId }], + // It got moved down to avoid errors with finding translations. + ["reorder", "dialog", firstDialogId], + ["accept", "dialog", firstDialogId], + + // The second dialog just checks the state and is closed with the tab. + ["search", "main", secondDialogId], + ["cancel", "dialog", secondDialogId], + ]); +}); + +let hasSearchOption = popup => + Array.from(popup.children).some(el => el.value == "search"); + +add_task(async function testDownloadEnabled() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["intl.multilingual.enabled", true], + ["intl.multilingual.downloadEnabled", true], + ["intl.multilingual.liveReload", false], + ["intl.multilingual.liveReloadBidirectional", false], + ], + }); + + await openPreferencesViaOpenPreferencesAPI("paneGeneral", { + leaveOpen: true, + }); + let doc = gBrowser.contentDocument; + + let defaultMenulist = doc.getElementById("primaryBrowserLocale"); + ok( + hasSearchOption(defaultMenulist.menupopup), + "There's a search option in the General pane" + ); + + let { available } = await openDialog(doc, false); + ok( + hasSearchOption(available.menupopup), + "There's a search option in the dialog" + ); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +add_task(async function testDownloadDisabled() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["intl.multilingual.enabled", true], + ["intl.multilingual.downloadEnabled", false], + ["intl.multilingual.liveReload", false], + ["intl.multilingual.liveReloadBidirectional", false], + ], + }); + + await openPreferencesViaOpenPreferencesAPI("paneGeneral", { + leaveOpen: true, + }); + let doc = gBrowser.contentDocument; + + let defaultMenulist = doc.getElementById("primaryBrowserLocale"); + ok( + !hasSearchOption(defaultMenulist.menupopup), + "There's no search option in the General pane" + ); + + let { available } = await openDialog(doc, false); + ok( + !hasSearchOption(available.menupopup), + "There's no search option in the dialog" + ); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +add_task(async function testReorderMainPane() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["intl.multilingual.enabled", true], + ["intl.multilingual.downloadEnabled", false], + ["intl.multilingual.liveReload", false], + ["intl.multilingual.liveReloadBidirectional", false], + ["intl.locale.requested", "en-US"], + ["extensions.langpacks.signatures.required", false], + ], + }); + + // Clear the telemetry from other tests. + Services.telemetry.clearEvents(); + + let langpacks = await createTestLangpacks(); + let addons = await Promise.all( + langpacks.map(async ([locale, file]) => { + let install = await AddonTestUtils.promiseInstallFile(file); + return install.addon; + }) + ); + + await openPreferencesViaOpenPreferencesAPI("paneGeneral", { + leaveOpen: true, + }); + let doc = gBrowser.contentDocument; + + let messageBar = doc.getElementById("confirmBrowserLanguage"); + is(messageBar.hidden, true, "The message bar is hidden at first"); + + let available = doc.getElementById("primaryBrowserLocale"); + let availableLocales = Array.from(available.menupopup.children); + let availableCodes = availableLocales + .map(item => item.value) + .sort() + .join(","); + is( + availableCodes, + "en-US,fr,he,pl", + "All of the available locales are listed" + ); + + is(available.selectedItem.value, "en-US", "English is selected"); + + let hebrew = availableLocales.find(item => item.value == "he"); + hebrew.click(); + available.menupopup.hidePopup(); + + await BrowserTestUtils.waitForCondition( + () => !messageBar.hidden, + "Wait for message bar to show" + ); + + is(messageBar.hidden, false, "The message bar is now shown"); + is( + messageBar.querySelector("button").getAttribute("locales"), + "he,en-US", + "The locales are set on the message bar button" + ); + + await Promise.all(addons.map(addon => addon.uninstall())); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + assertTelemetryRecorded([["reorder", "main"]]); +}); + +add_task(async function testLiveLanguageReloading() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["intl.multilingual.enabled", true], + ["intl.multilingual.downloadEnabled", true], + ["intl.multilingual.liveReload", true], + ["intl.multilingual.liveReloadBidirectional", false], + ["intl.locale.requested", "en-US,fr,he,de"], + ["extensions.langpacks.signatures.required", false], + ], + }); + + // Clear the telemetry from other tests. + Services.telemetry.clearEvents(); + + let langpacks = await createTestLangpacks(); + let addons = await Promise.all( + langpacks.map(async ([locale, file]) => { + let install = await AddonTestUtils.promiseInstallFile(file); + return install.addon; + }) + ); + + await openPreferencesViaOpenPreferencesAPI("paneGeneral", { + leaveOpen: true, + }); + + let doc = gBrowser.contentDocument; + + let available = doc.getElementById("primaryBrowserLocale"); + let availableLocales = Array.from(available.menupopup.children); + + is( + Services.locale.appLocaleAsBCP47, + "en-US", + "The app locale starts as English." + ); + + Assert.deepEqual( + Services.locale.requestedLocales, + ["en-US", "fr", "he", "de"], + "The locale order starts as what was initially requested." + ); + + // French and English are both LTR languages. + let french = availableLocales.find(item => item.value == "fr"); + + french.click(); + available.menupopup.hidePopup(); + + is( + Services.locale.appLocaleAsBCP47, + "fr", + "The app locale was changed to French" + ); + + Assert.deepEqual( + Services.locale.requestedLocales, + ["fr", "en-US", "he", "de"], + "The locale order is switched to french first." + ); + + await Promise.all(addons.map(addon => addon.uninstall())); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + assertTelemetryRecorded([["reorder", "main"]]); +}); + +add_task(async function testLiveLanguageReloadingBidiOff() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["intl.multilingual.enabled", true], + ["intl.multilingual.downloadEnabled", true], + ["intl.multilingual.liveReload", true], + ["intl.multilingual.liveReloadBidirectional", false], + ["intl.locale.requested", "en-US,fr,he,de"], + ["extensions.langpacks.signatures.required", false], + ], + }); + + // Clear the telemetry from other tests. + Services.telemetry.clearEvents(); + + let langpacks = await createTestLangpacks(); + let addons = await Promise.all( + langpacks.map(async ([locale, file]) => { + let install = await AddonTestUtils.promiseInstallFile(file); + return install.addon; + }) + ); + + await openPreferencesViaOpenPreferencesAPI("paneGeneral", { + leaveOpen: true, + }); + + let doc = gBrowser.contentDocument; + + let available = doc.getElementById("primaryBrowserLocale"); + let availableLocales = Array.from(available.menupopup.children); + + is( + Services.locale.appLocaleAsBCP47, + "en-US", + "The app locale starts as English." + ); + + Assert.deepEqual( + Services.locale.requestedLocales, + ["en-US", "fr", "he", "de"], + "The locale order starts as what was initially requested." + ); + + let messageBar = doc.getElementById("confirmBrowserLanguage"); + is(messageBar.hidden, true, "The message bar is hidden at first"); + + // English is LTR and Hebrew is RTL. + let hebrew = availableLocales.find(item => item.value == "he"); + + hebrew.click(); + available.menupopup.hidePopup(); + + await BrowserTestUtils.waitForCondition( + () => !messageBar.hidden, + "Wait for message bar to show" + ); + + is(messageBar.hidden, false, "The message bar is now shown"); + + is( + Services.locale.appLocaleAsBCP47, + "en-US", + "The app locale remains in English" + ); + + Assert.deepEqual( + Services.locale.requestedLocales, + ["en-US", "fr", "he", "de"], + "The locale order did not change." + ); + + await Promise.all(addons.map(addon => addon.uninstall())); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + assertTelemetryRecorded([["reorder", "main"]]); +}); + +add_task(async function testLiveLanguageReloadingBidiOn() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["intl.multilingual.enabled", true], + ["intl.multilingual.downloadEnabled", true], + ["intl.multilingual.liveReload", true], + ["intl.multilingual.liveReloadBidirectional", true], + ["intl.locale.requested", "en-US,fr,he,de"], + ["extensions.langpacks.signatures.required", false], + ], + }); + + // Clear the telemetry from other tests. + Services.telemetry.clearEvents(); + + let langpacks = await createTestLangpacks(); + let addons = await Promise.all( + langpacks.map(async ([locale, file]) => { + let install = await AddonTestUtils.promiseInstallFile(file); + return install.addon; + }) + ); + + await openPreferencesViaOpenPreferencesAPI("paneGeneral", { + leaveOpen: true, + }); + + let doc = gBrowser.contentDocument; + + let available = doc.getElementById("primaryBrowserLocale"); + let availableLocales = Array.from(available.menupopup.children); + + is( + Services.locale.appLocaleAsBCP47, + "en-US", + "The app locale starts as English." + ); + + Assert.deepEqual( + Services.locale.requestedLocales, + ["en-US", "fr", "he", "de"], + "The locale order starts as what was initially requested." + ); + + let messageBar = doc.getElementById("confirmBrowserLanguage"); + is(messageBar.hidden, true, "The message bar is hidden at first"); + + // English is LTR and Hebrew is RTL. + let hebrew = availableLocales.find(item => item.value == "he"); + + hebrew.click(); + available.menupopup.hidePopup(); + + is(messageBar.hidden, true, "The message bar is still hidden"); + + is( + Services.locale.appLocaleAsBCP47, + "he", + "The app locale was changed to Hebrew." + ); + + Assert.deepEqual( + Services.locale.requestedLocales, + ["he", "en-US", "fr", "de"], + "The locale changed with Hebrew first." + ); + + await Promise.all(addons.map(addon => addon.uninstall())); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + assertTelemetryRecorded([["reorder", "main"]]); +}); diff --git a/browser/components/preferences/tests/browser_bug1018066_resetScrollPosition.js b/browser/components/preferences/tests/browser_bug1018066_resetScrollPosition.js new file mode 100644 index 0000000000..bc928656ab --- /dev/null +++ b/browser/components/preferences/tests/browser_bug1018066_resetScrollPosition.js @@ -0,0 +1,30 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +var originalWindowHeight; +registerCleanupFunction(function () { + window.resizeTo(window.outerWidth, originalWindowHeight); + while (gBrowser.tabs[1]) { + gBrowser.removeTab(gBrowser.tabs[1]); + } +}); + +add_task(async function () { + originalWindowHeight = window.outerHeight; + window.resizeTo(window.outerWidth, 300); + let prefs = await openPreferencesViaOpenPreferencesAPI("paneSearch", { + leaveOpen: true, + }); + is(prefs.selectedPane, "paneSearch", "Search pane was selected"); + let mainContent = gBrowser.contentDocument.querySelector(".main-content"); + mainContent.scrollTop = 50; + is(mainContent.scrollTop, 50, "main-content should be scrolled 50 pixels"); + + await gBrowser.contentWindow.gotoPref("paneGeneral"); + + is( + mainContent.scrollTop, + 0, + "Switching to a different category should reset the scroll position" + ); +}); diff --git a/browser/components/preferences/tests/browser_bug1020245_openPreferences_to_paneContent.js b/browser/components/preferences/tests/browser_bug1020245_openPreferences_to_paneContent.js new file mode 100644 index 0000000000..26e79b648d --- /dev/null +++ b/browser/components/preferences/tests/browser_bug1020245_openPreferences_to_paneContent.js @@ -0,0 +1,163 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test opening to the differerent panes and subcategories in Preferences +add_task(async function () { + let prefs = await openPreferencesViaOpenPreferencesAPI("panePrivacy"); + is(prefs.selectedPane, "panePrivacy", "Privacy pane was selected"); + prefs = await openPreferencesViaHash("privacy"); + is( + prefs.selectedPane, + "panePrivacy", + "Privacy pane is selected when hash is 'privacy'" + ); + prefs = await openPreferencesViaOpenPreferencesAPI("nonexistant-category"); + is( + prefs.selectedPane, + "paneGeneral", + "General pane is selected by default when a nonexistant-category is requested" + ); + prefs = await openPreferencesViaHash("nonexistant-category"); + is( + prefs.selectedPane, + "paneGeneral", + "General pane is selected when hash is a nonexistant-category" + ); + prefs = await openPreferencesViaHash(); + is(prefs.selectedPane, "paneGeneral", "General pane is selected by default"); + prefs = await openPreferencesViaOpenPreferencesAPI("privacy-reports", { + leaveOpen: true, + }); + is(prefs.selectedPane, "panePrivacy", "Privacy pane is selected by default"); + let doc = gBrowser.contentDocument; + is( + doc.location.hash, + "#privacy", + "The subcategory should be removed from the URI" + ); + await TestUtils.waitForCondition( + () => doc.querySelector(".spotlight"), + "Wait for the reports section is spotlighted." + ); + is( + doc.querySelector(".spotlight").getAttribute("data-subcategory"), + "reports", + "The reports section is spotlighted." + ); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +// Test opening Preferences with subcategory on an existing Preferences tab. See bug 1358475. +add_task(async function () { + let prefs = await openPreferencesViaOpenPreferencesAPI("general", { + leaveOpen: true, + }); + is(prefs.selectedPane, "paneGeneral", "General pane is selected by default"); + let doc = gBrowser.contentDocument; + is( + doc.location.hash, + "#general", + "The subcategory should be removed from the URI" + ); + // The reasons that here just call the `openPreferences` API without the helping function are + // - already opened one about:preferences tab up there and + // - the goal is to test on the existing tab and + // - using `openPreferencesViaOpenPreferencesAPI` would introduce more handling of additional about:blank and unneccessary event + await openPreferences("privacy-reports"); + let selectedPane = gBrowser.contentWindow.history.state; + is(selectedPane, "panePrivacy", "Privacy pane should be selected"); + is( + doc.location.hash, + "#privacy", + "The subcategory should be removed from the URI" + ); + await TestUtils.waitForCondition( + () => doc.querySelector(".spotlight"), + "Wait for the reports section is spotlighted." + ); + is( + doc.querySelector(".spotlight").getAttribute("data-subcategory"), + "reports", + "The reports section is spotlighted." + ); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +// Test opening to a subcategory displays the correct values for preferences +add_task(async function () { + // Skip if crash reporting isn't enabled since the checkbox will be missing. + if (!AppConstants.MOZ_CRASHREPORTER) { + return; + } + + await SpecialPowers.pushPrefEnv({ + set: [["browser.crashReports.unsubmittedCheck.autoSubmit2", true]], + }); + await openPreferencesViaOpenPreferencesAPI("privacy-reports", { + leaveOpen: true, + }); + + let doc = gBrowser.contentDocument; + ok( + doc.querySelector("#automaticallySubmitCrashesBox").checked, + "Checkbox for automatically submitting crashes should be checked when the pref is true and only Reports are requested" + ); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + await SpecialPowers.popPrefEnv(); +}); + +add_task(async function () { + // Skip if crash reporting isn't enabled since the checkbox will be missing. + if (!AppConstants.MOZ_CRASHREPORTER) { + return; + } + + await SpecialPowers.pushPrefEnv({ + set: [["browser.crashReports.unsubmittedCheck.autoSubmit2", false]], + }); + await openPreferencesViaOpenPreferencesAPI("privacy-reports", { + leaveOpen: true, + }); + + let doc = gBrowser.contentDocument; + ok( + !doc.querySelector("#automaticallySubmitCrashesBox").checked, + "Checkbox for automatically submitting crashes should not be checked when the pref is false only Reports are requested" + ); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + await SpecialPowers.popPrefEnv(); +}); + +function openPreferencesViaHash(aPane) { + return new Promise(resolve => { + let finalPrefPaneLoaded = TestUtils.topicObserved( + "sync-pane-loaded", + () => true + ); + gBrowser.selectedTab = BrowserTestUtils.addTab( + gBrowser, + "about:preferences" + (aPane ? "#" + aPane : "") + ); + let newTabBrowser = gBrowser.selectedBrowser; + + newTabBrowser.addEventListener( + "Initialized", + function () { + newTabBrowser.contentWindow.addEventListener( + "load", + async function () { + let win = gBrowser.contentWindow; + let selectedPane = win.history.state; + await finalPrefPaneLoaded; + gBrowser.removeCurrentTab(); + resolve({ selectedPane }); + }, + { once: true } + ); + }, + { capture: true, once: true } + ); + }); +} diff --git a/browser/components/preferences/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.js b/browser/components/preferences/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.js new file mode 100644 index 0000000000..ef387f9a9d --- /dev/null +++ b/browser/components/preferences/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.js @@ -0,0 +1,116 @@ +const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL; + +add_task(async function () { + waitForExplicitFinish(); + + const tabURL = + getRootDirectory(gTestPath) + + "browser_bug1184989_prevent_scrolling_when_preferences_flipped.xhtml"; + + await BrowserTestUtils.withNewTab( + { gBrowser, url: tabURL }, + async function (browser) { + let doc = browser.contentDocument; + let container = doc.getElementById("container"); + + // Test button + let button = doc.getElementById("button"); + button.focus(); + let initialScrollTop = container.scrollTop; + EventUtils.sendString(" "); + await checkPageScrolling(container, "button", initialScrollTop); + + // Test checkbox + let checkbox = doc.getElementById("checkbox"); + checkbox.focus(); + initialScrollTop = container.scrollTop; + EventUtils.sendString(" "); + ok(checkbox.checked, "Checkbox is checked"); + await checkPageScrolling(container, "checkbox", initialScrollTop); + + // Test radio + let radiogroup = doc.getElementById("radiogroup"); + radiogroup.focus(); + initialScrollTop = container.scrollTop; + EventUtils.sendString(" "); + await checkPageScrolling(container, "radio", initialScrollTop); + } + ); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:preferences#search" }, + async function (browser) { + let doc = browser.contentDocument; + let container = doc.getElementsByClassName("main-content")[0]; + + // Test search + let engineList = doc.getElementById("engineList"); + engineList.focus(); + let initialScrollTop = container.scrollTop; + EventUtils.sendString(" "); + is( + engineList.view.selection.currentIndex, + 0, + "Search engineList is selected" + ); + EventUtils.sendString(" "); + await checkPageScrolling( + container, + "search engineList", + initialScrollTop + ); + } + ); + + // Test session restore + const CRASH_URL = "about:mozilla"; + const CRASH_FAVICON = "chrome://branding/content/icon32.png"; + const CRASH_SHENTRY = { url: CRASH_URL }; + const CRASH_TAB = { entries: [CRASH_SHENTRY], image: CRASH_FAVICON }; + const CRASH_STATE = { windows: [{ tabs: [CRASH_TAB] }] }; + + const TAB_URL = "about:sessionrestore"; + const TAB_FORMDATA = { url: TAB_URL, id: { sessionData: CRASH_STATE } }; + const TAB_SHENTRY = { url: TAB_URL, triggeringPrincipal_base64 }; + const TAB_STATE = { entries: [TAB_SHENTRY], formdata: TAB_FORMDATA }; + + let tab = (gBrowser.selectedTab = BrowserTestUtils.addTab( + gBrowser, + "about:blank" + )); + + // Fake a post-crash tab + SessionStore.setTabState(tab, JSON.stringify(TAB_STATE)); + + await BrowserTestUtils.browserLoaded(tab.linkedBrowser); + let doc = tab.linkedBrowser.contentDocument; + + // Make body scrollable + doc.body.style.height = doc.body.clientHeight + 100 + "px"; + + let tabsToggle = doc.getElementById("tabsToggle"); + tabsToggle.focus(); + let initialScrollTop = doc.documentElement.scrollTop; + EventUtils.sendString(" "); + await checkPageScrolling( + doc.documentElement, + "session restore", + initialScrollTop + ); + + gBrowser.removeCurrentTab(); + finish(); +}); + +function checkPageScrolling(container, type, initialScrollTop = 0) { + return new Promise(resolve => { + setTimeout(() => { + is( + container.scrollTop, + initialScrollTop, + "Page should not scroll when " + type + " flipped" + ); + resolve(); + }, 0); + }); +} diff --git a/browser/components/preferences/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.xhtml b/browser/components/preferences/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.xhtml new file mode 100644 index 0000000000..8b3e39a39c --- /dev/null +++ b/browser/components/preferences/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.xhtml @@ -0,0 +1,26 @@ + + + + + + + +