summaryrefslogtreecommitdiffstats
path: root/toolkit/mozapps
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/mozapps')
-rw-r--r--toolkit/mozapps/defaultagent/BackgroundTask_defaultagent.sys.mjs45
-rw-r--r--toolkit/mozapps/defaultagent/DefaultAgent.cpp59
-rw-r--r--toolkit/mozapps/defaultagent/DefaultBrowser.cpp11
-rw-r--r--toolkit/mozapps/defaultagent/DefaultBrowser.h4
-rw-r--r--toolkit/mozapps/defaultagent/Notification.cpp602
-rw-r--r--toolkit/mozapps/defaultagent/Notification.h7
-rw-r--r--toolkit/mozapps/defaultagent/ScheduledTask.cpp3
-rw-r--r--toolkit/mozapps/defaultagent/SetDefaultBrowser.cpp393
-rw-r--r--toolkit/mozapps/defaultagent/defaultagent.ini9
-rw-r--r--toolkit/mozapps/defaultagent/moz.build20
-rw-r--r--toolkit/mozapps/defaultagent/nsIDefaultAgent.idl14
-rw-r--r--toolkit/mozapps/defaultagent/proxy/main.cpp2
-rw-r--r--toolkit/mozapps/defaultagent/proxy/moz.build1
-rw-r--r--toolkit/mozapps/downloads/DownloadLastDir.sys.mjs2
-rw-r--r--toolkit/mozapps/downloads/DownloadUtils.sys.mjs2
-rw-r--r--toolkit/mozapps/downloads/HelperAppDlg.sys.mjs32
-rw-r--r--toolkit/mozapps/downloads/tests/browser/browser_save_wrongextension.js2
-rw-r--r--toolkit/mozapps/downloads/tests/browser/browser_unknownContentType_delayedbutton.js6
-rw-r--r--toolkit/mozapps/downloads/tests/browser/browser_unknownContentType_dialog_layout.js4
-rw-r--r--toolkit/mozapps/downloads/tests/unit/test_lowMinutes.js2
-rw-r--r--toolkit/mozapps/extensions/AddonManager.sys.mjs4
-rw-r--r--toolkit/mozapps/extensions/content/aboutaddons.css12
-rw-r--r--toolkit/mozapps/extensions/content/aboutaddons.js27
-rw-r--r--toolkit/mozapps/extensions/content/aboutaddonsCommon.js6
-rw-r--r--toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs2
-rw-r--r--toolkit/mozapps/extensions/internal/AddonTestUtils.sys.mjs31
-rw-r--r--toolkit/mozapps/extensions/internal/AddonUpdateChecker.sys.mjs2
-rw-r--r--toolkit/mozapps/extensions/internal/SitePermsAddonProvider.sys.mjs23
-rw-r--r--toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs2
-rw-r--r--toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs33
-rw-r--r--toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs2
-rw-r--r--toolkit/mozapps/extensions/test/browser/browser.toml2
-rw-r--r--toolkit/mozapps/extensions/test/browser/browser_html_options_ui.js11
-rw-r--r--toolkit/mozapps/extensions/test/browser/browser_page_options_install_addon.js2
-rw-r--r--toolkit/mozapps/extensions/test/browser/browser_sidebar_preferences_button.js73
-rw-r--r--toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js4
-rw-r--r--toolkit/mozapps/extensions/test/xpcshell/test_system_update_enterprisepolicy.js26
-rw-r--r--toolkit/mozapps/handling/content/appChooser.js2
-rw-r--r--toolkit/mozapps/installer/packager.py2
-rw-r--r--toolkit/mozapps/update/AppUpdater.sys.mjs14
-rw-r--r--toolkit/mozapps/update/BackgroundUpdate.sys.mjs2
-rw-r--r--toolkit/mozapps/update/UpdateService.sys.mjs28
-rw-r--r--toolkit/mozapps/update/UpdateTelemetry.sys.mjs2
-rw-r--r--toolkit/mozapps/update/common/updatererrors.h18
-rw-r--r--toolkit/mozapps/update/docs/BackgroundUpdates.rst6
-rw-r--r--toolkit/mozapps/update/tests/browser/browser_elevationDialog.js4
-rw-r--r--toolkit/mozapps/update/tests/browser/head.js2
-rw-r--r--toolkit/mozapps/update/tests/data/app_update.sjs4
-rw-r--r--toolkit/mozapps/update/tests/data/shared.js2
-rw-r--r--toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js14
-rw-r--r--toolkit/mozapps/update/tests/marionette/test_no_window_update_restart.py4
-rw-r--r--toolkit/mozapps/update/tests/unit_aus_update/languagePackUpdates.js6
-rw-r--r--toolkit/mozapps/update/tests/unit_aus_update/multiUpdate.js10
-rw-r--r--toolkit/mozapps/update/tests/unit_aus_update/updateSyncManager.js4
-rw-r--r--toolkit/mozapps/update/tests/unit_background_update/test_backgroundupdate_glean.js6
-rw-r--r--toolkit/mozapps/update/updater/updater.cpp2
56 files changed, 695 insertions, 919 deletions
diff --git a/toolkit/mozapps/defaultagent/BackgroundTask_defaultagent.sys.mjs b/toolkit/mozapps/defaultagent/BackgroundTask_defaultagent.sys.mjs
index c727a55997..691f76c319 100644
--- a/toolkit/mozapps/defaultagent/BackgroundTask_defaultagent.sys.mjs
+++ b/toolkit/mozapps/defaultagent/BackgroundTask_defaultagent.sys.mjs
@@ -17,8 +17,6 @@ const EXIT_CODE = {
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
setTimeout: "resource://gre/modules/Timer.sys.mjs",
- BackgroundTasksUtils: "resource://gre/modules/BackgroundTasksUtils.sys.mjs",
- NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
// eslint-disable-next-line mozilla/no-browser-refs-in-toolkit
ShellService: "resource:///modules/ShellService.sys.mjs",
});
@@ -37,11 +35,20 @@ ChromeUtils.defineLazyGetter(lazy, "log", () => {
return new ConsoleAPI(consoleOptions);
});
-// Should be slightly longer than NOTIFICATION_WAIT_TIMEOUT_MS in
-// Notification.cpp (divided by 1000 to convert millseconds to seconds) to not
-// cause race between timeouts. Currently 12 hours + 5 additional minutes.
-export const backgroundTaskTimeoutSec = 12 * 60 * 60 + 60 * 5;
-const kNotificationTimeoutMs = 12 * 60 * 60 * 1000;
+// Should be slightly longer than kNotificationTimeoutMs and kGleanSendWait below
+// (divided by 1000 to convert millseconds to seconds) to not cause race
+// between timeouts.
+//
+// Additionally, should be less than the Windows Scheduled Task timeout
+// execTimeLimitBStr in ScheduledTask.cpp.
+//
+// Current bounds are 11 hours 55 minutes 10 seconds and 12 hours 5 minutes.
+export const backgroundTaskTimeoutSec = 12 * 60 * 60;
+
+// 11 hours 55 minutes in milliseconds.
+const kNotificationTimeoutMs = 11 * 60 * 60 * 1000 + 55 * 60 * 1000;
+// 10 seconds in milliseconds.
+const kGleanSendWait = 10000;
const kNotificationShown = Object.freeze({
notShown: "not-shown",
@@ -148,25 +155,11 @@ export async function runBackgroundTask(commandLine) {
lazy.log.info(`Running do-task with AUMID "${aumid}"`);
- let cppFallback = false;
try {
- await lazy.BackgroundTasksUtils.enableNimbus(commandLine);
- cppFallback =
- lazy.NimbusFeatures.defaultAgent.getVariable("cppFallback");
- } catch (e) {
- lazy.log.error(`Error enabling nimbus: ${e}`);
- }
-
- try {
- if (!cppFallback) {
- lazy.log.info("Running JS do-task.");
- await runWithRegistryLocked(async () => {
- await doTask(defaultAgent, force);
- });
- } else {
- lazy.log.info("Running C++ do-task.");
- defaultAgent.doTask(aumid, force);
- }
+ lazy.log.info("Running JS do-task.");
+ await runWithRegistryLocked(async () => {
+ await doTask(defaultAgent, force);
+ });
} catch (e) {
if (e.message) {
lazy.log.error(e.message);
@@ -181,7 +174,7 @@ export async function runBackgroundTask(commandLine) {
// Bug 1857333: We wait for arbitrary time for Glean to submit telemetry.
lazy.log.info("Pinged glean, waiting for submission.");
- await new Promise(resolve => lazy.setTimeout(resolve, 5000));
+ await new Promise(resolve => lazy.setTimeout(resolve, kGleanSendWait));
return EXIT_CODE.SUCCESS;
}
diff --git a/toolkit/mozapps/defaultagent/DefaultAgent.cpp b/toolkit/mozapps/defaultagent/DefaultAgent.cpp
index 2ebb5e466e..3bff6e3243 100644
--- a/toolkit/mozapps/defaultagent/DefaultAgent.cpp
+++ b/toolkit/mozapps/defaultagent/DefaultAgent.cpp
@@ -7,11 +7,8 @@
#include <windows.h>
#include <shlwapi.h>
#include <objbase.h>
-#include <string.h>
-#include <vector>
#include "nsAutoRef.h"
-#include "nsDebug.h"
#include "nsProxyRelease.h"
#include "nsWindowsHelpers.h"
#include "nsString.h"
@@ -304,62 +301,6 @@ DefaultAgent::Uninstall(const nsAString& aUniqueToken) {
}
NS_IMETHODIMP
-DefaultAgent::DoTask(const nsAString& aUniqueToken, const bool aForce) {
- // Acquire() has a short timeout. Since this runs in the background, we
- // could use a longer timeout in this situation. However, if another
- // installation's agent is already running, it will update CurrentDefault,
- // possibly send a ping, and possibly show a notification.
- // Once all that has happened, there is no real reason to do it again. We
- // only send one ping per day, so we aren't going to do that again. And
- // the only time we ever show a second notification is 7 days after the
- // first one, so we aren't going to do that again either.
- // If the other process didn't take those actions, there is no reason that
- // this process would take them.
- // If the other process fails, this one will most likely fail for the same
- // reason.
- // So we'll just bail if we can't get the mutex quickly.
- RegistryMutex regMutex;
- if (!regMutex.Acquire()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- // Check that Firefox ran recently, if not then stop here.
- // Also stop if no timestamp was found, which most likely indicates
- // that Firefox was not yet run.
- bool ranRecently = false;
- if (!aForce && (!CheckIfAppRanRecently(&ranRecently) || !ranRecently)) {
- return NS_ERROR_FAILURE;
- }
-
- DefaultBrowserResult defaultBrowserResult = GetDefaultBrowserInfo();
- DefaultBrowserInfo browserInfo{};
- if (defaultBrowserResult.isOk()) {
- browserInfo = defaultBrowserResult.unwrap();
- } else {
- browserInfo.currentDefaultBrowser = Browser::Error;
- browserInfo.previousDefaultBrowser = Browser::Error;
- }
-
- DefaultPdfResult defaultPdfResult = GetDefaultPdfInfo();
- DefaultPdfInfo pdfInfo{};
- if (defaultPdfResult.isOk()) {
- pdfInfo = defaultPdfResult.unwrap();
- } else {
- pdfInfo.currentDefaultPdf = PDFHandler::Error;
- }
-
- NotificationActivities activitiesPerformed;
- // We block while waiting for the notification which prevents STA thread
- // callbacks from running as the event loop won't run. Moving notification
- // handling to an MTA thread prevents this conflict.
- activitiesPerformed = MaybeShowNotification(
- browserInfo, PromiseFlatString(aUniqueToken).get(), aForce);
-
- HRESULT hr = SendDefaultAgentPing(browserInfo, pdfInfo, activitiesPerformed);
- return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
DefaultAgent::AppRanRecently(bool* aRanRecently) {
bool ranRecently = false;
*aRanRecently = CheckIfAppRanRecently(&ranRecently) && ranRecently;
diff --git a/toolkit/mozapps/defaultagent/DefaultBrowser.cpp b/toolkit/mozapps/defaultagent/DefaultBrowser.cpp
index 87d3f62632..d9543665b7 100644
--- a/toolkit/mozapps/defaultagent/DefaultBrowser.cpp
+++ b/toolkit/mozapps/defaultagent/DefaultBrowser.cpp
@@ -184,17 +184,6 @@ BrowserResult TryGetReplacePreviousDefaultBrowser(Browser currentDefault) {
return GetBrowserFromString(previousDefault);
}
-DefaultBrowserResult GetDefaultBrowserInfo() {
- DefaultBrowserInfo browserInfo;
-
- MOZ_TRY_VAR(browserInfo.currentDefaultBrowser, TryGetDefaultBrowser());
- MOZ_TRY_VAR(
- browserInfo.previousDefaultBrowser,
- TryGetReplacePreviousDefaultBrowser(browserInfo.currentDefaultBrowser));
-
- return browserInfo;
-}
-
// We used to prefix this key with the installation directory, but that causes
// problems with our new "only one ping per day across installs" restriction.
// To make sure all installations use consistent data, the value's name is
diff --git a/toolkit/mozapps/defaultagent/DefaultBrowser.h b/toolkit/mozapps/defaultagent/DefaultBrowser.h
index f1b940959f..081f3b9ccf 100644
--- a/toolkit/mozapps/defaultagent/DefaultBrowser.h
+++ b/toolkit/mozapps/defaultagent/DefaultBrowser.h
@@ -10,7 +10,6 @@
#include <string>
#include "mozilla/DefineEnum.h"
-#include "mozilla/WinHeaderOnlyUtils.h"
namespace mozilla::default_agent {
@@ -24,9 +23,6 @@ struct DefaultBrowserInfo {
Browser previousDefaultBrowser;
};
-using DefaultBrowserResult = mozilla::WindowsErrorResult<DefaultBrowserInfo>;
-
-DefaultBrowserResult GetDefaultBrowserInfo();
Browser GetDefaultBrowser();
Browser GetReplacePreviousDefaultBrowser(Browser currentBrowser);
diff --git a/toolkit/mozapps/defaultagent/Notification.cpp b/toolkit/mozapps/defaultagent/Notification.cpp
index 961e57c9b3..39236eac15 100644
--- a/toolkit/mozapps/defaultagent/Notification.cpp
+++ b/toolkit/mozapps/defaultagent/Notification.cpp
@@ -7,616 +7,22 @@
#include "Notification.h"
#include <shlwapi.h>
-#include <wchar.h>
#include <windows.h>
#include <winnt.h>
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/CmdLineAndEnvUtils.h"
-#include "mozilla/ErrorResult.h"
-#include "mozilla/mscom/EnsureMTA.h"
-#include "mozilla/intl/FileSource.h"
-#include "mozilla/intl/Localization.h"
-#include "mozilla/ShellHeaderOnlyUtils.h"
-#include "mozilla/UniquePtr.h"
-#include "mozilla/Unused.h"
-#include "mozilla/WinHeaderOnlyUtils.h"
-#include "nsString.h"
-#include "nsTArray.h"
-#include "nsWindowsHelpers.h"
-#include "readstrings.h"
-#include "updatererrors.h"
-#include "WindowsDefaultBrowser.h"
-
-#include "common.h"
-#include "DefaultBrowser.h"
-#include "EventLog.h"
-#include "Registry.h"
-#include "SetDefaultBrowser.h"
-
-#include "wintoastlib.h"
-
-using mozilla::intl::Localization;
+#include "nsLiteralString.h"
#define SEVEN_DAYS_IN_SECONDS (7 * 24 * 60 * 60)
-// If the notification hasn't been activated or dismissed within 12 hours,
-// stop waiting for it.
-#define NOTIFICATION_WAIT_TIMEOUT_MS (12 * 60 * 60 * 1000)
+// If the notification hasn't been activated or dismissed within 11 hours 55
+// minutes, stop waiting for it.
+#define NOTIFICATION_WAIT_TIMEOUT_MS (11 * 60 * 60 * 1000 + 55 * 60 * 1000)
// If the mutex hasn't been released within a few minutes, something is wrong
// and we should give up on it
#define MUTEX_TIMEOUT_MS (10 * 60 * 1000)
namespace mozilla::default_agent {
-bool FirefoxInstallIsEnglish();
-
-static bool SetInitialNotificationShown(bool wasShown) {
- return !RegistrySetValueBool(IsPrefixed::Unprefixed,
- L"InitialNotificationShown", wasShown)
- .isErr();
-}
-
-static bool GetInitialNotificationShown() {
- return RegistryGetValueBool(IsPrefixed::Unprefixed,
- L"InitialNotificationShown")
- .unwrapOr(mozilla::Some(false))
- .valueOr(false);
-}
-
-static bool ResetInitialNotificationShown() {
- return RegistryDeleteValue(IsPrefixed::Unprefixed,
- L"InitialNotificationShown")
- .isOk();
-}
-
-static bool SetFollowupNotificationShown(bool wasShown) {
- return !RegistrySetValueBool(IsPrefixed::Unprefixed,
- L"FollowupNotificationShown", wasShown)
- .isErr();
-}
-
-static bool GetFollowupNotificationShown() {
- return RegistryGetValueBool(IsPrefixed::Unprefixed,
- L"FollowupNotificationShown")
- .unwrapOr(mozilla::Some(false))
- .valueOr(false);
-}
-
-static bool SetFollowupNotificationSuppressed(bool value) {
- return !RegistrySetValueBool(IsPrefixed::Unprefixed,
- L"FollowupNotificationSuppressed", value)
- .isErr();
-}
-
-static bool GetFollowupNotificationSuppressed() {
- return RegistryGetValueBool(IsPrefixed::Unprefixed,
- L"FollowupNotificationSuppressed")
- .unwrapOr(mozilla::Some(false))
- .valueOr(false);
-}
-
-// Returns 0 if no value is set.
-static ULONGLONG GetFollowupNotificationRequestTime() {
- return RegistryGetValueQword(IsPrefixed::Unprefixed, L"FollowupRequestTime")
- .unwrapOr(mozilla::Some(0))
- .valueOr(0);
-}
-
-// Returns false if no value is set.
-static bool GetPrefSetDefaultBrowserUserChoice() {
- return RegistryGetValueBool(IsPrefixed::Prefixed,
- L"SetDefaultBrowserUserChoice")
- .unwrapOr(mozilla::Some(false))
- .valueOr(false);
-}
-
-struct ToastStrings {
- mozilla::UniquePtr<wchar_t[]> text1;
- mozilla::UniquePtr<wchar_t[]> text2;
- mozilla::UniquePtr<wchar_t[]> action1;
- mozilla::UniquePtr<wchar_t[]> action2;
- mozilla::UniquePtr<wchar_t[]> relImagePath;
-};
-
-struct Strings {
- // Toast notification button text is hard to localize because it tends to
- // overflow. Thus, we have 3 different toast notifications:
- // - The initial notification, which includes a button with text like
- // "Ask me later". Since we cannot easily localize this, we will display
- // it only in English.
- // - The followup notification, to be shown if the user clicked "Ask me
- // later". Since we only have that button in English, we only need this
- // notification in English.
- // - The localized notification, which has much shorter button text to
- // (hopefully) prevent overflow: just "Yes" and "No". Since we no longer
- // have an "Ask me later" button, a followup localized notification is not
- // needed.
- ToastStrings initialToast;
- ToastStrings followupToast;
- ToastStrings localizedToast;
-
- // Returned pointer points within this struct and should not be freed.
- const ToastStrings* GetToastStrings(NotificationType whichToast,
- bool englishStrings) const {
- if (!englishStrings) {
- return &localizedToast;
- }
- if (whichToast == NotificationType::Initial) {
- return &initialToast;
- }
- return &followupToast;
- }
-};
-
-// Gets all strings out of the relevant INI files.
-// Returns true on success, false on failure
-static bool GetStrings(Strings& strings) {
- mozilla::UniquePtr<wchar_t[]> installPath;
- bool success = GetInstallDirectory(installPath);
- if (!success) {
- LOG_ERROR_MESSAGE(L"Failed to get install directory when getting strings");
- return false;
- }
- nsTArray<nsCString> resIds = {"branding/brand.ftl"_ns,
- "browser/backgroundtasks/defaultagent.ftl"_ns};
- RefPtr<Localization> l10n = Localization::Create(resIds, true);
- nsAutoCString daHeaderText, daBodyText, daYesButton, daNoButton;
- mozilla::ErrorResult daRv;
- l10n->FormatValueSync("default-browser-notification-header-text"_ns, {},
- daHeaderText, daRv);
- ENSURE_SUCCESS(daRv, false);
- l10n->FormatValueSync("default-browser-notification-body-text"_ns, {},
- daBodyText, daRv);
- ENSURE_SUCCESS(daRv, false);
- l10n->FormatValueSync("default-browser-notification-yes-button-text"_ns, {},
- daYesButton, daRv);
- ENSURE_SUCCESS(daRv, false);
- l10n->FormatValueSync("default-browser-notification-no-button-text"_ns, {},
- daNoButton, daRv);
- ENSURE_SUCCESS(daRv, false);
-
- NS_ConvertUTF8toUTF16 daHeaderTextW(daHeaderText), daBodyTextW(daBodyText),
- daYesButtonW(daYesButton), daNoButtonW(daNoButton);
- strings.localizedToast.text1 =
- mozilla::MakeUnique<wchar_t[]>(daHeaderTextW.Length() + 1);
- wcsncpy(strings.localizedToast.text1.get(), daHeaderTextW.get(),
- daHeaderTextW.Length() + 1);
- strings.localizedToast.text2 =
- mozilla::MakeUnique<wchar_t[]>(daBodyTextW.Length() + 1);
- wcsncpy(strings.localizedToast.text2.get(), daBodyTextW.get(),
- daBodyTextW.Length() + 1);
- strings.localizedToast.action1 =
- mozilla::MakeUnique<wchar_t[]>(daYesButtonW.Length() + 1);
- wcsncpy(strings.localizedToast.action1.get(), daYesButtonW.get(),
- daYesButtonW.Length() + 1);
- strings.localizedToast.action2 =
- mozilla::MakeUnique<wchar_t[]>(daNoButtonW.Length() + 1);
- wcsncpy(strings.localizedToast.action2.get(), daNoButtonW.get(),
- daNoButtonW.Length() + 1);
- const wchar_t* iniFormat = L"%s\\defaultagent.ini";
- int bufferSize = _scwprintf(iniFormat, installPath.get());
- ++bufferSize; // Extra character for terminating null
- mozilla::UniquePtr<wchar_t[]> iniPath =
- mozilla::MakeUnique<wchar_t[]>(bufferSize);
- _snwprintf_s(iniPath.get(), bufferSize, _TRUNCATE, iniFormat,
- installPath.get());
-
- IniReader nonlocalizedReader(iniPath.get(), "Nonlocalized");
- nonlocalizedReader.AddKey("InitialToastRelativeImagePath",
- &strings.initialToast.relImagePath);
- nonlocalizedReader.AddKey("FollowupToastRelativeImagePath",
- &strings.followupToast.relImagePath);
- nonlocalizedReader.AddKey("LocalizedToastRelativeImagePath",
- &strings.localizedToast.relImagePath);
- int result = nonlocalizedReader.Read();
- if (result != OK) {
- LOG_ERROR_MESSAGE(L"Unable to read non-localized strings: %d", result);
- return false;
- }
-
- return true;
-}
-
-static mozilla::WindowsError LaunchFirefoxToHandleDefaultBrowserAgent() {
- // Could also be `MOZ_APP_NAME.exe`, but there's no generality to be gained:
- // the WDBA is Firefox-only.
- FilePathResult firefoxPathResult = GetRelativeBinaryPath(L"firefox.exe");
- if (firefoxPathResult.isErr()) {
- return firefoxPathResult.unwrapErr();
- }
- std::wstring firefoxPath = firefoxPathResult.unwrap();
-
- _bstr_t cmd = firefoxPath.c_str();
- // Omit argv[0] because ShellExecute doesn't need it.
- _variant_t args(L"-to-handle-default-browser-agent");
- _variant_t operation(L"open");
- _variant_t directory;
- _variant_t showCmd(SW_SHOWNORMAL);
-
- // To prevent inheriting environment variables from the background task, we
- // run Firefox via Explorer instead of our own process. This mimics the
- // implementation of the Windows Launcher Process.
- auto result =
- ShellExecuteByExplorer(cmd, args, operation, directory, showCmd);
- NS_ENSURE_TRUE(result.isOk(), result.unwrapErr());
-
- return mozilla::WindowsError::CreateSuccess();
-}
-
-/*
- * Set the default browser.
- *
- * First check if we can directly write UserChoice, if so attempt that.
- * If we can't write UserChoice, or if the attempt fails, fall back to
- * showing the Default Apps page of Settings.
- *
- * @param aAumi The AUMI of the installation to set as default.
- */
-static void SetDefaultBrowserFromNotification(const wchar_t* aumi) {
- nsresult rv = NS_ERROR_FAILURE;
- if (GetPrefSetDefaultBrowserUserChoice()) {
- rv = SetDefaultBrowserUserChoice(aumi);
- }
-
- if (NS_SUCCEEDED(rv)) {
- mozilla::Unused << LaunchFirefoxToHandleDefaultBrowserAgent();
- } else {
- LOG_ERROR_MESSAGE(L"Failed to SetDefaultBrowserUserChoice: %#X",
- GetLastError());
- LaunchModernSettingsDialogDefaultApps();
- }
-}
-
-// This encapsulates the data that needs to be protected by a mutex because it
-// will be shared by the main thread and the handler thread.
-// To ensure the data is only written once, handlerDataHasBeenSet should be
-// initialized to false, then set to true when the handler writes data into the
-// structure.
-struct HandlerData {
- NotificationActivities activitiesPerformed;
- bool handlerDataHasBeenSet;
-};
-
-// The value that ToastHandler writes into should be a global. We can't control
-// when ToastHandler is called, and if this value isn't a global, ToastHandler
-// may be called and attempt to access this after it has been deconstructed.
-// Since this value is accessed by the handler thread and the main thread, it
-// is protected by a mutex (gHandlerMutex).
-// Since ShowNotification deconstructs the mutex, it might seem like once
-// ShowNotification exits, we can just rely on the inability to wait on an
-// invalid mutex to protect the deconstructed data, but it's possible that
-// we could deconstruct the mutex while the handler is holding it and is
-// already accessing the protected data.
-static HandlerData gHandlerReturnData;
-static HANDLE gHandlerMutex = INVALID_HANDLE_VALUE;
-
-class ToastHandler : public WinToastLib::IWinToastHandler {
- private:
- NotificationType mWhichNotification;
- HANDLE mEvent;
- const std::wstring mAumiStr;
-
- public:
- ToastHandler(NotificationType whichNotification, HANDLE event,
- const wchar_t* aumi)
- : mWhichNotification(whichNotification), mEvent(event), mAumiStr(aumi) {}
-
- void FinishHandler(NotificationActivities& returnData) const {
- SetReturnData(returnData);
-
- BOOL success = SetEvent(mEvent);
- if (!success) {
- LOG_ERROR_MESSAGE(L"Event could not be set: %#X", GetLastError());
- }
- }
-
- void SetReturnData(NotificationActivities& toSet) const {
- DWORD result = WaitForSingleObject(gHandlerMutex, MUTEX_TIMEOUT_MS);
- if (result == WAIT_TIMEOUT) {
- LOG_ERROR_MESSAGE(L"Unable to obtain mutex ownership");
- return;
- } else if (result == WAIT_FAILED) {
- LOG_ERROR_MESSAGE(L"Failed to wait on mutex: %#X", GetLastError());
- return;
- } else if (result == WAIT_ABANDONED) {
- LOG_ERROR_MESSAGE(L"Found abandoned mutex");
- ReleaseMutex(gHandlerMutex);
- return;
- }
-
- // Only set this data once
- if (!gHandlerReturnData.handlerDataHasBeenSet) {
- gHandlerReturnData.activitiesPerformed = toSet;
- gHandlerReturnData.handlerDataHasBeenSet = true;
- }
-
- BOOL success = ReleaseMutex(gHandlerMutex);
- if (!success) {
- LOG_ERROR_MESSAGE(L"Unable to release mutex ownership: %#X",
- GetLastError());
- }
- }
-
- void toastActivated() const override {
- NotificationActivities activitiesPerformed;
- activitiesPerformed.type = mWhichNotification;
- activitiesPerformed.shown = NotificationShown::Shown;
- activitiesPerformed.action = NotificationAction::ToastClicked;
-
- // Notification strings are written to indicate the default browser is
- // restored to Firefox when the notification body is clicked to prevent
- // ambiguity when buttons aren't pressed.
- SetDefaultBrowserFromNotification(mAumiStr.c_str());
-
- FinishHandler(activitiesPerformed);
- }
-
- void toastActivated(int actionIndex) const override {
- NotificationActivities activitiesPerformed;
- activitiesPerformed.type = mWhichNotification;
- activitiesPerformed.shown = NotificationShown::Shown;
- // Override this below
- activitiesPerformed.action = NotificationAction::NoAction;
-
- if (actionIndex == 0) {
- // "Make Firefox the default" button, on both the initial and followup
- // notifications. "Yes" button on the localized notification.
- activitiesPerformed.action = NotificationAction::MakeFirefoxDefaultButton;
-
- SetDefaultBrowserFromNotification(mAumiStr.c_str());
- } else if (actionIndex == 1) {
- // Do nothing. As long as we don't call
- // SetFollowupNotificationRequestTime, there will be no followup
- // notification.
- activitiesPerformed.action = NotificationAction::DismissedByButton;
- }
-
- FinishHandler(activitiesPerformed);
- }
-
- void toastDismissed(WinToastDismissalReason state) const override {
- NotificationActivities activitiesPerformed;
- activitiesPerformed.type = mWhichNotification;
- activitiesPerformed.shown = NotificationShown::Shown;
- // Override this below
- activitiesPerformed.action = NotificationAction::NoAction;
-
- if (state == WinToastDismissalReason::TimedOut) {
- activitiesPerformed.action = NotificationAction::DismissedByTimeout;
- } else if (state == WinToastDismissalReason::ApplicationHidden) {
- activitiesPerformed.action =
- NotificationAction::DismissedByApplicationHidden;
- } else if (state == WinToastDismissalReason::UserCanceled) {
- activitiesPerformed.action = NotificationAction::DismissedToActionCenter;
- }
-
- FinishHandler(activitiesPerformed);
- }
-
- void toastFailed() const override {
- NotificationActivities activitiesPerformed;
- activitiesPerformed.type = mWhichNotification;
- activitiesPerformed.shown = NotificationShown::Error;
- activitiesPerformed.action = NotificationAction::NoAction;
-
- LOG_ERROR_MESSAGE(L"Toast notification failed to display");
- FinishHandler(activitiesPerformed);
- }
-};
-
-// This function blocks until the shown notification is activated or dismissed.
-static NotificationActivities ShowNotification(
- NotificationType whichNotification, const wchar_t* aumi) {
- // Initially set the value that will be returned to error. If the notification
- // is shown successfully, we'll update it.
- NotificationActivities activitiesPerformed = {whichNotification,
- NotificationShown::Error,
- NotificationAction::NoAction};
-
- bool isEnglishInstall = FirefoxInstallIsEnglish();
-
- Strings strings;
- if (!GetStrings(strings)) {
- return activitiesPerformed;
- }
- const ToastStrings* toastStrings =
- strings.GetToastStrings(whichNotification, isEnglishInstall);
-
- mozilla::mscom::EnsureMTA([&] {
- using namespace WinToastLib;
-
- if (!WinToast::isCompatible()) {
- LOG_ERROR_MESSAGE(L"System is not compatible with WinToast");
- return;
- }
- WinToast::instance()->setAppName(L"" MOZ_APP_DISPLAYNAME);
- std::wstring aumiStr = aumi;
- WinToast::instance()->setAppUserModelId(aumiStr);
- WinToast::instance()->setShortcutPolicy(
- WinToastLib::WinToast::SHORTCUT_POLICY_REQUIRE_NO_CREATE);
- WinToast::WinToastError error;
- if (!WinToast::instance()->initialize(&error)) {
- LOG_ERROR_MESSAGE(WinToast::strerror(error).c_str());
- return;
- }
-
- // This event object will let the handler notify us when it has handled the
- // notification.
- nsAutoHandle event(CreateEventW(nullptr, TRUE, FALSE, nullptr));
- if (event.get() == nullptr) {
- LOG_ERROR_MESSAGE(L"Unable to create event object: %#X", GetLastError());
- return;
- }
-
- bool success = false;
- if (whichNotification == NotificationType::Initial) {
- success = SetInitialNotificationShown(true);
- } else {
- success = SetFollowupNotificationShown(true);
- }
- if (!success) {
- // Return early in this case to prevent the notification from being shown
- // on every run.
- LOG_ERROR_MESSAGE(L"Unable to set notification as displayed");
- return;
- }
-
- // We need the absolute image path, not the relative path.
- mozilla::UniquePtr<wchar_t[]> installPath;
- success = GetInstallDirectory(installPath);
- if (!success) {
- LOG_ERROR_MESSAGE(L"Failed to get install directory for the image path");
- return;
- }
- const wchar_t* absPathFormat = L"%s\\%s";
- int bufferSize = _scwprintf(absPathFormat, installPath.get(),
- toastStrings->relImagePath.get());
- ++bufferSize; // Extra character for terminating null
- mozilla::UniquePtr<wchar_t[]> absImagePath =
- mozilla::MakeUnique<wchar_t[]>(bufferSize);
- _snwprintf_s(absImagePath.get(), bufferSize, _TRUNCATE, absPathFormat,
- installPath.get(), toastStrings->relImagePath.get());
-
- // This is used to protect gHandlerReturnData.
- gHandlerMutex = CreateMutexW(nullptr, TRUE, nullptr);
- if (gHandlerMutex == nullptr) {
- LOG_ERROR_MESSAGE(L"Unable to create mutex: %#X", GetLastError());
- return;
- }
- // Automatically close this mutex when this function exits.
- nsAutoHandle autoMutex(gHandlerMutex);
- // No need to initialize gHandlerReturnData.activitiesPerformed, since it
- // will be set by the handler. But we do need to initialize
- // gHandlerReturnData.handlerDataHasBeenSet so the handler knows that no
- // data has been set yet.
- gHandlerReturnData.handlerDataHasBeenSet = false;
- success = ReleaseMutex(gHandlerMutex);
- if (!success) {
- LOG_ERROR_MESSAGE(L"Unable to release mutex ownership: %#X",
- GetLastError());
- }
-
- // Finally ready to assemble the notification and dispatch it.
- WinToastTemplate toastTemplate =
- WinToastTemplate(WinToastTemplate::ImageAndText02);
- toastTemplate.setTextField(toastStrings->text1.get(),
- WinToastTemplate::FirstLine);
- toastTemplate.setTextField(toastStrings->text2.get(),
- WinToastTemplate::SecondLine);
- toastTemplate.addAction(toastStrings->action1.get());
- toastTemplate.addAction(toastStrings->action2.get());
- toastTemplate.setImagePath(absImagePath.get());
- toastTemplate.setScenario(WinToastTemplate::Scenario::Reminder);
- ToastHandler* handler =
- new ToastHandler(whichNotification, event.get(), aumi);
- INT64 id = WinToast::instance()->showToast(toastTemplate, handler, &error);
- if (id < 0) {
- LOG_ERROR_MESSAGE(WinToast::strerror(error).c_str());
- return;
- }
-
- DWORD result =
- WaitForSingleObject(event.get(), NOTIFICATION_WAIT_TIMEOUT_MS);
- // Don't return after these errors. Attempt to hide the notification.
- if (result == WAIT_FAILED) {
- LOG_ERROR_MESSAGE(L"Unable to wait on event object: %#X", GetLastError());
- } else if (result == WAIT_TIMEOUT) {
- LOG_ERROR_MESSAGE(L"Timed out waiting for event object");
- } else {
- result = WaitForSingleObject(gHandlerMutex, MUTEX_TIMEOUT_MS);
- if (result == WAIT_TIMEOUT) {
- LOG_ERROR_MESSAGE(L"Unable to obtain mutex ownership");
- // activitiesPerformed is already set to error. No change needed.
- } else if (result == WAIT_FAILED) {
- LOG_ERROR_MESSAGE(L"Failed to wait on mutex: %#X", GetLastError());
- // activitiesPerformed is already set to error. No change needed.
- } else if (result == WAIT_ABANDONED) {
- LOG_ERROR_MESSAGE(L"Found abandoned mutex");
- ReleaseMutex(gHandlerMutex);
- // activitiesPerformed is already set to error. No change needed.
- } else {
- // Mutex is being held. It is safe to access gHandlerReturnData.
- // If gHandlerReturnData.handlerDataHasBeenSet is false, the handler
- // never ran. Use the error value activitiesPerformed already contains.
- if (gHandlerReturnData.handlerDataHasBeenSet) {
- activitiesPerformed = gHandlerReturnData.activitiesPerformed;
- }
-
- success = ReleaseMutex(gHandlerMutex);
- if (!success) {
- LOG_ERROR_MESSAGE(L"Unable to release mutex ownership: %#X",
- GetLastError());
- }
- }
- }
-
- if (!WinToast::instance()->hideToast(id)) {
- LOG_ERROR_MESSAGE(L"Failed to hide notification");
- }
- });
- return activitiesPerformed;
-}
-
-// Previously this function checked that the Firefox build was using English.
-// This was checked because of the peculiar way we were localizing toast
-// notifications where we used a completely different set of strings in English.
-//
-// We've since unified the notification flows but need to clean up unused code
-// and config files - Bug 1826375.
-bool FirefoxInstallIsEnglish() { return false; }
-
-// If a notification is shown, this function will block until the notification
-// is activated or dismissed.
-// aumi is the App User Model ID.
-NotificationActivities MaybeShowNotification(
- const DefaultBrowserInfo& browserInfo, const wchar_t* aumi, bool force) {
- // Default to not showing a notification. Any other value will be returned
- // directly from ShowNotification.
- NotificationActivities activitiesPerformed = {NotificationType::Initial,
- NotificationShown::NotShown,
- NotificationAction::NoAction};
-
- // Reset notification state machine, user setting default browser to Firefox
- // is a strong signal that they intend to have it as the default browser.
- if (browserInfo.currentDefaultBrowser == Browser::Firefox) {
- ResetInitialNotificationShown();
- }
-
- bool initialNotificationShown = GetInitialNotificationShown();
- if (!initialNotificationShown || force) {
- if ((browserInfo.currentDefaultBrowser == Browser::EdgeWithBlink &&
- browserInfo.previousDefaultBrowser == Browser::Firefox) ||
- force) {
- return ShowNotification(NotificationType::Initial, aumi);
- }
- return activitiesPerformed;
- }
- activitiesPerformed.type = NotificationType::Followup;
-
- ULONGLONG followupNotificationRequestTime =
- GetFollowupNotificationRequestTime();
- bool followupNotificationRequested = followupNotificationRequestTime != 0;
- bool followupNotificationShown = GetFollowupNotificationShown();
- if (followupNotificationRequested && !followupNotificationShown &&
- !GetFollowupNotificationSuppressed()) {
- ULONGLONG secondsSinceRequestTime =
- SecondsPassedSince(followupNotificationRequestTime);
-
- if (secondsSinceRequestTime >= SEVEN_DAYS_IN_SECONDS) {
- // If we go to show the followup notification and the user has already
- // changed the default browser, permanently suppress the followup since
- // it's no longer relevant.
- if (browserInfo.currentDefaultBrowser == Browser::EdgeWithBlink) {
- return ShowNotification(NotificationType::Followup, aumi);
- } else {
- SetFollowupNotificationSuppressed(true);
- }
- }
- }
- return activitiesPerformed;
-}
-
std::string GetStringForNotificationType(NotificationType type) {
switch (type) {
case NotificationType::Initial:
diff --git a/toolkit/mozapps/defaultagent/Notification.h b/toolkit/mozapps/defaultagent/Notification.h
index 210c55f559..e4e007088d 100644
--- a/toolkit/mozapps/defaultagent/Notification.h
+++ b/toolkit/mozapps/defaultagent/Notification.h
@@ -7,7 +7,9 @@
#ifndef __DEFAULT_BROWSER_NOTIFICATION_H__
#define __DEFAULT_BROWSER_NOTIFICATION_H__
-#include "DefaultBrowser.h"
+#include <string>
+
+#include "nsStringFwd.h"
namespace mozilla::default_agent {
@@ -39,9 +41,6 @@ struct NotificationActivities {
NotificationAction action;
};
-NotificationActivities MaybeShowNotification(
- const DefaultBrowserInfo& browserInfo, const wchar_t* aumi, bool force);
-
// These take enum values and get strings suitable for telemetry
std::string GetStringForNotificationType(NotificationType type);
std::string GetStringForNotificationShown(NotificationShown shown);
diff --git a/toolkit/mozapps/defaultagent/ScheduledTask.cpp b/toolkit/mozapps/defaultagent/ScheduledTask.cpp
index a9cd647c03..c867e59b76 100644
--- a/toolkit/mozapps/defaultagent/ScheduledTask.cpp
+++ b/toolkit/mozapps/defaultagent/ScheduledTask.cpp
@@ -13,14 +13,11 @@
#include <comutil.h>
#include <taskschd.h>
-#include "readstrings.h"
-#include "updatererrors.h"
#include "EventLog.h"
#include "mozilla/RefPtr.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WinHeaderOnlyUtils.h"
-#include "WindowsDefaultBrowser.h"
#include "DefaultBrowser.h"
diff --git a/toolkit/mozapps/defaultagent/SetDefaultBrowser.cpp b/toolkit/mozapps/defaultagent/SetDefaultBrowser.cpp
index 8bc0889e67..6d829ff045 100644
--- a/toolkit/mozapps/defaultagent/SetDefaultBrowser.cpp
+++ b/toolkit/mozapps/defaultagent/SetDefaultBrowser.cpp
@@ -6,17 +6,16 @@
#include <windows.h>
#include <appmodel.h>
#include <shlobj.h> // for SHChangeNotify and IApplicationAssociationRegistration
-#include <functional>
#include <timeapi.h>
#include "mozilla/ArrayUtils.h"
#include "mozilla/CmdLineAndEnvUtils.h"
#include "mozilla/RefPtr.h"
+#include "mozilla/Result.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/WinHeaderOnlyUtils.h"
#include "WindowsUserChoice.h"
-#include "nsThreadUtils.h"
#include "EventLog.h"
#include "SetDefaultBrowser.h"
@@ -70,6 +69,77 @@ static bool AddMillisecondsToSystemTime(SYSTEMTIME& aSystemTime,
return true;
}
+/*
+ * Takes two times: the start time and the current time, and returns the number
+ * of seconds left before the current time hits the next minute from the start
+ * time. Used to check if we are within the same minute as the start time and
+ * how much time we have left to perform an operation in the same minute.
+ *
+ * Used with user choice hashes, which have to be written to the registry
+ * in the same minute as they are generated.
+ *
+ * Example 1:
+ * operationStartTime - 10m 20s 800ms
+ * currentTime - 10m 22s 0ms
+ * The next minute is 11, so the return value is 11m - 10m 22s 0ms, converted to
+ * milliseconds.
+ *
+ * Example 2:
+ * operationStartTime - 10m 59s 800ms
+ * currentTime - 11m 0s 0ms
+ * The next minute is 11, but the minute the operation started on was 10, so the
+ * time to the next minute is 0 (because the current time is already at the next
+ * minute).
+ *
+ * @param operationStartTime
+ * @param currentTime
+ *
+ * @returns the number of milliseconds left from the current time to the
+ * next minute from operationStartTime, or zero if the currentTime is already at
+ * the next minute or greater
+ */
+static WORD GetMillisecondsToNextMinute(SYSTEMTIME operationStartTime,
+ SYSTEMTIME currentTime) {
+ SYSTEMTIME operationStartTimeMinute = operationStartTime;
+ SYSTEMTIME currentTimeMinute = currentTime;
+
+ // Zero out the seconds and milliseconds so that we can confirm they are the
+ // same minutes
+ operationStartTimeMinute.wSecond = 0;
+ operationStartTimeMinute.wMilliseconds = 0;
+
+ currentTimeMinute.wSecond = 0;
+ currentTimeMinute.wMilliseconds = 0;
+
+ // Convert to a 64 bit value so we can compare them directly
+ FILETIME fileTime1;
+ FILETIME fileTime2;
+ if (!::SystemTimeToFileTime(&operationStartTimeMinute, &fileTime1) ||
+ !::SystemTimeToFileTime(&currentTimeMinute, &fileTime2)) {
+ // Error: report that there is 0 milliseconds till the next minute
+ return 0;
+ }
+
+ // The minutes for both times have to be the same, so confirm that they are,
+ // and if they aren't, return 0 milliseconds to indicate that we're already
+ // not on the minute that operationStartTime was on
+ if ((fileTime1.dwLowDateTime != fileTime2.dwLowDateTime) ||
+ (fileTime1.dwHighDateTime != fileTime2.dwHighDateTime)) {
+ return 0;
+ }
+
+ // The minutes are the same; determine the number of milliseconds left until
+ // the next minute
+ const WORD secondsToMilliseconds = 1000;
+ const WORD minutesToSeconds = 60;
+
+ // 1 minute converted to milliseconds - (the current second converted to
+ // milliseconds + the current milliseconds)
+ return (1 * minutesToSeconds * secondsToMilliseconds) -
+ ((currentTime.wSecond * secondsToMilliseconds) +
+ currentTime.wMilliseconds);
+}
+
// Compare two SYSTEMTIMEs as FILETIME after clearing everything
// below minutes.
static bool CheckEqualMinutes(SYSTEMTIME aSystemTime1,
@@ -149,6 +219,75 @@ static bool SetUserChoiceRegistry(const wchar_t* aExt, const wchar_t* aProgID,
return true;
}
+struct LaunchExeErr {};
+using LaunchExeResult =
+ mozilla::Result<std::tuple<DWORD, mozilla::UniquePtr<wchar_t[]>>,
+ LaunchExeErr>;
+
+static LaunchExeResult LaunchExecutable(const wchar_t* exePath, int aArgsLength,
+ const wchar_t* const* aArgs) {
+ const wchar_t* args[] = {exePath};
+ mozilla::UniquePtr<wchar_t[]> cmdLine(mozilla::MakeCommandLine(
+ mozilla::ArrayLength(args), const_cast<wchar_t**>(args), aArgsLength,
+ const_cast<wchar_t**>(aArgs)));
+
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si = {sizeof(si)};
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE;
+
+ if (!::CreateProcessW(exePath, cmdLine.get(), nullptr, nullptr, FALSE, 0,
+ nullptr, nullptr, &si, &pi)) {
+ HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
+ LOG_ERROR(hr);
+ return Err(LaunchExeErr());
+ }
+
+ nsAutoHandle process(pi.hProcess);
+ nsAutoHandle mainThread(pi.hThread);
+
+ DWORD exitCode;
+ if (::WaitForSingleObject(process.get(), INFINITE) == WAIT_OBJECT_0 &&
+ ::GetExitCodeProcess(process.get(), &exitCode)) {
+ return std::make_tuple(exitCode, std::move(cmdLine));
+ }
+
+ return Err(LaunchExeErr());
+}
+
+static bool LaunchPowershell(const wchar_t* command,
+ const wchar_t* powershellPath) {
+ const wchar_t* args[] = {
+ L"-NoProfile", // ensure nothing is monkeying with powershell
+ L"-c",
+ command,
+ };
+
+ return LaunchExecutable(powershellPath, mozilla::ArrayLength(args), args)
+ .map([](auto result) {
+ auto& [exitCode, regCmdLine] = result;
+ bool success = (exitCode == 0);
+ if (!success) {
+ LOG_ERROR_MESSAGE(L"%s returned failure exitCode %d",
+ regCmdLine.get(), exitCode);
+ }
+ return success;
+ })
+ .unwrapOr(false);
+}
+
+static bool FindPowershell(mozilla::UniquePtr<wchar_t[]>& powershellPath) {
+ auto exePath = mozilla::MakeUnique<wchar_t[]>(MAX_PATH + 1);
+ if (!ConstructSystem32Path(L"WindowsPowershell\\v1.0\\powershell.exe",
+ exePath.get(), MAX_PATH + 1)) {
+ LOG_ERROR_MESSAGE(L"Failed to construct path to powershell.exe");
+ return false;
+ }
+
+ powershellPath.swap(exePath);
+ return true;
+}
+
/*
* Set an association with a UserChoice key
*
@@ -165,7 +304,9 @@ static bool SetUserChoiceRegistry(const wchar_t* aExt, const wchar_t* aProgID,
static bool SetUserChoice(const wchar_t* aExt, const wchar_t* aSid,
const wchar_t* aProgID, bool inMsix) {
if (inMsix) {
- LOG_ERROR_MESSAGE(L"SetUserChoice does not work on MSIX builds.");
+ LOG_ERROR_MESSAGE(
+ L"SetUserChoice should not be called on MSIX builds. Call "
+ L"SetDefaultExtensionHandlersUserChoiceImplMsix instead.");
return false;
}
@@ -298,6 +439,247 @@ nsresult SetDefaultExtensionHandlersUserChoice(
return rv;
}
+/*
+ * Takes the list of file extension pairs and fills a list of program ids for
+ * each pair.
+ *
+ * @param aFileExtensions array of file association pairs to
+ * set as default, like `[ ".pdf", "FirefoxPDF" ]`.
+ */
+static nsresult GenerateProgramIDs(const nsTArray<nsString>& aFileExtensions,
+ nsTArray<nsString>& progIDs) {
+ for (size_t i = 0; i + 1 < aFileExtensions.Length(); i += 2) {
+ const wchar_t* fileExtension = aFileExtensions[i].get();
+
+ // Formatting the ProgID here prevents using this helper to target arbitrary
+ // ProgIDs.
+ mozilla::UniquePtr<wchar_t[]> progID;
+ nsresult rv = GetMsixProgId(fileExtension, progID);
+ if (NS_FAILED(rv)) {
+ LOG_ERROR_MESSAGE(L"Failed to retrieve MSIX progID for %s",
+ fileExtension);
+ return rv;
+ }
+
+ progIDs.AppendElement(nsString(progID.get()));
+ }
+
+ return NS_OK;
+}
+
+/*
+ * Takes the list of file extension pairs and a matching list of program ids for
+ * each of those pairs and verifies that the system is successfully to match
+ * each.
+ *
+ * @param aFileExtensions array of file association pairs to set as default,
+ * like `[ ".pdf", "FirefoxPDF" ]`.
+ * @param aProgIDs array of program ids. The order of this array matches the
+ * file extensions parameter.
+ */
+static nsresult VerifyUserDefaults(const nsTArray<nsString>& aFileExtensions,
+ const nsTArray<nsString>& aProgIDs) {
+ for (size_t i = 0; i + 1 < aFileExtensions.Length(); i += 2) {
+ const wchar_t* fileExtension = aFileExtensions[i].get();
+
+ if (!VerifyUserDefault(fileExtension, aProgIDs[i / 2].get())) {
+ return NS_ERROR_WDBA_REJECTED;
+ }
+ }
+
+ return NS_OK;
+}
+
+/*
+ * Queries the system for the minimum resolution (or tick time) in milliseconds
+ * that can be used with ::Sleep. If a Sleep is not triggered with a time
+ * divisible by the tick time, control can return to the thread before the time
+ * specified to Sleep.
+ *
+ * @param defaultValue what to return if the system query fails.
+ */
+static UINT GetSystemSleepIntervalInMilliseconds(UINT defaultValue) {
+ TIMECAPS timeCapabilities;
+ bool timeCapsFetchSuccessful =
+ (MMSYSERR_NOERROR ==
+ timeGetDevCaps(&timeCapabilities, sizeof(timeCapabilities)));
+ if (!timeCapsFetchSuccessful) {
+ return defaultValue;
+ }
+
+ return timeCapabilities.wPeriodMin > 0 ? timeCapabilities.wPeriodMin
+ : defaultValue;
+}
+
+/*
+ * MSIX implementation for SetDefaultExtensionHandlersUserChoice.
+ *
+ * Due to the fact that MSIX builds run in a virtual, walled off environment,
+ * calling into the Win32 registry APIs doesn't work to set registry keys.
+ * MSIX builds access a virtual registry.
+ *
+ * Sends a "script" via command line to Powershell to modify the registry
+ * in an executable that is outside of the walled garden MSIX FX package
+ * environment, which is the only way to do that so far. Only works
+ * on slightly older versions of Windows 11 (older than 23H2).
+ *
+ * This was originally done using calls to Reg.exe, but permissions can't
+ * be changed that way, requiring using Powershell to call into .Net functions
+ * directly. Launching Powershell is slow (on the order of a second on some
+ * systems) so this method jams the calls to do everything into one launch of
+ * Powershell, to make it as quick as possible.
+ *
+ */
+static nsresult SetDefaultExtensionHandlersUserChoiceImplMsix(
+ const wchar_t* aAumi, const wchar_t* const aSid,
+ const nsTArray<nsString>& aFileExtensions) {
+ mozilla::UniquePtr<wchar_t[]> exePath;
+ if (!FindPowershell(exePath)) {
+ LOG_ERROR_MESSAGE(L"Could not locate Powershell");
+ return NS_ERROR_FAILURE;
+ }
+
+ // The following is the start of the script that will be sent to Powershell.
+ // In includes a function; calls to the function get appended per file
+ // extension, done below.
+ nsString startScript(
+ uR"(
+# Force exceptions to stop execution
+$ErrorActionPreference = 'Stop'
+
+function Set-DefaultHandlerRegistry($Path, $ProgID, $Hash) {
+ $Path = "$Path\UserChoice"
+ $CurrentUser = [Microsoft.Win32.Registry]::CurrentUser
+
+ # DeleteSubKey throws if we don't have sufficient permissions to delete key,
+ # signaling failure to launching process.
+ #
+ # Note: DeleteSubKeyTree fails when DENY permissions are set on key, whereas
+ # DeleteSubKey succeeds.
+ $CurrentUser.DeleteSubKey($Path, $false)
+ $key = $CurrentUser.CreateSubKey($Path)
+
+ $StringType = [Microsoft.Win32.RegistryValueKind]::String
+ $key.SetValue('ProgID', $ProgID, $StringType)
+ $key.SetValue('Hash', $Hash, $StringType)
+}
+
+)"); // Newlines in the above powershell script at the end are important!!!
+
+ // NOTE!!!! CreateProcess / calling things on the command line has a character
+ // count limit. For CMD.exe, it's 8K. For CreateProcessW, it's technically
+ // 32K. I can't find documentation about Powershell, but think 8K is safe to
+ // assume as a good maximum. The above script is about 1000 characters, and we
+ // will append another 100 characters at most per extension, so we'd need to
+ // be setting about 70 handlers at once to worry about the theoretical limit.
+ // Which we won't do. So the length shouldn't be a problem.
+ if (aFileExtensions.Length() >= 70) {
+ LOG_ERROR_MESSAGE(
+ L"SetDefaultExtensionHandlersUserChoiceImplMsix can't cope with 70 or "
+ L"more file extensions at once. Please break it up into multiple calls "
+ L"with fewer extensions per call.");
+ return NS_ERROR_FAILURE;
+ }
+
+ // NOTE!!!!
+ // User choice hashes have to be generated and written to the registry in the
+ // same minute. So we do everything we can upfront before we get to the hash
+ // generation, to ensure that hash generation and the call to Powershell to
+ // write to the registry has as much time as possible to run.
+
+ // Program ID fetch / generation might be slow, so do that ahead of time.
+ nsTArray<nsString> progIDs;
+ nsresult rv = GenerateProgramIDs(aFileExtensions, progIDs);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsString scriptBuffer;
+
+ // Everyting in the loop below should succeed or fail reasonably fast (within
+ // 20 milliseconds or something well under a second) besides the Powershell
+ // call. The Powershell call itself will either fail or succeed and break out
+ // of the loop, so repeating 10 times should be fine and is mostly to allow
+ // for getting the timing right with the user choice hash generation happening
+ // in the same minute - meaning this should likely only happen twice through
+ // the loop at most.
+ for (int i = 0; i < 10; i++) {
+ // Pre-allocate the memory for the scriptBuffer upfront so that we don't
+ // have to keep allocating every time Append is called.
+ const int scriptBufferCapacity = 16 * 1024;
+ scriptBuffer = startScript;
+ scriptBuffer.SetCapacity(scriptBufferCapacity);
+
+ SYSTEMTIME hashTimestamp;
+ ::GetSystemTime(&hashTimestamp);
+
+ // Time critical stuff starts here:
+
+ for (size_t i = 0; i + 1 < aFileExtensions.Length(); i += 2) {
+ const wchar_t* fileExtension = aFileExtensions[i].get();
+
+ nsAutoString keyPath;
+ AppendAssociationKeyPath(fileExtension, keyPath);
+
+ auto hashWchar = GenerateUserChoiceHash(
+ fileExtension, aSid, progIDs[i / 2].get(), hashTimestamp);
+ if (!hashWchar) {
+ return NS_ERROR_FAILURE;
+ }
+ auto hash = nsDependentString(hashWchar.get());
+
+ // Append a line to the script buffer in the form:
+ // Set-DefaultHandlerRegistry $RegistryKeyPath $ProgID $UserChoiceHash
+ scriptBuffer += u"Set-DefaultHandlerRegistry "_ns + keyPath + u" "_ns +
+ progIDs[i / 2] + u" "_ns + hash + u"\n"_ns;
+ }
+
+ // The hash changes at the end of each minute, so check that the hash should
+ // be the same by the time we're done writing.
+ const ULONGLONG kWriteTimingThresholdMilliseconds = 2000;
+
+ // Generating the hash could have taken some time, so figure out what time
+ // we are at right now.
+ SYSTEMTIME writeEndTimestamp;
+ ::GetSystemTime(&writeEndTimestamp);
+
+ // Check if we have enough time to launch Powershell or if we should sleep
+ // to the next minute and try again
+ auto millisecondsLeftUntilNextMinute =
+ GetMillisecondsToNextMinute(hashTimestamp, writeEndTimestamp);
+ if (millisecondsLeftUntilNextMinute >= kWriteTimingThresholdMilliseconds) {
+ break;
+ }
+
+ LOG_ERROR_MESSAGE(
+ L"Hash is too close to next minute, sleeping until next minute to "
+ L"ensure that hash generation matches write to registry.");
+
+ UINT sleepUntilNextMinuteBufferMilliseconds =
+ GetSystemSleepIntervalInMilliseconds(
+ 50); // Default to 50ms if we can't figure out the right interval
+ // to sleep for
+ ::Sleep(millisecondsLeftUntilNextMinute +
+ (sleepUntilNextMinuteBufferMilliseconds * 2));
+
+ // Try again, if we have any attempts left
+ }
+
+ // Call Powershell to set the registry keys now - this is the really time
+ // consuming thing 250ms to launch on a VM in a reasonably fast case, possibly
+ // a lot slower on other systems
+ bool powershellSuccessful =
+ LaunchPowershell(scriptBuffer.get(), exePath.get());
+ if (!powershellSuccessful) {
+ // If powershell failed, it likely means that something got mucked with
+ // the registry and that Windows is popping up notifications to the user,
+ // so don't try again right now, so as to not overwhelm the user and annoy
+ // them.
+ return NS_ERROR_FAILURE;
+ }
+
+ // Validate now
+ return VerifyUserDefaults(aFileExtensions, progIDs);
+}
+
nsresult SetDefaultExtensionHandlersUserChoiceImpl(
const wchar_t* aAumi, const wchar_t* const aSid,
const nsTArray<nsString>& aFileExtensions) {
@@ -306,9 +688,8 @@ nsresult SetDefaultExtensionHandlersUserChoiceImpl(
GetCurrentPackageFullName(&pfnLen, nullptr) != APPMODEL_ERROR_NO_PACKAGE;
if (inMsix) {
- // MSIX packages can not meaningfully modify the registry keys related to
- // default handlers
- return NS_ERROR_FAILURE;
+ return SetDefaultExtensionHandlersUserChoiceImplMsix(aAumi, aSid,
+ aFileExtensions);
}
for (size_t i = 0; i + 1 < aFileExtensions.Length(); i += 2) {
diff --git a/toolkit/mozapps/defaultagent/defaultagent.ini b/toolkit/mozapps/defaultagent/defaultagent.ini
deleted file mode 100644
index 9300b20c46..0000000000
--- a/toolkit/mozapps/defaultagent/defaultagent.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-; This Source Code Form is subject to the terms of the Mozilla Public
-; License, v. 2.0. If a copy of the MPL was not distributed with this
-; file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-; This file is in the UTF-8 encoding
-[Nonlocalized]
-InitialToastRelativeImagePath=browser/VisualElements/VisualElements_150.png
-FollowupToastRelativeImagePath=browser/VisualElements/VisualElements_150.png
-LocalizedToastRelativeImagePath=browser/VisualElements/VisualElements_150.png
diff --git a/toolkit/mozapps/defaultagent/moz.build b/toolkit/mozapps/defaultagent/moz.build
index 86b68c6371..f8ae506d9c 100644
--- a/toolkit/mozapps/defaultagent/moz.build
+++ b/toolkit/mozapps/defaultagent/moz.build
@@ -15,6 +15,7 @@ UNIFIED_SOURCES += [
"DefaultBrowser.cpp",
"DefaultPDF.cpp",
"EventLog.cpp",
+ "Notification.cpp",
"Policy.cpp",
"Registry.cpp",
"ScheduledTask.cpp",
@@ -25,21 +26,6 @@ UNIFIED_SOURCES += [
"WindowsMutex.cpp",
]
-SOURCES += [
- "/third_party/WinToast/wintoastlib.cpp",
- "/toolkit/mozapps/update/common/readstrings.cpp",
- "Notification.cpp",
-]
-
-# Suppress warnings from third-party code.
-SOURCES["/third_party/WinToast/wintoastlib.cpp"].flags += [
- "-Wno-implicit-fallthrough",
- "-Wno-nonportable-include-path", # Needed for wintoastlib.h including "Windows.h"
-]
-SOURCES["Notification.cpp"].flags += [
- "-Wno-nonportable-include-path", # Needed for wintoastlib.h including "Windows.h"
-]
-
EXPORTS.mozilla += [
"DefaultAgent.h",
"WindowsMutex.h",
@@ -52,9 +38,7 @@ USE_LIBS += [
LOCAL_INCLUDES += [
"/browser/components/shell/",
"/other-licenses/nsis/Contrib/CityHash/cityhash",
- "/third_party/WinToast",
"/toolkit/components/jsoncpp/include",
- "/toolkit/mozapps/update/common",
]
OS_LIBS += [
@@ -98,8 +82,6 @@ for var in ("MOZ_APP_BASENAME", "MOZ_APP_DISPLAYNAME", "MOZ_APP_VENDOR"):
DEFINES["UNICODE"] = True
DEFINES["_UNICODE"] = True
-FINAL_TARGET_FILES += ["defaultagent.ini"]
-
FINAL_LIBRARY = "xul"
if CONFIG["ENABLE_TESTS"]:
diff --git a/toolkit/mozapps/defaultagent/nsIDefaultAgent.idl b/toolkit/mozapps/defaultagent/nsIDefaultAgent.idl
index 7e78e1b30d..8472dea3af 100644
--- a/toolkit/mozapps/defaultagent/nsIDefaultAgent.idl
+++ b/toolkit/mozapps/defaultagent/nsIDefaultAgent.idl
@@ -52,20 +52,6 @@ interface nsIDefaultAgent : nsISupports
void uninstall(in AString aUniqueToken);
/**
- * Actually performs the default agent task, which currently means generating
- * and sending our telemetry ping and possibly showing a notification to the
- * user if their browser has switched from Firefox to Edge with Blink.
- *
- * @param {AString} aUniqueToken
- * A unique identifier for this installation; the same one provided when
- * the task was registered.
- * @param {boolean} aForce
- * For debugging, forces the task to run even if it has run in the last
- * 24 hours, and forces the notification to show.
- */
- void doTask(in AString aUniqueToken, in boolean aForce);
-
- /**
* Checks that the main app ran recently.
*
* @return {boolean} true if the app ran recently.
diff --git a/toolkit/mozapps/defaultagent/proxy/main.cpp b/toolkit/mozapps/defaultagent/proxy/main.cpp
index 53efdcb9ae..7ba63c2095 100644
--- a/toolkit/mozapps/defaultagent/proxy/main.cpp
+++ b/toolkit/mozapps/defaultagent/proxy/main.cpp
@@ -7,10 +7,8 @@
#include <windows.h>
#include <shlwapi.h>
#include <objbase.h>
-#include <string.h>
#include <filesystem>
-#include "../ScheduledTask.h"
#include "../ScheduledTaskRemove.h"
#include "mozilla/CmdLineAndEnvUtils.h"
diff --git a/toolkit/mozapps/defaultagent/proxy/moz.build b/toolkit/mozapps/defaultagent/proxy/moz.build
index 40d7655dfa..3ff6932ac2 100644
--- a/toolkit/mozapps/defaultagent/proxy/moz.build
+++ b/toolkit/mozapps/defaultagent/proxy/moz.build
@@ -17,7 +17,6 @@ UNIFIED_SOURCES += [
SOURCES += [
"/browser/components/shell/WindowsDefaultBrowser.cpp",
"/other-licenses/nsis/Contrib/CityHash/cityhash/city.cpp",
- "/toolkit/mozapps/update/common/readstrings.cpp",
]
LOCAL_INCLUDES += [
diff --git a/toolkit/mozapps/downloads/DownloadLastDir.sys.mjs b/toolkit/mozapps/downloads/DownloadLastDir.sys.mjs
index da0439dcc5..dfd5d2cd26 100644
--- a/toolkit/mozapps/downloads/DownloadLastDir.sys.mjs
+++ b/toolkit/mozapps/downloads/DownloadLastDir.sys.mjs
@@ -48,7 +48,7 @@ var observer = {
"nsISupportsWeakReference",
]),
- observe(aSubject, aTopic, aData) {
+ observe(aSubject, aTopic) {
switch (aTopic) {
case "last-pb-context-exited":
gDownloadLastDirFile = null;
diff --git a/toolkit/mozapps/downloads/DownloadUtils.sys.mjs b/toolkit/mozapps/downloads/DownloadUtils.sys.mjs
index 3bf97f3c9e..6684a73699 100644
--- a/toolkit/mozapps/downloads/DownloadUtils.sys.mjs
+++ b/toolkit/mozapps/downloads/DownloadUtils.sys.mjs
@@ -610,7 +610,7 @@ function convertTimeUnitsUnits(timeValue, aIndex) {
* Error message to log or an array of strings to concat
*/
// function log(aMsg) {
-// let msg = "DownloadUtils.jsm: " + (aMsg.join ? aMsg.join("") : aMsg);
+// let msg = "DownloadUtils.sys.mjs: " + (aMsg.join ? aMsg.join("") : aMsg);
// Services.console.logStringMessage(msg);
// dump(msg + "\n");
// }
diff --git a/toolkit/mozapps/downloads/HelperAppDlg.sys.mjs b/toolkit/mozapps/downloads/HelperAppDlg.sys.mjs
index 66f77d38e4..01d1a518d8 100644
--- a/toolkit/mozapps/downloads/HelperAppDlg.sys.mjs
+++ b/toolkit/mozapps/downloads/HelperAppDlg.sys.mjs
@@ -72,33 +72,19 @@ nsUnknownContentTypeDialogProgressListener.prototype = {
},
// Ignore onProgressChange, onProgressChange64, onStateChange, onLocationChange, onSecurityChange, onContentBlockingEvent and onRefreshAttempted notifications.
- onProgressChange(
- aWebProgress,
- aRequest,
- aCurSelfProgress,
- aMaxSelfProgress,
- aCurTotalProgress,
- aMaxTotalProgress
- ) {},
+ onProgressChange() {},
- onProgressChange64(
- aWebProgress,
- aRequest,
- aCurSelfProgress,
- aMaxSelfProgress,
- aCurTotalProgress,
- aMaxTotalProgress
- ) {},
+ onProgressChange64() {},
- onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {},
+ onStateChange() {},
- onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {},
+ onLocationChange() {},
- onSecurityChange(aWebProgress, aRequest, aState) {},
+ onSecurityChange() {},
- onContentBlockingEvent(aWebProgress, aRequest, aEvent) {},
+ onContentBlockingEvent() {},
- onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI) {
+ onRefreshAttempted() {
return true;
},
};
@@ -309,7 +295,7 @@ nsUnknownContentTypeDialog.prototype = {
var picker =
Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
var windowTitle = bundle.GetStringFromName("saveDialogTitle");
- picker.init(parent, windowTitle, nsIFilePicker.modeSave);
+ picker.init(parent.browsingContext, windowTitle, nsIFilePicker.modeSave);
if (aDefaultFileName) {
picker.defaultString = this.getFinalLeafName(aDefaultFileName);
}
@@ -1270,7 +1256,7 @@ nsUnknownContentTypeDialog.prototype = {
var nsIFilePicker = Ci.nsIFilePicker;
var fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
fp.init(
- this.mDialog,
+ this.mDialog.browsingContext,
this.dialogElement("strings").getString("chooseAppFilePickerTitle"),
nsIFilePicker.modeOpen
);
diff --git a/toolkit/mozapps/downloads/tests/browser/browser_save_wrongextension.js b/toolkit/mozapps/downloads/tests/browser/browser_save_wrongextension.js
index 83e668076a..ad83bb3689 100644
--- a/toolkit/mozapps/downloads/tests/browser/browser_save_wrongextension.js
+++ b/toolkit/mozapps/downloads/tests/browser/browser_save_wrongextension.js
@@ -8,7 +8,7 @@ let url =
"data:text/html,<a id='link' href='http://localhost:8000/thefile.js'>Link</a>";
let MockFilePicker = SpecialPowers.MockFilePicker;
-MockFilePicker.init(window);
+MockFilePicker.init(window.browsingContext);
let httpServer = null;
diff --git a/toolkit/mozapps/downloads/tests/browser/browser_unknownContentType_delayedbutton.js b/toolkit/mozapps/downloads/tests/browser/browser_unknownContentType_delayedbutton.js
index 06a5a9d238..9bd494e245 100644
--- a/toolkit/mozapps/downloads/tests/browser/browser_unknownContentType_delayedbutton.js
+++ b/toolkit/mozapps/downloads/tests/browser/browser_unknownContentType_delayedbutton.js
@@ -13,14 +13,14 @@ let UCTObserver = {
opened: Promise.withResolvers(),
closed: Promise.withResolvers(),
- observe(aSubject, aTopic, aData) {
+ observe(aSubject, aTopic) {
let win = aSubject;
switch (aTopic) {
case "domwindowopened":
win.addEventListener(
"load",
- function onLoad(event) {
+ function onLoad() {
// Let the dialog initialize
SimpleTest.executeSoon(function () {
UCTObserver.opened.resolve(win);
@@ -40,7 +40,7 @@ let UCTObserver = {
};
function waitDelay(delay) {
- return new Promise((resolve, reject) => {
+ return new Promise(resolve => {
/* eslint-disable mozilla/no-arbitrary-setTimeout */
window.setTimeout(resolve, delay);
});
diff --git a/toolkit/mozapps/downloads/tests/browser/browser_unknownContentType_dialog_layout.js b/toolkit/mozapps/downloads/tests/browser/browser_unknownContentType_dialog_layout.js
index 6755c1aadb..e42951696d 100644
--- a/toolkit/mozapps/downloads/tests/browser/browser_unknownContentType_dialog_layout.js
+++ b/toolkit/mozapps/downloads/tests/browser/browser_unknownContentType_dialog_layout.js
@@ -38,14 +38,14 @@ add_task(async function test_unknownContentType_dialog_layout() {
opened: Promise.withResolvers(),
closed: Promise.withResolvers(),
- observe(aSubject, aTopic, aData) {
+ observe(aSubject, aTopic) {
let win = aSubject;
switch (aTopic) {
case "domwindowopened":
win.addEventListener(
"load",
- function onLoad(event) {
+ function onLoad() {
// Let the dialog initialize
SimpleTest.executeSoon(function () {
UCTObserver.opened.resolve(win);
diff --git a/toolkit/mozapps/downloads/tests/unit/test_lowMinutes.js b/toolkit/mozapps/downloads/tests/unit/test_lowMinutes.js
index 786da28b75..9076fa7c76 100644
--- a/toolkit/mozapps/downloads/tests/unit/test_lowMinutes.js
+++ b/toolkit/mozapps/downloads/tests/unit/test_lowMinutes.js
@@ -20,7 +20,7 @@ const { DownloadUtils } = ChromeUtils.importESModule(
* @usage _("Hello World") -> prints "Hello World"
* @usage _(1, 2, 3) -> prints "1 2 3"
*/
-var _ = function (some, debug, text, to) {
+var _ = function () {
print(Array.from(arguments).join(" "));
};
diff --git a/toolkit/mozapps/extensions/AddonManager.sys.mjs b/toolkit/mozapps/extensions/AddonManager.sys.mjs
index e4e51885cf..c69cf4029e 100644
--- a/toolkit/mozapps/extensions/AddonManager.sys.mjs
+++ b/toolkit/mozapps/extensions/AddonManager.sys.mjs
@@ -1610,10 +1610,10 @@ var AddonManagerInternal = {
// Temporary hack until bug 520124 lands.
// We can get here during synchronous startup, at which point it's
- // considered unsafe (and therefore disallowed by AddonManager.jsm) to
+ // considered unsafe (and therefore disallowed by AddonManager.sys.mjs) to
// access providers that haven't been initialized yet. Since this is when
// XPIProvider is starting up, XPIProvider can't access itself via APIs
- // going through AddonManager.jsm. Thankfully, this is the only use
+ // going through AddonManager.sys.mjs. Thankfully, this is the only use
// of this API, and we know it's safe to use this API with both
// providers; so we have this hack to allow bypassing the normal
// safetey guard.
diff --git a/toolkit/mozapps/extensions/content/aboutaddons.css b/toolkit/mozapps/extensions/content/aboutaddons.css
index 3f4e80797a..2f5157bea3 100644
--- a/toolkit/mozapps/extensions/content/aboutaddons.css
+++ b/toolkit/mozapps/extensions/content/aboutaddons.css
@@ -643,12 +643,18 @@ panel-item[action="report"]::part(button) {
text-decoration: none;
}
-.inline-options-stack {
- /* If the options browser triggers an alert we need room to show it. */
- min-height: 250px;
+.addon-inline-options {
width: 100%;
background-color: white;
margin-block: 4px;
+ /*
+ * Makes sure the browser minimal height is going to be the same as when
+ * this browser element was wrapper in a stack and a min-height was necessary
+ * for the prompts to fit inside the browser element.
+ * That stack element has been removed as part of Bug 1881055, but keeping
+ * the min-height unchanged to avoid potential regressions in the short term.
+ */
+ min-height: 250px;
}
addon-permissions-list > .addon-detail-row {
diff --git a/toolkit/mozapps/extensions/content/aboutaddons.js b/toolkit/mozapps/extensions/content/aboutaddons.js
index 37687a8be7..39c4656210 100644
--- a/toolkit/mozapps/extensions/content/aboutaddons.js
+++ b/toolkit/mozapps/extensions/content/aboutaddons.js
@@ -1423,10 +1423,23 @@ class SidebarFooter extends HTMLElement {
labelL10nId: "addons-settings-button",
onClick: e => {
e.preventDefault();
- windowRoot.ownerGlobal.switchToTabHavingURI("about:preferences", true, {
- ignoreFragment: "whenComparing",
- triggeringPrincipal: systemPrincipal,
- });
+ let hasAboutSettings = windowRoot.ownerGlobal.switchToTabHavingURI(
+ "about:settings",
+ false,
+ {
+ ignoreFragment: "whenComparing",
+ }
+ );
+ if (!hasAboutSettings) {
+ windowRoot.ownerGlobal.switchToTabHavingURI(
+ "about:preferences",
+ true,
+ {
+ ignoreFragment: "whenComparing",
+ triggeringPrincipal: systemPrincipal,
+ }
+ );
+ }
},
});
@@ -1695,6 +1708,7 @@ class InlineOptionsBrowser extends HTMLElement {
browser.setAttribute("disableglobalhistory", "true");
browser.setAttribute("messagemanagergroup", "webext-browsers");
browser.setAttribute("id", "addon-inline-options");
+ browser.setAttribute("class", "addon-inline-options");
browser.setAttribute("transparent", "true");
browser.setAttribute("forcemessagemanager", "true");
browser.setAttribute("autocompletepopup", "PopupAutoComplete");
@@ -1731,10 +1745,7 @@ class InlineOptionsBrowser extends HTMLElement {
readyPromise = promiseEvent("load", browser, true);
}
- let stack = document.createXULElement("stack");
- stack.classList.add("inline-options-stack");
- stack.appendChild(browser);
- this.appendChild(stack);
+ this.appendChild(browser);
this.browser = browser;
// Force bindings to apply synchronously.
diff --git a/toolkit/mozapps/extensions/content/aboutaddonsCommon.js b/toolkit/mozapps/extensions/content/aboutaddonsCommon.js
index 739e7629d7..9315e35861 100644
--- a/toolkit/mozapps/extensions/content/aboutaddonsCommon.js
+++ b/toolkit/mozapps/extensions/content/aboutaddonsCommon.js
@@ -237,7 +237,11 @@ async function installAddonsFromFilePicker() {
]);
const nsIFilePicker = Ci.nsIFilePicker;
var fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
- fp.init(window, dialogTitle.value, nsIFilePicker.modeOpenMultiple);
+ fp.init(
+ window.browsingContext,
+ dialogTitle.value,
+ nsIFilePicker.modeOpenMultiple
+ );
try {
fp.appendFilter(filterName.value, "*.xpi;*.jar;*.zip");
fp.appendFilters(nsIFilePicker.filterAll);
diff --git a/toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs b/toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs
index e854e04b3c..e53e4af7a4 100644
--- a/toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs
@@ -78,7 +78,7 @@ import { Log } from "resource://gre/modules/Log.sys.mjs";
const LOGGER_ID = "addons.repository";
// Create a new logger for use by the Addons Repository
-// (Requires AddonManager.jsm)
+// (Requires AddonManager.sys.mjs)
var logger = Log.repository.getLogger(LOGGER_ID);
function convertHTMLToPlainText(html) {
diff --git a/toolkit/mozapps/extensions/internal/AddonTestUtils.sys.mjs b/toolkit/mozapps/extensions/internal/AddonTestUtils.sys.mjs
index 7b30daa0e2..f53d32092d 100644
--- a/toolkit/mozapps/extensions/internal/AddonTestUtils.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/AddonTestUtils.sys.mjs
@@ -298,7 +298,7 @@ export var AddonTestUtils = {
// And scan for changes at startup
Services.prefs.setIntPref("extensions.startupScanScopes", 15);
- // By default, don't cache add-ons in AddonRepository.jsm
+ // By default, don't cache add-ons in AddonRepository.sys.mjs
Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", false);
// Point update checks to the local machine for fast failures
@@ -567,7 +567,7 @@ export var AddonTestUtils = {
},
overrideCertDB() {
- let verifyCert = async (file, result, cert, callback) => {
+ let verifyCert = async (file, result, signatureInfos, callback) => {
if (
result == Cr.NS_ERROR_SIGNED_JAR_NOT_SIGNED &&
!this.useRealCertChecks &&
@@ -606,7 +606,16 @@ export var AddonTestUtils = {
};
}
- return [callback, Cr.NS_OK, fakeCert];
+ return [
+ callback,
+ Cr.NS_OK,
+ [
+ {
+ signerCert: fakeCert,
+ signatureAlgorithm: Ci.nsIAppSignatureInfo.COSE_WITH_SHA256,
+ },
+ ],
+ ];
} catch (e) {
// If there is any error then just pass along the original results
} finally {
@@ -621,7 +630,7 @@ export var AddonTestUtils = {
}
}
- return [callback, result, cert];
+ return [callback, result, signatureInfos];
};
let FakeCertDB = {
@@ -644,10 +653,14 @@ export var AddonTestUtils = {
this._genuine.openSignedAppFileAsync(
root,
file,
- (result, zipReader, cert) => {
- verifyCert(file.clone(), result, cert, callback).then(
- ([callback, result, cert]) => {
- callback.openSignedAppFileFinished(result, zipReader, cert);
+ (result, zipReader, signatureInfos) => {
+ verifyCert(file.clone(), result, signatureInfos, callback).then(
+ ([callback, result, signatureInfos]) => {
+ callback.openSignedAppFileFinished(
+ result,
+ zipReader,
+ signatureInfos
+ );
}
);
}
@@ -1730,7 +1743,7 @@ export var AddonTestUtils = {
* @param {object} extension
* The return value of ExtensionTestUtils.loadExtension.
* For browser tests, see mochitest/tests/SimpleTest/ExtensionTestUtils.js
- * For xpcshell tests, see toolkit/components/extensions/ExtensionXPCShellUtils.jsm
+ * For xpcshell tests, see toolkit/components/extensions/ExtensionXPCShellUtils.sys.mjs
* @param {object} [options]
* Optional options.
* @param {boolean} [options.expectPending = false]
diff --git a/toolkit/mozapps/extensions/internal/AddonUpdateChecker.sys.mjs b/toolkit/mozapps/extensions/internal/AddonUpdateChecker.sys.mjs
index a3935a26f9..5b7b10a764 100644
--- a/toolkit/mozapps/extensions/internal/AddonUpdateChecker.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/AddonUpdateChecker.sys.mjs
@@ -26,7 +26,7 @@ import { Log } from "resource://gre/modules/Log.sys.mjs";
const LOGGER_ID = "addons.update-checker";
// Create a new logger for use by the Addons Update Checker
-// (Requires AddonManager.jsm)
+// (Requires AddonManager.sys.mjs)
var logger = Log.repository.getLogger(LOGGER_ID);
/**
diff --git a/toolkit/mozapps/extensions/internal/SitePermsAddonProvider.sys.mjs b/toolkit/mozapps/extensions/internal/SitePermsAddonProvider.sys.mjs
index ccac484a1e..7ca952dc8a 100644
--- a/toolkit/mozapps/extensions/internal/SitePermsAddonProvider.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/SitePermsAddonProvider.sys.mjs
@@ -148,20 +148,30 @@ class SitePermsAddonWrapper {
});
}
- get creator() {}
+ get creator() {
+ return undefined;
+ }
- get homepageURL() {}
+ get homepageURL() {
+ return undefined;
+ }
- get description() {}
+ get description() {
+ return undefined;
+ }
- get fullDescription() {}
+ get fullDescription() {
+ return undefined;
+ }
get version() {
// We consider the previous implementation attempt (signed addons) to be the initial version,
// hence the 2.0 for this approach.
return "2.0";
}
- get updateDate() {}
+ get updateDate() {
+ return undefined;
+ }
get isActive() {
return true;
@@ -273,8 +283,6 @@ class SitePermsAddonWrapper {
}
class SitePermsAddonInstalling extends SitePermsAddonWrapper {
- #install = null;
-
/**
* @param {string} siteOriginNoSuffix: The origin this addon is installed
* for, WITHOUT the suffix generated from
@@ -293,7 +301,6 @@ class SitePermsAddonInstalling extends SitePermsAddonWrapper {
};
super(siteOriginNoSuffix, [permission]);
- this.#install = install;
}
get existingAddon() {
diff --git a/toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs b/toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs
index 5d1d2c1970..af0b02444a 100644
--- a/toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs
@@ -117,7 +117,7 @@ const nsIFile = Components.Constructor(
);
// Create a new logger for use by the Addons XPI Provider Utils
-// (Requires AddonManager.jsm)
+// (Requires AddonManager.sys.mjs)
var logger = Log.repository.getLogger(LOGGER_ID);
const FILE_JSON_DB = "extensions.json";
diff --git a/toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs b/toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs
index 1a80407ad2..0402c2f2ca 100644
--- a/toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs
@@ -99,6 +99,17 @@ const PREF_SELECTED_THEME = "extensions.activeThemeID";
const TOOLKIT_ID = "toolkit@mozilla.org";
+ChromeUtils.defineLazyGetter(lazy, "MOZ_UNSIGNED_SCOPES", () => {
+ let result = 0;
+ if (AppConstants.MOZ_UNSIGNED_APP_SCOPE) {
+ result |= AddonManager.SCOPE_APPLICATION;
+ }
+ if (AppConstants.MOZ_UNSIGNED_SYSTEM_SCOPE) {
+ result |= AddonManager.SCOPE_SYSTEM;
+ }
+ return result;
+});
+
/**
* Returns a nsIFile instance for the given path, relative to the given
* base file, if provided.
@@ -168,7 +179,7 @@ import { Log } from "resource://gre/modules/Log.sys.mjs";
const LOGGER_ID = "addons.xpi";
// Create a new logger for use by all objects in this Addons XPI Provider module
-// (Requires AddonManager.jsm)
+// (Requires AddonManager.sys.mjs)
var logger = Log.repository.getLogger(LOGGER_ID);
// Stores the ID of the theme which was selected during the last session,
@@ -316,13 +327,22 @@ XPIPackage = class XPIPackage extends Package {
verifySignedStateForRoot(addonId, root) {
return new Promise(resolve => {
let callback = {
- openSignedAppFileFinished(aRv, aZipReader, aCert) {
+ openSignedAppFileFinished(aRv, aZipReader, aSignatureInfos) {
+ // aSignatureInfos is an array of nsIAppSignatureInfo.
+ // In the future, this code can iterate through the array to
+ // determine if one of the verified signatures used a satisfactory
+ // algorithm and signing certificate.
+ // For now, any verified signature is acceptable.
+ let cert;
+ if (aRv == Cr.NS_OK && aSignatureInfos.length) {
+ cert = aSignatureInfos[0].signerCert;
+ }
if (aZipReader) {
aZipReader.close();
}
resolve({
- signedState: getSignedStatus(aRv, aCert, addonId),
- cert: aCert,
+ signedState: getSignedStatus(aRv, cert, addonId),
+ cert,
});
},
};
@@ -872,10 +892,7 @@ function shouldVerifySignedState(aAddonType, aLocation) {
return true;
}
- if (
- aLocation.isBuiltin ||
- aLocation.scope & AppConstants.MOZ_UNSIGNED_SCOPES
- ) {
+ if (aLocation.isBuiltin || aLocation.scope & lazy.MOZ_UNSIGNED_SCOPES) {
return false;
}
diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs b/toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs
index d5ffd06d11..12d4fa1172 100644
--- a/toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs
@@ -185,7 +185,7 @@ import { Log } from "resource://gre/modules/Log.sys.mjs";
const LOGGER_ID = "addons.xpi";
// Create a new logger for use by all objects in this Addons XPI Provider module
-// (Requires AddonManager.jsm)
+// (Requires AddonManager.sys.mjs)
var logger = Log.repository.getLogger(LOGGER_ID);
/**
diff --git a/toolkit/mozapps/extensions/test/browser/browser.toml b/toolkit/mozapps/extensions/test/browser/browser.toml
index 1daf6211f8..0b4a2d8f0a 100644
--- a/toolkit/mozapps/extensions/test/browser/browser.toml
+++ b/toolkit/mozapps/extensions/test/browser/browser.toml
@@ -156,6 +156,8 @@ https_first_disabled = true
["browser_sidebar_hidden_categories.js"]
+["browser_sidebar_preferences_button.js"]
+
["browser_sidebar_restore_category.js"]
["browser_subframe_install.js"]
diff --git a/toolkit/mozapps/extensions/test/browser/browser_html_options_ui.js b/toolkit/mozapps/extensions/test/browser/browser_html_options_ui.js
index c5bfa1022f..efe28cf218 100644
--- a/toolkit/mozapps/extensions/test/browser/browser_html_options_ui.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_html_options_ui.js
@@ -115,13 +115,7 @@ add_task(async function testInlineOptions() {
"The browser has the expected options URL"
);
is(url, card.addon.optionsURL, "Browser has the expected options URL loaded");
- let stack = browser.closest("stack");
- is(
- browser.clientWidth,
- stack.clientWidth,
- "Browser should be the same width as its direct parent"
- );
- Assert.greater(stack.clientWidth, 0, "The stack has a width");
+ Assert.greater(browser.clientWidth, 0, "The browser has a width");
ok(
card.querySelector('[action="preferences"]').hidden,
"The preferences option is hidden now"
@@ -163,8 +157,7 @@ add_task(async function testInlineOptions() {
info("Switch back, check browser is shown");
prefsBtn.click();
- is(browser.clientWidth, stack.clientWidth, "The browser width is set again");
- Assert.greater(stack.clientWidth, 0, "The stack has a width");
+ Assert.greater(browser.clientWidth, 0, "The browser has a width");
await closeView(win);
await extension.unload();
diff --git a/toolkit/mozapps/extensions/test/browser/browser_page_options_install_addon.js b/toolkit/mozapps/extensions/test/browser/browser_page_options_install_addon.js
index 5007731927..7bc7c08345 100644
--- a/toolkit/mozapps/extensions/test/browser/browser_page_options_install_addon.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_page_options_install_addon.js
@@ -5,7 +5,7 @@
// Tests bug 567127 - Add install button to the add-ons manager
var MockFilePicker = SpecialPowers.MockFilePicker;
-MockFilePicker.init(window);
+MockFilePicker.init(window.browsingContext);
async function checkInstallConfirmation(...names) {
let notificationCount = 0;
diff --git a/toolkit/mozapps/extensions/test/browser/browser_sidebar_preferences_button.js b/toolkit/mozapps/extensions/test/browser/browser_sidebar_preferences_button.js
new file mode 100644
index 0000000000..91a631bca2
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/browser/browser_sidebar_preferences_button.js
@@ -0,0 +1,73 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function testNoOtherTabsPresent() {
+ let addonsWin = await loadInitialView("extension");
+ let preferencesButton =
+ addonsWin.document.querySelector("#preferencesButton");
+
+ let preferencesPromise = BrowserTestUtils.waitForNewTab(
+ gBrowser,
+ "about:preferences"
+ );
+
+ preferencesButton.click();
+
+ let preferencesTab = await preferencesPromise;
+
+ is(
+ gBrowser.currentURI.spec,
+ "about:preferences",
+ "about:preferences should open if neither it nor about:settings are present"
+ );
+
+ gBrowser.removeTab(preferencesTab);
+
+ await closeView(addonsWin);
+});
+
+async function ensurePreferencesButtonFocusesTab(expectedUri) {
+ let addonsWin = await loadInitialView("extension");
+ let preferencesButton =
+ addonsWin.document.querySelector("#preferencesButton");
+
+ let tabCountBeforeClick = gBrowser.tabCount;
+ preferencesButton.click();
+ let tabCountAfterClick = gBrowser.tabCount;
+
+ is(
+ tabCountAfterClick,
+ tabCountBeforeClick,
+ "preferences button should not open new tabs"
+ );
+ is(
+ gBrowser.currentURI.spec,
+ expectedUri,
+ "the correct tab should be focused"
+ );
+
+ addonsWin.focus();
+ await closeView(addonsWin);
+}
+
+add_task(async function testAboutPreferencesPresent() {
+ await BrowserTestUtils.withNewTab("about:preferences", async () => {
+ await ensurePreferencesButtonFocusesTab("about:preferences");
+ });
+});
+
+add_task(async function testAboutSettingsPresent() {
+ await BrowserTestUtils.withNewTab("about:settings", async () => {
+ await ensurePreferencesButtonFocusesTab("about:settings");
+ });
+});
+
+add_task(async function testAboutSettingsAndPreferencesPresent() {
+ await BrowserTestUtils.withNewTab("about:settings", async () => {
+ await BrowserTestUtils.withNewTab("about:preferences", async () => {
+ await ensurePreferencesButtonFocusesTab("about:settings");
+ });
+ });
+});
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js
index 727c643763..33e81c13bd 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js
@@ -196,7 +196,7 @@ add_task(async function test_after_corruption() {
await Assert.rejects(
promiseShutdownManager(),
- /NotAllowedError: Could not open the file at .+ for writing/
+ /NotAllowedError: Could not write to `.+'/
);
});
@@ -211,6 +211,6 @@ add_task(async function test_after_second_restart() {
await Assert.rejects(
promiseShutdownManager(),
- /NotAllowedError: Could not open the file at .+ for writing/
+ /NotAllowedError: Could not write to `.+'/
);
});
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_update_enterprisepolicy.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_enterprisepolicy.js
index d36b97a3cc..e25890515f 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/test_system_update_enterprisepolicy.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_enterprisepolicy.js
@@ -44,12 +44,32 @@ const TEST_CONDITIONS = {
add_task(async function test_update_disabled_by_policy() {
await setupSystemAddonConditions(TEST_CONDITIONS, distroDir);
+ const TEST_POLICY_DATA = {
+ DisableSystemAddonUpdate: true,
+ };
await EnterprisePolicyTesting.setupPolicyEngineWithJson({
- policies: {
- DisableSystemAddonUpdate: true,
- },
+ policies: TEST_POLICY_DATA,
});
+ Assert.deepEqual(
+ Services.policies.getActivePolicies(),
+ TEST_POLICY_DATA,
+ "Got the expected test policy data as the active policy " +
+ "(if this assertions fails, check your system for enterprise policies installed at system level)"
+ );
+
+ Assert.equal(
+ Services.policies.isAllowed("SysAddonUpdate"),
+ false,
+ "Expected SysAddonUpdate feature to be disabled by policies"
+ );
+
+ Assert.equal(
+ Services.prefs.getBoolPref("extensions.systemAddon.update.enabled"),
+ true,
+ "Expected system addon updates to not be already disabled through prefs"
+ );
+
await updateAllSystemAddons(
buildSystemAddonUpdates([
{
diff --git a/toolkit/mozapps/handling/content/appChooser.js b/toolkit/mozapps/handling/content/appChooser.js
index 2958ad68b4..6c04717783 100644
--- a/toolkit/mozapps/handling/content/appChooser.js
+++ b/toolkit/mozapps/handling/content/appChooser.js
@@ -225,7 +225,7 @@ let dialog = {
let title = await this.getChooseAppWindowTitle();
var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
- fp.init(window, title, Ci.nsIFilePicker.modeOpen);
+ fp.init(window.browsingContext, title, Ci.nsIFilePicker.modeOpen);
fp.appendFilters(Ci.nsIFilePicker.filterApps);
fp.open(rv => {
diff --git a/toolkit/mozapps/installer/packager.py b/toolkit/mozapps/installer/packager.py
index 29364045dd..f9d28d9c0c 100644
--- a/toolkit/mozapps/installer/packager.py
+++ b/toolkit/mozapps/installer/packager.py
@@ -63,7 +63,7 @@ class RemovedFiles(GeneratedFile):
return
if self.copier.contains(f):
errors.error("Removal of packaged file(s): %s" % f)
- self.content = f + "\n"
+ self.content += f.encode("utf-8") + b"\n"
def split_define(define):
diff --git a/toolkit/mozapps/update/AppUpdater.sys.mjs b/toolkit/mozapps/update/AppUpdater.sys.mjs
index 6133fb613b..f837982b84 100644
--- a/toolkit/mozapps/update/AppUpdater.sys.mjs
+++ b/toolkit/mozapps/update/AppUpdater.sys.mjs
@@ -411,20 +411,6 @@ export class AppUpdater {
return Services.sysinfo.getProperty("isPackagedApp");
}
- // true when updating in background is enabled.
- get #updateStagingEnabled() {
- LOG(
- "AppUpdater:#updateStagingEnabled" +
- "canStageUpdates: " +
- this.aus.canStageUpdates
- );
- return (
- !this.aus.disabled &&
- !this.#updateDisabledByPackage &&
- this.aus.canStageUpdates
- );
- }
-
/**
* Downloads an update mar or connects to an in-progress download.
* Doesn't resolve until the update is ready to install, or a failure state
diff --git a/toolkit/mozapps/update/BackgroundUpdate.sys.mjs b/toolkit/mozapps/update/BackgroundUpdate.sys.mjs
index 28d0fc8538..3022c9ffde 100644
--- a/toolkit/mozapps/update/BackgroundUpdate.sys.mjs
+++ b/toolkit/mozapps/update/BackgroundUpdate.sys.mjs
@@ -570,7 +570,7 @@ export var BackgroundUpdate = {
};
try {
- // Interacting with `TaskScheduler.jsm` can throw, so we'll catch.
+ // Interacting with `TaskScheduler.sys.mjs` can throw, so we'll catch.
if (!enabled) {
lazy.log.info(
`${SLUG}: not scheduling background update: '${JSON.stringify(
diff --git a/toolkit/mozapps/update/UpdateService.sys.mjs b/toolkit/mozapps/update/UpdateService.sys.mjs
index 16ebf64ef3..34bf1b9e19 100644
--- a/toolkit/mozapps/update/UpdateService.sys.mjs
+++ b/toolkit/mozapps/update/UpdateService.sys.mjs
@@ -193,7 +193,7 @@ const WRITE_ERROR_DIR_ACCESS_DENIED = 68;
const WRITE_ERROR_DELETE_BACKUP = 69;
const WRITE_ERROR_EXTRACT = 70;
-// Error codes 80 through 99 are reserved for UpdateService.jsm and are not
+// Error codes 80 through 99 are reserved for UpdateService.sys.mjs and are not
// defined in common/updatererrors.h
const ERR_UPDATER_CRASHED = 89;
const ERR_OLDER_VERSION_OR_SAME_BUILD = 90;
@@ -440,7 +440,7 @@ let gOtherInstancePollPromise;
*
* @return true if at least one other instance is running, false if not
*/
-function isOtherInstanceRunning(callback) {
+function isOtherInstanceRunning() {
const checkEnabled = Services.prefs.getBoolPref(
PREF_APP_UPDATE_CHECK_ONLY_INSTANCE_ENABLED,
true
@@ -497,7 +497,7 @@ function waitForOtherInstances() {
let iterations = 0;
const maxIterations = Math.ceil(timeout / interval);
- gOtherInstancePollPromise = new Promise(function (resolve, reject) {
+ gOtherInstancePollPromise = new Promise(function (resolve) {
let poll = function () {
iterations++;
if (!isOtherInstanceRunning()) {
@@ -1907,7 +1907,7 @@ function pingStateAndStatusCodes(aUpdate, aStartup, aStatus) {
stateCode = 13;
break;
// Note: Do not use stateCode 14 here. It is defined in
- // UpdateTelemetry.jsm
+ // UpdateTelemetry.sys.mjs
default:
stateCode = 1;
}
@@ -3352,10 +3352,10 @@ UpdateService.prototype = {
/**
* Notified when a timer fires
- * @param timer
+ * @param _timer
* The timer that fired
*/
- notify: function AUS_notify(timer) {
+ notify: function AUS_notify(_timer) {
this._checkForBackgroundUpdates(true);
},
@@ -3399,7 +3399,7 @@ UpdateService.prototype = {
// See Bug 1599590.
// Note that we exit unconditionally here if we are only doing manual
// update checks, because manual update checking uses a completely
- // different code path (AppUpdater.jsm creates its own nsIUpdateChecker),
+ // different code path (AppUpdater.sys.mjs creates its own nsIUpdateChecker),
// bypassing this function completely.
AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_DISABLED_BY_POLICY);
return false;
@@ -4907,7 +4907,7 @@ UpdateManager.prototype = {
/**
* See nsIUpdateService.idl
*/
- doInstallCleanup: async function UM_doInstallCleanup(isUninstall) {
+ doInstallCleanup: async function UM_doInstallCleanup() {
LOG("UpdateManager:doInstallCleanup - cleaning up");
let completionPromises = [];
@@ -4949,7 +4949,7 @@ UpdateManager.prototype = {
/**
* See nsIUpdateService.idl
*/
- doUninstallCleanup: async function UM_doUninstallCleanup(isUninstall) {
+ doUninstallCleanup: async function UM_doUninstallCleanup() {
LOG("UpdateManager:doUninstallCleanup - cleaning up.");
let completionPromises = [];
@@ -5272,13 +5272,13 @@ export class CheckerService {
return;
}
- let onLoad = event => {
+ let onLoad = _event => {
request.removeEventListener("load", onLoad);
LOG("CheckerService:#updateCheck - request got 'load' event");
resolve(UPDATE_CHECK_LOAD_SUCCESS);
};
request.addEventListener("load", onLoad);
- let onError = event => {
+ let onError = _event => {
request.removeEventListener("error", onLoad);
LOG("CheckerService:#updateCheck - request got 'error' event");
resolve(UPDATE_CHECK_LOAD_ERROR);
@@ -5702,11 +5702,9 @@ Downloader.prototype = {
* set of update patches.
* @param update
* A nsIUpdate object to select a patch from
- * @param updateDir
- * A nsIFile representing the update directory
* @return A nsIUpdatePatch object to download
*/
- _selectPatch: function Downloader__selectPatch(update, updateDir) {
+ _selectPatch: function Downloader__selectPatch(update) {
// Given an update to download, we will always try to download the patch
// for a partial update over the patch for a full update.
@@ -5934,7 +5932,7 @@ Downloader.prototype = {
// This function may return null, which indicates that there are no patches
// to download.
- this._patch = this._selectPatch(update, updateDir);
+ this._patch = this._selectPatch(update);
if (!this._patch) {
LOG("Downloader:downloadUpdate - no patch to download");
AUSTLMY.pingDownloadCode(undefined, AUSTLMY.DWNLD_ERR_NO_UPDATE_PATCH);
diff --git a/toolkit/mozapps/update/UpdateTelemetry.sys.mjs b/toolkit/mozapps/update/UpdateTelemetry.sys.mjs
index 20fb0ab4a4..f3c350267c 100644
--- a/toolkit/mozapps/update/UpdateTelemetry.sys.mjs
+++ b/toolkit/mozapps/update/UpdateTelemetry.sys.mjs
@@ -316,7 +316,7 @@ export var AUSTLMY = {
* This value is also used to determine the key for the keyed scalar
* update.bitshresult (key is either "COMPLETE" or "PARTIAL")
* @param aError
- * The BitsError that occurred. See Bits.jsm for details on BitsError.
+ * The BitsError that occurred. See Bits.sys.mjs for details on BitsError.
*/
pingBitsError: function UT_pingBitsError(aIsComplete, aError) {
if (AppConstants.platform != "win") {
diff --git a/toolkit/mozapps/update/common/updatererrors.h b/toolkit/mozapps/update/common/updatererrors.h
index f2663d5b57..d3abf14ffe 100644
--- a/toolkit/mozapps/update/common/updatererrors.h
+++ b/toolkit/mozapps/update/common/updatererrors.h
@@ -10,7 +10,7 @@
#define OK 0
// Error codes that are no longer used should not be used again unless they
-// aren't used in client code (e.g. UpdateService.jsm, updates.js, etc.).
+// aren't used in client code (e.g. UpdateService.sys.mjs, updates.js, etc.).
#define MAR_ERROR_EMPTY_ACTION_LIST 1
#define LOADSOURCE_ERROR_WRONG_SIZE 2
@@ -26,8 +26,8 @@
// Error codes 10-14 are related to memory allocation failures.
// Note: If more memory allocation error codes are added, the implementation of
-// isMemoryAllocationErrorCode in UpdateService.jsm should be updated to account
-// for them.
+// isMemoryAllocationErrorCode in UpdateService.sys.mjs should be updated to
+// account for them.
#define READ_STRINGS_MEM_ERROR 10
#define ARCHIVE_READER_MEM_ERROR 11
#define BSPATCH_MEM_ERROR 12
@@ -49,8 +49,8 @@
// Error codes 24-33 and 49-58 are for the Windows maintenance service.
// Note: If more maintenance service error codes are added, the implementations
-// of IsServiceSpecificErrorCode in updater.cpp and UpdateService.jsm should be
-// updated to account for them.
+// of IsServiceSpecificErrorCode in updater.cpp and UpdateService.sys.mjs should
+// be updated to account for them.
#define SERVICE_UPDATER_COULD_NOT_BE_STARTED 24
#define SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS 25
#define SERVICE_UPDATER_SIGN_ERROR 26
@@ -79,8 +79,8 @@
// Error codes 24-33 and 49-58 are for the Windows maintenance service.
// Note: If more maintenance service error codes are added, the implementations
-// of IsServiceSpecificErrorCode in updater.cpp and UpdateService.jsm should be
-// updated to account for them.
+// of IsServiceSpecificErrorCode in updater.cpp and UpdateService.sys.mjs should
+// be updated to account for them.
#define SERVICE_COULD_NOT_COPY_UPDATER 49
#define SERVICE_STILL_APPLYING_TERMINATED 50
#define SERVICE_STILL_APPLYING_NO_EXIT_CODE 51
@@ -112,7 +112,7 @@
#define INVALID_CALLBACK_DIR_ERROR 78
#define UPDATE_STATUS_UNCHANGED 79
-// Error codes 80 through 99 are reserved for UpdateService.jsm
+// Error codes 80 through 99 are reserved for UpdateService.sys.mjs
// The following error codes are only used by updater.exe
// when a fallback key exists for tests.
@@ -125,6 +125,6 @@
#define SILENT_UPDATE_NEEDED_ELEVATION_ERROR 105
#define WRITE_ERROR_BACKGROUND_TASK_SHARING_VIOLATION 106
-// Error codes 110 and 111 are reserved for UpdateService.jsm
+// Error codes 110 and 111 are reserved for UpdateService.sys.mjs
#endif // UPDATEERRORS_H
diff --git a/toolkit/mozapps/update/docs/BackgroundUpdates.rst b/toolkit/mozapps/update/docs/BackgroundUpdates.rst
index 7f97f58c74..d8a154cb39 100644
--- a/toolkit/mozapps/update/docs/BackgroundUpdates.rst
+++ b/toolkit/mozapps/update/docs/BackgroundUpdates.rst
@@ -65,7 +65,7 @@ observe and control these settings.
But there are some other pieces of state which absolutely must come from a
profile, such as the telemetry client ID and logging level settings (see
-`BackgroundTasksUtils.jsm <https://searchfox.org/mozilla-central/source/toolkit/components/backgroundtasks/BackgroundTasksUtils.jsm>`__).
+`BackgroundTasksUtils.sys.mjs <https://searchfox.org/mozilla-central/source/toolkit/components/backgroundtasks/BackgroundTasksUtils.sys.mjs>`__).
This means that, in addition to our per-installation prefs, we also need
to be able to identify and load a profile. To do that, we leverage `the profile
@@ -137,7 +137,7 @@ API <https://docs.microsoft.com/en-us/windows/win32/taskschd/task-scheduler-star
on macOS this will use
`launchd <https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html>`__.
For platform-specific scheduling details, see the
-`TaskScheduler.jsm <https://searchfox.org/mozilla-central/source/toolkit/components/taskscheduler/TaskScheduler.jsm>`__
+`TaskScheduler.sys.mjs <https://searchfox.org/mozilla-central/source/toolkit/components/taskscheduler/TaskScheduler.sys.mjs>`__
module.
These background tasks are scheduled per OS user and run with that user’s
@@ -177,7 +177,7 @@ visible to users: see `bug 1775132
After setting up this profile and reading all the configuration we need
into it, the regular
-`UpdateService.jsm <https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/UpdateService.jsm>`__
+`UpdateService.sys.mjs <https://searchfox.org/mozilla-central/source/toolkit/mozapps/update/UpdateService.sys.mjs>`__
check process is initiated. To the greatest extent possible, this process is
identical to what happens during any regular browsing session.
diff --git a/toolkit/mozapps/update/tests/browser/browser_elevationDialog.js b/toolkit/mozapps/update/tests/browser/browser_elevationDialog.js
index 6aa32a7fc9..639af1ffff 100644
--- a/toolkit/mozapps/update/tests/browser/browser_elevationDialog.js
+++ b/toolkit/mozapps/update/tests/browser/browser_elevationDialog.js
@@ -13,7 +13,7 @@ add_task(async function elevation_dialog() {
let { startup } = Services;
let appStartup = {
QueryInterface: ChromeUtils.generateQI(["nsIAppStartup"]),
- quit(mode) {
+ quit(_mode) {
if (elevationDialog) {
elevationDialog.close();
elevationDialog = null;
@@ -120,7 +120,7 @@ function waitForElevationDialog() {
var domwindow = aXULWindow.docShell.domWindow;
domwindow.addEventListener("load", elevationDialogOnLoad, true);
},
- onCloseWindow: aXULWindow => {},
+ onCloseWindow: _aXULWindow => {},
};
Services.wm.addListener(listener);
diff --git a/toolkit/mozapps/update/tests/browser/head.js b/toolkit/mozapps/update/tests/browser/head.js
index a18a72e581..c5acdad8e4 100644
--- a/toolkit/mozapps/update/tests/browser/head.js
+++ b/toolkit/mozapps/update/tests/browser/head.js
@@ -487,7 +487,7 @@ function waitForAboutDialog() {
var domwindow = aXULWindow.docShell.domWindow;
domwindow.addEventListener("load", aboutDialogOnLoad, true);
},
- onCloseWindow: aXULWindow => {},
+ onCloseWindow: _aXULWindow => {},
};
Services.wm.addListener(listener);
diff --git a/toolkit/mozapps/update/tests/data/app_update.sjs b/toolkit/mozapps/update/tests/data/app_update.sjs
index 2081118547..1d5d23bfb5 100644
--- a/toolkit/mozapps/update/tests/data/app_update.sjs
+++ b/toolkit/mozapps/update/tests/data/app_update.sjs
@@ -79,7 +79,7 @@ function handleRequest(aRequest, aResponse) {
let retries = 0;
gSlowDownloadTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
gSlowDownloadTimer.initWithCallback(
- function (aTimer) {
+ function (_aTimer) {
let continueFile = getTestDataFile(CONTINUE_DOWNLOAD);
retries++;
if (continueFile.exists() || retries == MAX_SLOW_RESPONSE_RETRIES) {
@@ -197,7 +197,7 @@ function respond(aResponse, aParams, aResponseString) {
aResponse.processAsync();
gSlowCheckTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
gSlowCheckTimer.initWithCallback(
- function (aTimer) {
+ function (_aTimer) {
retries++;
let continueFile = getTestDataFile(CONTINUE_CHECK);
if (continueFile.exists() || retries == MAX_SLOW_RESPONSE_RETRIES) {
diff --git a/toolkit/mozapps/update/tests/data/shared.js b/toolkit/mozapps/update/tests/data/shared.js
index fc3d358586..60de6feeb8 100644
--- a/toolkit/mozapps/update/tests/data/shared.js
+++ b/toolkit/mozapps/update/tests/data/shared.js
@@ -922,7 +922,7 @@ async function continueFileHandler(leafName) {
"Waiting for file to be deleted, path: " + continueFile.path,
interval,
retries
- ).catch(e => {
+ ).catch(_e => {
logTestInfo(
"Continue file was not removed after checking " +
retries +
diff --git a/toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js b/toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
index e88a4418cb..4b12edf6f0 100644
--- a/toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
+++ b/toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
@@ -3766,7 +3766,7 @@ function checkFilesAfterUpdateSuccess(
"xattr value changed"
);
},
- reason => {
+ _reason => {
Assert.fail(MAC_APP_XATTR_KEY + " xattr is missing!");
}
);
@@ -4233,9 +4233,9 @@ async function waitForUpdateDownload(aUpdates, aExpectedStatus) {
}
return new Promise(resolve =>
gAUS.addDownloadListener({
- onStartRequest: aRequest => {},
- onProgress: (aRequest, aContext, aProgress, aMaxProgress) => {},
- onStatus: (aRequest, aStatus, aStatusText) => {},
+ onStartRequest: _aRequest => {},
+ onProgress: (_aRequest, _aContext, _aProgress, _aMaxProgress) => {},
+ onStatus: (_aRequest, _aStatus, _aStatusText) => {},
onStopRequest(request, status) {
gAUS.removeDownloadListener(this);
Assert.equal(
@@ -4552,7 +4552,7 @@ function adjustGeneralPaths() {
* The timer callback to kill the process if it takes too long.
*/
const gAppTimerCallback = {
- notify: function TC_notify(aTimer) {
+ notify: function TC_notify(_aTimer) {
gAppTimer = null;
if (gProcess.isRunning) {
logTestInfo("attempting to kill process");
@@ -4662,7 +4662,7 @@ function IncrementalDownload() {
IncrementalDownload.prototype = {
/* nsIIncrementalDownload */
- init(uri, file, chunkSize, intervalInSeconds) {
+ init(uri, file, _chunkSize, _intervalInSeconds) {
this._destination = file;
this._URI = uri;
this._finalURI = uri;
@@ -4729,7 +4729,7 @@ IncrementalDownload.prototype = {
},
/* nsIRequest */
- cancel(aStatus) {
+ cancel(_aStatus) {
throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
},
suspend() {
diff --git a/toolkit/mozapps/update/tests/marionette/test_no_window_update_restart.py b/toolkit/mozapps/update/tests/marionette/test_no_window_update_restart.py
index a8495064ef..9452a4fcd7 100644
--- a/toolkit/mozapps/update/tests/marionette/test_no_window_update_restart.py
+++ b/toolkit/mozapps/update/tests/marionette/test_no_window_update_restart.py
@@ -162,7 +162,9 @@ class TestNoWindowUpdateRestart(MarionetteTestCase):
let UM = Cc["@mozilla.org/updates/update-manager;1"].getService(Ci.nsIUpdateManager);
UM.QueryInterface(Ci.nsIObserver).observe(null, "um-reload-update-data", "skip-files");
- let { UpdateListener } = ChromeUtils.import("resource://gre/modules/UpdateListener.jsm");
+ let { UpdateListener } = ChromeUtils.importESModule(
+ "resource://gre/modules/UpdateListener.sys.mjs"
+ );
UpdateListener.reset();
let { AppMenuNotifications } = ChromeUtils.importESModule(
diff --git a/toolkit/mozapps/update/tests/unit_aus_update/languagePackUpdates.js b/toolkit/mozapps/update/tests/unit_aus_update/languagePackUpdates.js
index 0ae35ef77a..9e23fab5e0 100644
--- a/toolkit/mozapps/update/tests/unit_aus_update/languagePackUpdates.js
+++ b/toolkit/mozapps/update/tests/unit_aus_update/languagePackUpdates.js
@@ -243,9 +243,9 @@ add_task(async function testRedownload() {
let downloadCount = 0;
let listener = {
- onStartRequest: aRequest => {},
- onProgress: (aRequest, aContext, aProgress, aMaxProgress) => {},
- onStatus: (aRequest, aStatus, aStatusText) => {},
+ onStartRequest: _aRequest => {},
+ onProgress: (_aRequest, _aContext, _aProgress, _aMaxProgress) => {},
+ onStatus: (_aRequest, _aStatus, _aStatusText) => {},
onStopRequest: (request, status) => {
Assert.equal(
status,
diff --git a/toolkit/mozapps/update/tests/unit_aus_update/multiUpdate.js b/toolkit/mozapps/update/tests/unit_aus_update/multiUpdate.js
index 3767a44feb..411b303331 100644
--- a/toolkit/mozapps/update/tests/unit_aus_update/multiUpdate.js
+++ b/toolkit/mozapps/update/tests/unit_aus_update/multiUpdate.js
@@ -73,14 +73,14 @@ async function downloadUpdate(appUpdateAuto, onDownloadStartCallback) {
}
let waitToStartPromise = new Promise(resolve => {
let listener = {
- onStartRequest: aRequest => {
+ onStartRequest: _aRequest => {
gAUS.removeDownloadListener(listener);
onDownloadStartCallback();
resolve();
},
- onProgress: (aRequest, aContext, aProgress, aMaxProgress) => {},
- onStatus: (aRequest, aStatus, aStatusText) => {},
- onStopRequest(request, status) {},
+ onProgress: (_aRequest, _aContext, _aProgress, _aMaxProgress) => {},
+ onStatus: (_aRequest, _aStatus, _aStatusText) => {},
+ onStopRequest(_request, _status) {},
QueryInterface: ChromeUtils.generateQI([
"nsIRequestObserver",
"nsIProgressEventSink",
@@ -149,7 +149,7 @@ async function testUpdateDoesNotDownload() {
);
let updateAvailableObserved = false;
- let observer = (subject, topic, status) => {
+ let observer = (_subject, _topic, _status) => {
updateAvailableObserved = true;
};
Services.obs.addObserver(observer, "update-available");
diff --git a/toolkit/mozapps/update/tests/unit_aus_update/updateSyncManager.js b/toolkit/mozapps/update/tests/unit_aus_update/updateSyncManager.js
index 9123f9e1e3..c705d536a4 100644
--- a/toolkit/mozapps/update/tests/unit_aus_update/updateSyncManager.js
+++ b/toolkit/mozapps/update/tests/unit_aus_update/updateSyncManager.js
@@ -79,7 +79,7 @@ add_task(async function () {
await TestUtils.waitForCondition(
() => syncManager.isOtherInstanceRunning(),
"waiting for child process to take the lock"
- ).catch(e => {
+ ).catch(_e => {
// Rather than throwing out of waitForCondition(), catch and log the failure
// manually so that we get output that's a bit more readable.
Assert.ok(
@@ -93,7 +93,7 @@ add_task(async function () {
await TestUtils.waitForCondition(
() => !syncManager.isOtherInstanceRunning(),
"waiting for child process to release the lock"
- ).catch(e => {
+ ).catch(_e => {
Assert.ok(
!syncManager.isOtherInstanceRunning(),
"child process has released the lock"
diff --git a/toolkit/mozapps/update/tests/unit_background_update/test_backgroundupdate_glean.js b/toolkit/mozapps/update/tests/unit_background_update/test_backgroundupdate_glean.js
index 0d9c06b2d0..0ca74e4764 100644
--- a/toolkit/mozapps/update/tests/unit_background_update/test_backgroundupdate_glean.js
+++ b/toolkit/mozapps/update/tests/unit_background_update/test_backgroundupdate_glean.js
@@ -140,7 +140,7 @@ async function do_readTargeting(content, beforeNextSubmitCallback) {
// Missing targeting is anticipated.
add_task(async function test_targeting_missing() {
- await do_readTargeting(null, reason => {
+ await do_readTargeting(null, _reason => {
Assert.equal(false, Glean.backgroundUpdate.targetingExists.testGetValue());
Assert.equal(
@@ -152,7 +152,7 @@ add_task(async function test_targeting_missing() {
// Malformed JSON yields an exception.
add_task(async function test_targeting_exception() {
- await do_readTargeting("{", reason => {
+ await do_readTargeting("{", _reason => {
Assert.equal(false, Glean.backgroundUpdate.targetingExists.testGetValue());
Assert.equal(
@@ -193,7 +193,7 @@ add_task(async function test_targeting_exists() {
targets: [manager.createTargetingContext(), target],
});
- await do_readTargeting(JSON.stringify(targetSnapshot), reason => {
+ await do_readTargeting(JSON.stringify(targetSnapshot), _reason => {
Assert.equal(true, Glean.backgroundUpdate.targetingExists.testGetValue());
Assert.equal(
diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp
index 947e84aac3..6b01450b31 100644
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -3734,7 +3734,7 @@ int NS_main(int argc, NS_tchar** argv) {
}
// Set an error so we don't get into an update loop when the callback
// runs. This will be reset to pending by handleUpdateFailure in
- // UpdateService.jsm.
+ // UpdateService.sys.mjs.
WriteStatusFile(SILENT_UPDATE_NEEDED_ELEVATION_ERROR);
LOG(("Skipping update to avoid UAC prompt from background task."));
output_finish();