diff --git a/toolkit/components/backgroundtasks/tests/xpcshell/test_backgroundtask_locked_profile.js b/toolkit/components/backgroundtasks/tests/xpcshell/test_backgroundtask_locked_profile.js new file mode 100644 index 000000000000..20583aa4200a --- /dev/null +++ b/toolkit/components/backgroundtasks/tests/xpcshell/test_backgroundtask_locked_profile.js @@ -0,0 +1,42 @@ +/* -*- 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/. */ + +// Setup that allows to use the profile service, lifted from +// `toolkit/profile/xpcshell/head.js`. +let gProfD = do_get_profile(); +let gDataHome = gProfD.clone(); +gDataHome.append("data"); +gDataHome.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o755); +let gDataHomeLocal = gProfD.clone(); +gDataHomeLocal.append("local"); +gDataHomeLocal.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o755); + +let xreDirProvider = Cc["@mozilla.org/xre/directory-provider;1"].getService( + Ci.nsIXREDirProvider +); +xreDirProvider.setUserDataDirectory(gDataHome, false); +xreDirProvider.setUserDataDirectory(gDataHomeLocal, true); + +add_task(async function test_backgroundtask_locked_profile() { + let profileService = Cc["@mozilla.org/toolkit/profile-service;1"].getService( + Ci.nsIToolkitProfileService + ); + + let profile = profileService.createUniqueProfile( + do_get_profile(), + "test_locked_profile" + ); + let lock = profile.lock({}); + + try { + let exitCode = await do_backgroundtask("success", { + extraEnv: { XRE_PROFILE_PATH: lock.directory.path }, + }); + Assert.equal(1, exitCode); + } finally { + lock.unlock(); + } +}); diff --git a/toolkit/components/backgroundtasks/tests/xpcshell/xpcshell.ini b/toolkit/components/backgroundtasks/tests/xpcshell/xpcshell.ini index 21d1dfefc388..b9c8205e43ba 100644 --- a/toolkit/components/backgroundtasks/tests/xpcshell/xpcshell.ini +++ b/toolkit/components/backgroundtasks/tests/xpcshell/xpcshell.ini @@ -10,6 +10,7 @@ support-files = CatBackgroundTaskRegistrationComponents.manifest [test_backgroundtask_exitcodes.js] +[test_backgroundtask_locked_profile.js] [test_backgroundtask_policies.js] [test_backgroundtask_specific_pref.js] [test_backgroundtask_update_sync_manager.js] diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index eb95dd483f6c..a29f88892d6f 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -2289,6 +2289,14 @@ class ReturnAbortOnError { if (NS_SUCCEEDED(aRv) || aRv == NS_ERROR_LAUNCHED_CHILD_PROCESS) { return aRv; } +#ifdef MOZ_BACKGROUNDTASKS + // A background task that fails to lock its profile will return + // NS_ERROR_UNEXPECTED and this will allow the task to exit with a + // non-zero exit code. + if (aRv == NS_ERROR_UNEXPECTED && BackgroundTasks::IsBackgroundTaskMode()) { + return aRv; + } +#endif return NS_ERROR_ABORT; } @@ -2400,6 +2408,14 @@ static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir, rv = sb->FormatStringFromName("restartTitle", params, killTitle); NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); +#ifdef MOZ_BACKGROUNDTASKS + if (BackgroundTasks::IsBackgroundTaskMode()) { + // This error is handled specially to exit with a non-zero exit code. + printf_stderr("%s\n", NS_LossyConvertUTF16toASCII(killMessage).get()); + return NS_ERROR_UNEXPECTED; + } +#endif + if (gfxPlatform::IsHeadless()) { // TODO: make a way to turn off all dialogs when headless. Output(true, "%s\n", NS_LossyConvertUTF16toASCII(killMessage).get()); @@ -4496,14 +4512,17 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) { #ifdef MOZ_BACKGROUNDTASKS if (BackgroundTasks::IsBackgroundTaskMode()) { - nsCOMPtr file; - nsresult rv = BackgroundTasks::GetOrCreateTemporaryProfileDirectory( - getter_AddRefs(file)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return 1; - } + if (!EnvHasValue("XRE_PROFILE_PATH")) { + // Allow tests to specify profile path via the environment. + nsCOMPtr file; + nsresult rv = BackgroundTasks::GetOrCreateTemporaryProfileDirectory( + getter_AddRefs(file)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return 1; + } - SaveFileToEnv("XRE_PROFILE_PATH", file); + SaveFileToEnv("XRE_PROFILE_PATH", file); + } } #endif