tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 1346bd8346bccbccc64e48d89aeade48d27b9e2f
parent 2db2ad618c5d8148357fdd8d720f8c2225dfdc79
Author: Cristina Horotan <chorotan@mozilla.com>
Date:   Thu,  9 Oct 2025 02:08:24 +0300

Revert "Bug 1984458 - Add tests that `UpdateService` notices when `update.status` is inaccessible r=cdupuis,nrishel" for causing xpcshell failures on accessAndLockout.js

This reverts commit 2665adee74b624d68ed0fa0153396945b1f1a1e8.

Revert "Bug 1984458 - Add test utilities for `update.status` I/O failures r=cdupuis,nrishel"

This reverts commit ad4dbea294fbfbf7a9d5573330ad6a1d11e08846.

Revert "Bug 1984458 - Make `UpdateService` check for persistent access failures r=cdupuis,nrishel"

This reverts commit 2e959490d411967d2f1f87e272e052c8325f4dfa.

Diffstat:
Mtoolkit/mozapps/update/UpdateService.sys.mjs | 148+++++++------------------------------------------------------------------------
Mtoolkit/mozapps/update/metrics.yaml | 14--------------
Mtoolkit/mozapps/update/nsIUpdateService.idl | 3---
Mtoolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js | 88++++---------------------------------------------------------------------------
Mtoolkit/mozapps/update/tests/moz.build | 3---
Dtoolkit/mozapps/update/tests/test_file_hold_open.cpp | 53-----------------------------------------------------
Dtoolkit/mozapps/update/tests/test_file_update_mtime.cpp | 65-----------------------------------------------------------------
Dtoolkit/mozapps/update/tests/unit_aus_update/accessAndLockout.js | 122-------------------------------------------------------------------------------
Mtoolkit/mozapps/update/tests/unit_aus_update/xpcshell.toml | 4----
9 files changed, 17 insertions(+), 483 deletions(-)

diff --git a/toolkit/mozapps/update/UpdateService.sys.mjs b/toolkit/mozapps/update/UpdateService.sys.mjs @@ -84,11 +84,6 @@ const PREF_APP_UPDATE_ELEVATE_NEVER = "app.update.elevate.never"; const PREF_APP_UPDATE_ELEVATE_VERSION = "app.update.elevate.version"; const PREF_APP_UPDATE_ELEVATE_ATTEMPTS = "app.update.elevate.attempts"; const PREF_APP_UPDATE_ELEVATE_MAXATTEMPTS = "app.update.elevate.maxAttempts"; -const PREF_APP_UPDATE_LOCKEDOUT_COUNT = "app.update.lockedOut.count"; -const PREF_APP_UPDATE_LOCKEDOUT_DEBOUNCETIME = - "app.update.lockedOut.debounceTimeMs"; -const PREF_APP_UPDATE_LOCKEDOUT_MAXCOUNT = "app.update.lockedOut.maxCount"; -const PREF_APP_UPDATE_LOCKEDOUT_MAXAGE = "app.update.lockedOut.maxAgeMs"; const PREF_APP_UPDATE_LANGPACK_ENABLED = "app.update.langpack.enabled"; const PREF_APP_UPDATE_LANGPACK_TIMEOUT = "app.update.langpack.timeout"; const PREF_APP_UPDATE_NOTIFYDURINGDOWNLOAD = "app.update.notifyDuringDownload"; @@ -311,8 +306,6 @@ let gOnlyDownloadUpdatesThisSession = false; // This will be the backing for `nsIApplicationUpdateService.currentState` var gUpdateState = Ci.nsIApplicationUpdateService.STATE_IDLE; -let gLastLockoutDebouncedAt = 0; - /** * Simple container and constructor for a Promise and its resolve function. */ @@ -1050,92 +1043,6 @@ function getDownloadingUpdateDir() { } /** - * If there is a problem with accessing the status file, it may be a transient - * issue, such as another process checking for updates holding a lock, - * or it may be a persistent problem that needs attention. - * This function tries to determine if we should prompt the user to fix the - * issue. - * - * @param file - * An nsIFile object for the file with the issue - * @param ex - * The Exception object that was thrown when attempting to access the - * file. - */ -function onStateAccessFailure(file, ex) { - LOG("onStateAccessFailure. Ex: " + ex); - if ( - ex.result == Cr.NS_ERROR_FILE_ACCESS_DENIED || - ex.result == Cr.NS_ERROR_FILE_IS_LOCKED - ) { - // Looks like we can't access the file. If it hasn't changed in - // a long time, notify the user that we are persistently unable to update. - const oneMinMs = 60 * 1000; - const oneDayMs = 24 * 60 * oneMinMs; - const now = Date.now(); - - // A single update check can attempt to read and write the update state - // multiple times. We want `lockoutCount` to count the number of times that - // an update check fails, not the number of times that we fail to access the - // state. To deal with this, we will implement a debouncing period after - // each failure. - let debounceTimeMs = Services.prefs.getIntPref( - PREF_APP_UPDATE_LOCKEDOUT_DEBOUNCETIME, - 5 * oneMinMs - ); - debounceTimeMs = Math.min(debounceTimeMs, oneDayMs); - const debounceEnd = gLastLockoutDebouncedAt + debounceTimeMs; - if (now < debounceEnd) { - LOG(`onStateAccessFailure: debounced! (${debounceEnd - now}ms left)`); - return; - } - gLastLockoutDebouncedAt = now; - - // Not really the age, just the interval since last modified. - const fileAgeMs = now - file.lastModifiedTime; - - let lockoutCount = Services.prefs.getIntPref( - PREF_APP_UPDATE_LOCKEDOUT_COUNT, - 0 - ); - lockoutCount += 1; - Services.prefs.setIntPref(PREF_APP_UPDATE_LOCKEDOUT_COUNT, lockoutCount); - - let maxLockoutCount = Services.prefs.getIntPref( - PREF_APP_UPDATE_LOCKEDOUT_MAXCOUNT, - 4 - ); - maxLockoutCount = Math.min(maxLockoutCount, 20); - LOG( - `onStateAccessFailure: lockoutCount is ${lockoutCount}, maxLockoutCount is ${maxLockoutCount}` - ); - - let maxFileAgeMs = Services.prefs.getIntPref( - PREF_APP_UPDATE_LOCKEDOUT_MAXAGE, - oneDayMs * 2 - ); - maxFileAgeMs = Math.min(maxFileAgeMs, oneDayMs * 14); - LOG( - `onStateAccessFailure: fileAgeMs = ${fileAgeMs} maxFileAgeMs = ${maxFileAgeMs}` - ); - - if (lockoutCount >= maxLockoutCount && fileAgeMs >= maxFileAgeMs) { - Glean.update.stateWriteFailure.add(); - // Create an empty Update object for messaging. - let update = new Update(null); - LOG("onStateAccessFailure: reporting permission issue"); - Services.obs.notifyObservers(update, "update-error", "bad-perms"); - Services.prefs.setIntPref(PREF_APP_UPDATE_LOCKEDOUT_COUNT, 0); - } - } -} - -function onStateAccessSuccess() { - LOG("onStateAccessSuccess"); - Services.prefs.setIntPref(PREF_APP_UPDATE_LOCKEDOUT_COUNT, 0); -} - -/** * Reads the update state from the update.status file in the specified * directory. * @param dir @@ -1154,31 +1061,16 @@ function readStatusFile(dir) { * Writes the current update operation/state to a file in the patch * directory, indicating to the patching system that operations need * to be performed. - * - * This function does not throw on errors. It just returns the error. - * * @param dir * The patch directory where the update.status file should be * written. * @param state * The state value to write. - * @returns `null` on success or a JS exception on failure. */ function writeStatusFile(dir, state) { let statusFile = dir.clone(); statusFile.append(FILE_UPDATE_STATUS); - try { - writeStringToFile(statusFile, state); - LOG("writeStatusFile - status: " + state + ", path: " + statusFile.path); - try { - onStateAccessSuccess(); - } catch {} - } catch (ex) { - LOG("writeStatusFile failed: " + ex); - onStateAccessFailure(statusFile, ex); - return ex; - } - return null; + writeStringToFile(statusFile, state); } /** @@ -1189,9 +1081,6 @@ function writeStatusFile(dir, state) { * the update should be applied. Note that this won't provide protection from * downgrade of the application for the nightly user case where the application * version doesn't change. - * - * This function fails silently. - * * @param dir * The patch directory where the update.version file should be * written. @@ -1202,11 +1091,7 @@ function writeStatusFile(dir, state) { function writeVersionFile(dir, version) { let versionFile = dir.clone(); versionFile.append(FILE_UPDATE_VERSION); - try { - writeStringToFile(versionFile, version); - } catch (ex) { - LOG("writeVersionFile failed: " + ex); - } + writeStringToFile(versionFile, version); } /** @@ -1540,20 +1425,19 @@ async function cleanupActiveUpdates() { * written to the file. This function only works with ASCII text. * @param file An nsIFile indicating what file to write to. * @param text A string containing the text to write to the file. - * @throws Errors from file stream will be propagated. + * @return true on success, false on failure. */ function writeStringToFile(file, text) { - let fos = FileUtils.openSafeFileOutputStream(file); - text += "\n"; - fos.write(text, text.length); - // Don't use `FileUtils.closeSafeFileOutputStream` because it swallows errors, - // which we don't want to do here. try { - fos.QueryInterface(Ci.nsISafeOutputStream); - fos.finish(); - } finally { - fos.close(); + let fos = FileUtils.openSafeFileOutputStream(file); + text += "\n"; + fos.write(text, text.length); + FileUtils.closeSafeFileOutputStream(fos); + } catch (e) { + LOG(`writeStringToFile - Failed to write to file: "${file}". Error: ${e}"`); + return false; } + return true; } function readStringFromInputStream(inputStream) { @@ -6516,14 +6400,8 @@ class Downloader { } if (!lazy.UM.internal.readyUpdate) { - const error = writeStatusFile(getReadyUpdateDir(), STATE_DOWNLOADING); - if (error) { - LOG("Downloader:downloadUpdate - Failed to set status to downloading"); - await cleanupActiveUpdates(); - return Ci.nsIApplicationUpdateService - .DOWNLOAD_FAILURE_CANNOT_WRITE_STATE; - } - LOG("Downloader:downloadUpdate - Set status to downloading"); + LOG("Downloader:downloadUpdate - Setting status to downloading"); + writeStatusFile(getReadyUpdateDir(), STATE_DOWNLOADING); } if (this._patch.state != STATE_DOWNLOADING) { LOG("Downloader:downloadUpdate - Setting state to downloading"); diff --git a/toolkit/mozapps/update/metrics.yaml b/toolkit/mozapps/update/metrics.yaml @@ -467,20 +467,6 @@ update: expires: never telemetry_mirror: h#UPDATE_SERVICE_MANUALLY_UNINSTALLED_SUBSEQUENT - state_write_failure: - type: counter - description: > - Update: Count of the number of times we have shown a notification to the - user that they need to manually update because we cannot write to the - update status file. - bugs: - - https://bugzilla.mozilla.org/show_bug.cgi?id=1984458 - data_reviews: - - https://bugzilla.mozilla.org/show_bug.cgi?id=1984458 - notification_emails: - - application-update-telemetry-alerts@mozilla.com - expires: never - unable_to_apply_external: type: counter description: > diff --git a/toolkit/mozapps/update/nsIUpdateService.idl b/toolkit/mozapps/update/nsIUpdateService.idl @@ -490,9 +490,6 @@ interface nsIApplicationUpdateService : nsISupports // The update download cannot be started for a reason that doesn't have a more // specific failure code. const long DOWNLOAD_FAILURE_GENERIC = 3; - // The update download cannot be started because the update state could not - // be written to the update directory. - const long DOWNLOAD_FAILURE_CANNOT_WRITE_STATE = 4; /** * Starts downloading the update passed. Once the update is downloaded, it diff --git a/toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js b/toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js @@ -154,7 +154,6 @@ const APP_UPDATE_SJS_HOST = "http://127.0.0.1"; const APP_UPDATE_SJS_PATH = "/" + REL_PATH_DATA + "app_update.sjs"; var gIncrementalDownloadErrorType; -var gIncrementalDownloadCancelOk = false; var gResponseBody; @@ -5175,13 +5174,7 @@ IncrementalDownload.prototype = { /* nsIRequest */ cancel(_aStatus) { - // We aren't actually going to do anything to cancel this. The tests should - // clean up the completed download either way, so it should never really - // matter if we actually finish it after calling this. But we want to throw - // an error if a test calls this unexpectedly. - if (!gIncrementalDownloadCancelOk) { - throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED); - } + throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED); }, suspend() { throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED); @@ -5704,12 +5697,6 @@ const EXIT_CODE = ${JSON.stringify(TestUpdateMutexCrossProcess.EXIT_CODE)}; * expectedDownloadResult * This function asserts that the download should finish with this * result. Defaults to `NS_OK`. - * expectedDownloadStartResult - * This function asserts that `AUS.downloadUpdate` return the - * expected value. Defaults to - * `Ci.nsIApplicationUpdateService.DOWNLOAD_SUCCESS`. If a different - * value is specified, later checks that the download completed - * properly will be skipped. * incrementalDownloadErrorType * This can be used to specify an alternate value of * `gIncrementalDownloadErrorType`. The default value is `3`, which @@ -5732,7 +5719,6 @@ async function downloadUpdate({ expectDownloadRestriction, expectedCheckResult, expectedDownloadResult = Cr.NS_OK, - expectedDownloadStartResult = Ci.nsIApplicationUpdateService.DOWNLOAD_SUCCESS, incrementalDownloadErrorType = 3, onDownloadStartCallback, slowDownload, @@ -5750,10 +5736,7 @@ async function downloadUpdate({ "update-download-restriction-hit" ); }); - } else if ( - expectedDownloadStartResult == - Ci.nsIApplicationUpdateService.DOWNLOAD_SUCCESS - ) { + } else { downloadFinishedPromise = new Promise(resolve => gAUS.addDownloadListener({ onStartRequest: _aRequest => {}, @@ -5817,9 +5800,6 @@ async function downloadUpdate({ initMockIncrementalDownload(); gIncrementalDownloadErrorType = incrementalDownloadErrorType; - gIncrementalDownloadCancelOk = - expectedDownloadStartResult != - Ci.nsIApplicationUpdateService.DOWNLOAD_SUCCESS; update = await gAUS.selectUpdate(updates); } @@ -5844,12 +5824,9 @@ async function downloadUpdate({ const result = await gAUS.downloadUpdate(update); Assert.equal( result, - expectedDownloadStartResult, - "nsIApplicationUpdateService:downloadUpdate status should be correct" + Ci.nsIApplicationUpdateService.DOWNLOAD_SUCCESS, + "nsIApplicationUpdateService:downloadUpdate should succeed" ); - if (result != Ci.nsIApplicationUpdateService.DOWNLOAD_SUCCESS) { - return; - } } if (waitToStartPromise) { @@ -5879,60 +5856,3 @@ async function downloadUpdate({ await TestUtils.waitForTick(); } } - -/** - * Holds a file open until it ought to be closed. - * - * @param file - * The `nsIFile` for the file to be held open - * @param shareMode - * Optional. The share mode (`dwShareMode`) to pass to `CreateFileW` - * when opening the file. If provided, should be a string containing - * a combination of 'r', 'w', and 'd' to indicate sharing for the - * read, write, and delete permissions, respectively. The default is to - * share nothing. - * @return An asynchronous function taking no arguments. When it is called and - * the returned promise resolves, the file is no longer being held open. - */ -async function holdFileOpen(file, shareMode) { - const testHelper = getTestDirFile("test_file_hold_open.exe", false); - - const args = [file.path]; - if (shareMode) { - args.push(shareMode); - } - - const proc = await Subprocess.call({ - command: testHelper.path, - arguments: args, - }); - const isLocked = await proc.stdout.readString(); - - if (isLocked.trim() != "Locked") { - throw new Error("Expected status to be Locked, found " + isLocked); - } - - return async () => { - await proc.stdin.write("q"); - const rc = await proc.wait(1000); - Assert.equal(rc.exitCode, 0, "Expected process to have successful exit"); - }; -} - -async function setFileModifiedAge(outfile, ageInSeconds) { - const outfilePath = outfile.path; - const testHelper = getTestDirFile("test_file_update_mtime.exe"); - - let proc = await Subprocess.call({ - command: testHelper.path, - arguments: [outfilePath, ageInSeconds], - }); - - let stdout; - while ((stdout = await proc.stdout.readString())) { - logTestInfo(stdout); - } - - const rc = await proc.wait(1000); // Wait for it to exit. - Assert.equal(rc.exitCode, 0, "Expected process to have successful exit"); -} diff --git a/toolkit/mozapps/update/tests/moz.build b/toolkit/mozapps/update/tests/moz.build @@ -34,9 +34,6 @@ SimplePrograms( ] ) -if CONFIG["OS_ARCH"] == "WINNT": - SimplePrograms(["test_file_hold_open", "test_file_update_mtime"]) - LOCAL_INCLUDES += [ "/toolkit/mozapps/update", "/toolkit/mozapps/update/common", diff --git a/toolkit/mozapps/update/tests/test_file_hold_open.cpp b/toolkit/mozapps/update/tests/test_file_hold_open.cpp @@ -1,53 +0,0 @@ -#include <windows.h> -#include <iostream> -#include <string> - -// Opens a file and holds it open until the caller sends input. -// Then it closes the file and exits. - -void usage(int argc, wchar_t** argv) { - std::wcout << L"Usage:\n" - << L" " << argv[0] << L" filename [sharing]\n\n" - << L" filename\n" - << L" The path of the file to hold open.\n" - << L" sharing\n" - << L" File sharing flags. 'r', 'w', and/or 'd' can be\n" - << L" specified. Defaults to no sharing.\n\n"; -} - -int wmain(int argc, wchar_t** argv) { - DWORD dwShareMode = 0; - - if (argc < 2 || argc > 3) { - usage(argc, argv); - exit(1); - } - if (argc >= 3) { - for (wchar_t* curr = argv[2]; *curr; ++curr) { - switch (*curr) { - case L'w': - dwShareMode |= FILE_SHARE_WRITE; - break; - case L'r': - dwShareMode |= FILE_SHARE_READ; - break; - case L'd': - dwShareMode |= FILE_SHARE_DELETE; - break; - default: - usage(argc, argv); - return 1; - } - } - } - HANDLE handle = CreateFileW(argv[1], GENERIC_READ, dwShareMode, nullptr, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if (handle == INVALID_HANDLE_VALUE) { - std::wcout << L"failed to open file " << argv[1] << std::endl; - return 1; - } - std::wcout << "Locked" << std::endl; - (void)std::wcin.get(); - CloseHandle(handle); - return 0; -} diff --git a/toolkit/mozapps/update/tests/test_file_update_mtime.cpp b/toolkit/mozapps/update/tests/test_file_update_mtime.cpp @@ -1,65 +0,0 @@ -#include <windows.h> -#include <iostream> -#include <string> - -void usage(int argc, wchar_t** argv) { - std::wcout << L"Usage:\n" - << L" " << argv[0] << L" filename age\n\n" - << L" filename\n" - << L" The path of the file to change.\n" - << L" age\n" - << L" The number of seconds in the past to set the file's \n" - << L" modification time to.\n\n"; -} - -static const ULONGLONG FILETIME_TICKS_PER_SECOND = 10'000'000; - -static ULARGE_INTEGER secondsAgoTimestamp(ULONGLONG secondsAgo) { - FILETIME now{}; - GetSystemTimeAsFileTime(&now); - ULARGE_INTEGER systemTime; - systemTime.LowPart = now.dwLowDateTime; - systemTime.HighPart = now.dwHighDateTime; - systemTime.QuadPart -= secondsAgo * FILETIME_TICKS_PER_SECOND; - return systemTime; -} - -int wmain(int argc, wchar_t** argv) { - HANDLE handle; - FILE_BASIC_INFO fileBasicInfo{}; - long ageInSeconds; - if (argc != 3) { - usage(argc, argv); - return 1; - } - if (!swscanf(argv[2], L"%lu", &ageInSeconds)) { - std::wcout << "Invalid seconds: " << argv[2] << std::endl; - return 2; - } - if ((handle = CreateFileW(argv[1], GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, nullptr)) == - INVALID_HANDLE_VALUE) { - std::wcout << "Error opening file: " << argv[1] << ", " << GetLastError() - << std::endl; - return 3; - } - if (!GetFileInformationByHandleEx(handle, FileBasicInfo, &fileBasicInfo, - sizeof(fileBasicInfo))) { - std::wcout << "Error getting file info: " << GetLastError() << std::endl; - return 4; - } - - ULARGE_INTEGER desiredTimestamp = secondsAgoTimestamp(ageInSeconds); - fileBasicInfo.LastWriteTime.QuadPart = desiredTimestamp.QuadPart; - - if (!SetFileInformationByHandle(handle, FileBasicInfo, &fileBasicInfo, - sizeof(fileBasicInfo))) { - std::wcout << "Error setting file mtime: " << GetLastError() << std::endl; - return 5; - } - if (!CloseHandle(handle)) { - std::wcout << "Error closing handle: " << GetLastError() << std::endl; - return 6; - } - return 0; -} diff --git a/toolkit/mozapps/update/tests/unit_aus_update/accessAndLockout.js b/toolkit/mozapps/update/tests/unit_aus_update/accessAndLockout.js @@ -1,122 +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/. - */ - -const PREF_APP_UPDATE_LOCKEDOUT_COUNT = "app.update.lockedOut.count"; -const PREF_APP_UPDATE_LOCKEDOUT_DEBOUNCETIME = - "app.update.lockedOut.debounceTimeMs"; -const PREF_APP_UPDATE_LOCKEDOUT_MAXCOUNT = "app.update.lockedOut.maxCount"; -const PREF_APP_UPDATE_LOCKEDOUT_MAXAGE = "app.update.lockedOut.maxAgeMs"; - -const kMaxLockedOutCount = 10; -const kMaxStatusFileModifyAgeMs = 24 * 60 * 60 * 1000; // 1 day - -add_setup(async function setup() { - setupTestCommon(); - start_httpserver(); - setUpdateURL(gURLData + gHTTPHandlerPath); - setUpdateChannel("test_channel"); - - // FOG needs a profile directory to put its data in. - do_get_profile(); - Services.fog.initializeFOG(); -}); - -async function runLockedOutTest({ - isLockedOut, - statusFileIsOld, - lockoutsRemaining, -}) { - await reloadUpdateManagerData(); - await reInitUpdateService(); - Services.fog.testResetFOG(); - - const statusFile = getUpdateDirFile(FILE_UPDATE_STATUS); - - let lockoutCount = kMaxLockedOutCount - lockoutsRemaining; - Services.prefs.setIntPref(PREF_APP_UPDATE_LOCKEDOUT_COUNT, lockoutCount); - - // Write an empty status file to ensure that the path exists. - writeStatusFile(""); - if (statusFileIsOld) { - await setFileModifiedAge( - statusFile, - Math.floor((2 * kMaxStatusFileModifyAgeMs) / 1000) - ); - } else { - await setFileModifiedAge(statusFile, 0); - } - let unlockStatusFile; - if (isLockedOut) { - unlockStatusFile = await holdFileOpen(statusFile, "r"); - } else { - unlockStatusFile = async () => {}; - } - - const nextLockoutWillBeMax = lockoutsRemaining <= 1; - const expectNotifyUser = - isLockedOut && statusFileIsOld && nextLockoutWillBeMax; - const badPermsObserverPromise = expectNotifyUser - ? waitForEvent("update-error", "bad-perms") - : Promise.resolve(true); - const expectedDownloadStartResult = isLockedOut - ? Ci.nsIApplicationUpdateService.DOWNLOAD_FAILURE_CANNOT_WRITE_STATE - : Ci.nsIApplicationUpdateService.DOWNLOAD_SUCCESS; - - await downloadUpdate({ expectedDownloadStartResult }); - - const badPermsObserverResult = await badPermsObserverPromise; - Assert.ok(badPermsObserverResult); - - const newLockoutCount = Services.prefs.getIntPref( - PREF_APP_UPDATE_LOCKEDOUT_COUNT, - -1 - ); - if (!isLockedOut || expectNotifyUser) { - Assert.equal(newLockoutCount, 0, "lockout count should reset"); - } else { - Assert.equal( - newLockoutCount, - lockoutCount + 1, - "lockout count should incremented" - ); - } - if (expectNotifyUser) { - Assert.equal( - Glean.update.stateWriteFailure.testGetValue(), - 1, - "telemetry should be incremented" - ); - } else { - // Coerce the telemetry into an integer since this will generally return - // `null`. - Assert.equal( - Number(Glean.update.stateWriteFailure.testGetValue()), - 0, - "telemetry should not be incremented" - ); - } - - await unlockStatusFile(); -} - -add_task(async function testAccessAndLockout() { - Services.prefs.setIntPref( - PREF_APP_UPDATE_LOCKEDOUT_MAXCOUNT, - kMaxLockedOutCount - ); - Services.prefs.setIntPref(PREF_APP_UPDATE_LOCKEDOUT_DEBOUNCETIME, 0); - Services.prefs.setIntPref( - PREF_APP_UPDATE_LOCKEDOUT_MAXAGE, - kMaxStatusFileModifyAgeMs - ); - - await parameterizedTest(runLockedOutTest, { - isLockedOut: [true, false], - statusFileIsOld: [true, false], - lockoutsRemaining: [1, 2], - }); - - await doTestFinish(); -}); diff --git a/toolkit/mozapps/update/tests/unit_aus_update/xpcshell.toml b/toolkit/mozapps/update/tests/unit_aus_update/xpcshell.toml @@ -19,10 +19,6 @@ support-files = [ "../data/simple.mar", ] -["accessAndLockout.js"] -run-if = ["os == 'win'"] -reason = "Testing mechanism is Windows-only as it relies on CreateFileW" - ["ausReadStrings.js"] ["backgroundUpdateTaskInternalUpdater.js"]