Bug 1667276 - Part 3: Load a custom prefs file when running a background task. r=mossop,KrisWright

There are some complications here to handle unpackaged and packaged
builds.  In addition, there could be a difference between App prefs
and GRE prefs.  Since the underlying backgroundtasks code is built as
part of Gecko (i.e., `toolkit/...` rather than `browser/...`) I have
favoured GRE prefs.  I think, however, that what is written will work
for App-specific prefs, but I'm not concerned with that detail at this
time.

This also add tests for backgroundtask-specific prefs, which are
structured as both xpcshell and mochitest-chrome tests because
locally, the former tests unpackaged builds and the latter can
accommodate testing packaged builds.  We could use mochitest-chrome
for both, but this has been pleasant to work with locally.

Differential Revision: https://phabricator.services.mozilla.com/D97510
This commit is contained in:
Nick Alexander 2021-01-27 22:54:25 +00:00
Родитель 9862045082
Коммит 03ff66c89d
16 изменённых файлов: 238 добавлений и 0 удалений

Просмотреть файл

@ -220,3 +220,6 @@ tools/tryselect/selectors/chooser/templates/chooser.html
# Ignore preprocessed *(P)refs.js files in update-packaging.
tools/update-packaging/**/*refs.js
# Ignore backgroundtasks preferences files.
toolkit/components/backgroundtasks/defaults

Просмотреть файл

@ -58,3 +58,6 @@ devtools/client/debugger/src/test/mochitest/examples/ember/quickstart
# These are source mapped and the locations are asserted in the test case.
devtools/client/webconsole/test/browser/test-mangled-function.*
# Ignore backgroundtasks preferences files.
toolkit/components/backgroundtasks/defaults

Просмотреть файл

@ -56,6 +56,8 @@ if (AppConstants.platform == "macosx") {
}
if (AppConstants.MOZ_BACKGROUNDTASKS) {
// These preferences are active only when we're in background task mode.
gExceptionPaths.push("resource://gre/defaults/backgroundtasks/");
// `BackgroundTask_id.jsm` is loaded at runtime by `app --backgroundtask id ...`.
gExceptionPaths.push("resource://gre/modules/backgroundtasks/");
}

Просмотреть файл

@ -98,6 +98,10 @@ ifdef MOZ_DEFAULT_BROWSER_AGENT
DEFINES += -DMOZ_DEFAULT_BROWSER_AGENT=1
endif
ifdef MOZ_BACKGROUNDTASKS
DEFINES += -DMOZ_BACKGROUNDTASKS=1
endif
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
MOZ_PKG_MAC_DSSTORE=$(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/dsstore
MOZ_PKG_MAC_BACKGROUND=$(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/background.png

Просмотреть файл

@ -305,6 +305,12 @@
; gre location for now.
@RESPATH@/defaults/pref/channel-prefs.js
; Background tasks-specific preferences. These are in the GRE
; location since they apply to all tasks at this time.
#ifdef MOZ_BACKGROUNDTASKS
@RESPATH@/defaults/backgroundtasks/backgroundtasks.js
#endif
; [Layout Engine Resources]
; Style Sheets, Graphics and other Resources used by the layout engine.
@RESPATH@/res/EditorOverride.css

Просмотреть файл

@ -86,6 +86,9 @@
#include "plstr.h"
#include "prlink.h"
#include "xpcpublic.h"
#ifdef MOZ_BACKGROUNDTASKS
# include "mozilla/BackgroundTasks.h"
#endif
#ifdef DEBUG
# include <map>
@ -4530,6 +4533,13 @@ nsresult Preferences::InitInitialObjects(bool aIsStartup) {
rv = pref_ReadDefaultPrefs(jarReader, "defaults/pref/*.js$");
NS_ENSURE_SUCCESS(rv, rv);
#ifdef MOZ_BACKGROUNDTASKS
if (BackgroundTasks::IsBackgroundTaskMode()) {
rv = pref_ReadDefaultPrefs(jarReader, "defaults/backgroundtasks/*.js$");
NS_ENSURE_SUCCESS(rv, rv);
}
#endif
#ifdef MOZ_WIDGET_ANDROID
// Load jar:$gre/omni.jar!/defaults/pref/$MOZ_ANDROID_CPU_ABI/*.js.
nsAutoCString path;
@ -4609,6 +4619,25 @@ nsresult Preferences::InitInitialObjects(bool aIsStartup) {
NS_WARNING("Error parsing preferences.");
}
}
#ifdef MOZ_BACKGROUNDTASKS
if (BackgroundTasks::IsBackgroundTaskMode()) {
rv = appJarReader->FindInit("defaults/backgroundtasks/*.js$",
getter_Transfers(find));
NS_ENSURE_SUCCESS(rv, rv);
prefEntries.Clear();
while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
prefEntries.AppendElement(Substring(entryName, entryNameLen));
}
prefEntries.Sort();
for (uint32_t i = prefEntries.Length(); i--;) {
rv = pref_ReadPrefFromJar(appJarReader, prefEntries[i].get());
if (NS_FAILED(rv)) {
NS_WARNING("Error parsing preferences.");
}
}
}
#endif
}
nsCOMPtr<nsIProperties> dirSvc(

Просмотреть файл

@ -167,3 +167,6 @@ else:
FINAL_TARGET_PP_FILES += [
"greprefs.js",
]
if CONFIG["MOZ_BACKGROUNDTASKS"]:
DEFINES["MOZ_BACKGROUNDTASKS"] = True

Просмотреть файл

@ -0,0 +1,27 @@
/* 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/. */
pref("browser.dom.window.dump.enabled", true);
pref("devtools.console.stdout.chrome", true);
pref("network.process.enabled", false);
pref("toolkit.telemetry.archive.enabled", false);
pref("toolkit.telemetry.firstShutdownPing.enabled", false);
pref("toolkit.telemetry.healthping.enabled", false);
pref("toolkit.telemetry.newProfilePing.enabled", false);
pref("toolkit.telemetry.eventping.enabled", false);
pref("toolkit.telemetry.ecosystemtelemetry.enabled", false);
pref("toolkit.telemetry.prioping.enabled", false);
pref("datareporting.policy.dataSubmissionEnabled", false);
pref("datareporting.healthreport.uploadEnabled", false);
pref("browser.cache.offline.enable", false);
pref("browser.cache.offline.storage.enable", false);
pref("browser.cache.disk.enable", false);
pref("permissions.memory_only", true);
// For testing only: used to test that backgroundtask-specific prefs are
// processed. This just needs to be an unusual integer in the range 0..127.
pref("test.backgroundtask_specific_pref.exitCode", 79);

Просмотреть файл

@ -37,4 +37,13 @@ EXTRA_JS_MODULES.backgroundtasks += [
"BackgroundTask_success.jsm",
]
BROWSER_CHROME_MANIFESTS += ["tests/browser/browser.ini"]
XPCSHELL_TESTS_MANIFESTS += ["tests/xpcshell/xpcshell.ini"]
TESTING_JS_MODULES.backgroundtasks += [
"tests/BackgroundTask_backgroundtask_specific_pref.jsm",
]
FINAL_TARGET_FILES.defaults.backgroundtasks += [
"defaults/backgroundtasks.js",
]

Просмотреть файл

@ -0,0 +1,23 @@
/* -*- 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/. */
var EXPORTED_SYMBOLS = ["runBackgroundTask"];
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
async function runBackgroundTask(commandLine) {
let pref = commandLine.length
? commandLine.getArgument(0)
: "test.backgroundtask_specific_pref.exitCode";
// 0, 1, 2, 3 are all meaningful exit codes already.
let exitCode = Services.prefs.getIntPref(pref, 4);
console.error(
`runBackgroundTask: backgroundtask_specific_pref read pref '${pref}', exiting with exitCode ${exitCode}`
);
return exitCode;
}

Просмотреть файл

@ -0,0 +1,9 @@
# 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]
skip-if = toolkit == 'android'
head = head.js
[browser_backgroundtask_specific_pref.js]

Просмотреть файл

@ -0,0 +1,23 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
* vim: sw=4 ts=4 sts=4 et
* 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";
add_task(async function test_backgroundtask_specific_pref() {
// First, verify this pref isn't set in Gecko itself.
Assert.equal(
-1,
Services.prefs.getIntPref("test.backgroundtask_specific_pref.exitCode", -1)
);
// Second, verify that this pref is set in background tasks.
// mochitest-chrome tests locally test both unpackaged and packaged
// builds (with `--appname=dist`).
let exitCode = await do_backgroundtask("backgroundtask_specific_pref", {
extraArgs: ["test.backgroundtask_specific_pref.exitCode"],
});
Assert.equal(79, exitCode);
});

Просмотреть файл

@ -0,0 +1,66 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
* vim: sw=4 ts=4 sts=4 et
* 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";
async function do_backgroundtask(
task,
options = { extraArgs: [], extraEnv: {} }
) {
options = Object.assign({}, options);
options.extraArgs = options.extraArgs || [];
options.extraEnv = options.extraEnv || {};
let command = Services.dirsvc.get("XREExeF", Ci.nsIFile).path;
let args = ["--backgroundtask", task];
args.push(...options.extraArgs);
// Ensure `resource://testing-common` gets mapped.
let protocolHandler = Services.io
.getProtocolHandler("resource")
.QueryInterface(Ci.nsIResProtocolHandler);
let uri = protocolHandler.getSubstitution("testing-common");
Assert.ok(uri, "resource://testing-common is not substituted");
// The equivalent of _TESTING_MODULES_DIR in xpcshell.
options.extraEnv.XPCSHELL_TESTING_MODULES_URI = uri.spec;
// Now we can actually invoke the process.
info(
`launching child process ${command} with args: ${args} and extra environment: ${JSON.stringify(
options.extraEnv
)}`
);
const { Subprocess } = ChromeUtils.import(
"resource://gre/modules/Subprocess.jsm"
);
let proc = await Subprocess.call({
command,
arguments: args,
environment: options.extraEnv,
environmentAppend: true,
stderr: "stdout",
}).then(p => {
p.stdin.close();
const dumpPipe = async pipe => {
let data = await pipe.readString();
while (data) {
for (let line of data.split(/\r\n|\r|\n/).slice(0, -1)) {
dump("> " + line + "\n");
}
data = await pipe.readString();
}
};
dumpPipe(p.stdout);
return p;
});
let { exitCode } = await proc.wait();
return exitCode;
}

Просмотреть файл

@ -0,0 +1,20 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
* vim: sw=4 ts=4 sts=4 et
* 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/. */
add_task(async function test_backgroundtask_specific_pref() {
// First, verify this pref isn't set in Gecko itself.
Assert.equal(
-1,
Services.prefs.getIntPref("test.backgroundtask_specific_pref.exitCode", -1)
);
// Second, verify that this pref is set in background tasks.
// xpcshell tests locally test unpackaged builds.
let exitCode = await do_backgroundtask("backgroundtask_specific_pref", {
extraArgs: ["test.backgroundtask_specific_pref.exitCode"],
});
Assert.equal(79, exitCode);
});

Просмотреть файл

@ -8,5 +8,6 @@ support-files =
CatBackgroundTaskRegistrationComponents.manifest
[test_backgroundtask_exitcodes.js]
[test_backgroundtask_specific_pref.js]
[test_manifest_with_backgroundtask.js]
[test_manifest_without_backgroundtask.js]

Просмотреть файл

@ -853,6 +853,10 @@ static nsresult DeleteDirIfExists(nsIFile* dir) {
static const char* const kAppendPrefDir[] = {"defaults", "preferences",
nullptr};
#ifdef MOZ_BACKGROUNDTASKS
static const char* const kAppendBackgroundTasksPrefDir[] = {
"defaults", "backgroundtasks", nullptr};
#endif
nsresult nsXREDirProvider::GetFilesInternal(const char* aProperty,
nsISimpleEnumerator** aResult) {
@ -863,6 +867,12 @@ nsresult nsXREDirProvider::GetFilesInternal(const char* aProperty,
nsCOMArray<nsIFile> directories;
LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories);
#ifdef MOZ_BACKGROUNDTASKS
if (mozilla::BackgroundTasks::IsBackgroundTaskMode()) {
LoadDirIntoArray(mGREDir, kAppendBackgroundTasksPrefDir, directories);
LoadDirIntoArray(mXULAppDir, kAppendBackgroundTasksPrefDir, directories);
}
#endif
rv = NS_NewArrayEnumerator(aResult, directories, NS_GET_IID(nsIFile));
} else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) {