icecat: add release icecat-140.10.1-1gnu1 for ecne
This commit is contained in:
parent
a5f93cb214
commit
ff85d7c623
1256 changed files with 63469 additions and 24141 deletions
|
|
@ -28,9 +28,21 @@ export class FindBarParent extends JSWindowActorParent {
|
|||
}
|
||||
|
||||
switch (message.name) {
|
||||
case "Findbar:Keypress":
|
||||
findBar._onBrowserKeypress(message.data);
|
||||
case "Findbar:Keypress": {
|
||||
let d = message.data || {};
|
||||
findBar._onBrowserKeypress({
|
||||
type: "keypress",
|
||||
bubbles: false,
|
||||
cancelable: !!d.cancelable,
|
||||
ctrlKey: !!d.ctrlKey,
|
||||
altKey: !!d.altKey,
|
||||
shiftKey: !!d.shiftKey,
|
||||
metaKey: !!d.metaKey,
|
||||
keyCode: (d.keyCode | 0) & 0xffff,
|
||||
charCode: (d.charCode | 0) & 0xffff,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "Findbar:Mouseup":
|
||||
findBar.onMouseUp();
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1969,6 +1969,8 @@ export class PictureInPictureChild extends JSWindowActorChild {
|
|||
this.closePictureInPicture({ reason: "Fullscreen" });
|
||||
break;
|
||||
}
|
||||
case "playing":
|
||||
// Intentional fall-through
|
||||
case "play": {
|
||||
this.sendAsyncMessage("PictureInPicture:Playing");
|
||||
break;
|
||||
|
|
@ -2300,6 +2302,7 @@ export class PictureInPictureChild extends JSWindowActorChild {
|
|||
if (originatingWindow) {
|
||||
originatingWindow.addEventListener("pagehide", this);
|
||||
originatingVideo.addEventListener("play", this);
|
||||
originatingVideo.addEventListener("playing", this);
|
||||
originatingVideo.addEventListener("pause", this);
|
||||
originatingVideo.addEventListener("volumechange", this);
|
||||
originatingVideo.addEventListener("resize", this);
|
||||
|
|
@ -2352,6 +2355,7 @@ export class PictureInPictureChild extends JSWindowActorChild {
|
|||
if (originatingWindow) {
|
||||
originatingWindow.removeEventListener("pagehide", this);
|
||||
originatingVideo.removeEventListener("play", this);
|
||||
originatingVideo.removeEventListener("playing", this);
|
||||
originatingVideo.removeEventListener("pause", this);
|
||||
originatingVideo.removeEventListener("volumechange", this);
|
||||
originatingVideo.removeEventListener("resize", this);
|
||||
|
|
|
|||
|
|
@ -524,22 +524,27 @@ StorageAccessAPIHelper::CompleteAllowAccessForOnParentProcess(
|
|||
__func__);
|
||||
}
|
||||
|
||||
RefPtr<dom::BrowsingContext> parentBC = aParentContext;
|
||||
auto storePermission =
|
||||
[aParentContext, aTopLevelWindowId, trackingOrigin, trackingPrincipal,
|
||||
[parentBC, aTopLevelWindowId, trackingOrigin, trackingPrincipal,
|
||||
aCookieBehavior,
|
||||
aReason](int aAllowMode) -> RefPtr<StorageAccessPermissionGrantPromise> {
|
||||
if (parentBC->IsDiscarded()) {
|
||||
return StorageAccessPermissionGrantPromise::CreateAndReject(false,
|
||||
__func__);
|
||||
}
|
||||
// We don't have the window, send an IPC to the content process that
|
||||
// owns the parent window. But there is a special case, for window.open,
|
||||
// we'll return to the content process we need to inform when this
|
||||
// function is done. So we don't need to create an extra IPC for the case.
|
||||
if (aReason != ContentBlockingNotifier::eOpener) {
|
||||
dom::ContentParent* cp = aParentContext->Canonical()->GetContentParent();
|
||||
dom::ContentParent* cp = parentBC->Canonical()->GetContentParent();
|
||||
if (!cp) {
|
||||
return StorageAccessPermissionGrantPromise::CreateAndReject(false,
|
||||
__func__);
|
||||
}
|
||||
|
||||
Unused << cp->SendOnAllowAccessFor(aParentContext, trackingOrigin,
|
||||
Unused << cp->SendOnAllowAccessFor(parentBC, trackingOrigin,
|
||||
aCookieBehavior, aReason);
|
||||
}
|
||||
|
||||
|
|
@ -547,7 +552,7 @@ StorageAccessAPIHelper::CompleteAllowAccessForOnParentProcess(
|
|||
reportReason;
|
||||
// We can directly report here if we can know the origin of the top.
|
||||
ContentBlockingNotifier::ReportUnblockingToConsole(
|
||||
aParentContext, NS_ConvertUTF8toUTF16(trackingOrigin), aReason);
|
||||
parentBC, NS_ConvertUTF8toUTF16(trackingOrigin), aReason);
|
||||
// Set the report reason to nothing if we've already reported.
|
||||
reportReason = Nothing();
|
||||
|
||||
|
|
@ -555,9 +560,9 @@ StorageAccessAPIHelper::CompleteAllowAccessForOnParentProcess(
|
|||
bool frameOnly = StaticPrefs::dom_storage_access_frame_only() &&
|
||||
aReason == ContentBlockingNotifier::eStorageAccessAPI;
|
||||
|
||||
uint64_t innerWindowId = aParentContext->GetCurrentInnerWindowId();
|
||||
uint64_t innerWindowId = parentBC->GetCurrentInnerWindowId();
|
||||
|
||||
return SaveAccessForOriginOnParentProcess(aTopLevelWindowId, aParentContext,
|
||||
return SaveAccessForOriginOnParentProcess(aTopLevelWindowId, parentBC,
|
||||
trackingPrincipal, aAllowMode,
|
||||
frameOnly)
|
||||
->Then(GetCurrentSerialEventTarget(), __func__,
|
||||
|
|
@ -746,21 +751,26 @@ StorageAccessAPIHelper::CompleteAllowAccessForOnChildProcess(
|
|||
__func__);
|
||||
}
|
||||
|
||||
RefPtr<dom::BrowsingContext> parentBC = aParentContext;
|
||||
auto storePermission =
|
||||
[aParentContext, aTopLevelWindowId, trackingOrigin, trackingPrincipal,
|
||||
[parentBC, aTopLevelWindowId, trackingOrigin, trackingPrincipal,
|
||||
aCookieBehavior,
|
||||
aReason](int aAllowMode) -> RefPtr<StorageAccessPermissionGrantPromise> {
|
||||
if (parentBC->IsDiscarded()) {
|
||||
return StorageAccessPermissionGrantPromise::CreateAndReject(false,
|
||||
__func__);
|
||||
}
|
||||
// Inform the window we granted permission for. This has to be done in the
|
||||
// window's process. As a child this is always the case.
|
||||
StorageAccessAPIHelper::OnAllowAccessFor(aParentContext, trackingOrigin,
|
||||
StorageAccessAPIHelper::OnAllowAccessFor(parentBC, trackingOrigin,
|
||||
aCookieBehavior, aReason);
|
||||
|
||||
Maybe<ContentBlockingNotifier::StorageAccessPermissionGrantedReason>
|
||||
reportReason;
|
||||
// We can directly report here if we can know the origin of the top.
|
||||
if (aParentContext->Top()->IsInProcess()) {
|
||||
if (parentBC->Top()->IsInProcess()) {
|
||||
ContentBlockingNotifier::ReportUnblockingToConsole(
|
||||
aParentContext, NS_ConvertUTF8toUTF16(trackingOrigin), aReason);
|
||||
parentBC, NS_ConvertUTF8toUTF16(trackingOrigin), aReason);
|
||||
|
||||
// Set the report reason to nothing if we've already reported.
|
||||
reportReason = Nothing();
|
||||
|
|
@ -783,12 +793,12 @@ StorageAccessAPIHelper::CompleteAllowAccessForOnChildProcess(
|
|||
bool frameOnly = StaticPrefs::dom_storage_access_frame_only() &&
|
||||
aReason == ContentBlockingNotifier::eStorageAccessAPI;
|
||||
|
||||
uint64_t innerWindowId = aParentContext->GetCurrentInnerWindowId();
|
||||
uint64_t innerWindowId = parentBC->GetCurrentInnerWindowId();
|
||||
|
||||
return cc
|
||||
->SendStorageAccessPermissionGrantedForOrigin(
|
||||
aTopLevelWindowId, aParentContext, trackingPrincipal,
|
||||
trackingOrigin, aAllowMode, reportReason, frameOnly)
|
||||
aTopLevelWindowId, parentBC, trackingPrincipal, trackingOrigin,
|
||||
aAllowMode, reportReason, frameOnly)
|
||||
->Then(
|
||||
GetCurrentSerialEventTarget(), __func__,
|
||||
[aReason, trackingPrincipal,
|
||||
|
|
|
|||
|
|
@ -100,11 +100,12 @@ export var DownloadPaths = {
|
|||
// .*? Matches the base name non-greedily.
|
||||
// \.[A-Z0-9]{1,3} Up to three letters or numbers preceding a
|
||||
// double extension.
|
||||
// \.(?:gz|bz2|Z) The second part of common double extensions.
|
||||
// \.(?:bz2|gz|lzma|xz|zst|Z) The second part of common double extensions.
|
||||
// \.[^.]* Matches any extension or a single trailing dot.
|
||||
let [, base, ext] = /(.*?)(\.[A-Z0-9]{1,3}\.(?:gz|bz2|Z)|\.[^.]*)?$/i.exec(
|
||||
leafName
|
||||
);
|
||||
let [, base, ext] =
|
||||
/(.*?)(\.[A-Z0-9]{1,3}\.(?:bz2|gz|lzma|xz|zst|Z)|\.[^.]*)?$/i.exec(
|
||||
leafName
|
||||
);
|
||||
// Return an empty string instead of undefined if no extension is found.
|
||||
return [base, ext || ""];
|
||||
},
|
||||
|
|
|
|||
|
|
@ -173,10 +173,12 @@ add_task(async function test_createNiceUniqueFile() {
|
|||
testCreateNiceUniqueFile(tempFile, "test(2).txt");
|
||||
|
||||
// Double extension.
|
||||
tempFile.leafName = "test.tar.gz";
|
||||
testCreateNiceUniqueFile(tempFile, "test.tar.gz");
|
||||
testCreateNiceUniqueFile(tempFile, "test(1).tar.gz");
|
||||
testCreateNiceUniqueFile(tempFile, "test(2).tar.gz");
|
||||
for (let suffix of ["gz", "lzma", "xz", "zst", "bz2"]) {
|
||||
tempFile.leafName = "test.tar." + suffix;
|
||||
testCreateNiceUniqueFile(tempFile, "test.tar." + suffix);
|
||||
testCreateNiceUniqueFile(tempFile, "test(1).tar." + suffix);
|
||||
testCreateNiceUniqueFile(tempFile, "test(2).tar." + suffix);
|
||||
}
|
||||
|
||||
// Test automatic shortening of long file names. We don't know exactly how
|
||||
// many characters are removed, because it depends on the name of the folder
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ DEFINE_STATIC_ATOM_SET(HostLocatorSchemes, nsGkAtoms::http, nsGkAtoms::https,
|
|||
nsGkAtoms::ws, nsGkAtoms::wss, nsGkAtoms::file,
|
||||
nsGkAtoms::ftp, nsGkAtoms::moz_extension,
|
||||
nsGkAtoms::chrome, nsGkAtoms::resource, nsGkAtoms::moz,
|
||||
nsGkAtoms::moz_icon, nsGkAtoms::moz_gio);
|
||||
nsGkAtoms::moz_icon);
|
||||
|
||||
DEFINE_STATIC_ATOM_SET(WildcardSchemes, nsGkAtoms::http, nsGkAtoms::https,
|
||||
nsGkAtoms::ws, nsGkAtoms::wss);
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||
LoginHelper: "resource://gre/modules/LoginHelper.sys.mjs",
|
||||
MLAutofill: "resource://autofill/MLAutofill.sys.mjs",
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
|
||||
OSKeyStore: "resource://gre/modules/OSKeyStore.sys.mjs",
|
||||
});
|
||||
|
||||
ChromeUtils.defineLazyGetter(lazy, "log", () =>
|
||||
|
|
@ -67,6 +66,16 @@ const { ADDRESSES_COLLECTION_NAME, CREDITCARDS_COLLECTION_NAME, FIELD_STATES } =
|
|||
|
||||
let gMessageObservers = new Set();
|
||||
|
||||
const FORM_AUTOFILL_MESSAGES = new Set([
|
||||
"FormAutofill:InitStorage",
|
||||
"FormAutofill:OnFormSubmit",
|
||||
"FormAutofill:FieldsIdentified",
|
||||
"FormAutofill:OnFieldsDetected",
|
||||
"FormAutofill:OnFieldsUpdated",
|
||||
"FormAutofill:FieldFilledModified",
|
||||
"FormAutofill:FieldsUpdatedDuringAutofill",
|
||||
]);
|
||||
|
||||
export let FormAutofillStatus = {
|
||||
_initialized: false,
|
||||
|
||||
|
|
@ -306,6 +315,10 @@ export class FormAutofillParent extends JSWindowActorParent {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
if (!FORM_AUTOFILL_MESSAGES.has(name) && !Cu.isInAutomation) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
switch (name) {
|
||||
case "FormAutofill:InitStorage": {
|
||||
await lazy.gFormAutofillStorage.initialize();
|
||||
|
|
@ -364,12 +377,6 @@ export class FormAutofillParent extends JSWindowActorParent {
|
|||
break;
|
||||
}
|
||||
case "FormAutofill:SaveCreditCard": {
|
||||
// Setting the first parameter of OSKeyStore.ensurLoggedIn as false
|
||||
// since this case only called in tests. Also the reason why we're not calling FormAutofill.verifyUserOSAuth.
|
||||
if (!(await lazy.OSKeyStore.ensureLoggedIn(false)).authenticated) {
|
||||
lazy.log.warn("User canceled encryption login");
|
||||
return undefined;
|
||||
}
|
||||
await lazy.gFormAutofillStorage.creditCards.add(data.creditcard);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -718,12 +718,6 @@ export const SpecialMessageActions = {
|
|||
throw new Error(
|
||||
`Special message action with type ${action.type} is unsupported.`
|
||||
);
|
||||
case "CLICK_ELEMENT":
|
||||
const clickElement = window.document.querySelector(
|
||||
action.data.selector
|
||||
);
|
||||
clickElement?.click();
|
||||
break;
|
||||
case "RELOAD_BROWSER":
|
||||
browser.reload();
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -589,24 +589,6 @@
|
|||
"additionalProperties": false,
|
||||
"description": "Runs multiple actions"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"selector": {
|
||||
"type": "string",
|
||||
"description": "A CSS selector for the HTML element to be clicked"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["CLICK_ELEMENT"]
|
||||
}
|
||||
},
|
||||
"required": ["data", "type"],
|
||||
"additionalProperties": false,
|
||||
"description": "Selects an element in the current Window's document and triggers a click action"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -357,12 +357,6 @@ interface MultiAction {
|
|||
}
|
||||
```
|
||||
|
||||
### `CLICK_ELEMENT`
|
||||
|
||||
* args: `string` A CSS selector for the HTML element to be clicked
|
||||
|
||||
Selects an element in the current Window's document and triggers a click action
|
||||
|
||||
|
||||
### `RELOAD_BROWSER`
|
||||
|
||||
|
|
|
|||
|
|
@ -1502,7 +1502,7 @@ export class LoginManagerParent extends JSWindowActorParent {
|
|||
}
|
||||
|
||||
async searchAutoCompleteEntries(searchString, data) {
|
||||
return this.doAutocompleteSearch(data.formOrigin, data);
|
||||
return this.doAutocompleteSearch(this.origin, data);
|
||||
}
|
||||
|
||||
onAutoCompleteEntryHovered(_message, _data) {
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ const char* const ApplicationReputationService::kBinaryFileExtensions[] = {
|
|||
".class", // Java
|
||||
//".cmd", exec // Windows executable
|
||||
//".com", exec // Windows executable
|
||||
".command", // Mac script
|
||||
//".command", exec // Mac script
|
||||
".configprofile", // Configuration file for Apple systems
|
||||
".cpgz", // Mac archive
|
||||
".cpi", // Control Panel Item. Executable used for adding icons
|
||||
|
|
@ -434,7 +434,7 @@ const char* const ApplicationReputationService::kBinaryFileExtensions[] = {
|
|||
".scptd", // AppleScript
|
||||
//".scr", exec // Windows
|
||||
//".sct", exec // Windows shell
|
||||
".search-ms", // Windows
|
||||
//".search-ms", exec // Windows Saved Search
|
||||
".seplugin", // AppleScript
|
||||
".service", // Systemd service unit file
|
||||
//".settingcontent-ms", exec // Windows settings
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ class ApplicationReputationService final
|
|||
public:
|
||||
static const char* const kNonBinaryExecutables[6];
|
||||
#ifdef XP_WIN
|
||||
static const char* const kBinaryFileExtensions[184];
|
||||
static const char* const kBinaryFileExtensions[182];
|
||||
#else
|
||||
static const char* const kBinaryFileExtensions[183];
|
||||
static const char* const kBinaryFileExtensions[181];
|
||||
#endif
|
||||
|
||||
static already_AddRefed<ApplicationReputationService> GetSingleton();
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ static const char* const kTestFileExtensions[] = {
|
|||
".scptd", // AppleScript
|
||||
".scr", // Windows
|
||||
".sct", // Windows shell
|
||||
".search-ms", // Windows
|
||||
".search-ms", // Windows Saved Search
|
||||
".seplugin", // AppleScript
|
||||
".service", // Systemd service unit file
|
||||
".settingcontent-ms", // Windows settings
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@
|
|||
"title": "Partner Code",
|
||||
"description": "The partner code for the engine or variant. This will be inserted into parameters which include '{partnerCode}'",
|
||||
"type": "string",
|
||||
"pattern": "^[a-zA-Z0-9-_]*$"
|
||||
"pattern": "^[a-zA-Z0-9-_.]*$"
|
||||
},
|
||||
"urls": {
|
||||
"title": "URLs",
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ tests.push({
|
|||
});
|
||||
|
||||
tests.push({
|
||||
region: "CA", // Testing for "rest of world" (excluding US, RU, TR, BY, KZ)
|
||||
region: "CA", // Testing for "rest of world" (excluding US, RU, BY)
|
||||
distribution: "dt-002",
|
||||
application: "icecat-android",
|
||||
test: engines =>
|
||||
|
|
@ -332,7 +332,7 @@ tests.push({
|
|||
});
|
||||
|
||||
tests.push({
|
||||
region: "CA", // Testing for "rest of world" (excluding US, RU, TR, BY, KZ)
|
||||
region: "CA", // Testing for "rest of world" (excluding US, RU, BY)
|
||||
distribution: "dt-003",
|
||||
application: "icecat-android",
|
||||
test: engines =>
|
||||
|
|
@ -342,6 +342,28 @@ tests.push({
|
|||
hasTelemetryId(engines, "Google", "google-b-dt"),
|
||||
});
|
||||
|
||||
tests.push({
|
||||
region: "US",
|
||||
distribution: "xiaomi-001",
|
||||
application: "icecat-android",
|
||||
test: engines =>
|
||||
hasParams(engines, "Google", "client=icecat-b-1-dt") &&
|
||||
hasDefault(engines, "Google") &&
|
||||
hasEnginesFirst(engines, ["Google"]) &&
|
||||
hasTelemetryId(engines, "Google", "google-b-1-dt"),
|
||||
});
|
||||
|
||||
tests.push({
|
||||
region: "CA", // Testing for "rest of world" (excluding US, RU, BY)
|
||||
distribution: "xiaomi-001",
|
||||
application: "icecat-android",
|
||||
test: engines =>
|
||||
hasParams(engines, "Google", "client=icecat-b-dt") &&
|
||||
hasDefault(engines, "Google") &&
|
||||
hasEnginesFirst(engines, ["Google"]) &&
|
||||
hasTelemetryId(engines, "Google", "google-b-dt"),
|
||||
});
|
||||
|
||||
tests.push({
|
||||
region: "US",
|
||||
distribution: "aura-001",
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ const test = new SearchConfigTest({
|
|||
: "icecat-b-1-d",
|
||||
},
|
||||
{
|
||||
excluded: [{ regions: ["us", "by", "kz", "ru", "tr"] }],
|
||||
excluded: [{ regions: ["us", "by", "ru"] }],
|
||||
included: [{}],
|
||||
domain: "google.com",
|
||||
telemetryId:
|
||||
|
|
@ -62,7 +62,7 @@ const test = new SearchConfigTest({
|
|||
: "icecat-b-d",
|
||||
},
|
||||
{
|
||||
included: [{ regions: ["by", "kz", "ru", "tr"] }],
|
||||
included: [{ regions: ["by", "ru"] }],
|
||||
domain: "google.com",
|
||||
telemetryId: "google-com-nocodes",
|
||||
partnerCode: "",
|
||||
|
|
|
|||
|
|
@ -505,7 +505,7 @@ void LookupCache::GetLookupEntitylistFragments(
|
|||
if (FindCharInReadable('.', iter, end)) {
|
||||
iter++;
|
||||
nsAutoCString thirdPartyURLToAdd;
|
||||
thirdPartyURLToAdd.Assign(Substring(iter++, end));
|
||||
thirdPartyURLToAdd.Assign(Substring(iter, end));
|
||||
|
||||
// don't bother checking toplevel domains
|
||||
if (FindCharInReadable('.', iter, end)) {
|
||||
|
|
|
|||
|
|
@ -143,8 +143,8 @@ HttpIndexViewer.prototype = {
|
|||
aDocListenerResult
|
||||
) {
|
||||
// Bug 1824325: application/http-index-format is deprecated for almost all
|
||||
// sites, we only allow it for urls with a inner scheme of "file" or
|
||||
// "moz-gio" (specified in network.http_index_format.allowed_schemes).
|
||||
// sites, we only allow it for urls with a inner scheme of "file"
|
||||
// (specified in network.http_index_format.allowed_schemes).
|
||||
// This also includes jar: and resource:// uris, as jar: uris has a inner
|
||||
// scheme of "file", and resource:// uris have been turned into either a
|
||||
// jar: or file:// uri by the point where we are checking them here.
|
||||
|
|
|
|||
|
|
@ -797,10 +797,10 @@
|
|||
}
|
||||
|
||||
// The event information comes from the child process.
|
||||
let event = new target.ownerGlobal.KeyboardEvent(
|
||||
fakeEvent.type,
|
||||
fakeEvent
|
||||
);
|
||||
let event = new target.ownerGlobal.KeyboardEvent("keypress", {
|
||||
...fakeEvent,
|
||||
bubbles: false,
|
||||
});
|
||||
target.dispatchEvent(event);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
//! Glean telemetry integration.
|
||||
|
||||
use crate::config::{buildid, Config};
|
||||
use crate::prefs_parser::find_bool_pref;
|
||||
use crate::std::path::Path;
|
||||
use glean::{ClientInfoMetrics, Configuration, ConfigurationBuilder};
|
||||
|
||||
const APP_ID: &str = if cfg!(mock) {
|
||||
|
|
@ -18,6 +20,55 @@ const TELEMETRY_SERVER: &str = if cfg!(mock) {
|
|||
} else {
|
||||
"https://incoming.telemetry.mozilla.org"
|
||||
};
|
||||
const TELEMETRY_ENABLED_PREF_KEY: &str = "datareporting.healthreport.uploadEnabled";
|
||||
|
||||
/// Parse the telemetry enablement pref from the prefs file.
|
||||
///
|
||||
/// For example:
|
||||
/// ```rust
|
||||
/// let input = r#"user_pref("datareporting.healthreport.uploadEnabled", false);"#;
|
||||
/// assert_eq!(parse_telemetry_enabled_pref(input), Some(false));
|
||||
/// let input = r#"user_pref("datareporting.healthreport.uploadEnabled", true);"#;
|
||||
/// assert_eq!(parse_telemetry_enabled_pref(input), Some(true));
|
||||
/// ```
|
||||
fn parse_telemetry_enabled_pref(prefs_content: &str) -> Option<bool> {
|
||||
find_bool_pref(prefs_content, TELEMETRY_ENABLED_PREF_KEY)
|
||||
}
|
||||
|
||||
/// Determine whether telemetry should be enabled based on the profile.
|
||||
fn determine_telemetry_enabled(profile_dir: Option<&Path>) -> bool {
|
||||
// If there is no profile dir, we cannot determine whether telemetry is enabled or not. However,
|
||||
// disabling telemetry in this case will cause us to entirely miss the class of crashes that
|
||||
// occur before the profile is set up, so we leave it enabled.
|
||||
let Some(profile_dir) = profile_dir else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let prefs = profile_dir.join("prefs.js");
|
||||
|
||||
// If there is no pref file, default to true.
|
||||
if !prefs.exists() {
|
||||
return true;
|
||||
}
|
||||
|
||||
match crate::std::fs::read_to_string(&prefs) {
|
||||
Ok(prefs_contents) => {
|
||||
parse_telemetry_enabled_pref(&prefs_contents)
|
||||
// If there is no pref, default to true
|
||||
.unwrap_or(true)
|
||||
}
|
||||
Err(e) => {
|
||||
// Like the no-profile-dir case, if we can't read the prefs file, this might be the
|
||||
// cause of some crash that we are trying to report. So disabling telemetry in this case
|
||||
// would make us blind to the issue.
|
||||
log::error!(
|
||||
"failed to read prefs file at {} for disabling telemetry: {e}",
|
||||
prefs.display()
|
||||
);
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize glean based on the given configuration.
|
||||
///
|
||||
|
|
@ -34,7 +85,8 @@ pub fn init(cfg: &Config) {
|
|||
}
|
||||
|
||||
fn config(cfg: &Config) -> Configuration {
|
||||
ConfigurationBuilder::new(true, glean_data_dir(cfg), APP_ID)
|
||||
let upload_enabled = determine_telemetry_enabled(cfg.profile_dir.as_deref());
|
||||
ConfigurationBuilder::new(upload_enabled, glean_data_dir(cfg), APP_ID)
|
||||
.with_server_endpoint(TELEMETRY_SERVER)
|
||||
.with_use_core_mps(false)
|
||||
.with_internal_pings(false)
|
||||
|
|
@ -155,6 +207,27 @@ mod test {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_telemetry_enable_pref() {
|
||||
use crate::std::{
|
||||
fs::{MockFS, MockFiles},
|
||||
mock,
|
||||
path::Path,
|
||||
};
|
||||
|
||||
for pref_value in [false, true] {
|
||||
let files = MockFiles::new();
|
||||
files.add_dir("profile_dir").add_file(
|
||||
"profile_dir/prefs.js",
|
||||
format!(r#"user_pref("datareporting.healthreport.uploadEnabled", {pref_value});"#),
|
||||
);
|
||||
let result = mock::builder()
|
||||
.set(MockFS, files)
|
||||
.run(|| determine_telemetry_enabled(Some(Path::new("profile_dir"))));
|
||||
assert_eq!(result, pref_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@
|
|||
use super::language_info::LanguageInfo;
|
||||
use super::zip::{read_archive_file_as_string, read_zip, Archive};
|
||||
use crate::config::installation_resource_path;
|
||||
use crate::prefs_parser::find_string_pref;
|
||||
use crate::std::path::{Path, PathBuf};
|
||||
use anyhow::Context;
|
||||
|
||||
const LOCALE_PREF_KEY: &str = r#""intl.locale.requested""#;
|
||||
const LOCALE_PREF_KEY: &str = "intl.locale.requested";
|
||||
|
||||
/// Use the profile language preferences to determine the localization to use.
|
||||
pub fn read(
|
||||
|
|
@ -115,12 +116,9 @@ fn locales_from_prefs(profile_dir: &Path) -> anyhow::Result<Option<Vec<String>>>
|
|||
|
||||
/// Parse the language pref (if any) from the prefs file.
|
||||
///
|
||||
/// This finds the first string match for the regex `"intl.locale.requested"[ \t\n\r\f\v,]*"(.*)"`,
|
||||
/// and splits and trims the first match group, returning the set of strings that results.
|
||||
///
|
||||
/// For example:
|
||||
/// ```rust
|
||||
/// let input = r#""intl.locale.requested", "foo , bar,,""#;
|
||||
/// let input = r#"user_pref("intl.locale.requested", "foo , bar,,");"#;
|
||||
/// let expected_output = Some(vec!["foo","bar"]);
|
||||
/// assert_eq!(parse_requested_locales(input), output);
|
||||
/// ```
|
||||
|
|
@ -128,10 +126,7 @@ fn locales_from_prefs(profile_dir: &Path) -> anyhow::Result<Option<Vec<String>>>
|
|||
/// This will parse the locales out of the user prefs file contents, which looks like
|
||||
/// `user_pref("intl.locale.requested", "<LOCALE LIST>")`.
|
||||
fn parse_requested_locales(prefs_content: &str) -> Option<Vec<&str>> {
|
||||
let (_, s) = prefs_content.split_once(LOCALE_PREF_KEY)?;
|
||||
let s = s.trim_start_matches(|c: char| c.is_whitespace() || c == ',');
|
||||
let s = s.strip_prefix('"')?;
|
||||
let (v, _) = s.split_once('"')?;
|
||||
let v = find_string_pref(prefs_content, LOCALE_PREF_KEY)?;
|
||||
Some(
|
||||
v.split(",")
|
||||
.map(|s| s.trim())
|
||||
|
|
@ -187,7 +182,7 @@ mod test {
|
|||
#[test]
|
||||
fn parse_locales_empty() {
|
||||
assert_eq!(
|
||||
parse_requested_locales(r#"user_pref("intl.locale.requested","")"#),
|
||||
parse_requested_locales(r#"user_pref("intl.locale.requested","");"#),
|
||||
Some(vec![])
|
||||
);
|
||||
}
|
||||
|
|
@ -195,7 +190,7 @@ mod test {
|
|||
#[test]
|
||||
fn parse_locales() {
|
||||
assert_eq!(
|
||||
parse_requested_locales(r#"user_pref("intl.locale.requested", "fr,en-US")"#),
|
||||
parse_requested_locales(r#"user_pref("intl.locale.requested", "fr,en-US");"#),
|
||||
Some(vec!["fr", "en-US"])
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ mod logging;
|
|||
mod logic;
|
||||
mod memory_test;
|
||||
mod net;
|
||||
mod prefs_parser;
|
||||
mod process;
|
||||
mod settings;
|
||||
mod std;
|
||||
|
|
|
|||
86
icecat/toolkit/crashreporter/client/app/src/prefs_parser.rs
Normal file
86
icecat/toolkit/crashreporter/client/app/src/prefs_parser.rs
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/* 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/. */
|
||||
|
||||
//! Prefs file parsing utilities.
|
||||
|
||||
/// Parse a single pref value (if any) from the prefs file contents.
|
||||
///
|
||||
/// This parser could be improved (e.g., it doesn't respect comments), but it is compatible with
|
||||
/// prefs files generated by IceCat.
|
||||
///
|
||||
/// This finds the first string match for the regex `user_pref\("PREFSTRING"[ \t\n\r\f\v,]*(.*)[ \t\n\r\f\v]*\);`.
|
||||
///
|
||||
/// For example:
|
||||
/// ```rust
|
||||
/// let input = r#"user_pref("FOOBAR", "baz");"#;
|
||||
/// let expected_output = Some(r#""baz""#);
|
||||
/// assert_eq!(find_pref(input, "FOOBAR"), output);
|
||||
/// ```
|
||||
pub fn find_pref<'a>(prefs_content: &'a str, pref: &str) -> Option<&'a str> {
|
||||
let mut search_content = prefs_content;
|
||||
loop {
|
||||
let (before, s) = search_content.split_once(&format!("\"{pref}\""))?;
|
||||
if !before.trim().ends_with("user_pref(") {
|
||||
search_content = s;
|
||||
continue;
|
||||
}
|
||||
let s = s.trim_start_matches(|c: char| c.is_whitespace() || c == ',');
|
||||
let (content, _) = s.split_once(");")?;
|
||||
return Some(content.trim());
|
||||
}
|
||||
}
|
||||
|
||||
/// Find a single string pref (if any) from the prefs file contents.
|
||||
pub fn find_string_pref<'a>(prefs_content: &'a str, pref: &str) -> Option<&'a str> {
|
||||
find_pref(prefs_content, pref).and_then(|s| s.strip_prefix('"')?.strip_suffix('"'))
|
||||
}
|
||||
|
||||
/// Find a single bool pref (if any) from the prefs file contents.
|
||||
pub fn find_bool_pref(prefs_content: &str, pref: &str) -> Option<bool> {
|
||||
find_pref(prefs_content, pref).and_then(|s| s.parse().ok())
|
||||
}
|
||||
|
||||
// Doctests don't run for binaries, so make some unit tests instead.
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn find_pref_read_value() {
|
||||
let input = r#"user_pref("FOOBAR", "baz");"#;
|
||||
assert_eq!(find_pref(input, "FOOBAR"), Some(r#""baz""#));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_pref_continues_search() {
|
||||
let input = r#"
|
||||
user_pref("rawr", "FOOBAR");
|
||||
user_pref("FOOBAR", "baz");
|
||||
"#;
|
||||
assert_eq!(find_pref(input, "FOOBAR"), Some(r#""baz""#));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_pref_missing() {
|
||||
let input = r#"
|
||||
user_pref("rawr", "FOOBAR");
|
||||
user_pref("FOOBAR", "hello");
|
||||
"#;
|
||||
assert_eq!(find_pref(input, "hello"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_string_pref() {
|
||||
let input = r#"user_pref("FOOBAR", "baz");"#;
|
||||
assert_eq!(find_string_pref(input, "FOOBAR"), Some("baz"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_bool_pref() {
|
||||
let input = r#"user_pref("FOOBAR", true);"#;
|
||||
assert_eq!(find_bool_pref(input, "FOOBAR"), Some(true));
|
||||
let input = r#"user_pref("FOOBAR", false);"#;
|
||||
assert_eq!(find_bool_pref(input, "FOOBAR"), Some(false));
|
||||
}
|
||||
}
|
||||
|
|
@ -524,6 +524,12 @@ pub fn remove_file<P: AsRef<Path>>(path: P) -> Result<()> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn read_to_string<P: AsRef<Path>>(path: P) -> Result<String> {
|
||||
let mut s = String::new();
|
||||
File::open(path.as_ref())?.read_to_string(&mut s)?;
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()> {
|
||||
File::create(path.as_ref())?.write_all(contents.as_ref())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -247,25 +247,29 @@ impl GuiTest {
|
|||
..
|
||||
} = self;
|
||||
let before_run = self.before_run.take();
|
||||
let mut config = Arc::new(std::mem::take(config));
|
||||
let mut test_config = Arc::new(std::mem::take(config));
|
||||
|
||||
// Run the mock environment.
|
||||
mock.run(move || {
|
||||
let result = mock.run(|| {
|
||||
let _glean = if *enable_glean {
|
||||
Some(glean::test_init(&config))
|
||||
Some(glean::test_init(&test_config))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
gui_interact(
|
||||
move || {
|
||||
|| {
|
||||
if let Some(f) = before_run {
|
||||
f();
|
||||
}
|
||||
try_run(&mut config)
|
||||
try_run(&mut test_config)
|
||||
},
|
||||
interact,
|
||||
)
|
||||
})
|
||||
});
|
||||
|
||||
*config = Arc::into_inner(test_config).unwrap();
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Run the test as configured, using the given function to interact with the GUI.
|
||||
|
|
@ -991,6 +995,87 @@ fn glean_ping_extra_stack_trace_fields() {
|
|||
submitted_glean_ping.assert_one();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reads_profile_directory() {
|
||||
let mut test = GuiTest::new();
|
||||
let minidump_extra_contents = r#"{
|
||||
"Vendor": "FooCorp",
|
||||
"ProductName": "Bar",
|
||||
"ProfileDirectory": "profile_dir",
|
||||
"ReleaseChannel": "release",
|
||||
"BuildID": "1234",
|
||||
"AsyncShutdownTimeout": "{}",
|
||||
"StackTraces": {
|
||||
"status": "OK"
|
||||
},
|
||||
"Version": "100.0",
|
||||
"ServerURL": "https://reports.example.com",
|
||||
"TelemetryServerURL": "https://telemetry.example.com",
|
||||
"TelemetryClientId": "telemetry_client",
|
||||
"TelemetryProfileGroupId": "telemetry_profile_group",
|
||||
"TelemetrySessionId": "telemetry_session",
|
||||
"SomeNestedJson": { "foo": "bar" },
|
||||
"URL": "https://url.example.com"
|
||||
}"#;
|
||||
test.files = {
|
||||
let mock_files = MockFiles::new();
|
||||
mock_files
|
||||
.add_file_result(
|
||||
"minidump.dmp",
|
||||
Ok(MOCK_MINIDUMP_FILE.into()),
|
||||
current_system_time(),
|
||||
)
|
||||
.add_file_result(
|
||||
"minidump.extra",
|
||||
Ok(minidump_extra_contents.into()),
|
||||
current_system_time(),
|
||||
)
|
||||
.add_dir("profile_dir");
|
||||
test.mock.set(MockFS, mock_files.clone());
|
||||
mock_files
|
||||
};
|
||||
test.run(|interact| {
|
||||
interact.element("quit", |_style, b: &model::Button| b.click.fire(&()));
|
||||
});
|
||||
|
||||
assert_eq!(test.config.profile_dir, Some("profile_dir".into()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "This test often passes, however it relies on Glean network scheduling, which has been
|
||||
found to be unreliable for testing purposes. A more reliable unit test is in the glean module."]
|
||||
fn glean_ping_uses_pref() {
|
||||
for pref_value in [false, true] {
|
||||
let mut test = GuiTest::new();
|
||||
test.enable_glean_pings();
|
||||
// Set profile dir manually because glean is initialized earlier than the extra file is read
|
||||
// in tests. We check that the profile dir is correctly read in another test.
|
||||
test.config.profile_dir = Some("profile_dir".into());
|
||||
test.files.add_dir("profile_dir").add_file(
|
||||
"profile_dir/prefs.js",
|
||||
format!(r#"user_pref("datareporting.healthreport.uploadEnabled", {pref_value});"#),
|
||||
);
|
||||
|
||||
// Set a mock hook at the HTTP layer to check whether the ping is sent.
|
||||
// test_before_next_send is called whether upload is enabled or not.
|
||||
let submitted_glean_ping = Counter::new();
|
||||
test.mock.set(
|
||||
net::http::MockHttp,
|
||||
Box::new(cc! { (submitted_glean_ping) move |_request, url| {
|
||||
if url.starts_with("https://incoming.glean.example.com/submit/icecat-crashreporter-mock/crash") {
|
||||
submitted_glean_ping.inc();
|
||||
}
|
||||
Ok(Ok(vec!()))
|
||||
}}),
|
||||
);
|
||||
|
||||
test.run(|interact| {
|
||||
interact.element("quit", |_style, b: &model::Button| b.click.fire(&()));
|
||||
});
|
||||
assert_eq!(submitted_glean_ping.count(), if pref_value { 1 } else { 0 });
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eol_version() {
|
||||
let mut test = GuiTest::new();
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ impl UI {
|
|||
/// These types must be sized to avoid fat pointers (i.e., the pointers must be FFI-compatible, the
|
||||
/// same size as usize).
|
||||
trait ToPointer: Sized {
|
||||
/// Convert the value to a pointer, passing ownership.
|
||||
fn to_ptr(self) -> *mut ();
|
||||
/// # Safety
|
||||
/// The caller must ensure that the pointer was created as the result of `to_ptr` on the same
|
||||
|
|
@ -186,6 +187,33 @@ impl<T: Sized> ToPointer for &mut T {
|
|||
}
|
||||
}
|
||||
|
||||
/// An owned GLib Source.
|
||||
///
|
||||
/// Dropping will remove the source.
|
||||
#[repr(transparent)]
|
||||
struct GSource(u32);
|
||||
|
||||
impl ToPointer for GSource {
|
||||
fn to_ptr(self) -> *mut () {
|
||||
let ptr = self.0 as _;
|
||||
// to_ptr passes ownership
|
||||
std::mem::forget(self);
|
||||
ptr
|
||||
}
|
||||
|
||||
unsafe fn from_ptr(ptr: *mut ()) -> Self {
|
||||
GSource(ptr as _)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for GSource {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
gtk::g_source_remove(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Connect a GTK+ object signal to a function, providing an additional context value (by
|
||||
/// reference).
|
||||
macro_rules! connect_signal {
|
||||
|
|
@ -748,6 +776,11 @@ fn render_element_type(element_type: &model::ElementType) -> Option<*mut gtk::Gt
|
|||
property_read_only! {
|
||||
property amount;
|
||||
fn set(value: &Option<f32>) {
|
||||
// FIXME: The logic here assumes that if `amount` is None, it will remain that
|
||||
// way. Specifically, if we were to change back and forth, additional pulse
|
||||
// callbacks would be registered, and they are not be removed when changing to
|
||||
// a specific fraction. As this property is currently used, we don't encounter
|
||||
// this case.
|
||||
match &*value {
|
||||
Some(v) => unsafe {
|
||||
gtk::gtk_progress_bar_set_fraction(
|
||||
|
|
@ -758,29 +791,16 @@ fn render_element_type(element_type: &model::ElementType) -> Option<*mut gtk::Gt
|
|||
None => unsafe {
|
||||
gtk::gtk_progress_bar_pulse(progress_ptr as *mut _);
|
||||
|
||||
fn auto_pulse_progress_bar(progress: *mut gtk::GtkProgressBar) {
|
||||
unsafe extern "C" fn pulse(progress: *mut std::ffi::c_void) -> gtk::gboolean {
|
||||
if gtk::gtk_widget_is_visible(progress as _) == 0 {
|
||||
false.into()
|
||||
} else {
|
||||
gtk::gtk_progress_bar_pulse(progress as _);
|
||||
true.into()
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
gtk::g_timeout_add(100, Some(pulse as unsafe extern "C" fn(*mut std::ffi::c_void) -> gtk::gboolean), progress as _);
|
||||
}
|
||||
|
||||
unsafe extern "C" fn pulse(progress: *mut std::ffi::c_void) -> gtk::gboolean {
|
||||
gtk::gtk_progress_bar_pulse(progress as _);
|
||||
true.into()
|
||||
}
|
||||
|
||||
connect_signal! {
|
||||
object progress_ptr;
|
||||
with std::ptr::null_mut();
|
||||
signal show(_user_data: &(), progress: *mut gtk::GtkWidget) {
|
||||
auto_pulse_progress_bar(progress as *mut _);
|
||||
}
|
||||
}
|
||||
auto_pulse_progress_bar(progress_ptr as *mut _);
|
||||
// This will call even when the progress bar is hidden, but it's of
|
||||
// little consequence.
|
||||
let source = GSource(gtk::g_timeout_add(100, Some(pulse), progress_ptr as _));
|
||||
|
||||
source.drop_with_widget(progress_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ fn main() {
|
|||
.clang_args(GTK_CFLAGS)
|
||||
.allowlist_function("gtk_.*")
|
||||
.allowlist_function(
|
||||
"g_(application|main_context|memory_input_stream|object|signal|timeout)_.*",
|
||||
"g_(application|main_context|memory_input_stream|object|signal|source|timeout)_.*",
|
||||
)
|
||||
.allowlist_function("gdk_pixbuf_new_from_stream")
|
||||
.allowlist_function("pango_attr_.*")
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ static_prefs = { path = "../../../../modules/libpref/init/static_prefs" }
|
|||
profiler_helper = { path = "../../../../tools/profiler/rust-helper", optional = true }
|
||||
mozurl = { path = "../../../../netwerk/base/mozurl" }
|
||||
webrender_bindings = { path = "../../../../gfx/webrender_bindings" }
|
||||
cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "579b75af21c040700eee6a1d8520e222699fe4cd", optional = true }
|
||||
cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "bebaa23317332c95734df76e25193c24a83a6840", optional = true }
|
||||
cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="8678dcab1c287de79c4c184ccc2e065bc62b70e2", optional = true, features=["pulse-dlopen"] }
|
||||
cubeb-sys = { version = "0.13", optional = true, features=["gecko-in-tree"] }
|
||||
audioipc2-client = { git = "https://github.com/mozilla/audioipc", rev = "e6f44a2bd1e57d11dfc737632a9e849077632330", optional = true }
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ bool PerformInstallationFromDMG(int argc, char** argv);
|
|||
struct UpdateServerThreadArgs {
|
||||
int argc;
|
||||
const NS_tchar** argv;
|
||||
const char* marChannelID;
|
||||
const char* marChannelID = "";
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
@ -3004,16 +3004,17 @@ static int ReadMARChannelIDsFromBuffer(char* aChannels,
|
|||
* `OK` on success, `UPDATE_SETTINGS_FILE_CHANNEL` on failure.
|
||||
*/
|
||||
static int PopulategMARStrings() {
|
||||
if (gMARStrings.MARChannelID && gMARStrings.MARChannelID[0] != '\0') {
|
||||
return OK;
|
||||
}
|
||||
|
||||
int rv = UPDATE_SETTINGS_FILE_CHANNEL;
|
||||
# ifdef XP_MACOSX
|
||||
if (gInvocation == UpdaterInvocation::Second) {
|
||||
// An elevated update process will have already populated gMARStrings when
|
||||
// it connected to the unelevated update process to obtain the command line
|
||||
// args. See `ObtainUpdaterArguments`.
|
||||
rv = OK;
|
||||
} else if (auto marChannels =
|
||||
UpdateSettingsUtil::GetAcceptedMARChannelsValue()) {
|
||||
rv = ReadMARChannelIDsFromBuffer(marChannels->data(), &gMARStrings);
|
||||
if (gInvocation != UpdaterInvocation::Second) {
|
||||
if (std::optional<std::string> marChannels =
|
||||
UpdateSettingsUtil::GetAcceptedMARChannelsValue()) {
|
||||
rv = ReadMARChannelIDsFromBuffer(marChannels->data(), &gMARStrings);
|
||||
}
|
||||
}
|
||||
# else
|
||||
NS_tchar updateSettingsPath[MAXPATHLEN];
|
||||
|
|
@ -3698,17 +3699,33 @@ int NS_main(int argc, NS_tchar** argv) {
|
|||
UpdateServerThreadArgs threadArgs;
|
||||
threadArgs.argc = suiArgc;
|
||||
threadArgs.argv = suiArgv.get();
|
||||
threadArgs.marChannelID = gMARStrings.MARChannelID.get();
|
||||
threadArgs.marChannelID = "";
|
||||
bool shouldServeElevatedUpdate = true;
|
||||
|
||||
Thread t1;
|
||||
if (t1.Run(ServeElevatedUpdateThreadFunc, &threadArgs) == 0) {
|
||||
// Show an indeterminate progress bar while an elevated update is in
|
||||
// progress.
|
||||
if (!isDMGInstall) {
|
||||
ShowProgressUI(true);
|
||||
}
|
||||
# ifdef MOZ_VERIFY_MAR_SIGNATURE
|
||||
int rv = PopulategMARStrings();
|
||||
if (rv != OK) {
|
||||
shouldServeElevatedUpdate = false;
|
||||
WriteStatusFile(UPDATE_SETTINGS_FILE_CHANNEL);
|
||||
fprintf(stderr,
|
||||
"Unable to start unelevated update process to serve elevated "
|
||||
"updater due to inability to retrieve MAR channels.");
|
||||
} else {
|
||||
threadArgs.marChannelID = gMARStrings.MARChannelID.get();
|
||||
}
|
||||
# endif // MOZ_VERIFY_MAR_SIGNATURE
|
||||
|
||||
if (shouldServeElevatedUpdate) {
|
||||
Thread t1;
|
||||
if (t1.Run(ServeElevatedUpdateThreadFunc, &threadArgs) == 0) {
|
||||
// Show an indeterminate progress bar while an elevated update is in
|
||||
// progress.
|
||||
if (!isDMGInstall) {
|
||||
ShowProgressUI(true);
|
||||
}
|
||||
}
|
||||
t1.Join();
|
||||
}
|
||||
t1.Join();
|
||||
}
|
||||
|
||||
LaunchCallbackAndPostProcessApps(argc, argv, std::move(umaskContext));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue