import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,488 @@
/* 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/. */
"use strict";
this.EXPORTED_SYMBOLS = [
"AUSTLMY"
];
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm", this);
this.AUSTLMY = {
// Telemetry for the application update background update check occurs when
// the background update timer fires after the update interval which is
// determined by the app.update.interval preference and its telemetry
// histogram IDs have the suffix '_NOTIFY'.
// Telemetry for the externally initiated background update check occurs when
// a call is made to |checkForBackgroundUpdates| which is typically initiated
// by an application when it has determined that the application should have
// received an update. This has separate telemetry so it is possible to
// analyze using the telemetry data systems that have not been updating when
// they should have.
// The update check was performed by the call to checkForBackgroundUpdates in
// nsUpdateService.js.
EXTERNAL: "EXTERNAL",
// The update check was performed by the call to notify in nsUpdateService.js.
NOTIFY: "NOTIFY",
/**
* Values for the UPDATE_CHECK_CODE_NOTIFY and UPDATE_CHECK_CODE_EXTERNAL
* Telemetry histograms.
*/
// No update found (no notification)
CHK_NO_UPDATE_FOUND: 0,
// Update will be downloaded in the background (background download)
CHK_DOWNLOAD_UPDATE: 1,
// Showing prompt due to the update.xml specifying showPrompt
// (update notification)
CHK_SHOWPROMPT_SNIPPET: 2,
// Showing prompt due to preference (update notification)
CHK_SHOWPROMPT_PREF: 3,
// Already has an active update in progress (no notification)
CHK_HAS_ACTIVEUPDATE: 8,
// A background download is already in progress (no notification)
CHK_IS_DOWNLOADING: 9,
// An update is already staged (no notification)
CHK_IS_STAGED: 10,
// An update is already downloaded (no notification)
CHK_IS_DOWNLOADED: 11,
// Background checks disabled by preference (no notification)
CHK_PREF_DISABLED: 12,
// Update checks disabled by admin locked preference (no notification)
CHK_ADMIN_DISABLED: 13,
// Unable to check for updates per hasUpdateMutex() (no notification)
CHK_NO_MUTEX: 14,
// Unable to check for updates per gCanCheckForUpdates (no notification). This
// should be covered by other codes and is recorded just in case.
CHK_UNABLE_TO_CHECK: 15,
// Background checks disabled for the current session (no notification)
CHK_DISABLED_FOR_SESSION: 16,
// Unable to perform a background check while offline (no notification)
CHK_OFFLINE: 17,
// Note: codes 18 - 21 were removed along with the certificate checking code.
// General update check failure and threshold reached
// (check failure notification)
CHK_GENERAL_ERROR_PROMPT: 22,
// General update check failure and threshold not reached (no notification)
CHK_GENERAL_ERROR_SILENT: 23,
// No compatible update found though there were updates (no notification)
CHK_NO_COMPAT_UPDATE_FOUND: 24,
// Update found for a previous version (no notification)
CHK_UPDATE_PREVIOUS_VERSION: 25,
// Update found for a version with the never preference set (no notification)
CHK_UPDATE_NEVER_PREF: 26,
// Update found without a type attribute (no notification)
CHK_UPDATE_INVALID_TYPE: 27,
// The system is no longer supported (system unsupported notification)
CHK_UNSUPPORTED: 28,
// Unable to apply updates (manual install to update notification)
CHK_UNABLE_TO_APPLY: 29,
// Unable to check for updates due to no OS version (no notification)
CHK_NO_OS_VERSION: 30,
// Unable to check for updates due to no OS ABI (no notification)
CHK_NO_OS_ABI: 31,
// Invalid url for app.update.url default preference (no notification)
CHK_INVALID_DEFAULT_URL: 32,
// Update elevation failures or cancelations threshold reached for this
// version, OSX only (no notification)
CHK_ELEVATION_DISABLED_FOR_VERSION: 35,
// User opted out of elevated updates for the available update version, OSX
// only (no notification)
CHK_ELEVATION_OPTOUT_FOR_VERSION: 36,
/**
* Submit a telemetry ping for the update check result code or a telemetry
* ping for a count type histogram count when no update was found. The no
* update found ping is separate since it is the typical result, is less
* interesting than the other result codes, and it is easier to analyze the
* other codes without including it.
*
* @param aSuffix
* The histogram id suffix for histogram IDs:
* UPDATE_CHECK_CODE_EXTERNAL
* UPDATE_CHECK_CODE_NOTIFY
* UPDATE_CHECK_NO_UPDATE_EXTERNAL
* UPDATE_CHECK_NO_UPDATE_NOTIFY
* @param aCode
* An integer value as defined by the values that start with CHK_ in
* the above section.
*/
pingCheckCode: function UT_pingCheckCode(aSuffix, aCode) {
try {
if (aCode == this.CHK_NO_UPDATE_FOUND) {
let id = "UPDATE_CHECK_NO_UPDATE_" + aSuffix;
// count type histogram
Services.telemetry.getHistogramById(id).add();
} else {
let id = "UPDATE_CHECK_CODE_" + aSuffix;
// enumerated type histogram
Services.telemetry.getHistogramById(id).add(aCode);
}
} catch (e) {
Cu.reportError(e);
}
},
/**
* Submit a telemetry ping for a failed update check's unhandled error code
* when the pingCheckCode is CHK_GENERAL_ERROR_SILENT. The histogram is a
* keyed count type with key names that are prefixed with 'AUS_CHECK_EX_ERR_'.
*
* @param aSuffix
* The histogram id suffix for histogram IDs:
* UPDATE_CHK_EXTENDED_ERROR_EXTERNAL
* UPDATE_CHK_EXTENDED_ERROR_NOTIFY
* @param aCode
* The extended error value return by a failed update check.
*/
pingCheckExError: function UT_pingCheckExError(aSuffix, aCode) {
try {
let id = "UPDATE_CHECK_EXTENDED_ERROR_" + aSuffix;
let val = "AUS_CHECK_EX_ERR_" + aCode;
// keyed count type histogram
Services.telemetry.getKeyedHistogramById(id).add(val);
} catch (e) {
Cu.reportError(e);
}
},
// The state code and if present the status error code were read on startup.
STARTUP: "STARTUP",
// The state code and status error code if present were read after staging.
STAGE: "STAGE",
// Patch type Complete
PATCH_COMPLETE: "COMPLETE",
// Patch type partial
PATCH_PARTIAL: "PARTIAL",
// Patch type unknown
PATCH_UNKNOWN: "UNKNOWN",
/**
* Values for the UPDATE_DOWNLOAD_CODE_COMPLETE and
* UPDATE_DOWNLOAD_CODE_PARTIAL Telemetry histograms.
*/
DWNLD_SUCCESS: 0,
DWNLD_RETRY_OFFLINE: 1,
DWNLD_RETRY_NET_TIMEOUT: 2,
DWNLD_RETRY_CONNECTION_REFUSED: 3,
DWNLD_RETRY_NET_RESET: 4,
DWNLD_ERR_NO_UPDATE: 5,
DWNLD_ERR_NO_UPDATE_PATCH: 6,
DWNLD_ERR_NO_PATCH_FILE: 7,
DWNLD_ERR_PATCH_SIZE_LARGER: 8,
DWNLD_ERR_PATCH_SIZE_NOT_EQUAL: 9,
DWNLD_ERR_BINDING_ABORTED: 10,
DWNLD_ERR_ABORT: 11,
DWNLD_ERR_DOCUMENT_NOT_CACHED: 12,
DWNLD_ERR_VERIFY_NO_REQUEST: 13,
DWNLD_ERR_VERIFY_PATCH_SIZE_NOT_EQUAL: 14,
DWNLD_ERR_VERIFY_NO_HASH_MATCH: 15,
/**
* Submit a telemetry ping for the update download result code.
*
* @param aIsComplete
* If true the histogram is for a patch type complete, if false the
* histogram is for a patch type partial, and when undefined the
* histogram is for an unknown patch type. This is used to determine
* the histogram ID out of the following histogram IDs:
* UPDATE_DOWNLOAD_CODE_COMPLETE
* UPDATE_DOWNLOAD_CODE_PARTIAL
* @param aCode
* An integer value as defined by the values that start with DWNLD_ in
* the above section.
*/
pingDownloadCode: function UT_pingDownloadCode(aIsComplete, aCode) {
let patchType = this.PATCH_UNKNOWN;
if (aIsComplete === true) {
patchType = this.PATCH_COMPLETE;
} else if (aIsComplete === false) {
patchType = this.PATCH_PARTIAL;
}
try {
let id = "UPDATE_DOWNLOAD_CODE_" + patchType;
// enumerated type histogram
Services.telemetry.getHistogramById(id).add(aCode);
} catch (e) {
Cu.reportError(e);
}
},
/**
* Submit a telemetry ping for the update status state code.
*
* @param aSuffix
* The histogram id suffix for histogram IDs:
* UPDATE_STATE_CODE_COMPLETE_STARTUP
* UPDATE_STATE_CODE_PARTIAL_STARTUP
* UPDATE_STATE_CODE_UNKNOWN_STARTUP
* UPDATE_STATE_CODE_COMPLETE_STAGE
* UPDATE_STATE_CODE_PARTIAL_STAGE
* UPDATE_STATE_CODE_UNKNOWN_STAGE
* @param aCode
* An integer value as defined by the values that start with STATE_ in
* the above section for the update state from the update.status file.
*/
pingStateCode: function UT_pingStateCode(aSuffix, aCode) {
try {
let id = "UPDATE_STATE_CODE_" + aSuffix;
// enumerated type histogram
Services.telemetry.getHistogramById(id).add(aCode);
} catch (e) {
Cu.reportError(e);
}
},
/**
* Submit a telemetry ping for the update status error code. This does not
* submit a success value which can be determined from the state code.
*
* @param aSuffix
* The histogram id suffix for histogram IDs:
* UPDATE_STATUS_ERROR_CODE_COMPLETE_STARTUP
* UPDATE_STATUS_ERROR_CODE_PARTIAL_STARTUP
* UPDATE_STATUS_ERROR_CODE_UNKNOWN_STARTUP
* UPDATE_STATUS_ERROR_CODE_COMPLETE_STAGE
* UPDATE_STATUS_ERROR_CODE_PARTIAL_STAGE
* UPDATE_STATUS_ERROR_CODE_UNKNOWN_STAGE
* @param aCode
* An integer value for the error code from the update.status file.
*/
pingStatusErrorCode: function UT_pingStatusErrorCode(aSuffix, aCode) {
try {
let id = "UPDATE_STATUS_ERROR_CODE_" + aSuffix;
// enumerated type histogram
Services.telemetry.getHistogramById(id).add(aCode);
} catch (e) {
Cu.reportError(e);
}
},
/**
* Submit the interval in days since the last notification for this background
* update check or a boolean if the last notification is in the future.
*
* @param aSuffix
* The histogram id suffix for histogram IDs:
* UPDATE_INVALID_LASTUPDATETIME_EXTERNAL
* UPDATE_INVALID_LASTUPDATETIME_NOTIFY
* UPDATE_LAST_NOTIFY_INTERVAL_DAYS_EXTERNAL
* UPDATE_LAST_NOTIFY_INTERVAL_DAYS_NOTIFY
*/
pingLastUpdateTime: function UT_pingLastUpdateTime(aSuffix) {
const PREF_APP_UPDATE_LASTUPDATETIME = "app.update.lastUpdateTime.background-update-timer";
if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_LASTUPDATETIME)) {
let lastUpdateTimeSeconds = Services.prefs.getIntPref(PREF_APP_UPDATE_LASTUPDATETIME);
if (lastUpdateTimeSeconds) {
let currentTimeSeconds = Math.round(Date.now() / 1000);
if (lastUpdateTimeSeconds > currentTimeSeconds) {
try {
let id = "UPDATE_INVALID_LASTUPDATETIME_" + aSuffix;
// count type histogram
Services.telemetry.getHistogramById(id).add();
} catch (e) {
Cu.reportError(e);
}
} else {
let intervalDays = (currentTimeSeconds - lastUpdateTimeSeconds) /
(60 * 60 * 24);
try {
let id = "UPDATE_LAST_NOTIFY_INTERVAL_DAYS_" + aSuffix;
// exponential type histogram
Services.telemetry.getHistogramById(id).add(intervalDays);
} catch (e) {
Cu.reportError(e);
}
}
}
}
},
/**
* Submit a telemetry ping for the last page displayed by the update wizard.
*
* @param aPageID
* The page id for the last page displayed.
*/
pingWizLastPageCode: function UT_pingWizLastPageCode(aPageID) {
let pageMap = { invalid: 0,
dummy: 1,
checking: 2,
pluginupdatesfound: 3,
noupdatesfound: 4,
manualUpdate: 5,
unsupported: 6,
updatesfoundbasic: 8,
updatesfoundbillboard: 9,
downloading: 12,
errors: 13,
errorextra: 14,
errorpatching: 15,
finished: 16,
finishedBackground: 17,
installed: 18 };
try {
let id = "UPDATE_WIZ_LAST_PAGE_CODE";
// enumerated type histogram
Services.telemetry.getHistogramById(id).add(pageMap[aPageID] ||
pageMap.invalid);
} catch (e) {
Cu.reportError(e);
}
},
/**
* Submit a telemetry ping for a boolean type histogram that indicates if the
* service is installed and a telemetry ping for a boolean type histogram that
* indicates if the service was at some point installed and is now
* uninstalled.
*
* @param aSuffix
* The histogram id suffix for histogram IDs:
* UPDATE_SERVICE_INSTALLED_EXTERNAL
* UPDATE_SERVICE_INSTALLED_NOTIFY
* UPDATE_SERVICE_MANUALLY_UNINSTALLED_EXTERNAL
* UPDATE_SERVICE_MANUALLY_UNINSTALLED_NOTIFY
* @param aInstalled
* Whether the service is installed.
*/
pingServiceInstallStatus: function UT_PSIS(aSuffix, aInstalled) {
// Report the error but don't throw since it is more important to
// successfully update than to throw.
if (!("@mozilla.org/windows-registry-key;1" in Cc)) {
Cu.reportError(Cr.NS_ERROR_NOT_AVAILABLE);
return;
}
try {
let id = "UPDATE_SERVICE_INSTALLED_" + aSuffix;
// boolean type histogram
Services.telemetry.getHistogramById(id).add(aInstalled);
} catch (e) {
Cu.reportError(e);
}
let attempted = 0;
try {
let wrk = Cc["@mozilla.org/windows-registry-key;1"].
createInstance(Ci.nsIWindowsRegKey);
wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE,
"SOFTWARE\\Mozilla\\MaintenanceService",
wrk.ACCESS_READ | wrk.WOW64_64);
// Was the service at some point installed, but is now uninstalled?
attempted = wrk.readIntValue("Attempted");
wrk.close();
} catch (e) {
// Since this will throw if the registry key doesn't exist (e.g. the
// service has never been installed) don't report an error.
}
try {
let id = "UPDATE_SERVICE_MANUALLY_UNINSTALLED_" + aSuffix;
if (!aInstalled && attempted) {
// count type histogram
Services.telemetry.getHistogramById(id).add();
}
} catch (e) {
Cu.reportError(e);
}
},
/**
* Submit a telemetry ping for a count type histogram when the expected value
* does not equal the boolean value of a pref or if the pref isn't present
* when the expected value does not equal default value. This lessens the
* amount of data submitted to telemetry.
*
* @param aID
* The histogram ID to report to.
* @param aPref
* The preference to check.
* @param aDefault
* The default value when the preference isn't present.
* @param aExpected (optional)
* If specified and the value is the same as the value that will be
* added the value won't be added to telemetry.
*/
pingBoolPref: function UT_pingBoolPref(aID, aPref, aDefault, aExpected) {
try {
let val = aDefault;
if (Services.prefs.getPrefType(aPref) != Ci.nsIPrefBranch.PREF_INVALID) {
val = Services.prefs.getBoolPref(aPref);
}
if (val != aExpected) {
// count type histogram
Services.telemetry.getHistogramById(aID).add();
}
} catch (e) {
Cu.reportError(e);
}
},
/**
* Submit a telemetry ping for a histogram with the integer value of a
* preference when it is not the expected value or the default value when it
* is not the expected value. This lessens the amount of data submitted to
* telemetry.
*
* @param aID
* The histogram ID to report to.
* @param aPref
* The preference to check.
* @param aDefault
* The default value when the pref is not set.
* @param aExpected (optional)
* If specified and the value is the same as the value that will be
* added the value won't be added to telemetry.
*/
pingIntPref: function UT_pingIntPref(aID, aPref, aDefault, aExpected) {
try {
let val = aDefault;
if (Services.prefs.getPrefType(aPref) != Ci.nsIPrefBranch.PREF_INVALID) {
val = Services.prefs.getIntPref(aPref);
}
if (aExpected === undefined || val != aExpected) {
// enumerated or exponential type histogram
Services.telemetry.getHistogramById(aID).add(val);
}
} catch (e) {
Cu.reportError(e);
}
},
/**
* Submit a telemetry ping for all histogram types that take a single
* parameter to the telemetry add function and the count type histogram when
* the aExpected parameter is specified. If the aExpected parameter is
* specified and it equals the value specified by the aValue
* parameter the telemetry submission will be skipped.
*
* @param aID
* The histogram ID to report to.
* @param aValue
* The value to add when aExpected is not defined or the value to
* check if it is equal to when aExpected is defined.
* @param aExpected (optional)
* If specified and the value is the same as the value specified by
* aValue parameter the submission will be skipped.
*/
pingGeneric: function UT_pingGeneric(aID, aValue, aExpected) {
try {
if (aExpected === undefined) {
Services.telemetry.getHistogramById(aID).add(aValue);
} else if (aValue != aExpected) {
// count type histogram
Services.telemetry.getHistogramById(aID).add();
}
} catch (e) {
Cu.reportError(e);
}
}
};
Object.freeze(AUSTLMY);

View file

@ -0,0 +1,12 @@
# 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/.
Library('updatecommon-standalone')
srcdir = '../common'
include('../common/sources.mozbuild')
if CONFIG['OS_ARCH'] == 'WINNT':
USE_STATIC_LIBS = True

View file

@ -0,0 +1,250 @@
/* 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/. */
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <softpub.h>
#include <wintrust.h>
#include "certificatecheck.h"
#include "updatecommon.h"
static const int ENCODING = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
/**
* Checks to see if a file stored at filePath matches the specified info.
*
* @param filePath The PE file path to check
* @param infoToMatch The acceptable information to match
* @return ERROR_SUCCESS if successful, ERROR_NOT_FOUND if the info
* does not match, or the last error otherwise.
*/
DWORD
CheckCertificateForPEFile(LPCWSTR filePath,
CertificateCheckInfo &infoToMatch)
{
HCERTSTORE certStore = nullptr;
HCRYPTMSG cryptMsg = nullptr;
PCCERT_CONTEXT certContext = nullptr;
PCMSG_SIGNER_INFO signerInfo = nullptr;
DWORD lastError = ERROR_SUCCESS;
// Get the HCERTSTORE and HCRYPTMSG from the signed file.
DWORD encoding, contentType, formatType;
BOOL result = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
filePath,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_CONTENT_FLAG_ALL,
0, &encoding, &contentType,
&formatType, &certStore, &cryptMsg, nullptr);
if (!result) {
lastError = GetLastError();
LOG_WARN(("CryptQueryObject failed. (%d)", lastError));
goto cleanup;
}
// Pass in nullptr to get the needed signer information size.
DWORD signerInfoSize;
result = CryptMsgGetParam(cryptMsg, CMSG_SIGNER_INFO_PARAM, 0,
nullptr, &signerInfoSize);
if (!result) {
lastError = GetLastError();
LOG_WARN(("CryptMsgGetParam failed. (%d)", lastError));
goto cleanup;
}
// Allocate the needed size for the signer information.
signerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, signerInfoSize);
if (!signerInfo) {
lastError = GetLastError();
LOG_WARN(("Unable to allocate memory for Signer Info. (%d)", lastError));
goto cleanup;
}
// Get the signer information (PCMSG_SIGNER_INFO).
// In particular we want the issuer and serial number.
result = CryptMsgGetParam(cryptMsg, CMSG_SIGNER_INFO_PARAM, 0,
(PVOID)signerInfo, &signerInfoSize);
if (!result) {
lastError = GetLastError();
LOG_WARN(("CryptMsgGetParam failed. (%d)", lastError));
goto cleanup;
}
// Search for the signer certificate in the certificate store.
CERT_INFO certInfo;
certInfo.Issuer = signerInfo->Issuer;
certInfo.SerialNumber = signerInfo->SerialNumber;
certContext = CertFindCertificateInStore(certStore, ENCODING, 0,
CERT_FIND_SUBJECT_CERT,
(PVOID)&certInfo, nullptr);
if (!certContext) {
lastError = GetLastError();
LOG_WARN(("CertFindCertificateInStore failed. (%d)", lastError));
goto cleanup;
}
if (!DoCertificateAttributesMatch(certContext, infoToMatch)) {
lastError = ERROR_NOT_FOUND;
LOG_WARN(("Certificate did not match issuer or name. (%d)", lastError));
goto cleanup;
}
cleanup:
if (signerInfo) {
LocalFree(signerInfo);
}
if (certContext) {
CertFreeCertificateContext(certContext);
}
if (certStore) {
CertCloseStore(certStore, 0);
}
if (cryptMsg) {
CryptMsgClose(cryptMsg);
}
return lastError;
}
/**
* Checks to see if a file stored at filePath matches the specified info.
*
* @param certContext The certificate context of the file
* @param infoToMatch The acceptable information to match
* @return FALSE if the info does not match or if any error occurs in the check
*/
BOOL
DoCertificateAttributesMatch(PCCERT_CONTEXT certContext,
CertificateCheckInfo &infoToMatch)
{
DWORD dwData;
LPWSTR szName = nullptr;
if (infoToMatch.issuer) {
// Pass in nullptr to get the needed size of the issuer buffer.
dwData = CertGetNameString(certContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG, nullptr,
nullptr, 0);
if (!dwData) {
LOG_WARN(("CertGetNameString failed. (%d)", GetLastError()));
return FALSE;
}
// Allocate memory for Issuer name buffer.
szName = (LPWSTR)LocalAlloc(LPTR, dwData * sizeof(WCHAR));
if (!szName) {
LOG_WARN(("Unable to allocate memory for issuer name. (%d)",
GetLastError()));
return FALSE;
}
// Get Issuer name.
if (!CertGetNameStringW(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG, nullptr, szName, dwData)) {
LOG_WARN(("CertGetNameString failed. (%d)", GetLastError()));
LocalFree(szName);
return FALSE;
}
// If the issuer does not match, return a failure.
if (!infoToMatch.issuer ||
wcscmp(szName, infoToMatch.issuer)) {
LocalFree(szName);
return FALSE;
}
LocalFree(szName);
szName = nullptr;
}
if (infoToMatch.name) {
// Pass in nullptr to get the needed size of the name buffer.
dwData = CertGetNameString(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE,
0, nullptr, nullptr, 0);
if (!dwData) {
LOG_WARN(("CertGetNameString failed. (%d)", GetLastError()));
return FALSE;
}
// Allocate memory for the name buffer.
szName = (LPWSTR)LocalAlloc(LPTR, dwData * sizeof(WCHAR));
if (!szName) {
LOG_WARN(("Unable to allocate memory for subject name. (%d)",
GetLastError()));
return FALSE;
}
// Obtain the name.
if (!(CertGetNameStringW(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
nullptr, szName, dwData))) {
LOG_WARN(("CertGetNameString failed. (%d)", GetLastError()));
LocalFree(szName);
return FALSE;
}
// If the issuer does not match, return a failure.
if (!infoToMatch.name ||
wcscmp(szName, infoToMatch.name)) {
LocalFree(szName);
return FALSE;
}
// We have a match!
LocalFree(szName);
}
// If there were any errors we would have aborted by now.
return TRUE;
}
/**
* Verifies the trust of the specified file path.
*
* @param filePath The file path to check.
* @return ERROR_SUCCESS if successful, or the last error code otherwise.
*/
DWORD
VerifyCertificateTrustForFile(LPCWSTR filePath)
{
// Setup the file to check.
WINTRUST_FILE_INFO fileToCheck;
ZeroMemory(&fileToCheck, sizeof(fileToCheck));
fileToCheck.cbStruct = sizeof(WINTRUST_FILE_INFO);
fileToCheck.pcwszFilePath = filePath;
// Setup what to check, we want to check it is signed and trusted.
WINTRUST_DATA trustData;
ZeroMemory(&trustData, sizeof(trustData));
trustData.cbStruct = sizeof(trustData);
trustData.pPolicyCallbackData = nullptr;
trustData.pSIPClientData = nullptr;
trustData.dwUIChoice = WTD_UI_NONE;
trustData.fdwRevocationChecks = WTD_REVOKE_NONE;
trustData.dwUnionChoice = WTD_CHOICE_FILE;
trustData.dwStateAction = 0;
trustData.hWVTStateData = nullptr;
trustData.pwszURLReference = nullptr;
// no UI
trustData.dwUIContext = 0;
trustData.pFile = &fileToCheck;
GUID policyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
// Check if the file is signed by something that is trusted.
LONG ret = WinVerifyTrust(nullptr, &policyGUID, &trustData);
if (ERROR_SUCCESS == ret) {
// The hash that represents the subject is trusted and there were no
// verification errors. No publisher nor time stamp chain errors.
LOG(("The file \"%ls\" is signed and the signature was verified.",
filePath));
return ERROR_SUCCESS;
}
DWORD lastError = GetLastError();
LOG_WARN(("There was an error validating trust of the certificate for file"
" \"%ls\". Returned: %d. (%d)", filePath, ret, lastError));
return ret;
}

View file

@ -0,0 +1,22 @@
/* 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/. */
#ifndef _CERTIFICATECHECK_H_
#define _CERTIFICATECHECK_H_
#include <wincrypt.h>
struct CertificateCheckInfo
{
LPCWSTR name;
LPCWSTR issuer;
};
BOOL DoCertificateAttributesMatch(PCCERT_CONTEXT pCertContext,
CertificateCheckInfo &infoToMatch);
DWORD VerifyCertificateTrustForFile(LPCWSTR filePath);
DWORD CheckCertificateForPEFile(LPCWSTR filePath,
CertificateCheckInfo &infoToMatch);
#endif

View file

@ -0,0 +1,110 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef Errors_h__
#define Errors_h__
#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. nsUpdateService.js, updates.js,
// UpdatePrompt.js, etc.).
#define MAR_ERROR_EMPTY_ACTION_LIST 1
#define LOADSOURCE_ERROR_WRONG_SIZE 2
// Error codes 3-16 are for general update problems.
#define USAGE_ERROR 3
#define CRC_ERROR 4
#define PARSE_ERROR 5
#define READ_ERROR 6
#define WRITE_ERROR 7
// #define UNEXPECTED_ERROR 8 // Replaced with errors 38-42
#define ELEVATION_CANCELED 9
#define READ_STRINGS_MEM_ERROR 10
#define ARCHIVE_READER_MEM_ERROR 11
#define BSPATCH_MEM_ERROR 12
#define UPDATER_MEM_ERROR 13
#define UPDATER_QUOTED_PATH_MEM_ERROR 14
#define BAD_ACTION_ERROR 15
#define STRING_CONVERSION_ERROR 16
// Error codes 17-23 are related to security tasks for MAR
// signing and MAR protection.
#define CERT_LOAD_ERROR 17
#define CERT_HANDLING_ERROR 18
#define CERT_VERIFY_ERROR 19
#define ARCHIVE_NOT_OPEN 20
#define COULD_NOT_READ_PRODUCT_INFO_BLOCK_ERROR 21
#define MAR_CHANNEL_MISMATCH_ERROR 22
#define VERSION_DOWNGRADE_ERROR 23
// Error codes 24-33 and 49-57 are for the Windows maintenance service.
#define SERVICE_UPDATER_COULD_NOT_BE_STARTED 24
#define SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS 25
#define SERVICE_UPDATER_SIGN_ERROR 26
#define SERVICE_UPDATER_COMPARE_ERROR 27
#define SERVICE_UPDATER_IDENTITY_ERROR 28
#define SERVICE_STILL_APPLYING_ON_SUCCESS 29
#define SERVICE_STILL_APPLYING_ON_FAILURE 30
#define SERVICE_UPDATER_NOT_FIXED_DRIVE 31
#define SERVICE_COULD_NOT_LOCK_UPDATER 32
#define SERVICE_INSTALLDIR_ERROR 33
#define NO_INSTALLDIR_ERROR 34
#define WRITE_ERROR_ACCESS_DENIED 35
// #define WRITE_ERROR_SHARING_VIOLATION 36 // Replaced with errors 46-48
#define WRITE_ERROR_CALLBACK_APP 37
#define UNEXPECTED_BZIP_ERROR 39
#define UNEXPECTED_MAR_ERROR 40
#define UNEXPECTED_BSPATCH_ERROR 41
#define UNEXPECTED_FILE_OPERATION_ERROR 42
#define FILESYSTEM_MOUNT_READWRITE_ERROR 43
#define DELETE_ERROR_EXPECTED_DIR 46
#define DELETE_ERROR_EXPECTED_FILE 47
#define RENAME_ERROR_EXPECTED_FILE 48
// Error codes 24-33 and 49-57 are for the Windows maintenance service.
#define SERVICE_COULD_NOT_COPY_UPDATER 49
#define SERVICE_STILL_APPLYING_TERMINATED 50
#define SERVICE_STILL_APPLYING_NO_EXIT_CODE 51
#define SERVICE_INVALID_APPLYTO_DIR_STAGED_ERROR 52
#define SERVICE_CALC_REG_PATH_ERROR 53
#define SERVICE_INVALID_APPLYTO_DIR_ERROR 54
#define SERVICE_INVALID_INSTALL_DIR_PATH_ERROR 55
#define SERVICE_INVALID_WORKING_DIR_PATH_ERROR 56
#define SERVICE_INSTALL_DIR_REG_ERROR 57
#define WRITE_ERROR_FILE_COPY 61
#define WRITE_ERROR_DELETE_FILE 62
#define WRITE_ERROR_OPEN_PATCH_FILE 63
#define WRITE_ERROR_PATCH_FILE 64
#define WRITE_ERROR_APPLY_DIR_PATH 65
#define WRITE_ERROR_CALLBACK_PATH 66
#define WRITE_ERROR_FILE_ACCESS_DENIED 67
#define WRITE_ERROR_DIR_ACCESS_DENIED 68
#define WRITE_ERROR_DELETE_BACKUP 69
#define WRITE_ERROR_EXTRACT 70
#define REMOVE_FILE_SPEC_ERROR 71
#define INVALID_APPLYTO_DIR_STAGED_ERROR 72
#define LOCK_ERROR_PATCH_FILE 73
#define INVALID_APPLYTO_DIR_ERROR 74
#define INVALID_INSTALL_DIR_PATH_ERROR 75
#define INVALID_WORKING_DIR_PATH_ERROR 76
#define INVALID_CALLBACK_PATH_ERROR 77
#define INVALID_CALLBACK_DIR_ERROR 78
// Error codes 80 through 99 are reserved for nsUpdateService.js
// The following error codes are only used by updater.exe
// when a fallback key exists for tests.
#define FALLBACKKEY_UNKNOWN_ERROR 100
#define FALLBACKKEY_REGPATH_ERROR 101
#define FALLBACKKEY_NOKEY_ERROR 102
#define FALLBACKKEY_SERVICE_NO_STOP_ERROR 103
#define FALLBACKKEY_LAUNCH_ERROR 104
#endif // Errors_h__

View file

@ -0,0 +1,32 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
EXPORTS += [
'readstrings.h',
'updatecommon.h',
'updatedefines.h',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXPORTS += [
'pathhash.h',
'uachelper.h',
'updatehelper.cpp',
'updatehelper.h',
]
if CONFIG['MOZ_MAINTENANCE_SERVICE']:
EXPORTS += [
'certificatecheck.h',
'registrycertificates.h',
]
Library('updatecommon')
DEFINES['NS_NO_XPCOM'] = True
srcdir = '.'
include('sources.mozbuild')

View file

@ -0,0 +1,139 @@
/* 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/. */
#include <windows.h>
#include <wincrypt.h>
#include "pathhash.h"
/**
* Converts a binary sequence into a hex string
*
* @param hash The binary data sequence
* @param hashSize The size of the binary data sequence
* @param hexString A buffer to store the hex string, must be of
* size 2 * @hashSize
*/
static void
BinaryDataToHexString(const BYTE *hash, DWORD &hashSize,
LPWSTR hexString)
{
WCHAR *p = hexString;
for (DWORD i = 0; i < hashSize; ++i) {
wsprintfW(p, L"%.2x", hash[i]);
p += 2;
}
}
/**
* Calculates an MD5 hash for the given input binary data
*
* @param data Any sequence of bytes
* @param dataSize The number of bytes inside @data
* @param hash Output buffer to store hash, must be freed by the caller
* @param hashSize The number of bytes in the output buffer
* @return TRUE on success
*/
static BOOL
CalculateMD5(const char *data, DWORD dataSize,
BYTE **hash, DWORD &hashSize)
{
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
if (NTE_BAD_KEYSET != GetLastError()) {
return FALSE;
}
// Maybe it doesn't exist, try to create it.
if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)) {
return FALSE;
}
}
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
return FALSE;
}
if (!CryptHashData(hHash, reinterpret_cast<const BYTE*>(data),
dataSize, 0)) {
return FALSE;
}
DWORD dwCount = sizeof(DWORD);
if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&hashSize,
&dwCount, 0)) {
return FALSE;
}
*hash = new BYTE[hashSize];
ZeroMemory(*hash, hashSize);
if (!CryptGetHashParam(hHash, HP_HASHVAL, *hash, &hashSize, 0)) {
return FALSE;
}
if (hHash) {
CryptDestroyHash(hHash);
}
if (hProv) {
CryptReleaseContext(hProv,0);
}
return TRUE;
}
/**
* Converts a file path into a unique registry location for cert storage
*
* @param filePath The input file path to get a registry path from
* @param registryPath A buffer to write the registry path to, must
* be of size in WCHARs MAX_PATH + 1
* @return TRUE if successful
*/
BOOL
CalculateRegistryPathFromFilePath(const LPCWSTR filePath,
LPWSTR registryPath)
{
size_t filePathLen = wcslen(filePath);
if (!filePathLen) {
return FALSE;
}
// If the file path ends in a slash, ignore that character
if (filePath[filePathLen -1] == L'\\' ||
filePath[filePathLen - 1] == L'/') {
filePathLen--;
}
// Copy in the full path into our own buffer.
// Copying in the extra slash is OK because we calculate the hash
// based on the filePathLen which excludes the slash.
// +2 to account for the possibly trailing slash and the null terminator.
WCHAR *lowercasePath = new WCHAR[filePathLen + 2];
memset(lowercasePath, 0, (filePathLen + 2) * sizeof(WCHAR));
wcsncpy(lowercasePath, filePath, filePathLen + 1);
_wcslwr(lowercasePath);
BYTE *hash;
DWORD hashSize = 0;
if (!CalculateMD5(reinterpret_cast<const char*>(lowercasePath),
filePathLen * 2,
&hash, hashSize)) {
delete[] lowercasePath;
return FALSE;
}
delete[] lowercasePath;
LPCWSTR baseRegPath = L"SOFTWARE\\Mozilla\\"
L"MaintenanceService\\";
wcsncpy(registryPath, baseRegPath, MAX_PATH);
BinaryDataToHexString(hash, hashSize,
registryPath + wcslen(baseRegPath));
delete[] hash;
return TRUE;
}

View file

@ -0,0 +1,19 @@
/* 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/. */
#ifndef _PATHHASH_H_
#define _PATHHASH_H_
/**
* Converts a file path into a unique registry location for cert storage
*
* @param filePath The input file path to get a registry path from
* @param registryPath A buffer to write the registry path to, must
* be of size in WCHARs MAX_PATH + 1
* @return TRUE if successful
*/
BOOL CalculateRegistryPathFromFilePath(const LPCWSTR filePath,
LPWSTR registryPath);
#endif

View file

@ -0,0 +1,236 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include "readstrings.h"
#include "errors.h"
#ifdef XP_WIN
# define NS_tfopen _wfopen
# define OPEN_MODE L"rb"
#else
# define NS_tfopen fopen
# define OPEN_MODE "r"
#endif
// stack based FILE wrapper to ensure that fclose is called.
class AutoFILE {
public:
explicit AutoFILE(FILE *fp) : fp_(fp) {}
~AutoFILE() { if (fp_) fclose(fp_); }
operator FILE *() { return fp_; }
private:
FILE *fp_;
};
class AutoCharArray {
public:
explicit AutoCharArray(size_t len) { ptr_ = new char[len]; }
~AutoCharArray() { delete[] ptr_; }
operator char *() { return ptr_; }
private:
char *ptr_;
};
static const char kNL[] = "\r\n";
static const char kEquals[] = "=";
static const char kWhitespace[] = " \t";
static const char kRBracket[] = "]";
static const char*
NS_strspnp(const char *delims, const char *str)
{
const char *d;
do {
for (d = delims; *d != '\0'; ++d) {
if (*str == *d) {
++str;
break;
}
}
} while (*d);
return str;
}
static char*
NS_strtok(const char *delims, char **str)
{
if (!*str)
return nullptr;
char *ret = (char*) NS_strspnp(delims, *str);
if (!*ret) {
*str = ret;
return nullptr;
}
char *i = ret;
do {
for (const char *d = delims; *d != '\0'; ++d) {
if (*i == *d) {
*i = '\0';
*str = ++i;
return ret;
}
}
++i;
} while (*i);
*str = nullptr;
return ret;
}
/**
* Find a key in a keyList containing zero-delimited keys ending with "\0\0".
* Returns a zero-based index of the key in the list, or -1 if the key is not found.
*/
static int
find_key(const char *keyList, char* key)
{
if (!keyList)
return -1;
int index = 0;
const char *p = keyList;
while (*p)
{
if (strcmp(key, p) == 0)
return index;
p += strlen(p) + 1;
index++;
}
// The key was not found if we came here
return -1;
}
/**
* A very basic parser for updater.ini taken mostly from nsINIParser.cpp
* that can be used by standalone apps.
*
* @param path Path to the .ini file to read
* @param keyList List of zero-delimited keys ending with two zero characters
* @param numStrings Number of strings to read into results buffer - must be equal to the number of keys
* @param results Two-dimensional array of strings to be filled in the same order as the keys provided
* @param section Optional name of the section to read; defaults to "Strings"
*/
int
ReadStrings(const NS_tchar *path,
const char *keyList,
unsigned int numStrings,
char results[][MAX_TEXT_LEN],
const char *section)
{
AutoFILE fp(NS_tfopen(path, OPEN_MODE));
if (!fp)
return READ_ERROR;
/* get file size */
if (fseek(fp, 0, SEEK_END) != 0)
return READ_ERROR;
long len = ftell(fp);
if (len <= 0)
return READ_ERROR;
size_t flen = size_t(len);
AutoCharArray fileContents(flen + 1);
if (!fileContents)
return READ_STRINGS_MEM_ERROR;
/* read the file in one swoop */
if (fseek(fp, 0, SEEK_SET) != 0)
return READ_ERROR;
size_t rd = fread(fileContents, sizeof(char), flen, fp);
if (rd != flen)
return READ_ERROR;
fileContents[flen] = '\0';
char *buffer = fileContents;
bool inStringsSection = false;
unsigned int read = 0;
while (char *token = NS_strtok(kNL, &buffer)) {
if (token[0] == '#' || token[0] == ';') // it's a comment
continue;
token = (char*) NS_strspnp(kWhitespace, token);
if (!*token) // empty line
continue;
if (token[0] == '[') { // section header!
++token;
char const * currSection = token;
char *rb = NS_strtok(kRBracket, &token);
if (!rb || NS_strtok(kWhitespace, &token)) {
// there's either an unclosed [Section or a [Section]Moretext!
// we could frankly decide that this INI file is malformed right
// here and stop, but we won't... keep going, looking for
// a well-formed [section] to continue working with
inStringsSection = false;
}
else {
if (section)
inStringsSection = strcmp(currSection, section) == 0;
else
inStringsSection = strcmp(currSection, "Strings") == 0;
}
continue;
}
if (!inStringsSection) {
// If we haven't found a section header (or we found a malformed
// section header), or this isn't the [Strings] section don't bother
// parsing this line.
continue;
}
char *key = token;
char *e = NS_strtok(kEquals, &token);
if (!e)
continue;
int keyIndex = find_key(keyList, key);
if (keyIndex >= 0 && (unsigned int)keyIndex < numStrings)
{
strncpy(results[keyIndex], token, MAX_TEXT_LEN - 1);
results[keyIndex][MAX_TEXT_LEN - 1] = '\0';
read++;
}
}
return (read == numStrings) ? OK : PARSE_ERROR;
}
// A wrapper function to read strings for the updater.
// Added for compatibility with the original code.
int
ReadStrings(const NS_tchar *path, StringTable *results)
{
const unsigned int kNumStrings = 2;
const char *kUpdaterKeys = "Title\0Info\0";
char updater_strings[kNumStrings][MAX_TEXT_LEN];
int result = ReadStrings(path, kUpdaterKeys, kNumStrings, updater_strings);
strncpy(results->title, updater_strings[0], MAX_TEXT_LEN - 1);
results->title[MAX_TEXT_LEN - 1] = '\0';
strncpy(results->info, updater_strings[1], MAX_TEXT_LEN - 1);
results->info[MAX_TEXT_LEN - 1] = '\0';
return result;
}

View file

@ -0,0 +1,43 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef READSTRINGS_H__
#define READSTRINGS_H__
#define MAX_TEXT_LEN 600
#ifdef XP_WIN
# include <windows.h>
typedef WCHAR NS_tchar;
#else
typedef char NS_tchar;
#endif
#ifndef NULL
#define NULL 0
#endif
struct StringTable
{
char title[MAX_TEXT_LEN];
char info[MAX_TEXT_LEN];
};
/**
* This function reads in localized strings from updater.ini
*/
int ReadStrings(const NS_tchar *path, StringTable *results);
/**
* This function reads in localized strings corresponding to the keys from a given .ini
*/
int ReadStrings(const NS_tchar *path,
const char *keyList,
unsigned int numStrings,
char results[][MAX_TEXT_LEN],
const char *section = nullptr);
#endif // READSTRINGS_H__

View file

@ -0,0 +1,154 @@
/* 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/. */
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "registrycertificates.h"
#include "pathhash.h"
#include "updatecommon.h"
#include "updatehelper.h"
#define MAX_KEY_LENGTH 255
/**
* Verifies if the file path matches any certificate stored in the registry.
*
* @param filePath The file path of the application to check if allowed.
* @param allowFallbackKeySkip when this is TRUE the fallback registry key will
* be used to skip the certificate check. This is the default since the
* fallback registry key is located under HKEY_LOCAL_MACHINE which can't be
* written to by a low integrity process.
* Note: the maintenance service binary can be used to perform this check for
* testing or troubleshooting.
* @return TRUE if the binary matches any of the allowed certificates.
*/
BOOL
DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath,
BOOL allowFallbackKeySkip)
{
WCHAR maintenanceServiceKey[MAX_PATH + 1];
if (!CalculateRegistryPathFromFilePath(basePathForUpdate,
maintenanceServiceKey)) {
return FALSE;
}
// We use KEY_WOW64_64KEY to always force 64-bit view.
// The user may have both x86 and x64 applications installed
// which each register information. We need a consistent place
// to put those certificate attributes in and hence why we always
// force the non redirected registry under Wow6432Node.
// This flag is ignored on 32bit systems.
HKEY baseKey;
LONG retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
maintenanceServiceKey, 0,
KEY_READ | KEY_WOW64_64KEY, &baseKey);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not open key. (%d)", retCode));
// Our tests run with a different apply directory for each test.
// We use this registry key on our test slaves to store the
// allowed name/issuers.
retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
TEST_ONLY_FALLBACK_KEY_PATH, 0,
KEY_READ | KEY_WOW64_64KEY, &baseKey);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not open fallback key. (%d)", retCode));
return FALSE;
} else if (allowFallbackKeySkip) {
LOG_WARN(("Fallback key present, skipping VerifyCertificateTrustForFile "
"check and the certificate attribute registry matching "
"check."));
RegCloseKey(baseKey);
return TRUE;
}
}
// Get the number of subkeys.
DWORD subkeyCount = 0;
retCode = RegQueryInfoKeyW(baseKey, nullptr, nullptr, nullptr, &subkeyCount,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not query info key. (%d)", retCode));
RegCloseKey(baseKey);
return FALSE;
}
// Enumerate the subkeys, each subkey represents an allowed certificate.
for (DWORD i = 0; i < subkeyCount; i++) {
WCHAR subkeyBuffer[MAX_KEY_LENGTH];
DWORD subkeyBufferCount = MAX_KEY_LENGTH;
retCode = RegEnumKeyExW(baseKey, i, subkeyBuffer,
&subkeyBufferCount, nullptr,
nullptr, nullptr, nullptr);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not enum certs. (%d)", retCode));
RegCloseKey(baseKey);
return FALSE;
}
// Open the subkey for the current certificate
HKEY subKey;
retCode = RegOpenKeyExW(baseKey,
subkeyBuffer,
0,
KEY_READ | KEY_WOW64_64KEY,
&subKey);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not open subkey. (%d)", retCode));
continue; // Try the next subkey
}
const int MAX_CHAR_COUNT = 256;
DWORD valueBufSize = MAX_CHAR_COUNT * sizeof(WCHAR);
WCHAR name[MAX_CHAR_COUNT] = { L'\0' };
WCHAR issuer[MAX_CHAR_COUNT] = { L'\0' };
// Get the name from the registry
retCode = RegQueryValueExW(subKey, L"name", 0, nullptr,
(LPBYTE)name, &valueBufSize);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not obtain name from registry. (%d)", retCode));
RegCloseKey(subKey);
continue; // Try the next subkey
}
// Get the issuer from the registry
valueBufSize = MAX_CHAR_COUNT * sizeof(WCHAR);
retCode = RegQueryValueExW(subKey, L"issuer", 0, nullptr,
(LPBYTE)issuer, &valueBufSize);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not obtain issuer from registry. (%d)", retCode));
RegCloseKey(subKey);
continue; // Try the next subkey
}
CertificateCheckInfo allowedCertificate = {
name,
issuer,
};
retCode = CheckCertificateForPEFile(filePath, allowedCertificate);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Error on certificate check. (%d)", retCode));
RegCloseKey(subKey);
continue; // Try the next subkey
}
retCode = VerifyCertificateTrustForFile(filePath);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Error on certificate trust check. (%d)", retCode));
RegCloseKey(subKey);
continue; // Try the next subkey
}
RegCloseKey(baseKey);
// Raise the roof, we found a match!
return TRUE;
}
RegCloseKey(baseKey);
// No certificates match, :'(
return FALSE;
}

View file

@ -0,0 +1,14 @@
/* 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/. */
#ifndef _REGISTRYCERTIFICATES_H_
#define _REGISTRYCERTIFICATES_H_
#include "certificatecheck.h"
BOOL DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate,
LPCWSTR filePath,
BOOL allowFallbackKeySkip = TRUE);
#endif

View file

@ -0,0 +1,28 @@
# 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/.
sources = []
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
sources += [
'pathhash.cpp',
'uachelper.cpp',
'updatehelper.cpp',
]
if CONFIG['MOZ_MAINTENANCE_SERVICE']:
sources += [
'certificatecheck.cpp',
'registrycertificates.cpp',
]
OS_LIBS += [
'crypt32',
'wintrust',
]
sources += [
'readstrings.cpp',
'updatecommon.cpp',
]
SOURCES += sorted(['%s/%s' % (srcdir, s) for s in sources])

View file

@ -0,0 +1,222 @@
/* 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/. */
#include <windows.h>
#include <wtsapi32.h>
#include "uachelper.h"
#include "updatecommon.h"
// See the MSDN documentation with title: Privilege Constants
// At the time of this writing, this documentation is located at:
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb530716%28v=vs.85%29.aspx
LPCTSTR UACHelper::PrivsToDisable[] = {
SE_ASSIGNPRIMARYTOKEN_NAME,
SE_AUDIT_NAME,
SE_BACKUP_NAME,
// CreateProcess will succeed but the app will fail to launch on some WinXP
// machines if SE_CHANGE_NOTIFY_NAME is disabled. In particular this happens
// for limited user accounts on those machines. The define is kept here as a
// reminder that it should never be re-added.
// This permission is for directory watching but also from MSDN: "This
// privilege also causes the system to skip all traversal access checks."
// SE_CHANGE_NOTIFY_NAME,
SE_CREATE_GLOBAL_NAME,
SE_CREATE_PAGEFILE_NAME,
SE_CREATE_PERMANENT_NAME,
SE_CREATE_SYMBOLIC_LINK_NAME,
SE_CREATE_TOKEN_NAME,
SE_DEBUG_NAME,
SE_ENABLE_DELEGATION_NAME,
SE_IMPERSONATE_NAME,
SE_INC_BASE_PRIORITY_NAME,
SE_INCREASE_QUOTA_NAME,
SE_INC_WORKING_SET_NAME,
SE_LOAD_DRIVER_NAME,
SE_LOCK_MEMORY_NAME,
SE_MACHINE_ACCOUNT_NAME,
SE_MANAGE_VOLUME_NAME,
SE_PROF_SINGLE_PROCESS_NAME,
SE_RELABEL_NAME,
SE_REMOTE_SHUTDOWN_NAME,
SE_RESTORE_NAME,
SE_SECURITY_NAME,
SE_SHUTDOWN_NAME,
SE_SYNC_AGENT_NAME,
SE_SYSTEM_ENVIRONMENT_NAME,
SE_SYSTEM_PROFILE_NAME,
SE_SYSTEMTIME_NAME,
SE_TAKE_OWNERSHIP_NAME,
SE_TCB_NAME,
SE_TIME_ZONE_NAME,
SE_TRUSTED_CREDMAN_ACCESS_NAME,
SE_UNDOCK_NAME,
SE_UNSOLICITED_INPUT_NAME
};
/**
* Opens a user token for the given session ID
*
* @param sessionID The session ID for the token to obtain
* @return A handle to the token to obtain which will be primary if enough
* permissions exist. Caller should close the handle.
*/
HANDLE
UACHelper::OpenUserToken(DWORD sessionID)
{
HMODULE module = LoadLibraryW(L"wtsapi32.dll");
HANDLE token = nullptr;
decltype(WTSQueryUserToken)* wtsQueryUserToken =
(decltype(WTSQueryUserToken)*) GetProcAddress(module, "WTSQueryUserToken");
if (wtsQueryUserToken) {
wtsQueryUserToken(sessionID, &token);
}
FreeLibrary(module);
return token;
}
/**
* Opens a linked token for the specified token.
*
* @param token The token to get the linked token from
* @return A linked token or nullptr if one does not exist.
* Caller should close the handle.
*/
HANDLE
UACHelper::OpenLinkedToken(HANDLE token)
{
// Magic below...
// UAC creates 2 tokens. One is the restricted token which we have.
// the other is the UAC elevated one. Since we are running as a service
// as the system account we have access to both.
TOKEN_LINKED_TOKEN tlt;
HANDLE hNewLinkedToken = nullptr;
DWORD len;
if (GetTokenInformation(token, (TOKEN_INFORMATION_CLASS)TokenLinkedToken,
&tlt, sizeof(TOKEN_LINKED_TOKEN), &len)) {
token = tlt.LinkedToken;
hNewLinkedToken = token;
}
return hNewLinkedToken;
}
/**
* Enables or disables a privilege for the specified token.
*
* @param token The token to adjust the privilege on.
* @param priv The privilege to adjust.
* @param enable Whether to enable or disable it
* @return TRUE if the token was adjusted to the specified value.
*/
BOOL
UACHelper::SetPrivilege(HANDLE token, LPCTSTR priv, BOOL enable)
{
LUID luidOfPriv;
if (!LookupPrivilegeValue(nullptr, priv, &luidOfPriv)) {
return FALSE;
}
TOKEN_PRIVILEGES tokenPriv;
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privileges[0].Luid = luidOfPriv;
tokenPriv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
SetLastError(ERROR_SUCCESS);
if (!AdjustTokenPrivileges(token, false, &tokenPriv,
sizeof(tokenPriv), nullptr, nullptr)) {
return FALSE;
}
return GetLastError() == ERROR_SUCCESS;
}
/**
* For each privilege that is specified, an attempt will be made to
* drop the privilege.
*
* @param token The token to adjust the privilege on.
* Pass nullptr for current token.
* @param unneededPrivs An array of unneeded privileges.
* @param count The size of the array
* @return TRUE if there were no errors
*/
BOOL
UACHelper::DisableUnneededPrivileges(HANDLE token,
LPCTSTR *unneededPrivs,
size_t count)
{
HANDLE obtainedToken = nullptr;
if (!token) {
// Note: This handle is a pseudo-handle and need not be closed
HANDLE process = GetCurrentProcess();
if (!OpenProcessToken(process, TOKEN_ALL_ACCESS_P, &obtainedToken)) {
LOG_WARN(("Could not obtain token for current process, no "
"privileges changed. (%d)", GetLastError()));
return FALSE;
}
token = obtainedToken;
}
BOOL result = TRUE;
for (size_t i = 0; i < count; i++) {
if (SetPrivilege(token, unneededPrivs[i], FALSE)) {
LOG(("Disabled unneeded token privilege: %s.",
unneededPrivs[i]));
} else {
LOG(("Could not disable token privilege value: %s. (%d)",
unneededPrivs[i], GetLastError()));
result = FALSE;
}
}
if (obtainedToken) {
CloseHandle(obtainedToken);
}
return result;
}
/**
* Disables privileges for the specified token.
* The privileges to disable are in PrivsToDisable.
* In the future there could be new privs and we are not sure if we should
* explicitly disable these or not.
*
* @param token The token to drop the privilege on.
* Pass nullptr for current token.
* @return TRUE if there were no errors
*/
BOOL
UACHelper::DisablePrivileges(HANDLE token)
{
static const size_t PrivsToDisableSize =
sizeof(UACHelper::PrivsToDisable) / sizeof(UACHelper::PrivsToDisable[0]);
return DisableUnneededPrivileges(token, UACHelper::PrivsToDisable,
PrivsToDisableSize);
}
/**
* Check if the current user can elevate.
*
* @return true if the user can elevate.
* false otherwise.
*/
bool
UACHelper::CanUserElevate()
{
HANDLE token;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
return false;
}
TOKEN_ELEVATION_TYPE elevationType;
DWORD len;
bool canElevate = GetTokenInformation(token, TokenElevationType,
&elevationType,
sizeof(elevationType), &len) &&
(elevationType == TokenElevationTypeLimited);
CloseHandle(token);
return canElevate;
}

View file

@ -0,0 +1,23 @@
/* 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/. */
#ifndef _UACHELPER_H_
#define _UACHELPER_H_
class UACHelper
{
public:
static HANDLE OpenUserToken(DWORD sessionID);
static HANDLE OpenLinkedToken(HANDLE token);
static BOOL DisablePrivileges(HANDLE token);
static bool CanUserElevate();
private:
static BOOL SetPrivilege(HANDLE token, LPCTSTR privs, BOOL enable);
static BOOL DisableUnneededPrivileges(HANDLE token,
LPCTSTR *unneededPrivs, size_t count);
static LPCTSTR PrivsToDisable[];
};
#endif

View file

@ -0,0 +1,213 @@
/* 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/. */
#if defined(XP_WIN)
#include <windows.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "updatecommon.h"
UpdateLog::UpdateLog() : logFP(nullptr)
{
}
void UpdateLog::Init(NS_tchar* sourcePath,
const NS_tchar* fileName)
{
if (logFP) {
return;
}
int dstFilePathLen = NS_tsnprintf(mDstFilePath,
sizeof(mDstFilePath)/sizeof(mDstFilePath[0]),
NS_T("%s/%s"), sourcePath, fileName);
// If the destination path was over the length limit,
// disable logging by skipping opening the file and setting logFP.
if ((dstFilePathLen > 0) &&
(dstFilePathLen <
static_cast<int>(sizeof(mDstFilePath)/sizeof(mDstFilePath[0])))) {
#ifdef XP_WIN
if (GetTempFileNameW(sourcePath, L"log", 0, mTmpFilePath) != 0) {
logFP = NS_tfopen(mTmpFilePath, NS_T("w"));
// Delete this file now so it is possible to tell from the unelevated
// updater process if the elevated updater process has written the log.
DeleteFileW(mDstFilePath);
}
#elif XP_MACOSX
logFP = NS_tfopen(mDstFilePath, NS_T("w"));
#else
// On platforms that have an updates directory in the installation directory
// (e.g. platforms other than Windows and Mac) the update log is written to
// a temporary file and then to the update log file. This is needed since
// the installation directory is moved during a replace request. This can be
// removed when the platform's updates directory is located outside of the
// installation directory.
logFP = tmpfile();
#endif
}
}
void UpdateLog::Finish()
{
if (!logFP) {
return;
}
#if !defined(XP_WIN) && !defined(XP_MACOSX)
const int blockSize = 1024;
char buffer[blockSize];
fflush(logFP);
rewind(logFP);
FILE *updateLogFP = NS_tfopen(mDstFilePath, NS_T("wb+"));
while (!feof(logFP)) {
size_t read = fread(buffer, 1, blockSize, logFP);
if (ferror(logFP)) {
fclose(logFP);
logFP = nullptr;
fclose(updateLogFP);
updateLogFP = nullptr;
return;
}
size_t written = 0;
while (written < read) {
size_t chunkWritten = fwrite(buffer, 1, read - written, updateLogFP);
if (chunkWritten <= 0) {
fclose(logFP);
logFP = nullptr;
fclose(updateLogFP);
updateLogFP = nullptr;
return;
}
written += chunkWritten;
}
}
fclose(updateLogFP);
updateLogFP = nullptr;
#endif
fclose(logFP);
logFP = nullptr;
#ifdef XP_WIN
// When the log file already exists then the elevated updater has already
// written the log file and the temp file for the log should be discarded.
if (!NS_taccess(mDstFilePath, F_OK)) {
DeleteFileW(mTmpFilePath);
} else {
MoveFileW(mTmpFilePath, mDstFilePath);
}
#endif
}
void UpdateLog::Flush()
{
if (!logFP) {
return;
}
fflush(logFP);
}
void UpdateLog::Printf(const char *fmt, ... )
{
if (!logFP) {
return;
}
va_list ap;
va_start(ap, fmt);
vfprintf(logFP, fmt, ap);
fprintf(logFP, "\n");
va_end(ap);
}
void UpdateLog::WarnPrintf(const char *fmt, ... )
{
if (!logFP) {
return;
}
va_list ap;
va_start(ap, fmt);
fprintf(logFP, "*** Warning: ");
vfprintf(logFP, fmt, ap);
fprintf(logFP, "***\n");
va_end(ap);
}
/**
* Performs checks of a full path for validity for this application.
*
* @param origFullPath
* The full path to check.
* @return true if the path is valid for this application and false otherwise.
*/
bool
IsValidFullPath(NS_tchar* origFullPath)
{
// Subtract 1 from MAXPATHLEN for null termination.
if (NS_tstrlen(origFullPath) > MAXPATHLEN - 1) {
// The path is longer than acceptable for this application.
return false;
}
#ifdef XP_WIN
NS_tchar testPath[MAXPATHLEN] = {NS_T('\0')};
// GetFullPathNameW will replace / with \ which PathCanonicalizeW requires.
if (GetFullPathNameW(origFullPath, MAXPATHLEN, testPath, nullptr) == 0) {
// Unable to get the full name for the path (e.g. invalid path).
return false;
}
NS_tchar canonicalPath[MAXPATHLEN] = {NS_T('\0')};
if (!PathCanonicalizeW(canonicalPath, testPath)) {
// Path could not be canonicalized (e.g. invalid path).
return false;
}
// Check if the path passed in resolves to a differerent path.
if (NS_tstricmp(origFullPath, canonicalPath) != 0) {
// Case insensitive string comparison between the supplied path and the
// canonical path are not equal. This will prevent directory traversal and
// the use of / in paths since they are converted to \.
return false;
}
NS_tstrncpy(testPath, origFullPath, MAXPATHLEN);
if (!PathStripToRootW(testPath)) {
// It should always be possible to strip a valid path to its root.
return false;
}
if (origFullPath[0] == NS_T('\\')) {
// Only allow UNC server share paths.
if (!PathIsUNCServerShareW(testPath)) {
return false;
}
}
#else
// Only allow full paths.
if (origFullPath[0] != NS_T('/')) {
return false;
}
// The path must not traverse directories
if (NS_tstrstr(origFullPath, NS_T("..")) != nullptr ||
NS_tstrstr(origFullPath, NS_T("./")) != nullptr) {
return false;
}
#endif
return true;
}

View file

@ -0,0 +1,47 @@
/* 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/. */
#ifndef UPDATECOMMON_H
#define UPDATECOMMON_H
#include "updatedefines.h"
#include <stdio.h>
class UpdateLog
{
public:
static UpdateLog & GetPrimaryLog()
{
static UpdateLog primaryLog;
return primaryLog;
}
void Init(NS_tchar* sourcePath, const NS_tchar* fileName);
void Finish();
void Flush();
void Printf(const char *fmt, ... );
void WarnPrintf(const char *fmt, ... );
~UpdateLog()
{
Finish();
}
protected:
UpdateLog();
FILE *logFP;
NS_tchar mTmpFilePath[MAXPATHLEN];
NS_tchar mDstFilePath[MAXPATHLEN];
};
bool IsValidFullPath(NS_tchar* fullPath);
#define LOG_WARN(args) UpdateLog::GetPrimaryLog().WarnPrintf args
#define LOG(args) UpdateLog::GetPrimaryLog().Printf args
#define LogInit(PATHNAME_, FILENAME_) \
UpdateLog::GetPrimaryLog().Init(PATHNAME_, FILENAME_)
#define LogFinish() UpdateLog::GetPrimaryLog().Finish()
#define LogFlush() UpdateLog::GetPrimaryLog().Flush()
#endif

View file

@ -0,0 +1,142 @@
/* 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/. */
#ifndef UPDATEDEFINES_H
#define UPDATEDEFINES_H
#include "readstrings.h"
#ifndef MAXPATHLEN
# ifdef PATH_MAX
# define MAXPATHLEN PATH_MAX
# elif defined(MAX_PATH)
# define MAXPATHLEN MAX_PATH
# elif defined(_MAX_PATH)
# define MAXPATHLEN _MAX_PATH
# elif defined(CCHMAXPATH)
# define MAXPATHLEN CCHMAXPATH
# else
# define MAXPATHLEN 1024
# endif
#endif
#if defined(XP_WIN)
# include <windows.h>
# include <shlwapi.h>
# include <direct.h>
# include <io.h>
# include <stdio.h>
# include <stdarg.h>
# ifndef F_OK
# define F_OK 00
# endif
# ifndef W_OK
# define W_OK 02
# endif
# ifndef R_OK
# define R_OK 04
# endif
# define S_ISDIR(s) (((s) & _S_IFMT) == _S_IFDIR)
# define S_ISREG(s) (((s) & _S_IFMT) == _S_IFREG)
# define access _access
# define putenv _putenv
# if defined(_MSC_VER) && _MSC_VER < 1900
# define stat _stat
# endif
# define DELETE_DIR L"tobedeleted"
# define CALLBACK_BACKUP_EXT L".moz-callback"
# define LOG_S "%S"
# define NS_T(str) L ## str
# define NS_SLASH NS_T('\\')
static inline int mywcsprintf(WCHAR* dest, size_t count, const WCHAR* fmt, ...)
{
size_t _count = count - 1;
va_list varargs;
va_start(varargs, fmt);
int result = _vsnwprintf(dest, count - 1, fmt, varargs);
va_end(varargs);
dest[_count] = L'\0';
return result;
}
#define NS_tsnprintf mywcsprintf
# define NS_taccess _waccess
# define NS_tchdir _wchdir
# define NS_tchmod _wchmod
# define NS_tfopen _wfopen
# define NS_tmkdir(path, perms) _wmkdir(path)
# define NS_tremove _wremove
// _wrename is used to avoid the link tracking service.
# define NS_trename _wrename
# define NS_trmdir _wrmdir
# define NS_tstat _wstat
# define NS_tlstat _wstat // No symlinks on Windows
# define NS_tstat_t _stat
# define NS_tstrcat wcscat
# define NS_tstrcmp wcscmp
# define NS_tstricmp wcsicmp
# define NS_tstrcpy wcscpy
# define NS_tstrncpy wcsncpy
# define NS_tstrlen wcslen
# define NS_tstrchr wcschr
# define NS_tstrrchr wcsrchr
# define NS_tstrstr wcsstr
# include "win_dirent.h"
# define NS_tDIR DIR
# define NS_tdirent dirent
# define NS_topendir opendir
# define NS_tclosedir closedir
# define NS_treaddir readdir
#else
# include <sys/wait.h>
# include <unistd.h>
#ifdef SOLARIS
# include <sys/stat.h>
#else
# include <fts.h>
#endif
# include <dirent.h>
#ifdef XP_MACOSX
# include <sys/time.h>
#endif
# define LOG_S "%s"
# define NS_T(str) str
# define NS_SLASH NS_T('/')
# define NS_tsnprintf snprintf
# define NS_taccess access
# define NS_tchdir chdir
# define NS_tchmod chmod
# define NS_tfopen fopen
# define NS_tmkdir mkdir
# define NS_tremove remove
# define NS_trename rename
# define NS_trmdir rmdir
# define NS_tstat stat
# define NS_tstat_t stat
# define NS_tlstat lstat
# define NS_tstrcat strcat
# define NS_tstrcmp strcmp
# define NS_tstricmp strcasecmp
# define NS_tstrcpy strcpy
# define NS_tstrncpy strncpy
# define NS_tstrlen strlen
# define NS_tstrrchr strrchr
# define NS_tstrstr strstr
# define NS_tDIR DIR
# define NS_tdirent dirent
# define NS_topendir opendir
# define NS_tclosedir closedir
# define NS_treaddir readdir
#endif
#define BACKUP_EXT NS_T(".moz-backup")
#endif

View file

@ -0,0 +1,609 @@
/* 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/. */
#include <windows.h>
// Needed for CreateToolhelp32Snapshot
#include <tlhelp32.h>
#ifndef ONLY_SERVICE_LAUNCHING
#include <stdio.h>
#include "shlobj.h"
#include "updatehelper.h"
#include "uachelper.h"
#include "pathhash.h"
#include "mozilla/UniquePtr.h"
// Needed for PathAppendW
#include <shlwapi.h>
using mozilla::MakeUnique;
using mozilla::UniquePtr;
BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra);
BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer,
LPCWSTR siblingFilePath,
LPCWSTR newFileName);
/**
* Obtains the path of a file in the same directory as the specified file.
*
* @param destinationBuffer A buffer of size MAX_PATH + 1 to store the result.
* @param siblingFIlePath The path of another file in the same directory
* @param newFileName The filename of another file in the same directory
* @return TRUE if successful
*/
BOOL
PathGetSiblingFilePath(LPWSTR destinationBuffer,
LPCWSTR siblingFilePath,
LPCWSTR newFileName)
{
if (wcslen(siblingFilePath) >= MAX_PATH) {
return FALSE;
}
wcsncpy(destinationBuffer, siblingFilePath, MAX_PATH);
if (!PathRemoveFileSpecW(destinationBuffer)) {
return FALSE;
}
if (wcslen(destinationBuffer) + wcslen(newFileName) >= MAX_PATH) {
return FALSE;
}
return PathAppendSafe(destinationBuffer, newFileName);
}
/**
* Starts the upgrade process for update of the service if it is
* already installed.
*
* @param installDir the installation directory where
* maintenanceservice_installer.exe is located.
* @return TRUE if successful
*/
BOOL
StartServiceUpdate(LPCWSTR installDir)
{
// Get a handle to the local computer SCM database
SC_HANDLE manager = OpenSCManager(nullptr, nullptr,
SC_MANAGER_ALL_ACCESS);
if (!manager) {
return FALSE;
}
// Open the service
SC_HANDLE svc = OpenServiceW(manager, SVC_NAME,
SERVICE_ALL_ACCESS);
if (!svc) {
CloseServiceHandle(manager);
return FALSE;
}
// If we reach here, then the service is installed, so
// proceed with upgrading it.
CloseServiceHandle(manager);
// The service exists and we opened it, get the config bytes needed
DWORD bytesNeeded;
if (!QueryServiceConfigW(svc, nullptr, 0, &bytesNeeded) &&
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
CloseServiceHandle(svc);
return FALSE;
}
// Get the service config information, in particular we want the binary
// path of the service.
UniquePtr<char[]> serviceConfigBuffer = MakeUnique<char[]>(bytesNeeded);
if (!QueryServiceConfigW(svc,
reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()),
bytesNeeded, &bytesNeeded)) {
CloseServiceHandle(svc);
return FALSE;
}
CloseServiceHandle(svc);
QUERY_SERVICE_CONFIGW &serviceConfig =
*reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get());
PathUnquoteSpacesW(serviceConfig.lpBinaryPathName);
// Obtain the temp path of the maintenance service binary
WCHAR tmpService[MAX_PATH + 1] = { L'\0' };
if (!PathGetSiblingFilePath(tmpService, serviceConfig.lpBinaryPathName,
L"maintenanceservice_tmp.exe")) {
return FALSE;
}
// Get the new maintenance service path from the install dir
WCHAR newMaintServicePath[MAX_PATH + 1] = { L'\0' };
wcsncpy(newMaintServicePath, installDir, MAX_PATH);
PathAppendSafe(newMaintServicePath,
L"maintenanceservice.exe");
// Copy the temp file in alongside the maintenace service.
// This is a requirement for maintenance service upgrades.
if (!CopyFileW(newMaintServicePath, tmpService, FALSE)) {
return FALSE;
}
// Start the upgrade comparison process
STARTUPINFOW si = {0};
si.cb = sizeof(STARTUPINFOW);
// No particular desktop because no UI
si.lpDesktop = L"";
PROCESS_INFORMATION pi = {0};
WCHAR cmdLine[64] = { '\0' };
wcsncpy(cmdLine, L"dummyparam.exe upgrade",
sizeof(cmdLine) / sizeof(cmdLine[0]) - 1);
BOOL svcUpdateProcessStarted = CreateProcessW(tmpService,
cmdLine,
nullptr, nullptr, FALSE,
0,
nullptr, installDir, &si, &pi);
if (svcUpdateProcessStarted) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return svcUpdateProcessStarted;
}
#endif
/**
* Executes a maintenance service command
*
* @param argc The total number of arguments in argv
* @param argv An array of null terminated strings to pass to the service,
* @return ERROR_SUCCESS if the service command was started.
* Less than 16000, a windows system error code from StartServiceW
* More than 20000, 20000 + the last state of the service constant if
* the last state is something other than stopped.
* 17001 if the SCM could not be opened
* 17002 if the service could not be opened
*/
DWORD
StartServiceCommand(int argc, LPCWSTR* argv)
{
DWORD lastState = WaitForServiceStop(SVC_NAME, 5);
if (lastState != SERVICE_STOPPED) {
return 20000 + lastState;
}
// Get a handle to the SCM database.
SC_HANDLE serviceManager = OpenSCManager(nullptr, nullptr,
SC_MANAGER_CONNECT |
SC_MANAGER_ENUMERATE_SERVICE);
if (!serviceManager) {
return 17001;
}
// Get a handle to the service.
SC_HANDLE service = OpenServiceW(serviceManager,
SVC_NAME,
SERVICE_START);
if (!service) {
CloseServiceHandle(serviceManager);
return 17002;
}
// Wait at most 5 seconds trying to start the service in case of errors
// like ERROR_SERVICE_DATABASE_LOCKED or ERROR_SERVICE_REQUEST_TIMEOUT.
const DWORD maxWaitMS = 5000;
DWORD currentWaitMS = 0;
DWORD lastError = ERROR_SUCCESS;
while (currentWaitMS < maxWaitMS) {
BOOL result = StartServiceW(service, argc, argv);
if (result) {
lastError = ERROR_SUCCESS;
break;
} else {
lastError = GetLastError();
}
Sleep(100);
currentWaitMS += 100;
}
CloseServiceHandle(service);
CloseServiceHandle(serviceManager);
return lastError;
}
#ifndef ONLY_SERVICE_LAUNCHING
/**
* Launch a service initiated action for a software update with the
* specified arguments.
*
* @param exePath The path of the executable to run
* @param argc The total number of arguments in argv
* @param argv An array of null terminated strings to pass to the exePath,
* argv[0] must be the path to the updater.exe
* @return ERROR_SUCCESS if successful
*/
DWORD
LaunchServiceSoftwareUpdateCommand(int argc, LPCWSTR* argv)
{
// The service command is the same as the updater.exe command line except
// it has 2 extra args: 1) The Path to udpater.exe, and 2) the command
// being executed which is "software-update"
LPCWSTR *updaterServiceArgv = new LPCWSTR[argc + 2];
updaterServiceArgv[0] = L"MozillaMaintenance";
updaterServiceArgv[1] = L"software-update";
for (int i = 0; i < argc; ++i) {
updaterServiceArgv[i + 2] = argv[i];
}
// Execute the service command by starting the service with
// the passed in arguments.
DWORD ret = StartServiceCommand(argc + 2, updaterServiceArgv);
delete[] updaterServiceArgv;
return ret;
}
/**
* Joins a base directory path with a filename.
*
* @param base The base directory path of size MAX_PATH + 1
* @param extra The filename to append
* @return TRUE if the file name was successful appended to base
*/
BOOL
PathAppendSafe(LPWSTR base, LPCWSTR extra)
{
if (wcslen(base) + wcslen(extra) >= MAX_PATH) {
return FALSE;
}
return PathAppendW(base, extra);
}
/**
* Sets update.status to a specific failure code
*
* @param updateDirPath The path of the update directory
* @return TRUE if successful
*/
BOOL
WriteStatusFailure(LPCWSTR updateDirPath, int errorCode)
{
// The temp file is not removed on failure since there is client code that
// will remove it.
WCHAR tmpUpdateStatusFilePath[MAX_PATH + 1] = { L'\0' };
if (GetTempFileNameW(updateDirPath, L"svc", 0, tmpUpdateStatusFilePath) == 0) {
return FALSE;
}
HANDLE tmpStatusFile = CreateFileW(tmpUpdateStatusFilePath, GENERIC_WRITE, 0,
nullptr, CREATE_ALWAYS, 0, nullptr);
if (tmpStatusFile == INVALID_HANDLE_VALUE) {
return FALSE;
}
char failure[32];
sprintf(failure, "failed: %d", errorCode);
DWORD toWrite = strlen(failure);
DWORD wrote;
BOOL ok = WriteFile(tmpStatusFile, failure,
toWrite, &wrote, nullptr);
CloseHandle(tmpStatusFile);
if (!ok || wrote != toWrite) {
return FALSE;
}
WCHAR updateStatusFilePath[MAX_PATH + 1] = { L'\0' };
wcsncpy(updateStatusFilePath, updateDirPath, MAX_PATH);
if (!PathAppendSafe(updateStatusFilePath, L"update.status")) {
return FALSE;
}
if (MoveFileExW(tmpUpdateStatusFilePath, updateStatusFilePath,
MOVEFILE_REPLACE_EXISTING) == 0) {
return FALSE;
}
return TRUE;
}
#endif
/**
* Waits for a service to enter a stopped state.
* This function does not stop the service, it just blocks until the service
* is stopped.
*
* @param serviceName The service to wait for.
* @param maxWaitSeconds The maximum number of seconds to wait
* @return state of the service after a timeout or when stopped.
* A value of 255 is returned for an error. Typical values are:
* SERVICE_STOPPED 0x00000001
* SERVICE_START_PENDING 0x00000002
* SERVICE_STOP_PENDING 0x00000003
* SERVICE_RUNNING 0x00000004
* SERVICE_CONTINUE_PENDING 0x00000005
* SERVICE_PAUSE_PENDING 0x00000006
* SERVICE_PAUSED 0x00000007
* last status not set 0x000000CF
* Could no query status 0x000000DF
* Could not open service, access denied 0x000000EB
* Could not open service, invalid handle 0x000000EC
* Could not open service, invalid name 0x000000ED
* Could not open service, does not exist 0x000000EE
* Could not open service, other error 0x000000EF
* Could not open SCM, access denied 0x000000FD
* Could not open SCM, database does not exist 0x000000FE;
* Could not open SCM, other error 0x000000FF;
* Note: The strange choice of error codes above SERVICE_PAUSED are chosen
* in case Windows comes out with other service stats higher than 7, they
* would likely call it 8 and above. JS code that uses this in TestAUSHelper
* only handles values up to 255 so that's why we don't use GetLastError
* directly.
*/
DWORD
WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds)
{
// 0x000000CF is defined above to be not set
DWORD lastServiceState = 0x000000CF;
// Get a handle to the SCM database.
SC_HANDLE serviceManager = OpenSCManager(nullptr, nullptr,
SC_MANAGER_CONNECT |
SC_MANAGER_ENUMERATE_SERVICE);
if (!serviceManager) {
DWORD lastError = GetLastError();
switch(lastError) {
case ERROR_ACCESS_DENIED:
return 0x000000FD;
case ERROR_DATABASE_DOES_NOT_EXIST:
return 0x000000FE;
default:
return 0x000000FF;
}
}
// Get a handle to the service.
SC_HANDLE service = OpenServiceW(serviceManager,
serviceName,
SERVICE_QUERY_STATUS);
if (!service) {
DWORD lastError = GetLastError();
CloseServiceHandle(serviceManager);
switch(lastError) {
case ERROR_ACCESS_DENIED:
return 0x000000EB;
case ERROR_INVALID_HANDLE:
return 0x000000EC;
case ERROR_INVALID_NAME:
return 0x000000ED;
case ERROR_SERVICE_DOES_NOT_EXIST:
return 0x000000EE;
default:
return 0x000000EF;
}
}
DWORD currentWaitMS = 0;
SERVICE_STATUS_PROCESS ssp;
ssp.dwCurrentState = lastServiceState;
while (currentWaitMS < maxWaitSeconds * 1000) {
DWORD bytesNeeded;
if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded)) {
DWORD lastError = GetLastError();
switch (lastError) {
case ERROR_INVALID_HANDLE:
ssp.dwCurrentState = 0x000000D9;
break;
case ERROR_ACCESS_DENIED:
ssp.dwCurrentState = 0x000000DA;
break;
case ERROR_INSUFFICIENT_BUFFER:
ssp.dwCurrentState = 0x000000DB;
break;
case ERROR_INVALID_PARAMETER:
ssp.dwCurrentState = 0x000000DC;
break;
case ERROR_INVALID_LEVEL:
ssp.dwCurrentState = 0x000000DD;
break;
case ERROR_SHUTDOWN_IN_PROGRESS:
ssp.dwCurrentState = 0x000000DE;
break;
// These 3 errors can occur when the service is not yet stopped but
// it is stopping.
case ERROR_INVALID_SERVICE_CONTROL:
case ERROR_SERVICE_CANNOT_ACCEPT_CTRL:
case ERROR_SERVICE_NOT_ACTIVE:
currentWaitMS += 50;
Sleep(50);
continue;
default:
ssp.dwCurrentState = 0x000000DF;
}
// We couldn't query the status so just break out
break;
}
// The service is already in use.
if (ssp.dwCurrentState == SERVICE_STOPPED) {
break;
}
currentWaitMS += 50;
Sleep(50);
}
lastServiceState = ssp.dwCurrentState;
CloseServiceHandle(service);
CloseServiceHandle(serviceManager);
return lastServiceState;
}
#ifndef ONLY_SERVICE_LAUNCHING
/**
* Determines if there is at least one process running for the specified
* application. A match will be found across any session for any user.
*
* @param process The process to check for existance
* @return ERROR_NOT_FOUND if the process was not found
* ERROR_SUCCESS if the process was found and there were no errors
* Other Win32 system error code for other errors
**/
DWORD
IsProcessRunning(LPCWSTR filename)
{
// Take a snapshot of all processes in the system.
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == snapshot) {
return GetLastError();
}
PROCESSENTRY32W processEntry;
processEntry.dwSize = sizeof(PROCESSENTRY32W);
if (!Process32FirstW(snapshot, &processEntry)) {
DWORD lastError = GetLastError();
CloseHandle(snapshot);
return lastError;
}
do {
if (wcsicmp(filename, processEntry.szExeFile) == 0) {
CloseHandle(snapshot);
return ERROR_SUCCESS;
}
} while (Process32NextW(snapshot, &processEntry));
CloseHandle(snapshot);
return ERROR_NOT_FOUND;
}
/**
* Waits for the specified applicaiton to exit.
*
* @param filename The application to wait for.
* @param maxSeconds The maximum amount of seconds to wait for all
* instances of the application to exit.
* @return ERROR_SUCCESS if no instances of the application exist
* WAIT_TIMEOUT if the process is still running after maxSeconds.
* Any other Win32 system error code.
*/
DWORD
WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds)
{
DWORD applicationRunningError = WAIT_TIMEOUT;
for(DWORD i = 0; i < maxSeconds; i++) {
DWORD applicationRunningError = IsProcessRunning(filename);
if (ERROR_NOT_FOUND == applicationRunningError) {
return ERROR_SUCCESS;
}
Sleep(1000);
}
if (ERROR_SUCCESS == applicationRunningError) {
return WAIT_TIMEOUT;
}
return applicationRunningError;
}
/**
* Determines if the fallback key exists or not
*
* @return TRUE if the fallback key exists and there was no error checking
*/
BOOL
DoesFallbackKeyExist()
{
HKEY testOnlyFallbackKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
TEST_ONLY_FALLBACK_KEY_PATH, 0,
KEY_READ | KEY_WOW64_64KEY,
&testOnlyFallbackKey) != ERROR_SUCCESS) {
return FALSE;
}
RegCloseKey(testOnlyFallbackKey);
return TRUE;
}
#endif
/**
* Determines if the file system for the specified file handle is local
* @param file path to check the filesystem type for, must be at most MAX_PATH
* @param isLocal out parameter which will hold TRUE if the drive is local
* @return TRUE if the call succeeded
*/
BOOL
IsLocalFile(LPCWSTR file, BOOL &isLocal)
{
WCHAR rootPath[MAX_PATH + 1] = { L'\0' };
if (wcslen(file) > MAX_PATH) {
return FALSE;
}
wcsncpy(rootPath, file, MAX_PATH);
PathStripToRootW(rootPath);
isLocal = GetDriveTypeW(rootPath) == DRIVE_FIXED;
return TRUE;
}
/**
* Determines the DWORD value of a registry key value
*
* @param key The base key to where the value name exists
* @param valueName The name of the value
* @param retValue Out parameter which will hold the value
* @return TRUE on success
*/
static BOOL
GetDWORDValue(HKEY key, LPCWSTR valueName, DWORD &retValue)
{
DWORD regDWORDValueSize = sizeof(DWORD);
LONG retCode = RegQueryValueExW(key, valueName, 0, nullptr,
reinterpret_cast<LPBYTE>(&retValue),
&regDWORDValueSize);
return ERROR_SUCCESS == retCode;
}
/**
* Determines if the the system's elevation type allows
* unprmopted elevation.
*
* @param isUnpromptedElevation Out parameter which specifies if unprompted
* elevation is allowed.
* @return TRUE if the user can actually elevate and the value was obtained
* successfully.
*/
BOOL
IsUnpromptedElevation(BOOL &isUnpromptedElevation)
{
if (!UACHelper::CanUserElevate()) {
return FALSE;
}
LPCWSTR UACBaseRegKey =
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
HKEY baseKey;
LONG retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
UACBaseRegKey, 0,
KEY_READ, &baseKey);
if (retCode != ERROR_SUCCESS) {
return FALSE;
}
DWORD consent, secureDesktop;
BOOL success = GetDWORDValue(baseKey, L"ConsentPromptBehaviorAdmin",
consent);
success = success &&
GetDWORDValue(baseKey, L"PromptOnSecureDesktop", secureDesktop);
isUnpromptedElevation = !consent && !secureDesktop;
RegCloseKey(baseKey);
return success;
}

View file

@ -0,0 +1,29 @@
/* 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/. */
BOOL StartServiceUpdate(LPCWSTR installDir);
DWORD LaunchServiceSoftwareUpdateCommand(int argc, LPCWSTR *argv);
BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode);
DWORD WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds);
DWORD WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds);
DWORD IsProcessRunning(LPCWSTR filename);
BOOL DoesFallbackKeyExist();
BOOL IsLocalFile(LPCWSTR file, BOOL &isLocal);
DWORD StartServiceCommand(int argc, LPCWSTR* argv);
BOOL IsUnpromptedElevation(BOOL &isUnpromptedElevation);
#define SVC_NAME L"MozillaMaintenance"
#define BASE_SERVICE_REG_KEY \
L"SOFTWARE\\Mozilla\\MaintenanceService"
// The test only fallback key, as its name implies, is only present on machines
// that will use automated tests. Since automated tests always run from a
// different directory for each test, the presence of this key bypasses the
// "This is a valid installation directory" check. This key also stores
// the allowed name and issuer for cert checks so that the cert check
// code can still be run unchanged.
#define TEST_ONLY_FALLBACK_KEY_PATH \
BASE_SERVICE_REG_KEY L"\\3932ecacee736d366d6436db0f55bce4"

View file

@ -0,0 +1,32 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef WINDIRENT_H__
#define WINDIRENT_H__
#ifndef XP_WIN
#error This library should only be used on Windows
#endif
#include <windows.h>
struct DIR {
explicit DIR(const WCHAR* path);
~DIR();
HANDLE findHandle;
WCHAR name[MAX_PATH];
};
struct dirent {
dirent();
WCHAR d_name[MAX_PATH];
};
DIR* opendir(const WCHAR* path);
int closedir(DIR* dir);
dirent* readdir(DIR* dir);
#endif // WINDIRENT_H__

View file

@ -0,0 +1,70 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* 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 NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var gUpdateHistory = {
_view: null,
/**
* Initialize the User Interface
*/
onLoad: function() {
this._view = document.getElementById("historyItems");
var um =
Components.classes["@mozilla.org/updates/update-manager;1"].
getService(Components.interfaces.nsIUpdateManager);
var uc = um.updateCount;
if (uc) {
while (this._view.hasChildNodes())
this._view.removeChild(this._view.firstChild);
var bundle = document.getElementById("updateBundle");
for (var i = 0; i < uc; ++i) {
var update = um.getUpdateAt(i);
if (!update || !update.name)
continue;
// Don't display updates that are downloading since they don't have
// valid statusText for the UI (bug 485493).
if (!update.statusText)
continue;
var element = document.createElementNS(NS_XUL, "update");
this._view.appendChild(element);
element.name = bundle.getFormattedString("updateFullName",
[update.name, update.buildID]);
element.type = bundle.getString("updateType_" + update.type);
element.installDate = this._formatDate(update.installDate);
if (update.detailsURL)
element.detailsURL = update.detailsURL;
else
element.hideDetailsURL = true;
element.status = update.statusText;
}
}
var cancelbutton = document.documentElement.getButton("cancel");
cancelbutton.focus();
},
/**
* Formats a date into human readable form
* @param seconds
* A date in seconds since 1970 epoch
* @returns A human readable date string
*/
_formatDate: function(seconds) {
var date = new Date(seconds);
const locale = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
.getService(Components.interfaces.nsIXULChromeRegistry)
.getSelectedLocale("global", true);
const dtOptions = { year: 'numeric', month: 'long', day: 'numeric',
hour: 'numeric', minute: 'numeric', second: 'numeric' };
return date.toLocaleString(locale, dtOptions);
}
};

View file

@ -0,0 +1,39 @@
<?xml version="1.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/. -->
<!DOCTYPE dialog [
<!ENTITY % historyDTD SYSTEM "chrome://mozapps/locale/update/history.dtd">
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
%historyDTD;
%brandDTD;
]>
<?xml-stylesheet href="chrome://global/skin/"?>
<?xml-stylesheet href="chrome://mozapps/content/update/updates.css"?>
<?xml-stylesheet href="chrome://mozapps/skin/update/updates.css"?>
<dialog id="history" windowtype="Update:History"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
style="width: 35em;"
buttons="cancel"
defaultButton="cancel"
buttonlabelcancel="&closebutton.label;"
title="&history.title;"
onload="gUpdateHistory.onLoad();">
<script type="application/javascript"
src="chrome://mozapps/content/update/history.js"/>
<stringbundle id="updateBundle"
src="chrome://mozapps/locale/update/updates.properties"/>
<label>&history.intro;</label>
<separator class="thin"/>
<richlistbox id="historyItems" flex="1">
<label>&noupdates.label;</label>
</richlistbox>
<separator class="thin"/>
</dialog>

View file

@ -0,0 +1,33 @@
/* Stop animations on pages that aren't on the current page (bug 341749). */
#updates:not([currentpageid="checking"]) #checkingProgress,
#updates:not([currentpageid="downloading"]) #downloadProgress {
display: none;
}
/* Hide the wizard's header so the size of the billboard can size the window
on creation. A custom header will be used in its place when a header is
needed. */
.wizard-header {
display: none;
}
/* Display the custom header */
.update-header {
display: -moz-box !important;
}
/* Custom header implementation based on the Wizard's header. This allows the
size of the billboard's remotecontent to size the window since it does not
have an updateheader on the billboard page. */
updateheader {
-moz-binding: url("chrome://mozapps/content/update/updates.xml#updateheader");
display: -moz-box;
-moz-box-orient: horizontal;
}
/* Update History Window */
update {
-moz-binding: url("chrome://mozapps/content/update/updates.xml#update");
display: -moz-box;
-moz-box-orient: vertical;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,83 @@
<?xml version="1.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/. -->
<!DOCTYPE bindings SYSTEM "chrome://mozapps/locale/update/updates.dtd">
<bindings id="updatesBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="updateheader" extends="chrome://global/content/bindings/wizard.xml#wizard-header">
<resources>
<stylesheet src="chrome://global/skin/wizard.css"/>
</resources>
<content>
<xul:hbox class="wizard-header update-header" flex="1">
<xul:vbox class="wizard-header-box-1">
<xul:vbox class="wizard-header-box-text">
<xul:label class="wizard-header-label" xbl:inherits="value=label"/>
</xul:vbox>
</xul:vbox>
</xul:hbox>
</content>
</binding>
<binding id="update" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
<content>
<xul:hbox>
<xul:label class="update-name" xbl:inherits="value=name" flex="1" crop="right"/>
<xul:label xbl:inherits="href=detailsURL,hidden=hideDetailsURL" class="text-link"
value="&update.details.label;"/>
</xul:hbox>
<xul:label class="update-type" xbl:inherits="value=type"/>
<xul:grid>
<xul:columns>
<xul:column class="update-label-column"/>
<xul:column flex="1"/>
</xul:columns>
<xul:rows>
<xul:row>
<xul:label class="update-installedOn-label">&update.installedOn.label;</xul:label>
<xul:label class="update-installedOn-value" xbl:inherits="value=installDate" flex="1" crop="right"/>
</xul:row>
<xul:row>
<xul:label class="update-status-label">&update.status.label;</xul:label>
<xul:description class="update-status-value" flex="1"/>
</xul:row>
</xul:rows>
</xul:grid>
</content>
<implementation>
<property name="name"
onget="return this.getAttribute('name');"
onset="this.setAttribute('name', val); return val;"/>
<property name="detailsURL"
onget="return this.getAttribute('detailsURL');"
onset="this.setAttribute('detailsURL', val); return val;"/>
<property name="installDate"
onget="return this.getAttribute('installDate');"
onset="this.setAttribute('installDate', val); return val;"/>
<property name="type"
onget="return this.getAttribute('type');"
onset="this.setAttribute('type', val); return val;"/>
<property name="hideDetailsURL"
onget="return this.getAttribute('hideDetailsURL');"
onset="this.setAttribute('hideDetailsURL', val); return val;"/>
<property name="status"
onget="return this.getAttribute('status');">
<setter><![CDATA[
this.setAttribute("status", val);
var field = document.getAnonymousElementByAttribute(this, "class", "update-status-value");
while (field.hasChildNodes())
field.removeChild(field.firstChild);
field.appendChild(document.createTextNode(val));
return val;
]]></setter>
</property>
</implementation>
</binding>
</bindings>

View file

@ -0,0 +1,206 @@
<?xml version="1.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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://mozapps/content/update/updates.css"?>
<?xml-stylesheet href="chrome://mozapps/skin/update/updates.css"?>
<!DOCTYPE wizard [
<!ENTITY % updateDTD SYSTEM "chrome://mozapps/locale/update/updates.dtd">
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
%updateDTD;
%brandDTD;
]>
<wizard id="updates"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&updateWizard.title;"
windowtype="Update:Wizard"
style="width: auto; height: auto"
onwizardfinish="gUpdates.onWizardFinish();"
onwizardcancel="gUpdates.onWizardCancel();"
onwizardnext="gUpdates.onWizardNext();"
onload="gUpdates.onLoad();"
onunload="gUpdates.onUnload();">
<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
<script type="application/javascript" src="chrome://mozapps/content/update/updates.js"/>
<stringbundleset id="updateSet">
<stringbundle id="brandStrings" src="chrome://branding/locale/brand.properties"/>
<stringbundle id="updateStrings" src="chrome://mozapps/locale/update/updates.properties"/>
</stringbundleset>
<wizardpage id="dummy" pageid="dummy" firstpage="true"/>
<wizardpage id="checking" pageid="checking" next="noupdatesfound"
object="gCheckingPage" onpageshow="gCheckingPage.onPageShow();">
<updateheader label="&checking.title;"/>
<vbox class="update-content" flex="1">
<label>&updateCheck.label;</label>
<separator class="thin"/>
<progressmeter id="checkingProgress" mode="undetermined"/>
</vbox>
</wizardpage>
<wizardpage id="noupdatesfound" pageid="noupdatesfound"
object="gNoUpdatesPage" onpageshow="gNoUpdatesPage.onPageShow();">
<updateheader label="&noupdatesfound.title;"/>
<vbox class="update-content" flex="1">
<label id="noUpdatesAutoEnabled" hidden="true">&noupdatesautoenabled.intro;</label>
<label id="noUpdatesAutoDisabled" hidden="true">&noupdatesautodisabled.intro;</label>
</vbox>
</wizardpage>
<wizardpage id="manualUpdate" pageid="manualUpdate" object="gManualUpdatePage"
onpageshow="gManualUpdatePage.onPageShow();">
<updateheader label="&manualUpdate.title;"/>
<vbox class="update-content" flex="1">
<label id="manualUpdateDesc">&manualUpdate.desc;</label>
<label id="manualUpdateSpaceDesc"
hidden="true">&manualUpdate.space.desc;</label>
<separator class="thin"/>
<label>&manualUpdateGetMsg.label;</label>
<hbox>
<label class="text-link" id="manualUpdateLinkLabel" value=""
onclick="openUpdateURL(event);"/>
</hbox>
</vbox>
</wizardpage>
<wizardpage id="unsupported" pageid="unsupported"
object="gUnsupportedPage"
onpageshow="gUnsupportedPage.onPageShow();">
<updateheader label="&unsupported.title;"/>
<vbox class="update-content" flex="1">
<description flex="1">&unsupported.label;
<label id="unsupportedLinkLabel" class="text-link inline-link" onclick="openUpdateURL(event);">
&unsupportedLink.label;
</label>
</description>
</vbox>
</wizardpage>
<wizardpage id="updatesfoundbasic" pageid="updatesfoundbasic"
object="gUpdatesFoundBasicPage" next="downloading"
onpageshow="gUpdatesFoundBasicPage.onPageShow();"
onextra1="gUpdatesFoundBasicPage.onExtra1();"
onextra2="gUpdatesFoundBasicPage.onExtra2();">
<updateheader id="updatesFoundBasicHeader" label=""/>
<vbox class="update-content" flex="1">
<label id="updatesFoundInto"/>
<separator class="thin"/>
<label id="updateName" crop="right" value=""/>
<separator id="updateNameSep" class="thin"/>
<label id="upgradeEvangelism">&evangelism.desc;</label>
<separator id="upgradeEvangelismSep" flex="1"/>
<vbox flex="1">
<hbox id="moreInfoURL">
<label class="text-link" id="updateMoreInfoURL"
value="&clickHere.label;" onclick="openUpdateURL(event);"/>
</hbox>
</vbox>
</vbox>
</wizardpage>
<wizardpage id="downloading" pageid="downloading"
object="gDownloadingPage" onextra1="gDownloadingPage.onHide();"
onpageshow="gDownloadingPage.onPageShow();">
<updateheader label="&downloadPage.title;"/>
<vbox class="update-content" flex="1">
<hbox id="downloadStatusProgress">
<progressmeter id="downloadProgress" mode="undetermined" flex="1"/>
<button id="pauseButton" oncommand="gDownloadingPage.onPause();"
paused="false"/>
</hbox>
<separator class="thin"/>
<hbox id="downloadStatusLine">
<label id="downloadStatus" flex="1">&connecting.label;</label>
</hbox>
<separator/>
<hbox id="verificationFailed" align="start" hidden="true">
<image id="verificationFailedIcon"/>
<label flex="1">&verificationFailedText.label;</label>
</hbox>
</vbox>
</wizardpage>
<wizardpage id="errors" pageid="errors" object="gErrorsPage"
onpageshow="gErrorsPage.onPageShow();">
<updateheader label="&error.title;"/>
<vbox class="update-content" flex="1">
<label id="errorIntro">&error.label;</label>
<separator/>
<textbox class="plain" readonly="true" id="errorReason" multiline="true"
rows="3"/>
<separator/>
<label id="errorManual">&errorManual.label;</label>
<hbox>
<label class="text-link" id="errorLinkLabel" value=""
onclick="openUpdateURL(event);"/>
</hbox>
</vbox>
</wizardpage>
<wizardpage id="errorextra" pageid="errorextra"
object="gErrorExtraPage"
onpageshow="gErrorExtraPage.onPageShow();">
<updateheader label="&error.title;"/>
<vbox class="update-content" flex="1">
<label id="bgErrorLabel">&genericBackgroundError.label;</label>
<hbox>
<label id="errorExtraLinkLabel" class="text-link"
value="" onclick="openUpdateURL(event);"/>
</hbox>
</vbox>
</wizardpage>
<wizardpage id="errorpatching" pageid="errorpatching" next="downloading"
object="gErrorPatchingPage"
onpageshow="gErrorPatchingPage.onPageShow();">
<updateheader label="&error.title;"/>
<vbox class="update-content" flex="1">
<label>&errorpatching.intro;</label>
</vbox>
</wizardpage>
<wizardpage id="finished" pageid="finished" object="gFinishedPage"
onpageshow="gFinishedPage.onPageShow();"
onextra1="gFinishedPage.onExtra1()">
<updateheader label="&finishedPage.title;"/>
<vbox class="update-content" flex="1">
<label>&finishedPage.text;</label>
</vbox>
</wizardpage>
<wizardpage id="finishedBackground" pageid="finishedBackground"
object="gFinishedPage" onextra1="gFinishedPage.onExtra1()"
onextra2="gFinishedPage.onExtra2()"
onpageshow="gFinishedPage.onPageShowBackground();">
<updateheader label="&finishedPage.title;"/>
<vbox class="update-content" flex="1">
<label>&finishedBackgroundPage.text;</label>
<separator/>
<hbox align="center">
<label>&finishedBackground.name;</label>
<label id="updateFinishedName" flex="1" crop="right" value=""/>
<label id="finishedBackgroundLink" class="text-link" disabled="true"
value="&details.link;" onclick="openUpdateURL(event);"/>
</hbox>
<spacer flex="1"/>
<label id="finishedBackgroundMore">&finishedBackground.more;</label>
<label id="finishedBackgroundMoreElevated"
hidden="true">&finishedBackground.moreElevated;</label>
<label id="finishedBackgroundMoreElevatedLink"
hidden="true">&errorManual.label;</label>
<hbox>
<label class="text-link" id="finishedBackgroundMoreElevatedLinkLabel"
value="" onclick="openUpdateURL(event);" hidden="true"/>
</hbox>
</vbox>
</wizardpage>
</wizard>

View file

@ -0,0 +1,12 @@
# 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/.
toolkit.jar:
% content mozapps %content/mozapps/
content/mozapps/update/history.xul (content/history.xul)
content/mozapps/update/history.js (content/history.js)
content/mozapps/update/updates.css (content/updates.css)
content/mozapps/update/updates.js (content/updates.js)
content/mozapps/update/updates.xml (content/updates.xml)
content/mozapps/update/updates.xul (content/updates.xul)

View file

@ -0,0 +1,33 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
XPIDL_MODULE = 'update'
DIRS += [
'common',
'updater',
]
XPIDL_SOURCES += [
'nsIUpdateService.idl',
]
TEST_DIRS += ['tests']
EXTRA_COMPONENTS += [
'nsUpdateService.js',
'nsUpdateService.manifest',
'nsUpdateServiceStub.js',
]
EXTRA_JS_MODULES += [
'UpdateTelemetry.jsm',
]
JAR_MANIFESTS += ['jar.mn']
with Files('**'):
BUG_COMPONENT = ('Toolkit', 'Application Update')

View file

@ -0,0 +1,575 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "nsISupports.idl"
interface nsIDOMDocument;
interface nsIDOMElement;
interface nsIDOMWindow;
interface nsIRequest;
interface nsIRequestObserver;
interface nsISimpleEnumerator;
interface nsIFile;
/**
* An interface that describes an object representing a patch file that can
* be downloaded and applied to a version of this application so that it
* can be updated.
*/
[scriptable, uuid(dc8fb8a9-3a53-4031-9469-2a5197ea30e7)]
interface nsIUpdatePatch : nsISupports
{
/**
* The type of this patch:
* "partial" A binary difference between two application versions
* "complete" A complete patch containing all of the replacement files
* to update to the new version
*/
attribute AString type;
/**
* The URL this patch was being downloaded from
*/
attribute AString URL;
/**
* The final URL this patch was being downloaded from
*/
attribute AString finalURL;
/**
* The hash function to use when determining this file's integrity
*/
attribute AString hashFunction;
/**
* The value of the hash function named above that should be computed if
* this file is not corrupt.
*/
attribute AString hashValue;
/**
* The size of this file, in bytes.
*/
attribute unsigned long size;
/**
* The state of this patch
*/
attribute AString state;
/**
* true if this patch is currently selected as the patch to be downloaded and
* installed for this update transaction, false if another patch from this
* update has been selected.
*/
attribute boolean selected;
/**
* Serializes this patch object into a DOM Element
* @param updates
* The document to serialize into
* @returns The DOM Element created by the serialization process
*/
nsIDOMElement serialize(in nsIDOMDocument updates);
};
/**
* An interface that describes an object representing an available update to
* the current application - this update may have several available patches
* from which one must be selected to download and install, for example we
* might select a binary difference patch first and attempt to apply that,
* then if the application process fails fall back to downloading a complete
* file-replace patch. This object also contains information about the update
* that the front end and other application services can use to learn more
* about what is going on.
*/
[scriptable, uuid(e094c045-f4ff-41fd-92da-cd2effd2c7c9)]
interface nsIUpdate : nsISupports
{
/**
* The type of update:
* "major" A major new version of the Application
* "minor" A minor update to the Application (e.g. security update)
*/
attribute AString type;
/**
* The name of the update, or "<Application Name> <Update Version>"
*/
attribute AString name;
/**
* The string to display in the user interface for the version. If you want
* a real version number use appVersion.
*/
attribute AString displayVersion;
/**
* The Application version of this update.
*/
attribute AString appVersion;
/**
* The Application version prior to the application being updated.
*/
attribute AString previousAppVersion;
/**
* The Build ID of this update. Used to determine a particular build, down
* to the hour, minute and second of its creation. This allows the system
* to differentiate between several nightly builds with the same |version|
* for example.
*/
attribute AString buildID;
/**
* The URL to a page which offers details about the content of this
* update. Ideally, this page is not the release notes but some other page
* that summarizes the differences between this update and the previous,
* which also links to the release notes.
*/
attribute AString detailsURL;
/**
* The URL to the Update Service that supplied this update.
*/
attribute AString serviceURL;
/**
* The channel used to retrieve this update from the Update Service.
*/
attribute AString channel;
/**
* Whether to show the update prompt which requires user confirmation when an
* update is found during a background update check. This overrides the
* default setting to download the update in the background.
*/
attribute boolean showPrompt;
/**
* Whether to show the "No Thanks" button in the update prompt. This allows
* the user to never receive a notification for that specific update version
* again.
*/
attribute boolean showNeverForVersion;
/**
* Whether the update is no longer supported on this system.
*/
attribute boolean unsupported;
/**
* Allows overriding the default amount of time in seconds before prompting the
* user to apply an update. If not specified, the value of
* app.update.promptWaitTime will be used.
*/
attribute long long promptWaitTime;
/**
* Whether or not the update being downloaded is a complete replacement of
* the user's existing installation or a patch representing the difference
* between the new version and the previous version.
*/
attribute boolean isCompleteUpdate;
/**
* Whether or not the update is a security update or not. If this is true,
* then we present more serious sounding user interface messages to the
* user.
*/
attribute boolean isSecurityUpdate;
/**
* Whether or not the update being downloaded is an OS update. This is
* generally only possible in Gonk right now.
*/
attribute boolean isOSUpdate;
/**
* When the update was installed.
*/
attribute long long installDate;
/**
* A message associated with this update, if any.
*/
attribute AString statusText;
/**
* The currently selected patch for this update.
*/
readonly attribute nsIUpdatePatch selectedPatch;
/**
* The state of the selected patch:
* "downloading" The update is being downloaded.
* "pending" The update is ready to be applied.
* "pending-service" The update is ready to be applied with the service.
* "pending-elevate" The update is ready to be applied but requires elevation.
* "applying" The update is being applied.
* "applied" The update is ready to be switched to.
* "applied-os" The update is OS update and to be installed.
* "applied-service" The update is ready to be switched to with the service.
* "succeeded" The update was successfully applied.
* "download-failed" The update failed to be downloaded.
* "failed" The update failed to be applied.
*/
attribute AString state;
/**
* A numeric error code that conveys additional information about the state
* of a failed update or failed certificate attribute check during an update
* check. If the update is not in the "failed" state or the certificate
* attribute check has not failed the value is zero.
*
* TODO: Define typical error codes (for now, see updater/errors.h and the
* CERT_ATTR_CHECK_FAILED_* values in nsUpdateService.js)
*/
attribute long errorCode;
/**
* Whether an elevation failure has been encountered for this update.
*/
attribute boolean elevationFailure;
/**
* The number of patches supplied by this update.
*/
readonly attribute unsigned long patchCount;
/**
* Retrieves a patch.
* @param index
* The index of the patch to retrieve.
* @returns The nsIUpdatePatch at the specified index.
*/
nsIUpdatePatch getPatchAt(in unsigned long index);
/**
* Serializes this update object into a DOM Element
* @param updates
* The document to serialize into
* @returns The DOM Element created by the serialization process
*/
nsIDOMElement serialize(in nsIDOMDocument updates);
};
/**
* An interface describing an object that listens to the progress of an update
* check operation. This object is notified as the check continues, finishes
* and if it has an error.
*/
[scriptable, uuid(4aa2b4bb-39ea-407b-98ff-89f19134d4c0)]
interface nsIUpdateCheckListener : nsISupports
{
/**
* The update check was completed.
* @param request
* The XMLHttpRequest handling the update check.
* @param updates
* An array of nsIUpdate objects listing available updates.
* @param updateCount
* The size of the |updates| array.
*/
void onCheckComplete(in jsval request,
[array, size_is(updateCount)] in nsIUpdate updates,
in unsigned long updateCount);
/**
* An error occurred while loading the remote update service file.
* @param request
* The XMLHttpRequest handling the update check.
* @param update
* A nsIUpdate object that contains details about the
* error in its |statusText| property.
*/
void onError(in jsval request,
in nsIUpdate update);
};
/**
* An interface describing an object that knows how to check for updates.
*/
[scriptable, uuid(877ace25-8bc5-452a-8586-9c1cf2871994)]
interface nsIUpdateChecker : nsISupports
{
/**
* Checks for available updates, notifying a listener of the results.
* @param listener
* An object implementing nsIUpdateCheckListener which is notified
* of the results of an update check.
* @param force
* Forces the checker to check for updates, regardless of the
* current value of the user's update settings. This is used by
* any piece of UI that offers the user the imperative option to
* check for updates now, regardless of their update settings.
* force will not work if the system administrator has locked
* the app.update.enabled preference.
*/
void checkForUpdates(in nsIUpdateCheckListener listener, in boolean force);
/**
* Constants for the |stopChecking| function that tell the Checker how long
* to stop checking:
*
* CURRENT_CHECK: Stops the current (active) check only
* CURRENT_SESSION: Stops all checking for the current session
* ANY_CHECKS: Stops all checking, any session from now on
* (disables update checking preferences)
*/
const unsigned short CURRENT_CHECK = 1;
const unsigned short CURRENT_SESSION = 2;
const unsigned short ANY_CHECKS = 3;
/**
* Ends any pending update check.
* @param duration
* A value representing the set of checks to stop doing.
*/
void stopChecking(in unsigned short duration);
};
/**
* An interface describing a global application service that handles performing
* background update checks and provides utilities for selecting and
* downloading update patches.
*/
[scriptable, uuid(1107d207-a263-403a-b268-05772ec10757)]
interface nsIApplicationUpdateService : nsISupports
{
/**
* Checks for available updates in the background using the listener provided
* by the application update service for background checks.
*/
void checkForBackgroundUpdates();
/**
* The Update Checker used for background update checking.
*/
readonly attribute nsIUpdateChecker backgroundChecker;
/**
* Selects the best update to install from a list of available updates.
* @param updates
* An array of updates that are available
* @param updateCount
* The length of the |updates| array
*/
nsIUpdate selectUpdate([array, size_is(updateCount)] in nsIUpdate updates,
in unsigned long updateCount);
/**
* Adds a listener that receives progress and state information about the
* update that is currently being downloaded, e.g. to update a user
* interface.
* @param listener
* An object implementing nsIRequestObserver and optionally
* nsIProgressEventSink that is to be notified of state and
* progress information as the update is downloaded.
*/
void addDownloadListener(in nsIRequestObserver listener);
/**
* Removes a listener that is receiving progress and state information
* about the update that is currently being downloaded.
* @param listener
* The listener object to remove.
*/
void removeDownloadListener(in nsIRequestObserver listener);
/**
*
*/
AString downloadUpdate(in nsIUpdate update, in boolean background);
/**
* Apply the OS update which has been downloaded and staged as applied.
* @param update
* The update has been downloaded and staged as applied.
* @throws if the update object is not an OS update.
*/
void applyOsUpdate(in nsIUpdate update);
/**
* Get the Active Updates directory
* @returns An nsIFile for the active updates directory.
*/
nsIFile getUpdatesDirectory();
/**
* Pauses the active update download process
*/
void pauseDownload();
/**
* Whether or not there is an download happening at the moment.
*/
readonly attribute boolean isDownloading;
/**
* Whether or not the Update Service can check for updates. This is a function
* of whether or not application update is disabled by the application and the
* platform the application is running on.
*/
readonly attribute boolean canCheckForUpdates;
/**
* Whether or not the installation requires elevation. Currently only
* implemented on OSX, returns false on other platforms.
*/
readonly attribute boolean elevationRequired;
/**
* Whether or not the Update Service can download and install updates.
* On Windows, this is a function of whether or not the maintenance service
* is installed and enabled. On other systems, and as a fallback on Windows,
* this depends on whether the current user has write access to the install
* directory.
*/
readonly attribute boolean canApplyUpdates;
/**
* Whether or not a different instance is handling updates of this
* installation. This currently only ever returns true on Windows
* when 2 instances of an application are open. Only one of the instances
* will actually handle updates for the installation.
*/
readonly attribute boolean isOtherInstanceHandlingUpdates;
/**
* Whether the Update Service is able to stage updates.
*/
readonly attribute boolean canStageUpdates;
};
/**
* An interface describing a component which handles the job of processing
* an update after it's been downloaded.
*/
[scriptable, uuid(74439497-d796-4915-8cef-3dfe43027e4d)]
interface nsIUpdateProcessor : nsISupports
{
/**
* Processes the update which has been downloaded.
* This happens without restarting the application.
* On Windows, this can also be used for switching to an applied
* update request.
* @param update The update being applied, or null if this is a switch
* to updated application request. Must be non-null on GONK.
*/
void processUpdate(in nsIUpdate update);
};
/**
* An interface describing a global application service that maintains a list
* of updates previously performed as well as the current active update.
*/
[scriptable, uuid(0f1098e9-a447-4af9-b030-6f8f35c85f89)]
interface nsIUpdateManager : nsISupports
{
/**
* Gets the update at the specified index
* @param index
* The index within the updates array
* @returns The nsIUpdate object at the specified index
*/
nsIUpdate getUpdateAt(in long index);
/**
* Gets the total number of updates in the history list.
*/
readonly attribute long updateCount;
/**
* The active (current) update. The active update is not in the history list.
*/
attribute nsIUpdate activeUpdate;
/**
* Saves all updates to disk.
*/
void saveUpdates();
/**
* Refresh the update status based on the information in update.status.
*/
void refreshUpdateStatus();
/**
* The user agreed to proceed with an elevated update and we are now
* permitted to show an elevation prompt.
*/
void elevationOptedIn();
/**
* Clean up and remove the active update without applying it.
*/
void cleanupActiveUpdate();
};
/**
* An interface describing an object that can show various kinds of Update
* notification UI to the user.
*/
[scriptable, uuid(cee3bd60-c564-42ff-a2bf-d442cb15f75c)]
interface nsIUpdatePrompt : nsISupports
{
/**
* Shows the application update checking user interface and checks if there
* is an update available.
*/
void checkForUpdates();
/**
* Shows the application update available user interface advising that an
* update is available for download and install. If the app.update.silent
* preference is true or the user interface is already displayed the call will
* be a no-op.
* @param update
* The nsIUpdate object to be downloaded and installed
*/
void showUpdateAvailable(in nsIUpdate update);
/**
* Shows the application update downloaded user interface advising that an
* update has now been downloaded and a restart is necessary to complete the
* update. If background is true (e.g. the download was not user initiated)
* and the app.update.silent preference is true the call will be a no-op.
* @param update
* The nsIUpdate object that was downloaded
* @param background
* Less obtrusive UI, starting with a non-modal notification alert
*/
void showUpdateDownloaded(in nsIUpdate update,
[optional] in boolean background);
/**
* Shows the application update error user interface advising that an error
* occurred while checking for or applying an update. If the app.update.silent
* preference is true the call will be a no-op.
* @param update
* An nsIUpdate object representing the update that could not be
* installed. The nsIUpdate object will not be the actual update when
* the error occurred during an update check and will instead be an
* nsIUpdate object with the error information for the update check.
*/
void showUpdateError(in nsIUpdate update);
/**
* Shows a list of all updates installed to date.
* @param parent
* An nsIDOMWindow to set as the parent for this window. Can be null.
*/
void showUpdateHistory(in nsIDOMWindow parent);
/**
* Shows the application update downloaded user interface advising that an
* update, which requires elevation, has now been downloaded and a restart is
* necessary to complete the update.
*/
void showUpdateElevationRequired();
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
component {B3C290A6-3943-4B89-8BBE-C01EB7B3B311} nsUpdateService.js
contract @mozilla.org/updates/update-service;1 {B3C290A6-3943-4B89-8BBE-C01EB7B3B311}
category update-timer nsUpdateService @mozilla.org/updates/update-service;1,getService,background-update-timer,app.update.interval,43200,86400
component {093C2356-4843-4C65-8709-D7DBCBBE7DFB} nsUpdateService.js
contract @mozilla.org/updates/update-manager;1 {093C2356-4843-4C65-8709-D7DBCBBE7DFB}
component {898CDC9B-E43F-422F-9CC4-2F6291B415A3} nsUpdateService.js
contract @mozilla.org/updates/update-checker;1 {898CDC9B-E43F-422F-9CC4-2F6291B415A3}
component {27ABA825-35B5-4018-9FDD-F99250A0E722} nsUpdateService.js
contract @mozilla.org/updates/update-prompt;1 {27ABA825-35B5-4018-9FDD-F99250A0E722}
component {e43b0010-04ba-4da6-b523-1f92580bc150} nsUpdateServiceStub.js
contract @mozilla.org/updates/update-service-stub;1 {e43b0010-04ba-4da6-b523-1f92580bc150}
category profile-after-change nsUpdateServiceStub @mozilla.org/updates/update-service-stub;1

View file

@ -0,0 +1,45 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* 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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
Cu.import("resource://gre/modules/FileUtils.jsm", this);
const DIR_UPDATES = "updates";
const FILE_UPDATE_STATUS = "update.status";
const KEY_UPDROOT = "UpdRootD";
/**
* Gets the specified directory at the specified hierarchy under the update root
* directory without creating it if it doesn't exist.
* @param pathArray
* An array of path components to locate beneath the directory
* specified by |key|
* @return nsIFile object for the location specified.
*/
function getUpdateDirNoCreate(pathArray) {
return FileUtils.getDir(KEY_UPDROOT, pathArray, false);
}
function UpdateServiceStub() {
let statusFile = getUpdateDirNoCreate([DIR_UPDATES, "0"]);
statusFile.append(FILE_UPDATE_STATUS);
// If the update.status file exists then initiate post update processing.
if (statusFile.exists()) {
let aus = Cc["@mozilla.org/updates/update-service;1"].
getService(Ci.nsIApplicationUpdateService).
QueryInterface(Ci.nsIObserver);
aus.observe(null, "post-update-processing", "");
}
}
UpdateServiceStub.prototype = {
observe: function() {},
classID: Components.ID("{e43b0010-04ba-4da6-b523-1f92580bc150}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([UpdateServiceStub]);

View file

@ -0,0 +1,39 @@
# 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/.
XPCSHELLTESTROOT = $(topobjdir)/_tests/xpcshell/$(relativesrcdir)
pp_const_file = $(srcdir)/data/xpcshellConstantsPP.js
PP_TARGETS += aus-test-const
aus-test-const := $(pp_const_file)
aus-test-const_PATH := $(XPCSHELLTESTROOT)/data
aus-test-const_FLAGS := -Fsubstitution $(DEFINES) $(ACDEFINES)
aus-test-const_TARGET := misc
INI_TEST_FILES = \
TestAUSReadStrings1.ini \
TestAUSReadStrings2.ini \
TestAUSReadStrings3.ini \
$(NULL)
MOZ_WINCONSOLE = 1
include $(topsrcdir)/config/rules.mk
# TestAUSReadStrings runs during check in the following directory with a Unicode
# char in order to test bug 473417 on Windows.
ifeq ($(OS_ARCH),WINNT)
bug473417dir = test_bug473417-ó
else
bug473417dir = test_bug473417
endif
check::
$(RM) -rf $(DEPTH)/_tests/updater/ && $(NSINSTALL) -D $(DEPTH)/_tests/updater/$(bug473417dir)/
for i in $(INI_TEST_FILES); do \
$(INSTALL) $(srcdir)/$$i $(DEPTH)/_tests/updater/$(bug473417dir)/; \
done
$(INSTALL) $(FINAL_TARGET)/TestAUSReadStrings$(BIN_SUFFIX) $(DEPTH)/_tests/updater/$(bug473417dir)/
@$(RUN_TEST_PROGRAM) $(DEPTH)/_tests/updater/$(bug473417dir)/TestAUSReadStrings$(BIN_SUFFIX)

View file

@ -0,0 +1,423 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifdef XP_WIN
# include <windows.h>
# include <wintrust.h>
# include <tlhelp32.h>
# include <softpub.h>
# include <direct.h>
# include <io.h>
typedef WCHAR NS_tchar;
# define NS_main wmain
# ifndef F_OK
# define F_OK 00
# endif
# ifndef W_OK
# define W_OK 02
# endif
# ifndef R_OK
# define R_OK 04
# endif
# if defined(_MSC_VER) && _MSC_VER < 1900
# define stat _stat
# endif
# define NS_T(str) L ## str
# define NS_tsnprintf(dest, count, fmt, ...) \
{ \
int _count = count - 1; \
_snwprintf(dest, _count, fmt, ##__VA_ARGS__); \
dest[_count] = L'\0'; \
}
# define NS_taccess _waccess
# define NS_tchdir _wchdir
# define NS_tfopen _wfopen
# define NS_tstrcmp wcscmp
# define NS_ttoi _wtoi
# define NS_tstat _wstat
# define NS_tgetcwd _wgetcwd
# define LOG_S "%S"
#include "../common/updatehelper.h"
#include "../common/certificatecheck.h"
#else
# include <unistd.h>
# define NS_main main
typedef char NS_tchar;
# define NS_T(str) str
# define NS_tsnprintf snprintf
# define NS_taccess access
# define NS_tchdir chdir
# define NS_tfopen fopen
# define NS_tstrcmp strcmp
# define NS_ttoi atoi
# define NS_tstat stat
# define NS_tgetcwd getcwd
# define NS_tfputs fputs
# define LOG_S "%s"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef MAXPATHLEN
# ifdef PATH_MAX
# define MAXPATHLEN PATH_MAX
# elif defined(MAX_PATH)
# define MAXPATHLEN MAX_PATH
# elif defined(_MAX_PATH)
# define MAXPATHLEN _MAX_PATH
# elif defined(CCHMAXPATH)
# define MAXPATHLEN CCHMAXPATH
# else
# define MAXPATHLEN 1024
# endif
#endif
static void
WriteMsg(const NS_tchar *path, const char *status)
{
FILE* outFP = NS_tfopen(path, NS_T("wb"));
if (!outFP) {
return;
}
fprintf(outFP, "%s\n", status);
fclose(outFP);
outFP = nullptr;
}
static bool
CheckMsg(const NS_tchar *path, const char *expected)
{
if (NS_taccess(path, F_OK)) {
return false;
}
FILE *inFP = NS_tfopen(path, NS_T("rb"));
if (!inFP) {
return false;
}
struct stat ms;
if (fstat(fileno(inFP), &ms)) {
fclose(inFP);
inFP = nullptr;
return false;
}
char *mbuf = (char *) malloc(ms.st_size + 1);
if (!mbuf) {
fclose(inFP);
inFP = nullptr;
return false;
}
size_t r = ms.st_size;
char *rb = mbuf;
size_t c = fread(rb, sizeof(char), 50, inFP);
r -= c;
rb += c;
if (c == 0 && r) {
free(mbuf);
fclose(inFP);
inFP = nullptr;
return false;
}
mbuf[ms.st_size] = '\0';
rb = mbuf;
bool isMatch = strcmp(rb, expected) == 0;
free(mbuf);
fclose(inFP);
inFP = nullptr;
return isMatch;
}
int NS_main(int argc, NS_tchar **argv)
{
if (argc == 2) {
if (!NS_tstrcmp(argv[1], NS_T("post-update-async")) ||
!NS_tstrcmp(argv[1], NS_T("post-update-sync"))) {
NS_tchar exePath[MAXPATHLEN];
#ifdef XP_WIN
if (!::GetModuleFileNameW(0, exePath, MAXPATHLEN)) {
return 1;
}
#else
strcpy(exePath, argv[0]);
#endif
NS_tchar runFilePath[MAXPATHLEN];
NS_tsnprintf(runFilePath, sizeof(runFilePath)/sizeof(runFilePath[0]),
NS_T("%s.running"), exePath);
#ifdef XP_WIN
if (!NS_taccess(runFilePath, F_OK)) {
// This makes it possible to check if the post update process was
// launched twice which happens when the service performs an update.
NS_tchar runFilePathBak[MAXPATHLEN];
NS_tsnprintf(runFilePathBak, sizeof(runFilePathBak)/sizeof(runFilePathBak[0]),
NS_T("%s.bak"), runFilePath);
MoveFileExW(runFilePath, runFilePathBak, MOVEFILE_REPLACE_EXISTING);
}
#endif
WriteMsg(runFilePath, "running");
if (!NS_tstrcmp(argv[1], NS_T("post-update-sync"))) {
#ifdef XP_WIN
Sleep(2000);
#else
sleep(2);
#endif
}
NS_tchar logFilePath[MAXPATHLEN];
NS_tsnprintf(logFilePath, sizeof(logFilePath)/sizeof(logFilePath[0]),
NS_T("%s.log"), exePath);
WriteMsg(logFilePath, "post-update");
return 0;
}
}
if (argc < 3) {
fprintf(stderr, \
"\n" \
"Application Update Service Test Helper\n" \
"\n" \
"Usage: WORKINGDIR INFILE OUTFILE -s SECONDS [FILETOLOCK]\n" \
" or: WORKINGDIR LOGFILE [ARG2 ARG3...]\n" \
" or: signature-check filepath\n" \
" or: setup-symlink dir1 dir2 file symlink\n" \
" or: remove-symlink dir1 dir2 file symlink\n" \
" or: check-symlink symlink\n" \
" or: post-update\n" \
"\n" \
" WORKINGDIR \tThe relative path to the working directory to use.\n" \
" INFILE \tThe relative path from the working directory for the file to\n" \
" \tread actions to perform such as finish.\n" \
" OUTFILE \tThe relative path from the working directory for the file to\n" \
" \twrite status information.\n" \
" SECONDS \tThe number of seconds to sleep.\n" \
" FILETOLOCK \tThe relative path from the working directory to an existing\n" \
" \tfile to open exlusively.\n" \
" \tOnly available on Windows platforms and silently ignored on\n" \
" \tother platforms.\n" \
" LOGFILE \tThe relative path from the working directory to log the\n" \
" \tcommand line arguments.\n" \
" ARG2 ARG3...\tArguments to write to the LOGFILE after the preceding command\n" \
" \tline arguments.\n" \
"\n" \
"Note: All paths must be relative.\n" \
"\n");
return 1;
}
if (!NS_tstrcmp(argv[1], NS_T("check-signature"))) {
#if defined(XP_WIN) && defined(MOZ_MAINTENANCE_SERVICE)
if (ERROR_SUCCESS == VerifyCertificateTrustForFile(argv[2])) {
return 0;
} else {
return 1;
}
#else
// Not implemented on non-Windows platforms
return 1;
#endif
}
if (!NS_tstrcmp(argv[1], NS_T("setup-symlink"))) {
#ifdef XP_UNIX
NS_tchar path[MAXPATHLEN];
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
mkdir(path, 0755);
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
NS_T("%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3]);
mkdir(path, 0755);
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
NS_T("%s/%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3], argv[4]);
FILE * file = NS_tfopen(path, NS_T("w"));
if (file) {
NS_tfputs(NS_T("test"), file);
fclose(file);
}
if (symlink(path, argv[5]) != 0) {
return 1;
}
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
if (argc > 6 && !NS_tstrcmp(argv[6], NS_T("change-perm"))) {
chmod(path, 0644);
}
return 0;
#else
// Not implemented on non-Unix platforms
return 1;
#endif
}
if (!NS_tstrcmp(argv[1], NS_T("remove-symlink"))) {
#ifdef XP_UNIX
NS_tchar path[MAXPATHLEN];
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
chmod(path, 0755);
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
NS_T("%s/%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3], argv[4]);
unlink(path);
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
NS_T("%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3]);
rmdir(path);
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
rmdir(path);
return 0;
#else
// Not implemented on non-Unix platforms
return 1;
#endif
}
if (!NS_tstrcmp(argv[1], NS_T("check-symlink"))) {
#ifdef XP_UNIX
struct stat ss;
lstat(argv[2], &ss);
return S_ISLNK(ss.st_mode) ? 0 : 1;
#else
// Not implemented on non-Unix platforms
return 1;
#endif
}
if (!NS_tstrcmp(argv[1], NS_T("wait-for-service-stop"))) {
#ifdef XP_WIN
const int maxWaitSeconds = NS_ttoi(argv[3]);
LPCWSTR serviceName = argv[2];
DWORD serviceState = WaitForServiceStop(serviceName, maxWaitSeconds);
if (SERVICE_STOPPED == serviceState) {
return 0;
} else {
return serviceState;
}
#else
// Not implemented on non-Windows platforms
return 1;
#endif
}
if (!NS_tstrcmp(argv[1], NS_T("wait-for-application-exit"))) {
#ifdef XP_WIN
const int maxWaitSeconds = NS_ttoi(argv[3]);
LPCWSTR application = argv[2];
DWORD ret = WaitForProcessExit(application, maxWaitSeconds);
if (ERROR_SUCCESS == ret) {
return 0;
} else if (WAIT_TIMEOUT == ret) {
return 1;
} else {
return 2;
}
#else
// Not implemented on non-Windows platforms
return 1;
#endif
}
if (!NS_tstrcmp(argv[1], NS_T("is-process-running"))) {
#ifdef XP_WIN
LPCWSTR application = argv[2];
return (ERROR_NOT_FOUND == IsProcessRunning(application)) ? 0 : 1;
#else
// Not implemented on non-Windows platforms
return 1;
#endif
}
if (!NS_tstrcmp(argv[1], NS_T("launch-service"))) {
#ifdef XP_WIN
DWORD ret = LaunchServiceSoftwareUpdateCommand(argc - 2, (LPCWSTR *)argv + 2);
if (ret != ERROR_SUCCESS) {
// 192 is used to avoid reusing a possible return value from the call to
// WaitForServiceStop
return 0x000000C0;
}
// Wait a maximum of 120 seconds.
DWORD lastState = WaitForServiceStop(SVC_NAME, 120);
if (SERVICE_STOPPED == lastState) {
return 0;
}
return lastState;
#else
// Not implemented on non-Windows platforms
return 1;
#endif
}
if (NS_tchdir(argv[1]) != 0) {
return 1;
}
// File in use test helper section
if (!NS_tstrcmp(argv[4], NS_T("-s"))) {
NS_tchar *cwd = NS_tgetcwd(nullptr, 0);
NS_tchar inFilePath[MAXPATHLEN];
NS_tsnprintf(inFilePath, sizeof(inFilePath)/sizeof(inFilePath[0]),
NS_T("%s/%s"), cwd, argv[2]);
NS_tchar outFilePath[MAXPATHLEN];
NS_tsnprintf(outFilePath, sizeof(outFilePath)/sizeof(outFilePath[0]),
NS_T("%s/%s"), cwd, argv[3]);
int seconds = NS_ttoi(argv[5]);
#ifdef XP_WIN
HANDLE hFile = INVALID_HANDLE_VALUE;
if (argc == 7) {
hFile = CreateFileW(argv[6],
DELETE | GENERIC_WRITE, 0,
nullptr, OPEN_EXISTING, 0, nullptr);
if (hFile == INVALID_HANDLE_VALUE) {
WriteMsg(outFilePath, "error_locking");
return 1;
}
}
WriteMsg(outFilePath, "sleeping");
int i = 0;
while (!CheckMsg(inFilePath, "finish\n") && i++ <= seconds) {
Sleep(1000);
}
if (argc == 7) {
CloseHandle(hFile);
}
#else
WriteMsg(outFilePath, "sleeping");
int i = 0;
while (!CheckMsg(inFilePath, "finish\n") && i++ <= seconds) {
sleep(1);
}
#endif
WriteMsg(outFilePath, "finished");
return 0;
}
{
// Command line argument test helper section
NS_tchar logFilePath[MAXPATHLEN];
NS_tsnprintf(logFilePath, sizeof(logFilePath)/sizeof(logFilePath[0]),
NS_T("%s"), argv[2]);
FILE* logFP = NS_tfopen(logFilePath, NS_T("wb"));
for (int i = 1; i < argc; ++i) {
fprintf(logFP, LOG_S "\n", argv[i]);
}
fclose(logFP);
logFP = nullptr;
}
return 0;
}

View file

@ -0,0 +1,172 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 binary tests the updater's ReadStrings ini parser and should run in a
* directory with a Unicode character to test bug 473417.
*/
#ifdef XP_WIN
#include <windows.h>
#define NS_main wmain
#define NS_tstrrchr wcsrchr
#define NS_T(str) L ## str
#define PATH_SEPARATOR_CHAR L'\\'
// On Windows, argv[0] can also have forward slashes instead
#define ALT_PATH_SEPARATOR_CHAR L'/'
#else
#include <unistd.h>
#define NS_main main
#define NS_tstrrchr strrchr
#define NS_T(str) str
#define PATH_SEPARATOR_CHAR '/'
#endif
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "updater/resource.h"
#include "updater/progressui.h"
#include "common/readstrings.h"
#include "common/errors.h"
#include "mozilla/ArrayUtils.h"
#ifndef MAXPATHLEN
# ifdef PATH_MAX
# define MAXPATHLEN PATH_MAX
# elif defined(MAX_PATH)
# define MAXPATHLEN MAX_PATH
# elif defined(_MAX_PATH)
# define MAXPATHLEN _MAX_PATH
# elif defined(CCHMAXPATH)
# define MAXPATHLEN CCHMAXPATH
# else
# define MAXPATHLEN 1024
# endif
#endif
#define TEST_NAME "Updater ReadStrings"
using namespace mozilla;
static int gFailCount = 0;
/**
* Prints the given failure message and arguments using printf, prepending
* "TEST-UNEXPECTED-FAIL " for the benefit of the test harness and
* appending "\n" to eliminate having to type it at each call site.
*/
void fail(const char* msg, ...)
{
va_list ap;
printf("TEST-UNEXPECTED-FAIL | ");
va_start(ap, msg);
vprintf(msg, ap);
va_end(ap);
putchar('\n');
++gFailCount;
}
int NS_main(int argc, NS_tchar **argv)
{
printf("Running TestAUSReadStrings tests\n");
int rv = 0;
int retval;
NS_tchar inifile[MAXPATHLEN];
StringTable testStrings;
NS_tchar *slash = NS_tstrrchr(argv[0], PATH_SEPARATOR_CHAR);
#ifdef ALT_PATH_SEPARATOR_CHAR
NS_tchar *altslash = NS_tstrrchr(argv[0], ALT_PATH_SEPARATOR_CHAR);
slash = (slash > altslash) ? slash : altslash;
#endif // ALT_PATH_SEPARATOR_CHAR
if (!slash) {
fail("%s | unable to find platform specific path separator (check 1)", TEST_NAME);
return 20;
}
*(++slash) = '\0';
// Test success when the ini file exists with both Title and Info in the
// Strings section and the values for Title and Info.
NS_tsnprintf(inifile, ArrayLength(inifile), NS_T("%sTestAUSReadStrings1.ini"), argv[0]);
retval = ReadStrings(inifile, &testStrings);
if (retval == OK) {
if (strcmp(testStrings.title, "Title Test - \xD0\x98\xD1\x81\xD0\xBF\xD1\x8B" \
"\xD1\x82\xD0\xB0\xD0\xBD\xD0\xB8\xD0\xB5 " \
"\xCE\x94\xCE\xBF\xCE\xBA\xCE\xB9\xCE\xBC\xCE\xAE " \
"\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88 " \
"\xE6\xB8\xAC\xE8\xA9\xA6 " \
"\xE6\xB5\x8B\xE8\xAF\x95") != 0) {
rv = 21;
fail("%s | Title ini value incorrect (check 3)", TEST_NAME);
}
if (strcmp(testStrings.info, "Info Test - \xD0\x98\xD1\x81\xD0\xBF\xD1\x8B" \
"\xD1\x82\xD0\xB0\xD0\xBD\xD0\xB8\xD0\xB5 " \
"\xCE\x94\xCE\xBF\xCE\xBA\xCE\xB9\xCE\xBC\xCE\xAE " \
"\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88 " \
"\xE6\xB8\xAC\xE8\xA9\xA6 " \
"\xE6\xB5\x8B\xE8\xAF\x95\xE2\x80\xA6") != 0) {
rv = 22;
fail("%s | Info ini value incorrect (check 4)", TEST_NAME);
}
} else {
fail("%s | ReadStrings returned %i (check 2)", TEST_NAME, retval);
rv = 23;
}
// Test failure when the ini file exists without Title and with Info in the
// Strings section.
NS_tsnprintf(inifile, ArrayLength(inifile), NS_T("%sTestAUSReadStrings2.ini"), argv[0]);
retval = ReadStrings(inifile, &testStrings);
if (retval != PARSE_ERROR) {
rv = 24;
fail("%s | ReadStrings returned %i (check 5)", TEST_NAME, retval);
}
// Test failure when the ini file exists with Title and without Info in the
// Strings section.
NS_tsnprintf(inifile, ArrayLength(inifile), NS_T("%sTestAUSReadStrings3.ini"), argv[0]);
retval = ReadStrings(inifile, &testStrings);
if (retval != PARSE_ERROR) {
rv = 25;
fail("%s | ReadStrings returned %i (check 6)", TEST_NAME, retval);
}
// Test failure when the ini file doesn't exist
NS_tsnprintf(inifile, ArrayLength(inifile), NS_T("%sTestAUSReadStringsBogus.ini"), argv[0]);
retval = ReadStrings(inifile, &testStrings);
if (retval != READ_ERROR) {
rv = 26;
fail("%s | ini file doesn't exist (check 7)", TEST_NAME);
}
// Test reading a non-default section name
NS_tsnprintf(inifile, ArrayLength(inifile), NS_T("%sTestAUSReadStrings3.ini"), argv[0]);
retval = ReadStrings(inifile, "Title\0", 1, &testStrings.title, "BogusSection2");
if (retval == OK) {
if (strcmp(testStrings.title, "Bogus Title") != 0) {
rv = 27;
fail("%s | Title ini value incorrect (check 9)", TEST_NAME);
}
} else {
fail("%s | ReadStrings returned %i (check 8)", TEST_NAME, retval);
rv = 28;
}
if (rv == 0) {
printf("TEST-PASS | %s | all checks passed\n", TEST_NAME);
} else {
fail("%s | %i out of 9 checks failed", TEST_NAME, gFailCount);
}
return rv;
}

View file

@ -0,0 +1,47 @@
; This file is in the UTF-8 encoding
[BogusSection1]
; Comment
Title=Bogus Title
; Comment
Info=Bogus Info
; Comment
[Strings]
Bogus1=Bogus1
; Comment
Title=Title Test - Испытание Δοκιμή テスト 測試 测试
; Comment
Bogus2=Bogus2
; Comment
Info=Info Test - Испытание Δοκιμή テスト 測試 测试…
; Comment
Bogus3=Bogus3
; Comment
[BogusSection2]
; Comment
Title=Bogus Title
; Comment
Info=Bogus Info
; Comment

View file

@ -0,0 +1,39 @@
; This file is in the UTF-8 encoding
[BogusSection1]
; Comment
Title=Bogus Title
; Comment
Info=Bogus Info
; Comment
[Strings]
Bogus1=Bogus1
; Comment
Info=Info
; Comment
Bogus2=Bogus2
; Comment
[BogusSection2]
; Comment
Title=Bogus Title
; Comment
Info=Bogus Info
; Comment

View file

@ -0,0 +1,39 @@
; This file is in the UTF-8 encoding
[BogusSection1]
; Comment
Title=Bogus Title
; Comment
Info=Bogus Info
; Comment
[Strings]
Bogus1=Bogus1
; Comment
Title=Title
; Comment
Bogus2=Bogus2
; Comment
[BogusSection2]
; Comment
Title=Bogus Title
; Comment
Info=Bogus Info
; Comment

View file

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"extends": [
"../../../../../testing/mochitest/chrome.eslintrc.js"
]
};

View file

@ -0,0 +1,64 @@
; 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/.
[DEFAULT]
tags = appupdate
support-files =
utils.js
update.sjs
; mochitest-chrome tests must start with "test_" and are executed in sorted
; order and not in the order specified in the manifest.
[test_0010_background_basic.xul]
[test_0011_check_basic.xul]
[test_0012_check_basic_staging.xul]
skip-if = asan
reason = Bug 1168003
[test_0013_check_no_updates.xul]
[test_0014_check_error_xml_malformed.xul]
[test_0061_check_verifyFailPartial_noComplete.xul]
[test_0062_check_verifyFailComplete_noPartial.xul]
[test_0063_check_verifyFailPartialComplete.xul]
[test_0064_check_verifyFailPartial_successComplete.xul]
[test_0071_notify_verifyFailPartial_noComplete.xul]
[test_0072_notify_verifyFailComplete_noPartial.xul]
[test_0073_notify_verifyFailPartialComplete.xul]
[test_0074_notify_verifyFailPartial_successComplete.xul]
[test_0081_error_patchApplyFailure_partial_only.xul]
[test_0082_error_patchApplyFailure_complete_only.xul]
[test_0083_error_patchApplyFailure_partial_complete.xul]
[test_0084_error_patchApplyFailure_verify_failed.xul]
[test_0085_error_patchApplyFailure_partial_complete_staging.xul]
skip-if = asan
reason = Bug 1168003
[test_0092_finishedBackground.xul]
[test_0093_restartNotification.xul]
[test_0094_restartNotification_remote.xul]
[test_0095_restartNotification_remoteInvalidNumber.xul]
[test_0096_restartNotification_stagedBackground.xul]
skip-if = asan
reason = Bug 1168003
[test_0097_restartNotification_stagedServiceBackground.xul]
skip-if = os != 'win'
reason = only Windows has the maintenance service.
[test_0101_background_restartNotification.xul]
[test_0102_background_restartNotification_staging.xul]
skip-if = asan
reason = Bug 1168003
[test_0103_background_restartNotification_stagingService.xul]
skip-if = os != 'win'
reason = only Windows has the maintenance service.
[test_0111_neverButton_basic.xul]
[test_0113_showNeverForVersionRemovedWithPref.xul]
[test_0151_notify_backgroundCheckError.xul]
[test_0152_notify_backgroundCheckOfflineRetry.xul]
[test_0161_check_unsupported.xul]
[test_0162_notify_unsupported.xul]
[test_0171_check_noPerms_manual.xul]
skip-if = os != 'win'
reason = test must be able to prevent file deletion.
[test_0172_notify_noPerms_manual.xul]
skip-if = os != 'win'
reason = test must be able to prevent file deletion.
[test_9999_cleanup.xul]

View file

@ -0,0 +1,50 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: basic, download, and finished"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_FOUND_BASIC,
buttonClick: "next"
}, {
pageid: PAGEID_DOWNLOADING
}, {
pageid: PAGEID_FINISHED,
buttonClick: "extra1"
} ];
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?showDetails=1&showPrompt=1" +
getVersionParams();
setUpdateURL(url);
gAUS.checkForBackgroundUpdates();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,51 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: update check, basic, download, and finished"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_CHECKING
}, {
pageid: PAGEID_FOUND_BASIC,
buttonClick: "next"
}, {
pageid: PAGEID_DOWNLOADING
}, {
pageid: PAGEID_FINISHED,
buttonClick: "extra1"
} ];
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?showDetails=1" + getVersionParams();
setUpdateURL(url);
gUP.checkForUpdates();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,55 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: update check, basic, download with staging, and finished"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_CHECKING
}, {
pageid: PAGEID_FOUND_BASIC,
buttonClick: "next"
}, {
pageid: PAGEID_DOWNLOADING
}, {
pageid: PAGEID_FINISHED,
buttonClick: "extra1"
} ];
gUseTestUpdater = true;
function runTest() {
debugDump("entering");
Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, true);
let url = URL_HTTP_UPDATE_XML + "?showDetails=1" + getVersionParams();
setUpdateURL(url);
gUP.checkForUpdates();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,46 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: update check and no updates found"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_CHECKING
}, {
pageid: PAGEID_NO_UPDATES_FOUND,
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?noUpdates=1";
setUpdateURL(url);
gUP.checkForUpdates();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,46 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: update check and error (xml malformed)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_CHECKING
}, {
pageid: PAGEID_ERRORS,
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?xmlMalformed=1";
setUpdateURL(url);
gUP.checkForUpdates();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: update check, basic, download, and errors (partial patch with an invalid size)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_CHECKING
}, {
pageid: PAGEID_FOUND_BASIC,
buttonClick: "next"
}, {
pageid: PAGEID_DOWNLOADING
}, {
pageid: PAGEID_ERRORS,
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?showDetails=1&partialPatchOnly=1" +
"&invalidPartialSize=1" + getVersionParams();
setUpdateURL(url);
gUP.checkForUpdates();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: update check, basic, download, and errors (complete patch with an invalid size)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_CHECKING
}, {
pageid: PAGEID_FOUND_BASIC,
buttonClick: "next"
}, {
pageid: PAGEID_DOWNLOADING
}, {
pageid: PAGEID_ERRORS,
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?showDetails=1&completePatchOnly=1" +
"&invalidCompleteSize=1" + getVersionParams();
setUpdateURL(url);
gUP.checkForUpdates();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: update check, basic, download, and errors (partial and complete patches with invalid sizes)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_CHECKING
}, {
pageid: PAGEID_FOUND_BASIC,
buttonClick: "next"
}, {
pageid: PAGEID_DOWNLOADING
}, {
pageid: PAGEID_ERRORS,
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?showDetails=1&invalidPartialSize=1" +
"&invalidCompleteSize=1" + getVersionParams();
setUpdateURL(url);
gUP.checkForUpdates();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: update check, basic, download, and finished (partial patch with an invalid size and successful complete patch)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_CHECKING
}, {
pageid: PAGEID_FOUND_BASIC,
buttonClick: "next"
}, {
pageid: PAGEID_DOWNLOADING
}, {
pageid: PAGEID_FINISHED,
buttonClick: "extra1"
} ];
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?showDetails=1&invalidPartialSize=1" +
getVersionParams();
setUpdateURL(url);
gUP.checkForUpdates();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,53 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: errors (partial patch with an invalid size)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_ERRORS,
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
let patches = getLocalPatchString("partial", null, null, null, "1234", null,
STATE_DOWNLOADING);
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version,
Services.appinfo.platformVersion);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_DOWNLOADING);
reloadUpdateManagerData();
testPostUpdateProcessing();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: errors (complete patch with an invalid size)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_ERRORS,
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
let patches = getLocalPatchString("complete", null, null, null, "1234", null,
STATE_DOWNLOADING);
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_DOWNLOADING);
reloadUpdateManagerData();
testPostUpdateProcessing();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,55 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: errors (partial and complete patches with invalid sizes)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_ERRORS,
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
let patches = getLocalPatchString("partial", null, null, null, "1234", null,
STATE_DOWNLOADING) +
getLocalPatchString("complete", null, null, null, "1234",
"false");
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version, null,
null, null, null, null, "false");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_DOWNLOADING);
reloadUpdateManagerData();
testPostUpdateProcessing();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,55 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: finishedBackground (partial patch with an invalid size and successful complete patch)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_FINISHED_BKGRD,
buttonClick: "extra1"
} ];
function runTest() {
debugDump("entering");
let patches = getLocalPatchString("partial", null, null, null, "1234", null,
STATE_DOWNLOADING) +
getLocalPatchString("complete", null, null, null, null,
"false");
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version, null,
null, null, null, null, "false");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_DOWNLOADING);
reloadUpdateManagerData();
testPostUpdateProcessing();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,53 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: errors (partial only patch apply failure)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_ERRORS,
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
let patches = getLocalPatchString("partial", null, null, null, null, null,
STATE_PENDING);
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version, null,
null, null, null, null, "false");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_FAILED_CRC_ERROR);
reloadUpdateManagerData();
testPostUpdateProcessing();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: errors (complete only patch apply failure)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_ERRORS,
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
let patches = getLocalPatchString("complete", null, null, null, null, null,
STATE_PENDING);
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_FAILED_CRC_ERROR);
reloadUpdateManagerData();
testPostUpdateProcessing();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,67 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: error patching, download, and finished (partial failed and download complete)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_ERROR_PATCHING,
buttonClick: "next"
}, {
pageid: PAGEID_DOWNLOADING,
extraStartFunction: createContinueFile
}, {
pageid: PAGEID_FINISHED,
buttonClick: "extra1",
extraStartFunction: removeContinueFile
} ];
function runTest() {
debugDump("entering");
removeContinueFile();
// Specify the url to update.sjs with a slowDownloadMar param so the ui can
// load before the download completes.
let slowDownloadURL = URL_HTTP_UPDATE_XML + "?slowDownloadMar=1";
let patches = getLocalPatchString("partial", null, null, null, null, null,
STATE_PENDING) +
getLocalPatchString("complete", slowDownloadURL, null, null,
null, "false");
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version, null,
null, null, null, null, "false");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_FAILED_CRC_ERROR);
reloadUpdateManagerData();
testPostUpdateProcessing();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,68 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: error patching, download, and errors (partial failed and download complete verification failure)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_ERROR_PATCHING,
buttonClick: "next"
}, {
pageid: PAGEID_DOWNLOADING,
extraStartFunction: createContinueFile
}, {
pageid: PAGEID_ERRORS,
buttonClick: "finish",
extraStartFunction: removeContinueFile
} ];
function runTest() {
debugDump("entering");
removeContinueFile();
// Specify the url to update.sjs with a slowDownloadMar param so the ui can
// load before the download completes.
let slowDownloadURL = URL_HTTP_UPDATE_XML + "?slowDownloadMar=1";
let patches = getLocalPatchString("partial", null, null, null, null, null,
STATE_PENDING) +
getLocalPatchString("complete", slowDownloadURL, "MD5",
null, "1234",
"false");
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version, null,
null, null, null, null, "false");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_FAILED_CRC_ERROR);
reloadUpdateManagerData();
testPostUpdateProcessing();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,94 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: error patching, download with staging, and finished (partial failed and download complete), with fast MAR download"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
// This test forces the download to complete before the "next" button on the
// errorpatching wizard page is clicked. This is done by creating the continue
// file when the wizard loads to start the download, then clicking the "next"
// button in the download's onStopRequest event listener.
const testDownloadListener = {
onStartRequest(aRequest, aContext) { },
onProgress(aRequest, aContext, aProgress, aMaxProgress) { },
onStatus(aRequest, aContext, aStatus, aStatusText) { },
onStopRequest(aRequest, aContext, aStatus) {
debugDump("clicking errorpatching page next button");
gDocElem.getButton("next").click();
gAUS.removeDownloadListener(this);
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRequestObserver,
Ci.nsIProgressEventSink])
};
let TESTS = [ {
pageid: PAGEID_ERROR_PATCHING,
extraCheckFunction: createContinueFile
}, {
pageid: PAGEID_DOWNLOADING
}, {
pageid: PAGEID_FINISHED,
buttonClick: "extra1",
extraStartFunction: removeContinueFile
} ];
gUseTestUpdater = true;
function runTest() {
debugDump("entering");
removeContinueFile();
// Specify the url to update.sjs with a slowDownloadMar param so the ui can
// load before the download completes.
let slowDownloadURL = URL_HTTP_UPDATE_XML + "?slowDownloadMar=1";
let patches = getLocalPatchString("partial", null, null, null, null, null,
STATE_PENDING) +
getLocalPatchString("complete", slowDownloadURL, null, null,
null, "false");
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version, null,
null, null, null, null, "false");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_FAILED_READ_ERROR);
Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, true);
reloadUpdateManagerData();
testPostUpdateProcessing();
gAUS.addDownloadListener(testDownloadListener);
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,55 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: finished background"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_FINISHED_BKGRD,
buttonClick: "extra1"
} ];
function runTest() {
debugDump("entering");
let patches = getLocalPatchString("complete", null, null, null, null, null,
STATE_PENDING);
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version,
Services.appinfo.platformVersion);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_SUCCEEDED);
reloadUpdateManagerData();
is(gUpdateManager.activeUpdate.state, "pending",
"The active update should have a state of pending");
gUP.showUpdateDownloaded(gUpdateManager.activeUpdate);
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,60 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: restart notification pref promptWaitTime"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_FINISHED_BKGRD,
buttonClick: "extra1"
} ];
function runTest() {
debugDump("entering");
let patches = getLocalPatchString("complete", null, null, null, null, null,
STATE_PENDING);
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_SUCCEEDED);
Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 1);
reloadUpdateManagerData();
is(gUpdateManager.activeUpdate.state, STATE_PENDING,
"The active update should have a state of " + STATE_PENDING);
ok(gUpdateManager.activeUpdate.promptWaitTime == 1, "Checking that the " +
"update's promptWaitTime attribute value was set from the " +
PREF_APP_UPDATE_PROMPTWAITTIME + " preference");
gUP.showUpdateDownloaded(gUpdateManager.activeUpdate, true);
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,60 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: restart notification xml promptWaitTime"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_FINISHED_BKGRD,
buttonClick: "extra1"
} ];
function runTest() {
debugDump("entering");
let patches = getLocalPatchString("complete", null, null, null, null, null,
STATE_PENDING);
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version, null,
null, null, null, null, false,
null, false, false, false, 1);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_SUCCEEDED);
reloadUpdateManagerData();
is(gUpdateManager.activeUpdate.state, STATE_PENDING,
"The active update should have a state of " + STATE_PENDING);
ok(gUpdateManager.activeUpdate.promptWaitTime == 1, "Checking that the " +
"update's promptWaitTime attribute value was set by the XML");
gUP.showUpdateDownloaded(gUpdateManager.activeUpdate, true);
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,66 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: restart notification xml promptWaitTime with invalid number"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_FINISHED_BKGRD,
buttonClick: "extra1"
} ];
function runTest() {
debugDump("entering");
let patches = getLocalPatchString("complete", null, null, null, null, null,
STATE_PENDING);
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version,
null, null,
null, null, null,
null, false, null,
false, false,
false, "invalidNumber");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_SUCCEEDED);
Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 1);
reloadUpdateManagerData();
is(gUpdateManager.activeUpdate.state, STATE_PENDING,
"The active update should have a state of " + STATE_PENDING);
ok(gUpdateManager.activeUpdate.promptWaitTime == 1, "Checking that the " +
"update's promptWaitTime attribute value was set from the " +
PREF_APP_UPDATE_PROMPTWAITTIME + " preference");
gUP.showUpdateDownloaded(gUpdateManager.activeUpdate, true);
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,65 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: restart notification staged w/o service"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_FINISHED_BKGRD,
buttonClick: "extra1"
} ];
gUseTestUpdater = true;
function runTest() {
debugDump("entering");
let patches = getLocalPatchString("complete", null, null, null, null, null,
STATE_APPLIED);
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version,
Services.appinfo.platformVersion);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_APPLIED);
Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 1);
Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, true);
Services.prefs.setBoolPref(PREF_APP_UPDATE_SERVICE_ENABLED, false);
reloadUpdateManagerData();
is(gUpdateManager.activeUpdate.state, STATE_APPLIED,
"The active update should have a state of " + STATE_APPLIED);
ok(gUpdateManager.activeUpdate.promptWaitTime == 1, "Checking that the " +
"update's promptWaitTime attribute value was set from the " +
PREF_APP_UPDATE_PROMPTWAITTIME + " preference");
gUpdateManager.refreshUpdateStatus();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,65 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: restart notification staged with service"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_FINISHED_BKGRD,
buttonClick: "extra1"
} ];
gUseTestUpdater = true;
function runTest() {
debugDump("entering");
let patches = getLocalPatchString("complete", null, null, null, null, null,
STATE_APPLIED_SVC);
let updates = getLocalUpdateString(patches, null, null, null,
Services.appinfo.version,
Services.appinfo.platformVersion);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
writeStatusFile(STATE_APPLIED_SVC);
Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 1);
Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, true);
Services.prefs.setBoolPref(PREF_APP_UPDATE_SERVICE_ENABLED, true);
reloadUpdateManagerData();
is(gUpdateManager.activeUpdate.state, STATE_APPLIED_SVC,
"The active update should have a state of " + STATE_APPLIED_SVC);
ok(gUpdateManager.activeUpdate.promptWaitTime == 1, "Checking that the " +
"update's promptWaitTime attribute value was set from the " +
PREF_APP_UPDATE_PROMPTWAITTIME + " preference");
gUpdateManager.refreshUpdateStatus();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,46 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: background finish with a background download"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_FINISHED_BKGRD,
buttonClick: "extra1"
} ];
function runTest() {
debugDump("entering");
Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 1);
let url = URL_HTTP_UPDATE_XML + "?showDetails=1" + getVersionParams();
setUpdateURL(url);
gAUS.notify(null);
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,49 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: background finish with a background download and update staging"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_FINISHED_BKGRD,
buttonClick: "extra1"
} ];
gUseTestUpdater = true;
function runTest() {
debugDump("entering");
Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, true);
Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 1);
let url = URL_HTTP_UPDATE_XML + "?showDetails=1" + getVersionParams();
setUpdateURL(url);
gAUS.notify(null);
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,50 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: background finish with a background download and update staging and servicefs"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_FINISHED_BKGRD,
buttonClick: "extra1"
} ];
gUseTestUpdater = true;
function runTest() {
debugDump("entering");
Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, true);
Services.prefs.setBoolPref(PREF_APP_UPDATE_SERVICE_ENABLED, true);
Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 1);
let url = URL_HTTP_UPDATE_XML + "?showDetails=1" + getVersionParams();
setUpdateURL(url);
gAUS.notify(null);
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,61 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: update check and basic (never button test)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
gPrefToCheck = PREFBRANCH_APP_UPDATE_NEVER + Services.appinfo.version;
const TESTS = [ {
pageid: PAGEID_CHECKING
}, {
pageid: PAGEID_FOUND_BASIC,
extraDelayedCheckFunction: checkPrefHasUserValue,
prefHasUserValue: false,
neverButton: true,
buttonClick: "extra2"
} ];
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?showNever=1&showDetails=1" +
getVersionParams();
setUpdateURL(url);
// add the never preference for this version to verify that checking for
// updates clears the preference.
Services.prefs.setBoolPref(gPrefToCheck, true)
gUP.checkForUpdates();
}
function finishTest() {
checkPrefHasUserValue(true);
finishTestDefault();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,58 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: update available with never pref and without showNeverForVersion"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
gPrefToCheck = PREFBRANCH_APP_UPDATE_NEVER + Services.appinfo.version;
const TESTS = [ {
pageid: PAGEID_FOUND_BASIC,
extraDelayedCheckFunction: checkPrefHasUserValue,
prefHasUserValue: true,
buttonClick: "extra1"
} ];
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?showDetails=1&showPrompt=1" +
getVersionParams();
setUpdateURL(url);
// add the never preference for this version to verify that checking for
// updates clears the preference.
Services.prefs.setBoolPref(gPrefToCheck, true)
gAUS.notify(null);
}
function finishTest() {
Services.prefs.clearUserPref(gPrefToCheck)
finishTestDefault();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,50 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Test notification when multiple background check errors occur (bug 595455)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_ERROR_EXTRA,
extraDelayedCheckFunction: checkErrorExtraPage,
shouldBeHidden: false,
displayedTextElem: "bgErrorLabel",
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?xmlMalformed=1";
setUpdateURL(url);
errorsPrefObserver.init(PREF_APP_UPDATE_BACKGROUNDERRORS,
PREF_APP_UPDATE_BACKGROUNDMAXERRORS);
gAUS.notify(null);
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,96 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Test that an update check that fails due to being offline is performed after going online"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_FOUND_BASIC,
buttonClick: "extra1"
} ];
const NETWORK_ERROR_OFFLINE = 111;
var gProxyPrefValue;
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?showDetails=1" + getVersionParams();
setUpdateURL(url);
Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, true);
Services.prefs.setBoolPref(PREF_APP_UPDATE_AUTO, false);
Services.io.offline = true;
gProxyPrefValue = Services.prefs.getIntPref("network.proxy.type");
Services.prefs.setIntPref("network.proxy.type", 0);
gUpdateChecker.checkForUpdates(updateCheckListener, true);
}
function resetOffline() {
Services.prefs.setIntPref("network.proxy.type", gProxyPrefValue);
Services.io.offline = false;
}
/* Update check listener */
const updateCheckListener = {
onProgress: function UCL_onProgress(aRequest, aPosition, aTotalSize) {
},
onCheckComplete: function UCL_onCheckComplete(aRequest, aUpdates, aUpdateCount) {
let status = aRequest.status;
if (status == 0) {
status = aRequest.channel.QueryInterface(Ci.nsIRequest).status;
}
debugDump("url = " + aRequest.channel.originalURI.spec + ", " +
"request.status = " + status + ", " +
"updateCount = " + aUpdateCount);
ok(false, "Unexpected updateCheckListener::onCheckComplete called");
},
onError: function UCL_onError(aRequest, aUpdate) {
let status = aRequest.status;
if (status == 0) {
status = aRequest.channel.QueryInterface(Ci.nsIRequest).status;
}
is(status, Cr.NS_ERROR_OFFLINE,
"checking the request status value");
is(aUpdate.errorCode, NETWORK_ERROR_OFFLINE,
"checking the update error code");
debugDump("url = " + aRequest.channel.originalURI.spec + ", " +
"request.status = " + status + ", " +
"update.statusText = " +
(aUpdate.statusText ? aUpdate.statusText : "null"));
gAUS.onError(aRequest, aUpdate);
// Use a timeout to allow the XHR to complete
SimpleTest.executeSoon(resetOffline);
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdateCheckListener])
};
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,50 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Test checking for updates when system is no longer supported (bug 843497)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_CHECKING
}, {
pageid: PAGEID_UNSUPPORTED,
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
// When checking manually the unsupported page should still be shown even if
// it was shown previously.
Services.prefs.setBoolPref(PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED, true);
let url = URL_HTTP_UPDATE_XML + "?unsupported=1";
setUpdateURL(url);
gUP.checkForUpdates();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,44 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Test notification of updates when system is no longer supported (bug 843497)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_UNSUPPORTED,
buttonClick: "finish"
} ];
function runTest() {
debugDump("entering");
let url = URL_HTTP_UPDATE_XML + "?unsupported=1";
setUpdateURL(url);
gAUS.notify(null);
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,64 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: manual"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_CHECKING
}, {
pageid: PAGEID_MANUAL_UPDATE,
buttonClick: "finish",
extraCheckFunction: getWriteTestFile
} ];
function runTest() {
debugDump("entering");
let file = getWriteTestFile();
file.create(file.NORMAL_FILE_TYPE, 0o444);
file.fileAttributesWin |= file.WFA_READONLY;
file.fileAttributesWin &= ~file.WFA_READWRITE;
let url = URL_HTTP_UPDATE_XML + "?showDetails=1" + getVersionParams();
setUpdateURL(url);
gUP.checkForUpdates();
}
function getWriteTestFile() {
let file = getAppBaseDir();
file.append(FILE_UPDATE_TEST);
file.QueryInterface(Ci.nsILocalFileWin);
if (file.exists()) {
file.fileAttributesWin |= file.WFA_READWRITE;
file.fileAttributesWin &= ~file.WFA_READONLY;
file.remove(true);
}
return file;
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,63 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Update Wizard pages: manual"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTestDefault();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
const TESTS = [ {
pageid: PAGEID_MANUAL_UPDATE,
buttonClick: "finish",
extraCheckFunction: getWriteTestFile
} ];
function runTest() {
debugDump("entering");
let file = getWriteTestFile();
file.create(file.NORMAL_FILE_TYPE, 0o444);
file.fileAttributesWin |= file.WFA_READONLY;
file.fileAttributesWin &= ~file.WFA_READWRITE;
let url = URL_HTTP_UPDATE_XML + "?showDetails=1&showPrompt=1" +
getVersionParams();
setUpdateURL(url);
gAUS.checkForBackgroundUpdates();
}
function getWriteTestFile() {
let file = getAppBaseDir();
file.append(FILE_UPDATE_TEST);
file.QueryInterface(Ci.nsILocalFileWin);
if (file.exists()) {
file.fileAttributesWin |= file.WFA_READWRITE;
file.fileAttributesWin &= ~file.WFA_READONLY;
file.remove(true);
}
return file;
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,112 @@
<?xml version="1.0"?>
<!--
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/**
* Removes files and preferences for previous application update tests in case
* any of them had a fatal error. The test name ensures that it will run after
* all other tests as long as the test naming uses the same format as the
* existing tests.
*/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Application Update test cleanup"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTest();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="utils.js"/>
<script type="application/javascript">
<![CDATA[
/**
* If the application update tests left behind any of the files it uses it could
* be a very bad thing. The purpose of this test is to prevent that from
* happening.
*/
function runTest() {
debugDump("entering");
SimpleTest.waitForExplicitFinish();
if (DEBUG_AUS_TEST) {
Services.prefs.setBoolPref(PREF_APP_UPDATE_LOG, true);
}
closeUpdateWindow();
// Always leave the app.update.enabled and app.update.staging.enabled
// preferences set to false when cleaning up.
Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, false);
Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, false);
resetFiles();
removeUpdateDirsAndFiles();
reloadUpdateManagerData();
let file = getUpdatesXMLFile(true);
ok(!file.exists(), file.path + " should not exist");
file = getUpdatesXMLFile(false);
ok(!file.exists(), file.path + " should not exist");
let dir = getUpdatesDir();
file = dir.clone();
file.append(FILE_UPDATE_STATUS);
ok(!file.exists(), file.path + " should not exist");
file = dir.clone();
file.append(FILE_UPDATE_MAR);
ok(!file.exists(), file.path + " should not exist");
cleanupRestoreUpdaterBackup();
}
/**
* After all tests finish this will repeatedly attempt to restore the real
* updater if it exists and then call finishTest after the restore is
* successful.
*/
function cleanupRestoreUpdaterBackup() {
debugDump("entering");
try {
// Windows debug builds keep the updater file in use for a short period of
// time after the updater process exits.
restoreUpdaterBackup();
} catch (e) {
logTestInfo("Attempt to restore the backed up updater failed... " +
"will try again, Exception: " + e);
SimpleTest.executeSoon(cleanupRestoreUpdaterBackup);
return;
}
SimpleTest.executeSoon(finishTest);
}
function finishTest() {
debugDump("entering");
if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_LOG)) {
Services.prefs.clearUserPref(PREF_APP_UPDATE_LOG);
}
SimpleTest.finish();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -0,0 +1,194 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/**
* Server side http server script for application update tests.
*/
const { classes: Cc, interfaces: Ci } = Components;
const REL_PATH_DATA = "chrome/toolkit/mozapps/update/tests/data/";
function getTestDataFile(aFilename) {
let file = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).get("CurWorkD", Ci.nsILocalFile);
let pathParts = REL_PATH_DATA.split("/");
for (let i = 0; i < pathParts.length; ++i) {
file.append(pathParts[i]);
}
if (aFilename) {
file.append(aFilename);
}
return file;
}
function loadHelperScript() {
let scriptFile = getTestDataFile("sharedUpdateXML.js");
let io = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService2);
let scriptSpec = io.newFileURI(scriptFile).spec;
let scriptloader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
getService(Ci.mozIJSSubScriptLoader);
scriptloader.loadSubScript(scriptSpec, this);
}
loadHelperScript();
const URL_HOST = "http://example.com";
const URL_PATH_UPDATE_XML = "/chrome/toolkit/mozapps/update/tests/chrome/update.sjs";
const URL_HTTP_UPDATE_SJS = URL_HOST + URL_PATH_UPDATE_XML;
const SERVICE_URL = URL_HOST + "/" + REL_PATH_DATA + FILE_SIMPLE_MAR;
const SLOW_MAR_DOWNLOAD_INTERVAL = 100;
var gTimer;
function handleRequest(aRequest, aResponse) {
let params = { };
if (aRequest.queryString) {
params = parseQueryString(aRequest.queryString);
}
let statusCode = params.statusCode ? parseInt(params.statusCode) : 200;
let statusReason = params.statusReason ? params.statusReason : "OK";
aResponse.setStatusLine(aRequest.httpVersion, statusCode, statusReason);
aResponse.setHeader("Cache-Control", "no-cache", false);
// When a mar download is started by the update service it can finish
// downloading before the ui has loaded. By specifying a serviceURL for the
// update patch that points to this file and has a slowDownloadMar param the
// mar will be downloaded asynchronously which will allow the ui to load
// before the download completes.
if (params.slowDownloadMar) {
aResponse.processAsync();
aResponse.setHeader("Content-Type", "binary/octet-stream");
aResponse.setHeader("Content-Length", SIZE_SIMPLE_MAR);
var continueFile = getTestDataFile("continue");
var contents = readFileBytes(getTestDataFile(FILE_SIMPLE_MAR));
gTimer = Cc["@mozilla.org/timer;1"].
createInstance(Ci.nsITimer);
gTimer.initWithCallback(function(aTimer) {
if (continueFile.exists()) {
gTimer.cancel();
aResponse.write(contents);
aResponse.finish();
}
}, SLOW_MAR_DOWNLOAD_INTERVAL, Ci.nsITimer.TYPE_REPEATING_SLACK);
return;
}
if (params.uiURL) {
let remoteType = "";
if (!params.remoteNoTypeAttr && params.uiURL == "BILLBOARD") {
remoteType = " " + params.uiURL.toLowerCase() + "=\"1\"";
}
aResponse.write("<html><head><meta http-equiv=\"content-type\" content=" +
"\"text/html; charset=utf-8\"></head><body" +
remoteType + ">" + params.uiURL +
"<br><br>this is a test mar that will not affect your " +
"build.</body></html>");
return;
}
if (params.xmlMalformed) {
aResponse.write("xml error");
return;
}
if (params.noUpdates) {
aResponse.write(getRemoteUpdatesXMLString(""));
return;
}
if (params.unsupported) {
aResponse.write(getRemoteUpdatesXMLString(" <update type=\"major\" " +
"unsupported=\"true\" " +
"detailsURL=\"" + URL_HOST +
"\"></update>\n"));
return;
}
let size;
let patches = "";
if (!params.partialPatchOnly) {
size = SIZE_SIMPLE_MAR + (params.invalidCompleteSize ? "1" : "");
patches += getRemotePatchString("complete", SERVICE_URL, "SHA512",
SHA512_HASH_SIMPLE_MAR, size);
}
if (!params.completePatchOnly) {
size = SIZE_SIMPLE_MAR + (params.invalidPartialSize ? "1" : "");
patches += getRemotePatchString("partial", SERVICE_URL, "SHA512",
SHA512_HASH_SIMPLE_MAR, size);
}
let type = params.type ? params.type : "major";
let name = params.name ? params.name : "App Update Test";
let appVersion = params.appVersion ? params.appVersion : "999999.9";
let displayVersion = params.displayVersion ? params.displayVersion
: "version " + appVersion;
let buildID = params.buildID ? params.buildID : "01234567890123";
// XXXrstrong - not specifying a detailsURL will cause a leak due to bug 470244
// let detailsURL = params.showDetails ? URL_HTTP_UPDATE_SJS + "?uiURL=DETAILS" : null;
let detailsURL = URL_HTTP_UPDATE_SJS + "?uiURL=DETAILS";
let showPrompt = params.showPrompt ? "true" : null;
let showNever = params.showNever ? "true" : null;
let promptWaitTime = params.promptWaitTime ? params.promptWaitTime : null;
let updates = getRemoteUpdateString(patches, type, "App Update Test",
displayVersion, appVersion, buildID,
detailsURL, showPrompt, showNever,
promptWaitTime);
aResponse.write(getRemoteUpdatesXMLString(updates));
}
/**
* Helper function to create a JS object representing the url parameters from
* the request's queryString.
*
* @param aQueryString
* The request's query string.
* @return A JS object representing the url parameters from the request's
* queryString.
*/
function parseQueryString(aQueryString) {
let paramArray = aQueryString.split("&");
let regex = /^([^=]+)=(.*)$/;
let params = {};
for (let i = 0, sz = paramArray.length; i < sz; i++) {
let match = regex.exec(paramArray[i]);
if (!match) {
throw "Bad parameter in queryString! '" + paramArray[i] + "'";
}
params[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
}
return params;
}
/**
* Reads the binary contents of a file and returns it as a string.
*
* @param aFile
* The file to read from.
* @return The contents of the file as a string.
*/
function readFileBytes(aFile) {
let fis = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
fis.init(aFile, -1, -1, false);
let bis = Cc["@mozilla.org/binaryinputstream;1"].
createInstance(Ci.nsIBinaryInputStream);
bis.setInputStream(fis);
let data = [];
let count = fis.available();
while (count > 0) {
let bytes = bis.readByteArray(Math.min(65535, count));
data.push(String.fromCharCode.apply(null, bytes));
count -= bytes.length;
if (bytes.length == 0) {
throw "Nothing read from input stream!";
}
}
data.join('');
fis.close();
return data.toString();
}

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

View file

@ -0,0 +1,332 @@
UPDATE TYPE complete
PREPARE REMOVEFILE Contents/Resources/searchplugins/searchpluginstext0
PREPARE REMOVEFILE Contents/Resources/searchplugins/searchpluginspng0.png
PREPARE REMOVEFILE Contents/Resources/removed-files
PREPARE REMOVEFILE Contents/Resources/precomplete
PREPARE REMOVEFILE Contents/Resources/2/20/20text0
PREPARE REMOVEFILE Contents/Resources/2/20/20png0.png
PREPARE REMOVEFILE Contents/Resources/0/0exe0.exe
PREPARE REMOVEFILE Contents/Resources/0/00/00text0
PREPARE REMOVEFILE Contents/MacOS/exe0.exe
PREPARE REMOVEDIR Contents/Resources/searchplugins/
PREPARE REMOVEDIR Contents/Resources/defaults/pref/
PREPARE REMOVEDIR Contents/Resources/defaults/
PREPARE REMOVEDIR Contents/Resources/2/20/
PREPARE REMOVEDIR Contents/Resources/2/
PREPARE REMOVEDIR Contents/Resources/0/00/
PREPARE REMOVEDIR Contents/Resources/0/
PREPARE REMOVEDIR Contents/Resources/
PREPARE REMOVEDIR Contents/MacOS/
PREPARE REMOVEDIR Contents/
PREPARE ADD Contents/Resources/searchplugins/searchpluginstext0
PREPARE ADD Contents/Resources/searchplugins/searchpluginspng1.png
PREPARE ADD Contents/Resources/searchplugins/searchpluginspng0.png
PREPARE ADD Contents/Resources/removed-files
PREPARE ADD Contents/Resources/precomplete
PREPARE ADD Contents/Resources/distribution/extensions/extensions1/extensions1text0
PREPARE ADD Contents/Resources/distribution/extensions/extensions1/extensions1png1.png
PREPARE ADD Contents/Resources/distribution/extensions/extensions1/extensions1png0.png
PREPARE ADD Contents/Resources/distribution/extensions/extensions0/extensions0text0
PREPARE ADD Contents/Resources/distribution/extensions/extensions0/extensions0png1.png
PREPARE ADD Contents/Resources/distribution/extensions/extensions0/extensions0png0.png
PREPARE ADD Contents/Resources/1/10/10text0
PREPARE ADD Contents/Resources/0/0exe0.exe
PREPARE ADD Contents/Resources/0/00/00text1
PREPARE ADD Contents/Resources/0/00/00text0
PREPARE ADD Contents/Resources/0/00/00png0.png
PREPARE ADD Contents/MacOS/exe0.exe
PREPARE REMOVEDIR Contents/Resources/9/99/
PREPARE REMOVEDIR Contents/Resources/9/99/
PREPARE REMOVEDIR Contents/Resources/9/98/
PREPARE REMOVEFILE Contents/Resources/9/97/970/97xtext0
PREPARE REMOVEFILE Contents/Resources/9/97/970/97xtext1
PREPARE REMOVEDIR Contents/Resources/9/97/970/
PREPARE REMOVEFILE Contents/Resources/9/97/971/97xtext0
PREPARE REMOVEFILE Contents/Resources/9/97/971/97xtext1
PREPARE REMOVEDIR Contents/Resources/9/97/971/
PREPARE REMOVEDIR Contents/Resources/9/97/
PREPARE REMOVEFILE Contents/Resources/9/96/96text0
PREPARE REMOVEFILE Contents/Resources/9/96/96text1
PREPARE REMOVEDIR Contents/Resources/9/96/
PREPARE REMOVEDIR Contents/Resources/9/95/
PREPARE REMOVEDIR Contents/Resources/9/95/
PREPARE REMOVEDIR Contents/Resources/9/94/
PREPARE REMOVEDIR Contents/Resources/9/94/
PREPARE REMOVEDIR Contents/Resources/9/93/
PREPARE REMOVEDIR Contents/Resources/9/92/
PREPARE REMOVEDIR Contents/Resources/9/91/
PREPARE REMOVEDIR Contents/Resources/9/90/
PREPARE REMOVEDIR Contents/Resources/9/90/
PREPARE REMOVEDIR Contents/Resources/8/89/
PREPARE REMOVEDIR Contents/Resources/8/89/
PREPARE REMOVEDIR Contents/Resources/8/88/
PREPARE REMOVEFILE Contents/Resources/8/87/870/87xtext0
PREPARE REMOVEFILE Contents/Resources/8/87/870/87xtext1
PREPARE REMOVEDIR Contents/Resources/8/87/870/
PREPARE REMOVEFILE Contents/Resources/8/87/871/87xtext0
PREPARE REMOVEFILE Contents/Resources/8/87/871/87xtext1
PREPARE REMOVEDIR Contents/Resources/8/87/871/
PREPARE REMOVEDIR Contents/Resources/8/87/
PREPARE REMOVEFILE Contents/Resources/8/86/86text0
PREPARE REMOVEFILE Contents/Resources/8/86/86text1
PREPARE REMOVEDIR Contents/Resources/8/86/
PREPARE REMOVEDIR Contents/Resources/8/85/
PREPARE REMOVEDIR Contents/Resources/8/85/
PREPARE REMOVEDIR Contents/Resources/8/84/
PREPARE REMOVEDIR Contents/Resources/8/84/
PREPARE REMOVEDIR Contents/Resources/8/83/
PREPARE REMOVEDIR Contents/Resources/8/82/
PREPARE REMOVEDIR Contents/Resources/8/81/
PREPARE REMOVEDIR Contents/Resources/8/80/
PREPARE REMOVEDIR Contents/Resources/8/80/
PREPARE REMOVEFILE Contents/Resources/7/70/7xtest.exe
PREPARE REMOVEFILE Contents/Resources/7/70/7xtext0
PREPARE REMOVEFILE Contents/Resources/7/70/7xtext1
PREPARE REMOVEDIR Contents/Resources/7/70/
PREPARE REMOVEFILE Contents/Resources/7/71/7xtest.exe
PREPARE REMOVEFILE Contents/Resources/7/71/7xtext0
PREPARE REMOVEFILE Contents/Resources/7/71/7xtext1
PREPARE REMOVEDIR Contents/Resources/7/71/
PREPARE REMOVEFILE Contents/Resources/7/7text0
PREPARE REMOVEFILE Contents/Resources/7/7text1
PREPARE REMOVEDIR Contents/Resources/7/
PREPARE REMOVEDIR Contents/Resources/6/
PREPARE REMOVEFILE Contents/Resources/5/5text1
PREPARE REMOVEFILE Contents/Resources/5/5text0
PREPARE REMOVEFILE Contents/Resources/5/5test.exe
PREPARE REMOVEFILE Contents/Resources/5/5text0
PREPARE REMOVEFILE Contents/Resources/5/5text1
PREPARE REMOVEDIR Contents/Resources/5/
PREPARE REMOVEFILE Contents/Resources/4/4text1
PREPARE REMOVEFILE Contents/Resources/4/4text0
PREPARE REMOVEDIR Contents/Resources/4/
PREPARE REMOVEFILE Contents/Resources/3/3text1
PREPARE REMOVEFILE Contents/Resources/3/3text0
EXECUTE REMOVEFILE Contents/Resources/searchplugins/searchpluginstext0
EXECUTE REMOVEFILE Contents/Resources/searchplugins/searchpluginspng0.png
EXECUTE REMOVEFILE Contents/Resources/removed-files
EXECUTE REMOVEFILE Contents/Resources/precomplete
EXECUTE REMOVEFILE Contents/Resources/2/20/20text0
EXECUTE REMOVEFILE Contents/Resources/2/20/20png0.png
EXECUTE REMOVEFILE Contents/Resources/0/0exe0.exe
EXECUTE REMOVEFILE Contents/Resources/0/00/00text0
EXECUTE REMOVEFILE Contents/MacOS/exe0.exe
EXECUTE REMOVEDIR Contents/Resources/searchplugins/
EXECUTE REMOVEDIR Contents/Resources/defaults/pref/
EXECUTE REMOVEDIR Contents/Resources/defaults/
EXECUTE REMOVEDIR Contents/Resources/2/20/
EXECUTE REMOVEDIR Contents/Resources/2/
EXECUTE REMOVEDIR Contents/Resources/0/00/
EXECUTE REMOVEDIR Contents/Resources/0/
EXECUTE REMOVEDIR Contents/Resources/
EXECUTE REMOVEDIR Contents/MacOS/
EXECUTE REMOVEDIR Contents/
EXECUTE ADD Contents/Resources/searchplugins/searchpluginstext0
EXECUTE ADD Contents/Resources/searchplugins/searchpluginspng1.png
EXECUTE ADD Contents/Resources/searchplugins/searchpluginspng0.png
EXECUTE ADD Contents/Resources/removed-files
EXECUTE ADD Contents/Resources/precomplete
EXECUTE ADD Contents/Resources/distribution/extensions/extensions1/extensions1text0
EXECUTE ADD Contents/Resources/distribution/extensions/extensions1/extensions1png1.png
EXECUTE ADD Contents/Resources/distribution/extensions/extensions1/extensions1png0.png
EXECUTE ADD Contents/Resources/distribution/extensions/extensions0/extensions0text0
EXECUTE ADD Contents/Resources/distribution/extensions/extensions0/extensions0png1.png
EXECUTE ADD Contents/Resources/distribution/extensions/extensions0/extensions0png0.png
EXECUTE ADD Contents/Resources/1/10/10text0
EXECUTE ADD Contents/Resources/0/0exe0.exe
EXECUTE ADD Contents/Resources/0/00/00text1
EXECUTE ADD Contents/Resources/0/00/00text0
EXECUTE ADD Contents/Resources/0/00/00png0.png
EXECUTE ADD Contents/MacOS/exe0.exe
EXECUTE REMOVEDIR Contents/Resources/9/99/
EXECUTE REMOVEDIR Contents/Resources/9/99/
EXECUTE REMOVEDIR Contents/Resources/9/98/
EXECUTE REMOVEFILE Contents/Resources/9/97/970/97xtext0
EXECUTE REMOVEFILE Contents/Resources/9/97/970/97xtext1
EXECUTE REMOVEDIR Contents/Resources/9/97/970/
EXECUTE REMOVEFILE Contents/Resources/9/97/971/97xtext0
EXECUTE REMOVEFILE Contents/Resources/9/97/971/97xtext1
EXECUTE REMOVEDIR Contents/Resources/9/97/971/
EXECUTE REMOVEDIR Contents/Resources/9/97/
EXECUTE REMOVEFILE Contents/Resources/9/96/96text0
EXECUTE REMOVEFILE Contents/Resources/9/96/96text1
EXECUTE REMOVEDIR Contents/Resources/9/96/
EXECUTE REMOVEDIR Contents/Resources/9/95/
EXECUTE REMOVEDIR Contents/Resources/9/95/
EXECUTE REMOVEDIR Contents/Resources/9/94/
EXECUTE REMOVEDIR Contents/Resources/9/94/
EXECUTE REMOVEDIR Contents/Resources/9/93/
EXECUTE REMOVEDIR Contents/Resources/9/92/
EXECUTE REMOVEDIR Contents/Resources/9/91/
EXECUTE REMOVEDIR Contents/Resources/9/90/
EXECUTE REMOVEDIR Contents/Resources/9/90/
EXECUTE REMOVEDIR Contents/Resources/8/89/
EXECUTE REMOVEDIR Contents/Resources/8/89/
EXECUTE REMOVEDIR Contents/Resources/8/88/
EXECUTE REMOVEFILE Contents/Resources/8/87/870/87xtext0
EXECUTE REMOVEFILE Contents/Resources/8/87/870/87xtext1
EXECUTE REMOVEDIR Contents/Resources/8/87/870/
EXECUTE REMOVEFILE Contents/Resources/8/87/871/87xtext0
EXECUTE REMOVEFILE Contents/Resources/8/87/871/87xtext1
EXECUTE REMOVEDIR Contents/Resources/8/87/871/
EXECUTE REMOVEDIR Contents/Resources/8/87/
EXECUTE REMOVEFILE Contents/Resources/8/86/86text0
EXECUTE REMOVEFILE Contents/Resources/8/86/86text1
EXECUTE REMOVEDIR Contents/Resources/8/86/
EXECUTE REMOVEDIR Contents/Resources/8/85/
EXECUTE REMOVEDIR Contents/Resources/8/85/
EXECUTE REMOVEDIR Contents/Resources/8/84/
EXECUTE REMOVEDIR Contents/Resources/8/84/
EXECUTE REMOVEDIR Contents/Resources/8/83/
EXECUTE REMOVEDIR Contents/Resources/8/82/
EXECUTE REMOVEDIR Contents/Resources/8/81/
EXECUTE REMOVEDIR Contents/Resources/8/80/
EXECUTE REMOVEDIR Contents/Resources/8/80/
EXECUTE REMOVEFILE Contents/Resources/7/70/7xtest.exe
EXECUTE REMOVEFILE Contents/Resources/7/70/7xtext0
EXECUTE REMOVEFILE Contents/Resources/7/70/7xtext1
EXECUTE REMOVEDIR Contents/Resources/7/70/
EXECUTE REMOVEFILE Contents/Resources/7/71/7xtest.exe
EXECUTE REMOVEFILE Contents/Resources/7/71/7xtext0
EXECUTE REMOVEFILE Contents/Resources/7/71/7xtext1
EXECUTE REMOVEDIR Contents/Resources/7/71/
EXECUTE REMOVEFILE Contents/Resources/7/7text0
EXECUTE REMOVEFILE Contents/Resources/7/7text1
EXECUTE REMOVEDIR Contents/Resources/7/
EXECUTE REMOVEDIR Contents/Resources/6/
EXECUTE REMOVEFILE Contents/Resources/5/5text1
EXECUTE REMOVEFILE Contents/Resources/5/5text0
EXECUTE REMOVEFILE Contents/Resources/5/5test.exe
EXECUTE REMOVEFILE Contents/Resources/5/5text0
file cannot be removed because it does not exist; skipping
EXECUTE REMOVEFILE Contents/Resources/5/5text1
file cannot be removed because it does not exist; skipping
EXECUTE REMOVEDIR Contents/Resources/5/
EXECUTE REMOVEFILE Contents/Resources/4/4text1
EXECUTE REMOVEFILE Contents/Resources/4/4text0
EXECUTE REMOVEDIR Contents/Resources/4/
EXECUTE REMOVEFILE Contents/Resources/3/3text1
EXECUTE REMOVEFILE Contents/Resources/3/3text0
FINISH REMOVEFILE Contents/Resources/searchplugins/searchpluginstext0
FINISH REMOVEFILE Contents/Resources/searchplugins/searchpluginspng0.png
FINISH REMOVEFILE Contents/Resources/removed-files
FINISH REMOVEFILE Contents/Resources/precomplete
FINISH REMOVEFILE Contents/Resources/2/20/20text0
FINISH REMOVEFILE Contents/Resources/2/20/20png0.png
FINISH REMOVEFILE Contents/Resources/0/0exe0.exe
FINISH REMOVEFILE Contents/Resources/0/00/00text0
FINISH REMOVEFILE Contents/MacOS/exe0.exe
FINISH REMOVEDIR Contents/Resources/searchplugins/
removing directory: Contents/Resources/searchplugins/, rv: 0
FINISH REMOVEDIR Contents/Resources/defaults/pref/
removing directory: Contents/Resources/defaults/pref/, rv: 0
FINISH REMOVEDIR Contents/Resources/defaults/
removing directory: Contents/Resources/defaults/, rv: 0
FINISH REMOVEDIR Contents/Resources/2/20/
FINISH REMOVEDIR Contents/Resources/2/
FINISH REMOVEDIR Contents/Resources/0/00/
removing directory: Contents/Resources/0/00/, rv: 0
FINISH REMOVEDIR Contents/Resources/0/
removing directory: Contents/Resources/0/, rv: 0
FINISH REMOVEDIR Contents/Resources/
removing directory: Contents/Resources/, rv: 0
FINISH REMOVEDIR Contents/MacOS/
removing directory: Contents/MacOS/, rv: 0
FINISH REMOVEDIR Contents/
removing directory: Contents/, rv: 0
FINISH ADD Contents/Resources/searchplugins/searchpluginstext0
FINISH ADD Contents/Resources/searchplugins/searchpluginspng1.png
FINISH ADD Contents/Resources/searchplugins/searchpluginspng0.png
FINISH ADD Contents/Resources/removed-files
FINISH ADD Contents/Resources/precomplete
FINISH ADD Contents/Resources/distribution/extensions/extensions1/extensions1text0
FINISH ADD Contents/Resources/distribution/extensions/extensions1/extensions1png1.png
FINISH ADD Contents/Resources/distribution/extensions/extensions1/extensions1png0.png
FINISH ADD Contents/Resources/distribution/extensions/extensions0/extensions0text0
FINISH ADD Contents/Resources/distribution/extensions/extensions0/extensions0png1.png
FINISH ADD Contents/Resources/distribution/extensions/extensions0/extensions0png0.png
FINISH ADD Contents/Resources/1/10/10text0
FINISH ADD Contents/Resources/0/0exe0.exe
FINISH ADD Contents/Resources/0/00/00text1
FINISH ADD Contents/Resources/0/00/00text0
FINISH ADD Contents/Resources/0/00/00png0.png
FINISH ADD Contents/MacOS/exe0.exe
FINISH REMOVEDIR Contents/Resources/9/99/
FINISH REMOVEDIR Contents/Resources/9/99/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/9/98/
FINISH REMOVEFILE Contents/Resources/9/97/970/97xtext0
FINISH REMOVEFILE Contents/Resources/9/97/970/97xtext1
FINISH REMOVEDIR Contents/Resources/9/97/970/
FINISH REMOVEFILE Contents/Resources/9/97/971/97xtext0
FINISH REMOVEFILE Contents/Resources/9/97/971/97xtext1
FINISH REMOVEDIR Contents/Resources/9/97/971/
FINISH REMOVEDIR Contents/Resources/9/97/
FINISH REMOVEFILE Contents/Resources/9/96/96text0
FINISH REMOVEFILE Contents/Resources/9/96/96text1
FINISH REMOVEDIR Contents/Resources/9/96/
FINISH REMOVEDIR Contents/Resources/9/95/
FINISH REMOVEDIR Contents/Resources/9/95/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/9/94/
FINISH REMOVEDIR Contents/Resources/9/94/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/9/93/
FINISH REMOVEDIR Contents/Resources/9/92/
removing directory: Contents/Resources/9/92/, rv: 0
FINISH REMOVEDIR Contents/Resources/9/91/
removing directory: Contents/Resources/9/91/, rv: 0
FINISH REMOVEDIR Contents/Resources/9/90/
FINISH REMOVEDIR Contents/Resources/9/90/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/8/89/
FINISH REMOVEDIR Contents/Resources/8/89/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/8/88/
FINISH REMOVEFILE Contents/Resources/8/87/870/87xtext0
FINISH REMOVEFILE Contents/Resources/8/87/870/87xtext1
FINISH REMOVEDIR Contents/Resources/8/87/870/
FINISH REMOVEFILE Contents/Resources/8/87/871/87xtext0
FINISH REMOVEFILE Contents/Resources/8/87/871/87xtext1
FINISH REMOVEDIR Contents/Resources/8/87/871/
FINISH REMOVEDIR Contents/Resources/8/87/
FINISH REMOVEFILE Contents/Resources/8/86/86text0
FINISH REMOVEFILE Contents/Resources/8/86/86text1
FINISH REMOVEDIR Contents/Resources/8/86/
FINISH REMOVEDIR Contents/Resources/8/85/
FINISH REMOVEDIR Contents/Resources/8/85/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/8/84/
FINISH REMOVEDIR Contents/Resources/8/84/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/8/83/
FINISH REMOVEDIR Contents/Resources/8/82/
removing directory: Contents/Resources/8/82/, rv: 0
FINISH REMOVEDIR Contents/Resources/8/81/
removing directory: Contents/Resources/8/81/, rv: 0
FINISH REMOVEDIR Contents/Resources/8/80/
FINISH REMOVEDIR Contents/Resources/8/80/
directory no longer exists; skipping
FINISH REMOVEFILE Contents/Resources/7/70/7xtest.exe
FINISH REMOVEFILE Contents/Resources/7/70/7xtext0
FINISH REMOVEFILE Contents/Resources/7/70/7xtext1
FINISH REMOVEDIR Contents/Resources/7/70/
FINISH REMOVEFILE Contents/Resources/7/71/7xtest.exe
FINISH REMOVEFILE Contents/Resources/7/71/7xtext0
FINISH REMOVEFILE Contents/Resources/7/71/7xtext1
FINISH REMOVEDIR Contents/Resources/7/71/
FINISH REMOVEFILE Contents/Resources/7/7text0
FINISH REMOVEFILE Contents/Resources/7/7text1
FINISH REMOVEDIR Contents/Resources/7/
FINISH REMOVEDIR Contents/Resources/6/
FINISH REMOVEFILE Contents/Resources/5/5text1
FINISH REMOVEFILE Contents/Resources/5/5text0
FINISH REMOVEFILE Contents/Resources/5/5test.exe
FINISH REMOVEDIR Contents/Resources/5/
FINISH REMOVEFILE Contents/Resources/4/4text1
FINISH REMOVEFILE Contents/Resources/4/4text0
FINISH REMOVEDIR Contents/Resources/4/
FINISH REMOVEFILE Contents/Resources/3/3text1
FINISH REMOVEFILE Contents/Resources/3/3text0
succeeded
calling QuitProgressUI

View file

@ -0,0 +1,320 @@
UPDATE TYPE complete
PREPARE REMOVEFILE searchplugins/searchpluginstext0
PREPARE REMOVEFILE searchplugins/searchpluginspng0.png
PREPARE REMOVEFILE removed-files
PREPARE REMOVEFILE precomplete
PREPARE REMOVEFILE exe0.exe
PREPARE REMOVEFILE 2/20/20text0
PREPARE REMOVEFILE 2/20/20png0.png
PREPARE REMOVEFILE 0/0exe0.exe
PREPARE REMOVEFILE 0/00/00text0
PREPARE REMOVEDIR searchplugins/
PREPARE REMOVEDIR defaults/pref/
PREPARE REMOVEDIR defaults/
PREPARE REMOVEDIR 2/20/
PREPARE REMOVEDIR 2/
PREPARE REMOVEDIR 0/00/
PREPARE REMOVEDIR 0/
PREPARE ADD searchplugins/searchpluginstext0
PREPARE ADD searchplugins/searchpluginspng1.png
PREPARE ADD searchplugins/searchpluginspng0.png
PREPARE ADD removed-files
PREPARE ADD precomplete
PREPARE ADD exe0.exe
PREPARE ADD distribution/extensions/extensions1/extensions1text0
PREPARE ADD distribution/extensions/extensions1/extensions1png1.png
PREPARE ADD distribution/extensions/extensions1/extensions1png0.png
PREPARE ADD distribution/extensions/extensions0/extensions0text0
PREPARE ADD distribution/extensions/extensions0/extensions0png1.png
PREPARE ADD distribution/extensions/extensions0/extensions0png0.png
PREPARE ADD 1/10/10text0
PREPARE ADD 0/0exe0.exe
PREPARE ADD 0/00/00text1
PREPARE ADD 0/00/00text0
PREPARE ADD 0/00/00png0.png
PREPARE REMOVEDIR 9/99/
PREPARE REMOVEDIR 9/99/
PREPARE REMOVEDIR 9/98/
PREPARE REMOVEFILE 9/97/970/97xtext0
PREPARE REMOVEFILE 9/97/970/97xtext1
PREPARE REMOVEDIR 9/97/970/
PREPARE REMOVEFILE 9/97/971/97xtext0
PREPARE REMOVEFILE 9/97/971/97xtext1
PREPARE REMOVEDIR 9/97/971/
PREPARE REMOVEDIR 9/97/
PREPARE REMOVEFILE 9/96/96text0
PREPARE REMOVEFILE 9/96/96text1
PREPARE REMOVEDIR 9/96/
PREPARE REMOVEDIR 9/95/
PREPARE REMOVEDIR 9/95/
PREPARE REMOVEDIR 9/94/
PREPARE REMOVEDIR 9/94/
PREPARE REMOVEDIR 9/93/
PREPARE REMOVEDIR 9/92/
PREPARE REMOVEDIR 9/91/
PREPARE REMOVEDIR 9/90/
PREPARE REMOVEDIR 9/90/
PREPARE REMOVEDIR 8/89/
PREPARE REMOVEDIR 8/89/
PREPARE REMOVEDIR 8/88/
PREPARE REMOVEFILE 8/87/870/87xtext0
PREPARE REMOVEFILE 8/87/870/87xtext1
PREPARE REMOVEDIR 8/87/870/
PREPARE REMOVEFILE 8/87/871/87xtext0
PREPARE REMOVEFILE 8/87/871/87xtext1
PREPARE REMOVEDIR 8/87/871/
PREPARE REMOVEDIR 8/87/
PREPARE REMOVEFILE 8/86/86text0
PREPARE REMOVEFILE 8/86/86text1
PREPARE REMOVEDIR 8/86/
PREPARE REMOVEDIR 8/85/
PREPARE REMOVEDIR 8/85/
PREPARE REMOVEDIR 8/84/
PREPARE REMOVEDIR 8/84/
PREPARE REMOVEDIR 8/83/
PREPARE REMOVEDIR 8/82/
PREPARE REMOVEDIR 8/81/
PREPARE REMOVEDIR 8/80/
PREPARE REMOVEDIR 8/80/
PREPARE REMOVEFILE 7/70/7xtest.exe
PREPARE REMOVEFILE 7/70/7xtext0
PREPARE REMOVEFILE 7/70/7xtext1
PREPARE REMOVEDIR 7/70/
PREPARE REMOVEFILE 7/71/7xtest.exe
PREPARE REMOVEFILE 7/71/7xtext0
PREPARE REMOVEFILE 7/71/7xtext1
PREPARE REMOVEDIR 7/71/
PREPARE REMOVEFILE 7/7text0
PREPARE REMOVEFILE 7/7text1
PREPARE REMOVEDIR 7/
PREPARE REMOVEDIR 6/
PREPARE REMOVEFILE 5/5text1
PREPARE REMOVEFILE 5/5text0
PREPARE REMOVEFILE 5/5test.exe
PREPARE REMOVEFILE 5/5text0
PREPARE REMOVEFILE 5/5text1
PREPARE REMOVEDIR 5/
PREPARE REMOVEFILE 4/4text1
PREPARE REMOVEFILE 4/4text0
PREPARE REMOVEDIR 4/
PREPARE REMOVEFILE 3/3text1
PREPARE REMOVEFILE 3/3text0
EXECUTE REMOVEFILE searchplugins/searchpluginstext0
EXECUTE REMOVEFILE searchplugins/searchpluginspng0.png
EXECUTE REMOVEFILE removed-files
EXECUTE REMOVEFILE precomplete
EXECUTE REMOVEFILE exe0.exe
EXECUTE REMOVEFILE 2/20/20text0
EXECUTE REMOVEFILE 2/20/20png0.png
EXECUTE REMOVEFILE 0/0exe0.exe
EXECUTE REMOVEFILE 0/00/00text0
EXECUTE REMOVEDIR searchplugins/
EXECUTE REMOVEDIR defaults/pref/
EXECUTE REMOVEDIR defaults/
EXECUTE REMOVEDIR 2/20/
EXECUTE REMOVEDIR 2/
EXECUTE REMOVEDIR 0/00/
EXECUTE REMOVEDIR 0/
EXECUTE ADD searchplugins/searchpluginstext0
EXECUTE ADD searchplugins/searchpluginspng1.png
EXECUTE ADD searchplugins/searchpluginspng0.png
EXECUTE ADD removed-files
EXECUTE ADD precomplete
EXECUTE ADD exe0.exe
EXECUTE ADD distribution/extensions/extensions1/extensions1text0
EXECUTE ADD distribution/extensions/extensions1/extensions1png1.png
EXECUTE ADD distribution/extensions/extensions1/extensions1png0.png
EXECUTE ADD distribution/extensions/extensions0/extensions0text0
EXECUTE ADD distribution/extensions/extensions0/extensions0png1.png
EXECUTE ADD distribution/extensions/extensions0/extensions0png0.png
EXECUTE ADD 1/10/10text0
EXECUTE ADD 0/0exe0.exe
EXECUTE ADD 0/00/00text1
EXECUTE ADD 0/00/00text0
EXECUTE ADD 0/00/00png0.png
EXECUTE REMOVEDIR 9/99/
EXECUTE REMOVEDIR 9/99/
EXECUTE REMOVEDIR 9/98/
EXECUTE REMOVEFILE 9/97/970/97xtext0
EXECUTE REMOVEFILE 9/97/970/97xtext1
EXECUTE REMOVEDIR 9/97/970/
EXECUTE REMOVEFILE 9/97/971/97xtext0
EXECUTE REMOVEFILE 9/97/971/97xtext1
EXECUTE REMOVEDIR 9/97/971/
EXECUTE REMOVEDIR 9/97/
EXECUTE REMOVEFILE 9/96/96text0
EXECUTE REMOVEFILE 9/96/96text1
EXECUTE REMOVEDIR 9/96/
EXECUTE REMOVEDIR 9/95/
EXECUTE REMOVEDIR 9/95/
EXECUTE REMOVEDIR 9/94/
EXECUTE REMOVEDIR 9/94/
EXECUTE REMOVEDIR 9/93/
EXECUTE REMOVEDIR 9/92/
EXECUTE REMOVEDIR 9/91/
EXECUTE REMOVEDIR 9/90/
EXECUTE REMOVEDIR 9/90/
EXECUTE REMOVEDIR 8/89/
EXECUTE REMOVEDIR 8/89/
EXECUTE REMOVEDIR 8/88/
EXECUTE REMOVEFILE 8/87/870/87xtext0
EXECUTE REMOVEFILE 8/87/870/87xtext1
EXECUTE REMOVEDIR 8/87/870/
EXECUTE REMOVEFILE 8/87/871/87xtext0
EXECUTE REMOVEFILE 8/87/871/87xtext1
EXECUTE REMOVEDIR 8/87/871/
EXECUTE REMOVEDIR 8/87/
EXECUTE REMOVEFILE 8/86/86text0
EXECUTE REMOVEFILE 8/86/86text1
EXECUTE REMOVEDIR 8/86/
EXECUTE REMOVEDIR 8/85/
EXECUTE REMOVEDIR 8/85/
EXECUTE REMOVEDIR 8/84/
EXECUTE REMOVEDIR 8/84/
EXECUTE REMOVEDIR 8/83/
EXECUTE REMOVEDIR 8/82/
EXECUTE REMOVEDIR 8/81/
EXECUTE REMOVEDIR 8/80/
EXECUTE REMOVEDIR 8/80/
EXECUTE REMOVEFILE 7/70/7xtest.exe
EXECUTE REMOVEFILE 7/70/7xtext0
EXECUTE REMOVEFILE 7/70/7xtext1
EXECUTE REMOVEDIR 7/70/
EXECUTE REMOVEFILE 7/71/7xtest.exe
EXECUTE REMOVEFILE 7/71/7xtext0
EXECUTE REMOVEFILE 7/71/7xtext1
EXECUTE REMOVEDIR 7/71/
EXECUTE REMOVEFILE 7/7text0
EXECUTE REMOVEFILE 7/7text1
EXECUTE REMOVEDIR 7/
EXECUTE REMOVEDIR 6/
EXECUTE REMOVEFILE 5/5text1
EXECUTE REMOVEFILE 5/5text0
EXECUTE REMOVEFILE 5/5test.exe
EXECUTE REMOVEFILE 5/5text0
file cannot be removed because it does not exist; skipping
EXECUTE REMOVEFILE 5/5text1
file cannot be removed because it does not exist; skipping
EXECUTE REMOVEDIR 5/
EXECUTE REMOVEFILE 4/4text1
EXECUTE REMOVEFILE 4/4text0
EXECUTE REMOVEDIR 4/
EXECUTE REMOVEFILE 3/3text1
EXECUTE REMOVEFILE 3/3text0
FINISH REMOVEFILE searchplugins/searchpluginstext0
FINISH REMOVEFILE searchplugins/searchpluginspng0.png
FINISH REMOVEFILE removed-files
FINISH REMOVEFILE precomplete
FINISH REMOVEFILE exe0.exe
FINISH REMOVEFILE 2/20/20text0
FINISH REMOVEFILE 2/20/20png0.png
FINISH REMOVEFILE 0/0exe0.exe
FINISH REMOVEFILE 0/00/00text0
FINISH REMOVEDIR searchplugins/
removing directory: searchplugins/, rv: 0
FINISH REMOVEDIR defaults/pref/
removing directory: defaults/pref/, rv: 0
FINISH REMOVEDIR defaults/
removing directory: defaults/, rv: 0
FINISH REMOVEDIR 2/20/
FINISH REMOVEDIR 2/
FINISH REMOVEDIR 0/00/
removing directory: 0/00/, rv: 0
FINISH REMOVEDIR 0/
removing directory: 0/, rv: 0
FINISH ADD searchplugins/searchpluginstext0
FINISH ADD searchplugins/searchpluginspng1.png
FINISH ADD searchplugins/searchpluginspng0.png
FINISH ADD removed-files
FINISH ADD precomplete
FINISH ADD exe0.exe
FINISH ADD distribution/extensions/extensions1/extensions1text0
FINISH ADD distribution/extensions/extensions1/extensions1png1.png
FINISH ADD distribution/extensions/extensions1/extensions1png0.png
FINISH ADD distribution/extensions/extensions0/extensions0text0
FINISH ADD distribution/extensions/extensions0/extensions0png1.png
FINISH ADD distribution/extensions/extensions0/extensions0png0.png
FINISH ADD 1/10/10text0
FINISH ADD 0/0exe0.exe
FINISH ADD 0/00/00text1
FINISH ADD 0/00/00text0
FINISH ADD 0/00/00png0.png
FINISH REMOVEDIR 9/99/
FINISH REMOVEDIR 9/99/
directory no longer exists; skipping
FINISH REMOVEDIR 9/98/
FINISH REMOVEFILE 9/97/970/97xtext0
FINISH REMOVEFILE 9/97/970/97xtext1
FINISH REMOVEDIR 9/97/970/
FINISH REMOVEFILE 9/97/971/97xtext0
FINISH REMOVEFILE 9/97/971/97xtext1
FINISH REMOVEDIR 9/97/971/
FINISH REMOVEDIR 9/97/
FINISH REMOVEFILE 9/96/96text0
FINISH REMOVEFILE 9/96/96text1
FINISH REMOVEDIR 9/96/
FINISH REMOVEDIR 9/95/
FINISH REMOVEDIR 9/95/
directory no longer exists; skipping
FINISH REMOVEDIR 9/94/
FINISH REMOVEDIR 9/94/
directory no longer exists; skipping
FINISH REMOVEDIR 9/93/
FINISH REMOVEDIR 9/92/
removing directory: 9/92/, rv: 0
FINISH REMOVEDIR 9/91/
removing directory: 9/91/, rv: 0
FINISH REMOVEDIR 9/90/
FINISH REMOVEDIR 9/90/
directory no longer exists; skipping
FINISH REMOVEDIR 8/89/
FINISH REMOVEDIR 8/89/
directory no longer exists; skipping
FINISH REMOVEDIR 8/88/
FINISH REMOVEFILE 8/87/870/87xtext0
FINISH REMOVEFILE 8/87/870/87xtext1
FINISH REMOVEDIR 8/87/870/
FINISH REMOVEFILE 8/87/871/87xtext0
FINISH REMOVEFILE 8/87/871/87xtext1
FINISH REMOVEDIR 8/87/871/
FINISH REMOVEDIR 8/87/
FINISH REMOVEFILE 8/86/86text0
FINISH REMOVEFILE 8/86/86text1
FINISH REMOVEDIR 8/86/
FINISH REMOVEDIR 8/85/
FINISH REMOVEDIR 8/85/
directory no longer exists; skipping
FINISH REMOVEDIR 8/84/
FINISH REMOVEDIR 8/84/
directory no longer exists; skipping
FINISH REMOVEDIR 8/83/
FINISH REMOVEDIR 8/82/
removing directory: 8/82/, rv: 0
FINISH REMOVEDIR 8/81/
removing directory: 8/81/, rv: 0
FINISH REMOVEDIR 8/80/
FINISH REMOVEDIR 8/80/
directory no longer exists; skipping
FINISH REMOVEFILE 7/70/7xtest.exe
FINISH REMOVEFILE 7/70/7xtext0
FINISH REMOVEFILE 7/70/7xtext1
FINISH REMOVEDIR 7/70/
FINISH REMOVEFILE 7/71/7xtest.exe
FINISH REMOVEFILE 7/71/7xtext0
FINISH REMOVEFILE 7/71/7xtext1
FINISH REMOVEDIR 7/71/
FINISH REMOVEFILE 7/7text0
FINISH REMOVEFILE 7/7text1
FINISH REMOVEDIR 7/
FINISH REMOVEDIR 6/
FINISH REMOVEFILE 5/5text1
FINISH REMOVEFILE 5/5text0
FINISH REMOVEFILE 5/5test.exe
FINISH REMOVEDIR 5/
FINISH REMOVEFILE 4/4text1
FINISH REMOVEFILE 4/4text0
FINISH REMOVEDIR 4/
FINISH REMOVEFILE 3/3text1
FINISH REMOVEFILE 3/3text0
succeeded
calling QuitProgressUI

Binary file not shown.

View file

@ -0,0 +1,18 @@
remove "searchplugins/searchpluginstext0"
remove "searchplugins/searchpluginspng1.png"
remove "searchplugins/searchpluginspng0.png"
remove "removed-files"
remove "precomplete"
remove "exe0.exe"
remove "1/10/10text0"
remove "0/0exe0.exe"
remove "0/00/00text1"
remove "0/00/00text0"
remove "0/00/00png0.png"
rmdir "searchplugins/"
rmdir "defaults/pref/"
rmdir "defaults/"
rmdir "1/10/"
rmdir "1/"
rmdir "0/00/"
rmdir "0/"

View file

@ -0,0 +1,21 @@
remove "Contents/Resources/searchplugins/searchpluginstext0"
remove "Contents/Resources/searchplugins/searchpluginspng1.png"
remove "Contents/Resources/searchplugins/searchpluginspng0.png"
remove "Contents/Resources/removed-files"
remove "Contents/Resources/precomplete"
remove "Contents/Resources/1/10/10text0"
remove "Contents/Resources/0/0exe0.exe"
remove "Contents/Resources/0/00/00text1"
remove "Contents/Resources/0/00/00text0"
remove "Contents/Resources/0/00/00png0.png"
remove "Contents/MacOS/exe0.exe"
rmdir "Contents/Resources/searchplugins/"
rmdir "Contents/Resources/defaults/pref/"
rmdir "Contents/Resources/defaults/"
rmdir "Contents/Resources/1/10/"
rmdir "Contents/Resources/1/"
rmdir "Contents/Resources/0/00/"
rmdir "Contents/Resources/0/"
rmdir "Contents/Resources/"
rmdir "Contents/MacOS/"
rmdir "Contents/"

View file

@ -0,0 +1,41 @@
text0
text1
3/3text0
3/3text1
4/exe0.exe
4/4text0
4/4text1
4/
5/5text0
5/5text1
5/*
6/
7/*
8/80/
8/81/
8/82/
8/83/
8/84/
8/85/*
8/86/*
8/87/*
8/88/*
8/89/*
8/80/
8/84/*
8/85/*
8/89/
9/90/
9/91/
9/92/
9/93/
9/94/
9/95/*
9/96/*
9/97/*
9/98/*
9/99/*
9/90/
9/94/*
9/95/*
9/99/

View file

@ -0,0 +1,41 @@
Contents/Resources/text0
Contents/Resources/text1
Contents/Resources/3/3text0
Contents/Resources/3/3text1
Contents/Resources/4/exe0.exe
Contents/Resources/4/4text0
Contents/Resources/4/4text1
Contents/Resources/4/
Contents/Resources/5/5text0
Contents/Resources/5/5text1
Contents/Resources/5/*
Contents/Resources/6/
Contents/Resources/7/*
Contents/Resources/8/80/
Contents/Resources/8/81/
Contents/Resources/8/82/
Contents/Resources/8/83/
Contents/Resources/8/84/
Contents/Resources/8/85/*
Contents/Resources/8/86/*
Contents/Resources/8/87/*
Contents/Resources/8/88/*
Contents/Resources/8/89/*
Contents/Resources/8/80/
Contents/Resources/8/84/*
Contents/Resources/8/85/*
Contents/Resources/8/89/
Contents/Resources/9/90/
Contents/Resources/9/91/
Contents/Resources/9/92/
Contents/Resources/9/93/
Contents/Resources/9/94/
Contents/Resources/9/95/*
Contents/Resources/9/96/*
Contents/Resources/9/97/*
Contents/Resources/9/98/*
Contents/Resources/9/99/*
Contents/Resources/9/90/
Contents/Resources/9/94/*
Contents/Resources/9/95/*
Contents/Resources/9/99/

View file

@ -0,0 +1,59 @@
type "complete"
add "precomplete"
add "searchplugins/searchpluginstext0"
add "searchplugins/searchpluginspng1.png"
add "searchplugins/searchpluginspng0.png"
add "removed-files"
add-if "extensions/extensions1" "extensions/extensions1/extensions1text0"
add-if "extensions/extensions1" "extensions/extensions1/extensions1png1.png"
add-if "extensions/extensions1" "extensions/extensions1/extensions1png0.png"
add-if "extensions/extensions0" "extensions/extensions0/extensions0text0"
add-if "extensions/extensions0" "extensions/extensions0/extensions0png1.png"
add-if "extensions/extensions0" "extensions/extensions0/extensions0png0.png"
add "exe0.exe"
add "1/10/10text0"
add "0/0exe0.exe"
add "0/00/00text1"
add "0/00/00text0"
add "0/00/00png0.png"
remove "text1"
remove "text0"
rmrfdir "9/99/"
rmdir "9/99/"
rmrfdir "9/98/"
rmrfdir "9/97/"
rmrfdir "9/96/"
rmrfdir "9/95/"
rmrfdir "9/95/"
rmrfdir "9/94/"
rmdir "9/94/"
rmdir "9/93/"
rmdir "9/92/"
rmdir "9/91/"
rmdir "9/90/"
rmdir "9/90/"
rmrfdir "8/89/"
rmdir "8/89/"
rmrfdir "8/88/"
rmrfdir "8/87/"
rmrfdir "8/86/"
rmrfdir "8/85/"
rmrfdir "8/85/"
rmrfdir "8/84/"
rmdir "8/84/"
rmdir "8/83/"
rmdir "8/82/"
rmdir "8/81/"
rmdir "8/80/"
rmdir "8/80/"
rmrfdir "7/"
rmdir "6/"
remove "5/5text1"
remove "5/5text0"
rmrfdir "5/"
remove "4/exe0.exe"
remove "4/4text1"
remove "4/4text0"
rmdir "4/"
remove "3/3text1"
remove "3/3text0"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 776 B

View file

@ -0,0 +1,192 @@
UPDATE TYPE partial
PREPARE ADD Contents/Resources/searchplugins/searchpluginstext0
PREPARE PATCH Contents/Resources/searchplugins/searchpluginspng1.png
PREPARE PATCH Contents/Resources/searchplugins/searchpluginspng0.png
PREPARE ADD Contents/Resources/precomplete
PREPARE ADD Contents/Resources/distribution/extensions/extensions1/extensions1text0
PREPARE PATCH Contents/Resources/distribution/extensions/extensions1/extensions1png1.png
PREPARE PATCH Contents/Resources/distribution/extensions/extensions1/extensions1png0.png
PREPARE ADD Contents/Resources/distribution/extensions/extensions0/extensions0text0
PREPARE PATCH Contents/Resources/distribution/extensions/extensions0/extensions0png1.png
PREPARE PATCH Contents/Resources/distribution/extensions/extensions0/extensions0png0.png
PREPARE PATCH Contents/Resources/0/0exe0.exe
PREPARE ADD Contents/Resources/0/00/00text0
PREPARE PATCH Contents/Resources/0/00/00png0.png
PREPARE PATCH Contents/MacOS/exe0.exe
PREPARE ADD Contents/Resources/2/20/20text0
PREPARE ADD Contents/Resources/2/20/20png0.png
PREPARE ADD Contents/Resources/0/00/00text2
PREPARE REMOVEFILE Contents/Resources/1/10/10text0
PREPARE REMOVEFILE Contents/Resources/0/00/00text1
PREPARE REMOVEDIR Contents/Resources/9/99/
PREPARE REMOVEDIR Contents/Resources/9/99/
PREPARE REMOVEDIR Contents/Resources/9/98/
PREPARE REMOVEFILE Contents/Resources/9/97/970/97xtext0
PREPARE REMOVEFILE Contents/Resources/9/97/970/97xtext1
PREPARE REMOVEDIR Contents/Resources/9/97/970/
PREPARE REMOVEFILE Contents/Resources/9/97/971/97xtext0
PREPARE REMOVEFILE Contents/Resources/9/97/971/97xtext1
PREPARE REMOVEDIR Contents/Resources/9/97/971/
PREPARE REMOVEDIR Contents/Resources/9/97/
PREPARE REMOVEFILE Contents/Resources/9/96/96text0
PREPARE REMOVEFILE Contents/Resources/9/96/96text1
PREPARE REMOVEDIR Contents/Resources/9/96/
PREPARE REMOVEDIR Contents/Resources/9/95/
PREPARE REMOVEDIR Contents/Resources/9/95/
PREPARE REMOVEDIR Contents/Resources/9/94/
PREPARE REMOVEDIR Contents/Resources/9/94/
PREPARE REMOVEDIR Contents/Resources/9/93/
PREPARE REMOVEDIR Contents/Resources/9/92/
PREPARE REMOVEDIR Contents/Resources/9/91/
PREPARE REMOVEDIR Contents/Resources/9/90/
PREPARE REMOVEDIR Contents/Resources/9/90/
PREPARE REMOVEDIR Contents/Resources/8/89/
PREPARE REMOVEDIR Contents/Resources/8/89/
PREPARE REMOVEDIR Contents/Resources/8/88/
PREPARE REMOVEFILE Contents/Resources/8/87/870/87xtext0
PREPARE REMOVEFILE Contents/Resources/8/87/870/87xtext1
PREPARE REMOVEDIR Contents/Resources/8/87/870/
PREPARE REMOVEFILE Contents/Resources/8/87/871/87xtext0
PREPARE REMOVEFILE Contents/Resources/8/87/871/87xtext1
PREPARE REMOVEDIR Contents/Resources/8/87/871/
PREPARE REMOVEDIR Contents/Resources/8/87/
PREPARE REMOVEFILE Contents/Resources/8/86/86text0
PREPARE REMOVEFILE Contents/Resources/8/86/86text1
PREPARE REMOVEDIR Contents/Resources/8/86/
PREPARE REMOVEDIR Contents/Resources/8/85/
PREPARE REMOVEDIR Contents/Resources/8/85/
PREPARE REMOVEDIR Contents/Resources/8/84/
PREPARE REMOVEDIR Contents/Resources/8/84/
PREPARE REMOVEDIR Contents/Resources/8/83/
PREPARE REMOVEDIR Contents/Resources/8/82/
PREPARE REMOVEDIR Contents/Resources/8/81/
PREPARE REMOVEDIR Contents/Resources/8/80/
PREPARE REMOVEDIR Contents/Resources/8/80/
PREPARE REMOVEFILE Contents/Resources/7/70/7xtest.exe
PREPARE REMOVEFILE Contents/Resources/7/70/7xtext0
PREPARE REMOVEFILE Contents/Resources/7/70/7xtext1
PREPARE REMOVEDIR Contents/Resources/7/70/
PREPARE REMOVEFILE Contents/Resources/7/71/7xtest.exe
PREPARE REMOVEFILE Contents/Resources/7/71/7xtext0
PREPARE REMOVEFILE Contents/Resources/7/71/7xtext1
PREPARE REMOVEDIR Contents/Resources/7/71/
PREPARE REMOVEFILE Contents/Resources/7/7text0
PREPARE REMOVEFILE Contents/Resources/7/7text1
PREPARE REMOVEDIR Contents/Resources/7/
PREPARE REMOVEDIR Contents/Resources/6/
PREPARE REMOVEFILE Contents/Resources/5/5text1
PREPARE REMOVEFILE Contents/Resources/5/5text0
PREPARE REMOVEFILE Contents/Resources/5/5test.exe
PREPARE REMOVEFILE Contents/Resources/5/5text0
PREPARE REMOVEFILE Contents/Resources/5/5text1
PREPARE REMOVEDIR Contents/Resources/5/
PREPARE REMOVEFILE Contents/Resources/4/4text1
PREPARE REMOVEFILE Contents/Resources/4/4text0
PREPARE REMOVEDIR Contents/Resources/4/
PREPARE REMOVEFILE Contents/Resources/3/3text1
PREPARE REMOVEFILE Contents/Resources/3/3text0
PREPARE REMOVEDIR Contents/Resources/1/10/
PREPARE REMOVEDIR Contents/Resources/1/
EXECUTE ADD Contents/Resources/searchplugins/searchpluginstext0
EXECUTE PATCH Contents/Resources/searchplugins/searchpluginspng1.png
EXECUTE PATCH Contents/Resources/searchplugins/searchpluginspng0.png
EXECUTE ADD Contents/Resources/precomplete
EXECUTE ADD Contents/Resources/distribution/extensions/extensions1/extensions1text0
EXECUTE PATCH Contents/Resources/distribution/extensions/extensions1/extensions1png1.png
EXECUTE PATCH Contents/Resources/distribution/extensions/extensions1/extensions1png0.png
EXECUTE ADD Contents/Resources/distribution/extensions/extensions0/extensions0text0
EXECUTE PATCH Contents/Resources/distribution/extensions/extensions0/extensions0png1.png
EXECUTE PATCH Contents/Resources/distribution/extensions/extensions0/extensions0png0.png
EXECUTE PATCH Contents/Resources/0/0exe0.exe
LoadSourceFile: destination file size 776 does not match expected size 79872
LoadSourceFile failed
### execution failed
FINISH ADD Contents/Resources/searchplugins/searchpluginstext0
FINISH PATCH Contents/Resources/searchplugins/searchpluginspng1.png
FINISH PATCH Contents/Resources/searchplugins/searchpluginspng0.png
FINISH ADD Contents/Resources/precomplete
FINISH ADD Contents/Resources/distribution/extensions/extensions1/extensions1text0
backup_restore: backup file doesn't exist: Contents/Resources/distribution/extensions/extensions1/extensions1text0.moz-backup
FINISH PATCH Contents/Resources/distribution/extensions/extensions1/extensions1png1.png
FINISH PATCH Contents/Resources/distribution/extensions/extensions1/extensions1png0.png
FINISH ADD Contents/Resources/distribution/extensions/extensions0/extensions0text0
FINISH PATCH Contents/Resources/distribution/extensions/extensions0/extensions0png1.png
FINISH PATCH Contents/Resources/distribution/extensions/extensions0/extensions0png0.png
FINISH PATCH Contents/Resources/0/0exe0.exe
backup_restore: backup file doesn't exist: Contents/Resources/0/0exe0.exe.moz-backup
FINISH ADD Contents/Resources/0/00/00text0
backup_restore: backup file doesn't exist: Contents/Resources/0/00/00text0.moz-backup
FINISH PATCH Contents/Resources/0/00/00png0.png
backup_restore: backup file doesn't exist: Contents/Resources/0/00/00png0.png.moz-backup
FINISH PATCH Contents/MacOS/exe0.exe
backup_restore: backup file doesn't exist: Contents/MacOS/exe0.exe.moz-backup
FINISH ADD Contents/Resources/2/20/20text0
backup_restore: backup file doesn't exist: Contents/Resources/2/20/20text0.moz-backup
FINISH ADD Contents/Resources/2/20/20png0.png
backup_restore: backup file doesn't exist: Contents/Resources/2/20/20png0.png.moz-backup
FINISH ADD Contents/Resources/0/00/00text2
backup_restore: backup file doesn't exist: Contents/Resources/0/00/00text2.moz-backup
FINISH REMOVEFILE Contents/Resources/1/10/10text0
backup_restore: backup file doesn't exist: Contents/Resources/1/10/10text0.moz-backup
FINISH REMOVEFILE Contents/Resources/0/00/00text1
backup_restore: backup file doesn't exist: Contents/Resources/0/00/00text1.moz-backup
FINISH REMOVEFILE Contents/Resources/9/97/970/97xtext0
backup_restore: backup file doesn't exist: Contents/Resources/9/97/970/97xtext0.moz-backup
FINISH REMOVEFILE Contents/Resources/9/97/970/97xtext1
backup_restore: backup file doesn't exist: Contents/Resources/9/97/970/97xtext1.moz-backup
FINISH REMOVEFILE Contents/Resources/9/97/971/97xtext0
backup_restore: backup file doesn't exist: Contents/Resources/9/97/971/97xtext0.moz-backup
FINISH REMOVEFILE Contents/Resources/9/97/971/97xtext1
backup_restore: backup file doesn't exist: Contents/Resources/9/97/971/97xtext1.moz-backup
FINISH REMOVEFILE Contents/Resources/9/96/96text0
backup_restore: backup file doesn't exist: Contents/Resources/9/96/96text0.moz-backup
FINISH REMOVEFILE Contents/Resources/9/96/96text1
backup_restore: backup file doesn't exist: Contents/Resources/9/96/96text1.moz-backup
FINISH REMOVEFILE Contents/Resources/8/87/870/87xtext0
backup_restore: backup file doesn't exist: Contents/Resources/8/87/870/87xtext0.moz-backup
FINISH REMOVEFILE Contents/Resources/8/87/870/87xtext1
backup_restore: backup file doesn't exist: Contents/Resources/8/87/870/87xtext1.moz-backup
FINISH REMOVEFILE Contents/Resources/8/87/871/87xtext0
backup_restore: backup file doesn't exist: Contents/Resources/8/87/871/87xtext0.moz-backup
FINISH REMOVEFILE Contents/Resources/8/87/871/87xtext1
backup_restore: backup file doesn't exist: Contents/Resources/8/87/871/87xtext1.moz-backup
FINISH REMOVEFILE Contents/Resources/8/86/86text0
backup_restore: backup file doesn't exist: Contents/Resources/8/86/86text0.moz-backup
FINISH REMOVEFILE Contents/Resources/8/86/86text1
backup_restore: backup file doesn't exist: Contents/Resources/8/86/86text1.moz-backup
FINISH REMOVEFILE Contents/Resources/7/70/7xtest.exe
backup_restore: backup file doesn't exist: Contents/Resources/7/70/7xtest.exe.moz-backup
FINISH REMOVEFILE Contents/Resources/7/70/7xtext0
backup_restore: backup file doesn't exist: Contents/Resources/7/70/7xtext0.moz-backup
FINISH REMOVEFILE Contents/Resources/7/70/7xtext1
backup_restore: backup file doesn't exist: Contents/Resources/7/70/7xtext1.moz-backup
FINISH REMOVEFILE Contents/Resources/7/71/7xtest.exe
backup_restore: backup file doesn't exist: Contents/Resources/7/71/7xtest.exe.moz-backup
FINISH REMOVEFILE Contents/Resources/7/71/7xtext0
backup_restore: backup file doesn't exist: Contents/Resources/7/71/7xtext0.moz-backup
FINISH REMOVEFILE Contents/Resources/7/71/7xtext1
backup_restore: backup file doesn't exist: Contents/Resources/7/71/7xtext1.moz-backup
FINISH REMOVEFILE Contents/Resources/7/7text0
backup_restore: backup file doesn't exist: Contents/Resources/7/7text0.moz-backup
FINISH REMOVEFILE Contents/Resources/7/7text1
backup_restore: backup file doesn't exist: Contents/Resources/7/7text1.moz-backup
FINISH REMOVEFILE Contents/Resources/5/5text1
backup_restore: backup file doesn't exist: Contents/Resources/5/5text1.moz-backup
FINISH REMOVEFILE Contents/Resources/5/5text0
backup_restore: backup file doesn't exist: Contents/Resources/5/5text0.moz-backup
FINISH REMOVEFILE Contents/Resources/5/5test.exe
backup_restore: backup file doesn't exist: Contents/Resources/5/5test.exe.moz-backup
FINISH REMOVEFILE Contents/Resources/5/5text0
backup_restore: backup file doesn't exist: Contents/Resources/5/5text0.moz-backup
FINISH REMOVEFILE Contents/Resources/5/5text1
backup_restore: backup file doesn't exist: Contents/Resources/5/5text1.moz-backup
FINISH REMOVEFILE Contents/Resources/4/4text1
backup_restore: backup file doesn't exist: Contents/Resources/4/4text1.moz-backup
FINISH REMOVEFILE Contents/Resources/4/4text0
backup_restore: backup file doesn't exist: Contents/Resources/4/4text0.moz-backup
FINISH REMOVEFILE Contents/Resources/3/3text1
backup_restore: backup file doesn't exist: Contents/Resources/3/3text1.moz-backup
FINISH REMOVEFILE Contents/Resources/3/3text0
backup_restore: backup file doesn't exist: Contents/Resources/3/3text0.moz-backup
failed: 2
calling QuitProgressUI

View file

@ -0,0 +1,192 @@
UPDATE TYPE partial
PREPARE ADD searchplugins/searchpluginstext0
PREPARE PATCH searchplugins/searchpluginspng1.png
PREPARE PATCH searchplugins/searchpluginspng0.png
PREPARE ADD precomplete
PREPARE PATCH exe0.exe
PREPARE ADD distribution/extensions/extensions1/extensions1text0
PREPARE PATCH distribution/extensions/extensions1/extensions1png1.png
PREPARE PATCH distribution/extensions/extensions1/extensions1png0.png
PREPARE ADD distribution/extensions/extensions0/extensions0text0
PREPARE PATCH distribution/extensions/extensions0/extensions0png1.png
PREPARE PATCH distribution/extensions/extensions0/extensions0png0.png
PREPARE PATCH 0/0exe0.exe
PREPARE ADD 0/00/00text0
PREPARE PATCH 0/00/00png0.png
PREPARE ADD 2/20/20text0
PREPARE ADD 2/20/20png0.png
PREPARE ADD 0/00/00text2
PREPARE REMOVEFILE 1/10/10text0
PREPARE REMOVEFILE 0/00/00text1
PREPARE REMOVEDIR 9/99/
PREPARE REMOVEDIR 9/99/
PREPARE REMOVEDIR 9/98/
PREPARE REMOVEFILE 9/97/970/97xtext0
PREPARE REMOVEFILE 9/97/970/97xtext1
PREPARE REMOVEDIR 9/97/970/
PREPARE REMOVEFILE 9/97/971/97xtext0
PREPARE REMOVEFILE 9/97/971/97xtext1
PREPARE REMOVEDIR 9/97/971/
PREPARE REMOVEDIR 9/97/
PREPARE REMOVEFILE 9/96/96text0
PREPARE REMOVEFILE 9/96/96text1
PREPARE REMOVEDIR 9/96/
PREPARE REMOVEDIR 9/95/
PREPARE REMOVEDIR 9/95/
PREPARE REMOVEDIR 9/94/
PREPARE REMOVEDIR 9/94/
PREPARE REMOVEDIR 9/93/
PREPARE REMOVEDIR 9/92/
PREPARE REMOVEDIR 9/91/
PREPARE REMOVEDIR 9/90/
PREPARE REMOVEDIR 9/90/
PREPARE REMOVEDIR 8/89/
PREPARE REMOVEDIR 8/89/
PREPARE REMOVEDIR 8/88/
PREPARE REMOVEFILE 8/87/870/87xtext0
PREPARE REMOVEFILE 8/87/870/87xtext1
PREPARE REMOVEDIR 8/87/870/
PREPARE REMOVEFILE 8/87/871/87xtext0
PREPARE REMOVEFILE 8/87/871/87xtext1
PREPARE REMOVEDIR 8/87/871/
PREPARE REMOVEDIR 8/87/
PREPARE REMOVEFILE 8/86/86text0
PREPARE REMOVEFILE 8/86/86text1
PREPARE REMOVEDIR 8/86/
PREPARE REMOVEDIR 8/85/
PREPARE REMOVEDIR 8/85/
PREPARE REMOVEDIR 8/84/
PREPARE REMOVEDIR 8/84/
PREPARE REMOVEDIR 8/83/
PREPARE REMOVEDIR 8/82/
PREPARE REMOVEDIR 8/81/
PREPARE REMOVEDIR 8/80/
PREPARE REMOVEDIR 8/80/
PREPARE REMOVEFILE 7/70/7xtest.exe
PREPARE REMOVEFILE 7/70/7xtext0
PREPARE REMOVEFILE 7/70/7xtext1
PREPARE REMOVEDIR 7/70/
PREPARE REMOVEFILE 7/71/7xtest.exe
PREPARE REMOVEFILE 7/71/7xtext0
PREPARE REMOVEFILE 7/71/7xtext1
PREPARE REMOVEDIR 7/71/
PREPARE REMOVEFILE 7/7text0
PREPARE REMOVEFILE 7/7text1
PREPARE REMOVEDIR 7/
PREPARE REMOVEDIR 6/
PREPARE REMOVEFILE 5/5text1
PREPARE REMOVEFILE 5/5text0
PREPARE REMOVEFILE 5/5test.exe
PREPARE REMOVEFILE 5/5text0
PREPARE REMOVEFILE 5/5text1
PREPARE REMOVEDIR 5/
PREPARE REMOVEFILE 4/4text1
PREPARE REMOVEFILE 4/4text0
PREPARE REMOVEDIR 4/
PREPARE REMOVEFILE 3/3text1
PREPARE REMOVEFILE 3/3text0
PREPARE REMOVEDIR 1/10/
PREPARE REMOVEDIR 1/
EXECUTE ADD searchplugins/searchpluginstext0
EXECUTE PATCH searchplugins/searchpluginspng1.png
EXECUTE PATCH searchplugins/searchpluginspng0.png
EXECUTE ADD precomplete
EXECUTE PATCH exe0.exe
EXECUTE ADD distribution/extensions/extensions1/extensions1text0
EXECUTE PATCH distribution/extensions/extensions1/extensions1png1.png
EXECUTE PATCH distribution/extensions/extensions1/extensions1png0.png
EXECUTE ADD distribution/extensions/extensions0/extensions0text0
EXECUTE PATCH distribution/extensions/extensions0/extensions0png1.png
EXECUTE PATCH distribution/extensions/extensions0/extensions0png0.png
EXECUTE PATCH 0/0exe0.exe
LoadSourceFile: destination file size 776 does not match expected size 79872
LoadSourceFile failed
### execution failed
FINISH ADD searchplugins/searchpluginstext0
FINISH PATCH searchplugins/searchpluginspng1.png
FINISH PATCH searchplugins/searchpluginspng0.png
FINISH ADD precomplete
FINISH PATCH exe0.exe
FINISH ADD distribution/extensions/extensions1/extensions1text0
backup_restore: backup file doesn't exist: distribution/extensions/extensions1/extensions1text0.moz-backup
FINISH PATCH distribution/extensions/extensions1/extensions1png1.png
FINISH PATCH distribution/extensions/extensions1/extensions1png0.png
FINISH ADD distribution/extensions/extensions0/extensions0text0
FINISH PATCH distribution/extensions/extensions0/extensions0png1.png
FINISH PATCH distribution/extensions/extensions0/extensions0png0.png
FINISH PATCH 0/0exe0.exe
backup_restore: backup file doesn't exist: 0/0exe0.exe.moz-backup
FINISH ADD 0/00/00text0
backup_restore: backup file doesn't exist: 0/00/00text0.moz-backup
FINISH PATCH 0/00/00png0.png
backup_restore: backup file doesn't exist: 0/00/00png0.png.moz-backup
FINISH ADD 2/20/20text0
backup_restore: backup file doesn't exist: 2/20/20text0.moz-backup
FINISH ADD 2/20/20png0.png
backup_restore: backup file doesn't exist: 2/20/20png0.png.moz-backup
FINISH ADD 0/00/00text2
backup_restore: backup file doesn't exist: 0/00/00text2.moz-backup
FINISH REMOVEFILE 1/10/10text0
backup_restore: backup file doesn't exist: 1/10/10text0.moz-backup
FINISH REMOVEFILE 0/00/00text1
backup_restore: backup file doesn't exist: 0/00/00text1.moz-backup
FINISH REMOVEFILE 9/97/970/97xtext0
backup_restore: backup file doesn't exist: 9/97/970/97xtext0.moz-backup
FINISH REMOVEFILE 9/97/970/97xtext1
backup_restore: backup file doesn't exist: 9/97/970/97xtext1.moz-backup
FINISH REMOVEFILE 9/97/971/97xtext0
backup_restore: backup file doesn't exist: 9/97/971/97xtext0.moz-backup
FINISH REMOVEFILE 9/97/971/97xtext1
backup_restore: backup file doesn't exist: 9/97/971/97xtext1.moz-backup
FINISH REMOVEFILE 9/96/96text0
backup_restore: backup file doesn't exist: 9/96/96text0.moz-backup
FINISH REMOVEFILE 9/96/96text1
backup_restore: backup file doesn't exist: 9/96/96text1.moz-backup
FINISH REMOVEFILE 8/87/870/87xtext0
backup_restore: backup file doesn't exist: 8/87/870/87xtext0.moz-backup
FINISH REMOVEFILE 8/87/870/87xtext1
backup_restore: backup file doesn't exist: 8/87/870/87xtext1.moz-backup
FINISH REMOVEFILE 8/87/871/87xtext0
backup_restore: backup file doesn't exist: 8/87/871/87xtext0.moz-backup
FINISH REMOVEFILE 8/87/871/87xtext1
backup_restore: backup file doesn't exist: 8/87/871/87xtext1.moz-backup
FINISH REMOVEFILE 8/86/86text0
backup_restore: backup file doesn't exist: 8/86/86text0.moz-backup
FINISH REMOVEFILE 8/86/86text1
backup_restore: backup file doesn't exist: 8/86/86text1.moz-backup
FINISH REMOVEFILE 7/70/7xtest.exe
backup_restore: backup file doesn't exist: 7/70/7xtest.exe.moz-backup
FINISH REMOVEFILE 7/70/7xtext0
backup_restore: backup file doesn't exist: 7/70/7xtext0.moz-backup
FINISH REMOVEFILE 7/70/7xtext1
backup_restore: backup file doesn't exist: 7/70/7xtext1.moz-backup
FINISH REMOVEFILE 7/71/7xtest.exe
backup_restore: backup file doesn't exist: 7/71/7xtest.exe.moz-backup
FINISH REMOVEFILE 7/71/7xtext0
backup_restore: backup file doesn't exist: 7/71/7xtext0.moz-backup
FINISH REMOVEFILE 7/71/7xtext1
backup_restore: backup file doesn't exist: 7/71/7xtext1.moz-backup
FINISH REMOVEFILE 7/7text0
backup_restore: backup file doesn't exist: 7/7text0.moz-backup
FINISH REMOVEFILE 7/7text1
backup_restore: backup file doesn't exist: 7/7text1.moz-backup
FINISH REMOVEFILE 5/5text1
backup_restore: backup file doesn't exist: 5/5text1.moz-backup
FINISH REMOVEFILE 5/5text0
backup_restore: backup file doesn't exist: 5/5text0.moz-backup
FINISH REMOVEFILE 5/5test.exe
backup_restore: backup file doesn't exist: 5/5test.exe.moz-backup
FINISH REMOVEFILE 5/5text0
backup_restore: backup file doesn't exist: 5/5text0.moz-backup
FINISH REMOVEFILE 5/5text1
backup_restore: backup file doesn't exist: 5/5text1.moz-backup
FINISH REMOVEFILE 4/4text1
backup_restore: backup file doesn't exist: 4/4text1.moz-backup
FINISH REMOVEFILE 4/4text0
backup_restore: backup file doesn't exist: 4/4text0.moz-backup
FINISH REMOVEFILE 3/3text1
backup_restore: backup file doesn't exist: 3/3text1.moz-backup
FINISH REMOVEFILE 3/3text0
backup_restore: backup file doesn't exist: 3/3text0.moz-backup
failed: 2
calling QuitProgressUI

View file

@ -0,0 +1,279 @@
UPDATE TYPE partial
PREPARE ADD Contents/Resources/searchplugins/searchpluginstext0
PREPARE PATCH Contents/Resources/searchplugins/searchpluginspng1.png
PREPARE PATCH Contents/Resources/searchplugins/searchpluginspng0.png
PREPARE ADD Contents/Resources/precomplete
PREPARE ADD Contents/Resources/distribution/extensions/extensions1/extensions1text0
PREPARE PATCH Contents/Resources/distribution/extensions/extensions1/extensions1png1.png
PREPARE PATCH Contents/Resources/distribution/extensions/extensions1/extensions1png0.png
PREPARE ADD Contents/Resources/distribution/extensions/extensions0/extensions0text0
PREPARE PATCH Contents/Resources/distribution/extensions/extensions0/extensions0png1.png
PREPARE PATCH Contents/Resources/distribution/extensions/extensions0/extensions0png0.png
PREPARE PATCH Contents/Resources/0/0exe0.exe
PREPARE ADD Contents/Resources/0/00/00text0
PREPARE PATCH Contents/Resources/0/00/00png0.png
PREPARE PATCH Contents/MacOS/exe0.exe
PREPARE ADD Contents/Resources/2/20/20text0
PREPARE ADD Contents/Resources/2/20/20png0.png
PREPARE ADD Contents/Resources/0/00/00text2
PREPARE REMOVEFILE Contents/Resources/1/10/10text0
PREPARE REMOVEFILE Contents/Resources/0/00/00text1
PREPARE REMOVEDIR Contents/Resources/9/99/
PREPARE REMOVEDIR Contents/Resources/9/99/
PREPARE REMOVEDIR Contents/Resources/9/98/
PREPARE REMOVEFILE Contents/Resources/9/97/970/97xtext0
PREPARE REMOVEFILE Contents/Resources/9/97/970/97xtext1
PREPARE REMOVEDIR Contents/Resources/9/97/970/
PREPARE REMOVEFILE Contents/Resources/9/97/971/97xtext0
PREPARE REMOVEFILE Contents/Resources/9/97/971/97xtext1
PREPARE REMOVEDIR Contents/Resources/9/97/971/
PREPARE REMOVEDIR Contents/Resources/9/97/
PREPARE REMOVEFILE Contents/Resources/9/96/96text0
PREPARE REMOVEFILE Contents/Resources/9/96/96text1
PREPARE REMOVEDIR Contents/Resources/9/96/
PREPARE REMOVEDIR Contents/Resources/9/95/
PREPARE REMOVEDIR Contents/Resources/9/95/
PREPARE REMOVEDIR Contents/Resources/9/94/
PREPARE REMOVEDIR Contents/Resources/9/94/
PREPARE REMOVEDIR Contents/Resources/9/93/
PREPARE REMOVEDIR Contents/Resources/9/92/
PREPARE REMOVEDIR Contents/Resources/9/91/
PREPARE REMOVEDIR Contents/Resources/9/90/
PREPARE REMOVEDIR Contents/Resources/9/90/
PREPARE REMOVEDIR Contents/Resources/8/89/
PREPARE REMOVEDIR Contents/Resources/8/89/
PREPARE REMOVEDIR Contents/Resources/8/88/
PREPARE REMOVEFILE Contents/Resources/8/87/870/87xtext0
PREPARE REMOVEFILE Contents/Resources/8/87/870/87xtext1
PREPARE REMOVEDIR Contents/Resources/8/87/870/
PREPARE REMOVEFILE Contents/Resources/8/87/871/87xtext0
PREPARE REMOVEFILE Contents/Resources/8/87/871/87xtext1
PREPARE REMOVEDIR Contents/Resources/8/87/871/
PREPARE REMOVEDIR Contents/Resources/8/87/
PREPARE REMOVEFILE Contents/Resources/8/86/86text0
PREPARE REMOVEFILE Contents/Resources/8/86/86text1
PREPARE REMOVEDIR Contents/Resources/8/86/
PREPARE REMOVEDIR Contents/Resources/8/85/
PREPARE REMOVEDIR Contents/Resources/8/85/
PREPARE REMOVEDIR Contents/Resources/8/84/
PREPARE REMOVEDIR Contents/Resources/8/84/
PREPARE REMOVEDIR Contents/Resources/8/83/
PREPARE REMOVEDIR Contents/Resources/8/82/
PREPARE REMOVEDIR Contents/Resources/8/81/
PREPARE REMOVEDIR Contents/Resources/8/80/
PREPARE REMOVEDIR Contents/Resources/8/80/
PREPARE REMOVEFILE Contents/Resources/7/70/7xtest.exe
PREPARE REMOVEFILE Contents/Resources/7/70/7xtext0
PREPARE REMOVEFILE Contents/Resources/7/70/7xtext1
PREPARE REMOVEDIR Contents/Resources/7/70/
PREPARE REMOVEFILE Contents/Resources/7/71/7xtest.exe
PREPARE REMOVEFILE Contents/Resources/7/71/7xtext0
PREPARE REMOVEFILE Contents/Resources/7/71/7xtext1
PREPARE REMOVEDIR Contents/Resources/7/71/
PREPARE REMOVEFILE Contents/Resources/7/7text0
PREPARE REMOVEFILE Contents/Resources/7/7text1
PREPARE REMOVEDIR Contents/Resources/7/
PREPARE REMOVEDIR Contents/Resources/6/
PREPARE REMOVEFILE Contents/Resources/5/5text1
PREPARE REMOVEFILE Contents/Resources/5/5text0
PREPARE REMOVEFILE Contents/Resources/5/5test.exe
PREPARE REMOVEFILE Contents/Resources/5/5text0
PREPARE REMOVEFILE Contents/Resources/5/5text1
PREPARE REMOVEDIR Contents/Resources/5/
PREPARE REMOVEFILE Contents/Resources/4/4text1
PREPARE REMOVEFILE Contents/Resources/4/4text0
PREPARE REMOVEDIR Contents/Resources/4/
PREPARE REMOVEFILE Contents/Resources/3/3text1
PREPARE REMOVEFILE Contents/Resources/3/3text0
PREPARE REMOVEDIR Contents/Resources/1/10/
PREPARE REMOVEDIR Contents/Resources/1/
EXECUTE ADD Contents/Resources/searchplugins/searchpluginstext0
EXECUTE PATCH Contents/Resources/searchplugins/searchpluginspng1.png
EXECUTE PATCH Contents/Resources/searchplugins/searchpluginspng0.png
EXECUTE ADD Contents/Resources/precomplete
EXECUTE ADD Contents/Resources/distribution/extensions/extensions1/extensions1text0
EXECUTE PATCH Contents/Resources/distribution/extensions/extensions1/extensions1png1.png
EXECUTE PATCH Contents/Resources/distribution/extensions/extensions1/extensions1png0.png
EXECUTE ADD Contents/Resources/distribution/extensions/extensions0/extensions0text0
EXECUTE PATCH Contents/Resources/distribution/extensions/extensions0/extensions0png1.png
EXECUTE PATCH Contents/Resources/distribution/extensions/extensions0/extensions0png0.png
EXECUTE PATCH Contents/Resources/0/0exe0.exe
EXECUTE ADD Contents/Resources/0/00/00text0
EXECUTE PATCH Contents/Resources/0/00/00png0.png
EXECUTE PATCH Contents/MacOS/exe0.exe
EXECUTE ADD Contents/Resources/2/20/20text0
EXECUTE ADD Contents/Resources/2/20/20png0.png
EXECUTE ADD Contents/Resources/0/00/00text2
EXECUTE REMOVEFILE Contents/Resources/1/10/10text0
EXECUTE REMOVEFILE Contents/Resources/0/00/00text1
EXECUTE REMOVEDIR Contents/Resources/9/99/
EXECUTE REMOVEDIR Contents/Resources/9/99/
EXECUTE REMOVEDIR Contents/Resources/9/98/
EXECUTE REMOVEFILE Contents/Resources/9/97/970/97xtext0
EXECUTE REMOVEFILE Contents/Resources/9/97/970/97xtext1
EXECUTE REMOVEDIR Contents/Resources/9/97/970/
EXECUTE REMOVEFILE Contents/Resources/9/97/971/97xtext0
EXECUTE REMOVEFILE Contents/Resources/9/97/971/97xtext1
EXECUTE REMOVEDIR Contents/Resources/9/97/971/
EXECUTE REMOVEDIR Contents/Resources/9/97/
EXECUTE REMOVEFILE Contents/Resources/9/96/96text0
EXECUTE REMOVEFILE Contents/Resources/9/96/96text1
EXECUTE REMOVEDIR Contents/Resources/9/96/
EXECUTE REMOVEDIR Contents/Resources/9/95/
EXECUTE REMOVEDIR Contents/Resources/9/95/
EXECUTE REMOVEDIR Contents/Resources/9/94/
EXECUTE REMOVEDIR Contents/Resources/9/94/
EXECUTE REMOVEDIR Contents/Resources/9/93/
EXECUTE REMOVEDIR Contents/Resources/9/92/
EXECUTE REMOVEDIR Contents/Resources/9/91/
EXECUTE REMOVEDIR Contents/Resources/9/90/
EXECUTE REMOVEDIR Contents/Resources/9/90/
EXECUTE REMOVEDIR Contents/Resources/8/89/
EXECUTE REMOVEDIR Contents/Resources/8/89/
EXECUTE REMOVEDIR Contents/Resources/8/88/
EXECUTE REMOVEFILE Contents/Resources/8/87/870/87xtext0
EXECUTE REMOVEFILE Contents/Resources/8/87/870/87xtext1
EXECUTE REMOVEDIR Contents/Resources/8/87/870/
EXECUTE REMOVEFILE Contents/Resources/8/87/871/87xtext0
EXECUTE REMOVEFILE Contents/Resources/8/87/871/87xtext1
EXECUTE REMOVEDIR Contents/Resources/8/87/871/
EXECUTE REMOVEDIR Contents/Resources/8/87/
EXECUTE REMOVEFILE Contents/Resources/8/86/86text0
EXECUTE REMOVEFILE Contents/Resources/8/86/86text1
EXECUTE REMOVEDIR Contents/Resources/8/86/
EXECUTE REMOVEDIR Contents/Resources/8/85/
EXECUTE REMOVEDIR Contents/Resources/8/85/
EXECUTE REMOVEDIR Contents/Resources/8/84/
EXECUTE REMOVEDIR Contents/Resources/8/84/
EXECUTE REMOVEDIR Contents/Resources/8/83/
EXECUTE REMOVEDIR Contents/Resources/8/82/
EXECUTE REMOVEDIR Contents/Resources/8/81/
EXECUTE REMOVEDIR Contents/Resources/8/80/
EXECUTE REMOVEDIR Contents/Resources/8/80/
EXECUTE REMOVEFILE Contents/Resources/7/70/7xtest.exe
EXECUTE REMOVEFILE Contents/Resources/7/70/7xtext0
EXECUTE REMOVEFILE Contents/Resources/7/70/7xtext1
EXECUTE REMOVEDIR Contents/Resources/7/70/
EXECUTE REMOVEFILE Contents/Resources/7/71/7xtest.exe
EXECUTE REMOVEFILE Contents/Resources/7/71/7xtext0
EXECUTE REMOVEFILE Contents/Resources/7/71/7xtext1
EXECUTE REMOVEDIR Contents/Resources/7/71/
EXECUTE REMOVEFILE Contents/Resources/7/7text0
EXECUTE REMOVEFILE Contents/Resources/7/7text1
EXECUTE REMOVEDIR Contents/Resources/7/
EXECUTE REMOVEDIR Contents/Resources/6/
EXECUTE REMOVEFILE Contents/Resources/5/5text1
EXECUTE REMOVEFILE Contents/Resources/5/5text0
EXECUTE REMOVEFILE Contents/Resources/5/5test.exe
EXECUTE REMOVEFILE Contents/Resources/5/5text0
file cannot be removed because it does not exist; skipping
EXECUTE REMOVEFILE Contents/Resources/5/5text1
file cannot be removed because it does not exist; skipping
EXECUTE REMOVEDIR Contents/Resources/5/
EXECUTE REMOVEFILE Contents/Resources/4/4text1
EXECUTE REMOVEFILE Contents/Resources/4/4text0
EXECUTE REMOVEDIR Contents/Resources/4/
EXECUTE REMOVEFILE Contents/Resources/3/3text1
EXECUTE REMOVEFILE Contents/Resources/3/3text0
EXECUTE REMOVEDIR Contents/Resources/1/10/
EXECUTE REMOVEDIR Contents/Resources/1/
FINISH ADD Contents/Resources/searchplugins/searchpluginstext0
FINISH PATCH Contents/Resources/searchplugins/searchpluginspng1.png
FINISH PATCH Contents/Resources/searchplugins/searchpluginspng0.png
FINISH ADD Contents/Resources/precomplete
FINISH ADD Contents/Resources/distribution/extensions/extensions1/extensions1text0
FINISH PATCH Contents/Resources/distribution/extensions/extensions1/extensions1png1.png
FINISH PATCH Contents/Resources/distribution/extensions/extensions1/extensions1png0.png
FINISH ADD Contents/Resources/distribution/extensions/extensions0/extensions0text0
FINISH PATCH Contents/Resources/distribution/extensions/extensions0/extensions0png1.png
FINISH PATCH Contents/Resources/distribution/extensions/extensions0/extensions0png0.png
FINISH PATCH Contents/Resources/0/0exe0.exe
FINISH ADD Contents/Resources/0/00/00text0
FINISH PATCH Contents/Resources/0/00/00png0.png
FINISH PATCH Contents/MacOS/exe0.exe
FINISH ADD Contents/Resources/2/20/20text0
FINISH ADD Contents/Resources/2/20/20png0.png
FINISH ADD Contents/Resources/0/00/00text2
FINISH REMOVEFILE Contents/Resources/1/10/10text0
FINISH REMOVEFILE Contents/Resources/0/00/00text1
FINISH REMOVEDIR Contents/Resources/9/99/
FINISH REMOVEDIR Contents/Resources/9/99/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/9/98/
FINISH REMOVEFILE Contents/Resources/9/97/970/97xtext0
FINISH REMOVEFILE Contents/Resources/9/97/970/97xtext1
FINISH REMOVEDIR Contents/Resources/9/97/970/
FINISH REMOVEFILE Contents/Resources/9/97/971/97xtext0
FINISH REMOVEFILE Contents/Resources/9/97/971/97xtext1
FINISH REMOVEDIR Contents/Resources/9/97/971/
FINISH REMOVEDIR Contents/Resources/9/97/
FINISH REMOVEFILE Contents/Resources/9/96/96text0
FINISH REMOVEFILE Contents/Resources/9/96/96text1
FINISH REMOVEDIR Contents/Resources/9/96/
FINISH REMOVEDIR Contents/Resources/9/95/
FINISH REMOVEDIR Contents/Resources/9/95/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/9/94/
FINISH REMOVEDIR Contents/Resources/9/94/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/9/93/
FINISH REMOVEDIR Contents/Resources/9/92/
removing directory: Contents/Resources/9/92/, rv: 0
FINISH REMOVEDIR Contents/Resources/9/91/
removing directory: Contents/Resources/9/91/, rv: 0
FINISH REMOVEDIR Contents/Resources/9/90/
FINISH REMOVEDIR Contents/Resources/9/90/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/8/89/
FINISH REMOVEDIR Contents/Resources/8/89/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/8/88/
FINISH REMOVEFILE Contents/Resources/8/87/870/87xtext0
FINISH REMOVEFILE Contents/Resources/8/87/870/87xtext1
FINISH REMOVEDIR Contents/Resources/8/87/870/
FINISH REMOVEFILE Contents/Resources/8/87/871/87xtext0
FINISH REMOVEFILE Contents/Resources/8/87/871/87xtext1
FINISH REMOVEDIR Contents/Resources/8/87/871/
FINISH REMOVEDIR Contents/Resources/8/87/
FINISH REMOVEFILE Contents/Resources/8/86/86text0
FINISH REMOVEFILE Contents/Resources/8/86/86text1
FINISH REMOVEDIR Contents/Resources/8/86/
FINISH REMOVEDIR Contents/Resources/8/85/
FINISH REMOVEDIR Contents/Resources/8/85/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/8/84/
FINISH REMOVEDIR Contents/Resources/8/84/
directory no longer exists; skipping
FINISH REMOVEDIR Contents/Resources/8/83/
FINISH REMOVEDIR Contents/Resources/8/82/
removing directory: Contents/Resources/8/82/, rv: 0
FINISH REMOVEDIR Contents/Resources/8/81/
removing directory: Contents/Resources/8/81/, rv: 0
FINISH REMOVEDIR Contents/Resources/8/80/
FINISH REMOVEDIR Contents/Resources/8/80/
directory no longer exists; skipping
FINISH REMOVEFILE Contents/Resources/7/70/7xtest.exe
FINISH REMOVEFILE Contents/Resources/7/70/7xtext0
FINISH REMOVEFILE Contents/Resources/7/70/7xtext1
FINISH REMOVEDIR Contents/Resources/7/70/
FINISH REMOVEFILE Contents/Resources/7/71/7xtest.exe
FINISH REMOVEFILE Contents/Resources/7/71/7xtext0
FINISH REMOVEFILE Contents/Resources/7/71/7xtext1
FINISH REMOVEDIR Contents/Resources/7/71/
FINISH REMOVEFILE Contents/Resources/7/7text0
FINISH REMOVEFILE Contents/Resources/7/7text1
FINISH REMOVEDIR Contents/Resources/7/
FINISH REMOVEDIR Contents/Resources/6/
FINISH REMOVEFILE Contents/Resources/5/5text1
FINISH REMOVEFILE Contents/Resources/5/5text0
FINISH REMOVEFILE Contents/Resources/5/5test.exe
FINISH REMOVEDIR Contents/Resources/5/
FINISH REMOVEFILE Contents/Resources/4/4text1
FINISH REMOVEFILE Contents/Resources/4/4text0
FINISH REMOVEDIR Contents/Resources/4/
FINISH REMOVEFILE Contents/Resources/3/3text1
FINISH REMOVEFILE Contents/Resources/3/3text0
FINISH REMOVEDIR Contents/Resources/1/10/
FINISH REMOVEDIR Contents/Resources/1/
succeeded
calling QuitProgressUI

View file

@ -0,0 +1,279 @@
UPDATE TYPE partial
PREPARE ADD searchplugins/searchpluginstext0
PREPARE PATCH searchplugins/searchpluginspng1.png
PREPARE PATCH searchplugins/searchpluginspng0.png
PREPARE ADD precomplete
PREPARE PATCH exe0.exe
PREPARE ADD distribution/extensions/extensions1/extensions1text0
PREPARE PATCH distribution/extensions/extensions1/extensions1png1.png
PREPARE PATCH distribution/extensions/extensions1/extensions1png0.png
PREPARE ADD distribution/extensions/extensions0/extensions0text0
PREPARE PATCH distribution/extensions/extensions0/extensions0png1.png
PREPARE PATCH distribution/extensions/extensions0/extensions0png0.png
PREPARE PATCH 0/0exe0.exe
PREPARE ADD 0/00/00text0
PREPARE PATCH 0/00/00png0.png
PREPARE ADD 2/20/20text0
PREPARE ADD 2/20/20png0.png
PREPARE ADD 0/00/00text2
PREPARE REMOVEFILE 1/10/10text0
PREPARE REMOVEFILE 0/00/00text1
PREPARE REMOVEDIR 9/99/
PREPARE REMOVEDIR 9/99/
PREPARE REMOVEDIR 9/98/
PREPARE REMOVEFILE 9/97/970/97xtext0
PREPARE REMOVEFILE 9/97/970/97xtext1
PREPARE REMOVEDIR 9/97/970/
PREPARE REMOVEFILE 9/97/971/97xtext0
PREPARE REMOVEFILE 9/97/971/97xtext1
PREPARE REMOVEDIR 9/97/971/
PREPARE REMOVEDIR 9/97/
PREPARE REMOVEFILE 9/96/96text0
PREPARE REMOVEFILE 9/96/96text1
PREPARE REMOVEDIR 9/96/
PREPARE REMOVEDIR 9/95/
PREPARE REMOVEDIR 9/95/
PREPARE REMOVEDIR 9/94/
PREPARE REMOVEDIR 9/94/
PREPARE REMOVEDIR 9/93/
PREPARE REMOVEDIR 9/92/
PREPARE REMOVEDIR 9/91/
PREPARE REMOVEDIR 9/90/
PREPARE REMOVEDIR 9/90/
PREPARE REMOVEDIR 8/89/
PREPARE REMOVEDIR 8/89/
PREPARE REMOVEDIR 8/88/
PREPARE REMOVEFILE 8/87/870/87xtext0
PREPARE REMOVEFILE 8/87/870/87xtext1
PREPARE REMOVEDIR 8/87/870/
PREPARE REMOVEFILE 8/87/871/87xtext0
PREPARE REMOVEFILE 8/87/871/87xtext1
PREPARE REMOVEDIR 8/87/871/
PREPARE REMOVEDIR 8/87/
PREPARE REMOVEFILE 8/86/86text0
PREPARE REMOVEFILE 8/86/86text1
PREPARE REMOVEDIR 8/86/
PREPARE REMOVEDIR 8/85/
PREPARE REMOVEDIR 8/85/
PREPARE REMOVEDIR 8/84/
PREPARE REMOVEDIR 8/84/
PREPARE REMOVEDIR 8/83/
PREPARE REMOVEDIR 8/82/
PREPARE REMOVEDIR 8/81/
PREPARE REMOVEDIR 8/80/
PREPARE REMOVEDIR 8/80/
PREPARE REMOVEFILE 7/70/7xtest.exe
PREPARE REMOVEFILE 7/70/7xtext0
PREPARE REMOVEFILE 7/70/7xtext1
PREPARE REMOVEDIR 7/70/
PREPARE REMOVEFILE 7/71/7xtest.exe
PREPARE REMOVEFILE 7/71/7xtext0
PREPARE REMOVEFILE 7/71/7xtext1
PREPARE REMOVEDIR 7/71/
PREPARE REMOVEFILE 7/7text0
PREPARE REMOVEFILE 7/7text1
PREPARE REMOVEDIR 7/
PREPARE REMOVEDIR 6/
PREPARE REMOVEFILE 5/5text1
PREPARE REMOVEFILE 5/5text0
PREPARE REMOVEFILE 5/5test.exe
PREPARE REMOVEFILE 5/5text0
PREPARE REMOVEFILE 5/5text1
PREPARE REMOVEDIR 5/
PREPARE REMOVEFILE 4/4text1
PREPARE REMOVEFILE 4/4text0
PREPARE REMOVEDIR 4/
PREPARE REMOVEFILE 3/3text1
PREPARE REMOVEFILE 3/3text0
PREPARE REMOVEDIR 1/10/
PREPARE REMOVEDIR 1/
EXECUTE ADD searchplugins/searchpluginstext0
EXECUTE PATCH searchplugins/searchpluginspng1.png
EXECUTE PATCH searchplugins/searchpluginspng0.png
EXECUTE ADD precomplete
EXECUTE PATCH exe0.exe
EXECUTE ADD distribution/extensions/extensions1/extensions1text0
EXECUTE PATCH distribution/extensions/extensions1/extensions1png1.png
EXECUTE PATCH distribution/extensions/extensions1/extensions1png0.png
EXECUTE ADD distribution/extensions/extensions0/extensions0text0
EXECUTE PATCH distribution/extensions/extensions0/extensions0png1.png
EXECUTE PATCH distribution/extensions/extensions0/extensions0png0.png
EXECUTE PATCH 0/0exe0.exe
EXECUTE ADD 0/00/00text0
EXECUTE PATCH 0/00/00png0.png
EXECUTE ADD 2/20/20text0
EXECUTE ADD 2/20/20png0.png
EXECUTE ADD 0/00/00text2
EXECUTE REMOVEFILE 1/10/10text0
EXECUTE REMOVEFILE 0/00/00text1
EXECUTE REMOVEDIR 9/99/
EXECUTE REMOVEDIR 9/99/
EXECUTE REMOVEDIR 9/98/
EXECUTE REMOVEFILE 9/97/970/97xtext0
EXECUTE REMOVEFILE 9/97/970/97xtext1
EXECUTE REMOVEDIR 9/97/970/
EXECUTE REMOVEFILE 9/97/971/97xtext0
EXECUTE REMOVEFILE 9/97/971/97xtext1
EXECUTE REMOVEDIR 9/97/971/
EXECUTE REMOVEDIR 9/97/
EXECUTE REMOVEFILE 9/96/96text0
EXECUTE REMOVEFILE 9/96/96text1
EXECUTE REMOVEDIR 9/96/
EXECUTE REMOVEDIR 9/95/
EXECUTE REMOVEDIR 9/95/
EXECUTE REMOVEDIR 9/94/
EXECUTE REMOVEDIR 9/94/
EXECUTE REMOVEDIR 9/93/
EXECUTE REMOVEDIR 9/92/
EXECUTE REMOVEDIR 9/91/
EXECUTE REMOVEDIR 9/90/
EXECUTE REMOVEDIR 9/90/
EXECUTE REMOVEDIR 8/89/
EXECUTE REMOVEDIR 8/89/
EXECUTE REMOVEDIR 8/88/
EXECUTE REMOVEFILE 8/87/870/87xtext0
EXECUTE REMOVEFILE 8/87/870/87xtext1
EXECUTE REMOVEDIR 8/87/870/
EXECUTE REMOVEFILE 8/87/871/87xtext0
EXECUTE REMOVEFILE 8/87/871/87xtext1
EXECUTE REMOVEDIR 8/87/871/
EXECUTE REMOVEDIR 8/87/
EXECUTE REMOVEFILE 8/86/86text0
EXECUTE REMOVEFILE 8/86/86text1
EXECUTE REMOVEDIR 8/86/
EXECUTE REMOVEDIR 8/85/
EXECUTE REMOVEDIR 8/85/
EXECUTE REMOVEDIR 8/84/
EXECUTE REMOVEDIR 8/84/
EXECUTE REMOVEDIR 8/83/
EXECUTE REMOVEDIR 8/82/
EXECUTE REMOVEDIR 8/81/
EXECUTE REMOVEDIR 8/80/
EXECUTE REMOVEDIR 8/80/
EXECUTE REMOVEFILE 7/70/7xtest.exe
EXECUTE REMOVEFILE 7/70/7xtext0
EXECUTE REMOVEFILE 7/70/7xtext1
EXECUTE REMOVEDIR 7/70/
EXECUTE REMOVEFILE 7/71/7xtest.exe
EXECUTE REMOVEFILE 7/71/7xtext0
EXECUTE REMOVEFILE 7/71/7xtext1
EXECUTE REMOVEDIR 7/71/
EXECUTE REMOVEFILE 7/7text0
EXECUTE REMOVEFILE 7/7text1
EXECUTE REMOVEDIR 7/
EXECUTE REMOVEDIR 6/
EXECUTE REMOVEFILE 5/5text1
EXECUTE REMOVEFILE 5/5text0
EXECUTE REMOVEFILE 5/5test.exe
EXECUTE REMOVEFILE 5/5text0
file cannot be removed because it does not exist; skipping
EXECUTE REMOVEFILE 5/5text1
file cannot be removed because it does not exist; skipping
EXECUTE REMOVEDIR 5/
EXECUTE REMOVEFILE 4/4text1
EXECUTE REMOVEFILE 4/4text0
EXECUTE REMOVEDIR 4/
EXECUTE REMOVEFILE 3/3text1
EXECUTE REMOVEFILE 3/3text0
EXECUTE REMOVEDIR 1/10/
EXECUTE REMOVEDIR 1/
FINISH ADD searchplugins/searchpluginstext0
FINISH PATCH searchplugins/searchpluginspng1.png
FINISH PATCH searchplugins/searchpluginspng0.png
FINISH ADD precomplete
FINISH PATCH exe0.exe
FINISH ADD distribution/extensions/extensions1/extensions1text0
FINISH PATCH distribution/extensions/extensions1/extensions1png1.png
FINISH PATCH distribution/extensions/extensions1/extensions1png0.png
FINISH ADD distribution/extensions/extensions0/extensions0text0
FINISH PATCH distribution/extensions/extensions0/extensions0png1.png
FINISH PATCH distribution/extensions/extensions0/extensions0png0.png
FINISH PATCH 0/0exe0.exe
FINISH ADD 0/00/00text0
FINISH PATCH 0/00/00png0.png
FINISH ADD 2/20/20text0
FINISH ADD 2/20/20png0.png
FINISH ADD 0/00/00text2
FINISH REMOVEFILE 1/10/10text0
FINISH REMOVEFILE 0/00/00text1
FINISH REMOVEDIR 9/99/
FINISH REMOVEDIR 9/99/
directory no longer exists; skipping
FINISH REMOVEDIR 9/98/
FINISH REMOVEFILE 9/97/970/97xtext0
FINISH REMOVEFILE 9/97/970/97xtext1
FINISH REMOVEDIR 9/97/970/
FINISH REMOVEFILE 9/97/971/97xtext0
FINISH REMOVEFILE 9/97/971/97xtext1
FINISH REMOVEDIR 9/97/971/
FINISH REMOVEDIR 9/97/
FINISH REMOVEFILE 9/96/96text0
FINISH REMOVEFILE 9/96/96text1
FINISH REMOVEDIR 9/96/
FINISH REMOVEDIR 9/95/
FINISH REMOVEDIR 9/95/
directory no longer exists; skipping
FINISH REMOVEDIR 9/94/
FINISH REMOVEDIR 9/94/
directory no longer exists; skipping
FINISH REMOVEDIR 9/93/
FINISH REMOVEDIR 9/92/
removing directory: 9/92/, rv: 0
FINISH REMOVEDIR 9/91/
removing directory: 9/91/, rv: 0
FINISH REMOVEDIR 9/90/
FINISH REMOVEDIR 9/90/
directory no longer exists; skipping
FINISH REMOVEDIR 8/89/
FINISH REMOVEDIR 8/89/
directory no longer exists; skipping
FINISH REMOVEDIR 8/88/
FINISH REMOVEFILE 8/87/870/87xtext0
FINISH REMOVEFILE 8/87/870/87xtext1
FINISH REMOVEDIR 8/87/870/
FINISH REMOVEFILE 8/87/871/87xtext0
FINISH REMOVEFILE 8/87/871/87xtext1
FINISH REMOVEDIR 8/87/871/
FINISH REMOVEDIR 8/87/
FINISH REMOVEFILE 8/86/86text0
FINISH REMOVEFILE 8/86/86text1
FINISH REMOVEDIR 8/86/
FINISH REMOVEDIR 8/85/
FINISH REMOVEDIR 8/85/
directory no longer exists; skipping
FINISH REMOVEDIR 8/84/
FINISH REMOVEDIR 8/84/
directory no longer exists; skipping
FINISH REMOVEDIR 8/83/
FINISH REMOVEDIR 8/82/
removing directory: 8/82/, rv: 0
FINISH REMOVEDIR 8/81/
removing directory: 8/81/, rv: 0
FINISH REMOVEDIR 8/80/
FINISH REMOVEDIR 8/80/
directory no longer exists; skipping
FINISH REMOVEFILE 7/70/7xtest.exe
FINISH REMOVEFILE 7/70/7xtext0
FINISH REMOVEFILE 7/70/7xtext1
FINISH REMOVEDIR 7/70/
FINISH REMOVEFILE 7/71/7xtest.exe
FINISH REMOVEFILE 7/71/7xtext0
FINISH REMOVEFILE 7/71/7xtext1
FINISH REMOVEDIR 7/71/
FINISH REMOVEFILE 7/7text0
FINISH REMOVEFILE 7/7text1
FINISH REMOVEDIR 7/
FINISH REMOVEDIR 6/
FINISH REMOVEFILE 5/5text1
FINISH REMOVEFILE 5/5text0
FINISH REMOVEFILE 5/5test.exe
FINISH REMOVEDIR 5/
FINISH REMOVEFILE 4/4text1
FINISH REMOVEFILE 4/4text0
FINISH REMOVEDIR 4/
FINISH REMOVEFILE 3/3text1
FINISH REMOVEFILE 3/3text0
FINISH REMOVEDIR 1/10/
FINISH REMOVEDIR 1/
succeeded
calling QuitProgressUI

Binary file not shown.

View file

@ -0,0 +1,19 @@
remove "searchplugins/searchpluginstext0"
remove "searchplugins/searchpluginspng1.png"
remove "searchplugins/searchpluginspng0.png"
remove "removed-files"
remove "precomplete"
remove "exe0.exe"
remove "2/20/20text0"
remove "2/20/20png0.png"
remove "0/0exe0.exe"
remove "0/00/00text2"
remove "0/00/00text0"
remove "0/00/00png0.png"
rmdir "searchplugins/"
rmdir "defaults/pref/"
rmdir "defaults/"
rmdir "2/20/"
rmdir "2/"
rmdir "0/00/"
rmdir "0/"

Some files were not shown because too many files have changed in this diff Show more