Backed out 2 changesets (bug 1893341, bug 1895744) for causing bc failures in browser_windows_launch_on_login_msix.js. CLOSED TREE

Backed out changeset ce5384469c24 (bug 1893341)
Backed out changeset 658645fa9303 (bug 1895744)
This commit is contained in:
Tamas Szentpeteri
2024-05-15 11:24:17 +03:00
parent 2b8d8ca135
commit 833395877b
11 changed files with 42 additions and 728 deletions

View File

@@ -1312,11 +1312,9 @@ BrowserGlue.prototype = {
); );
} }
Services.prefs.setBoolPref(launchOnLoginPref, false); Services.prefs.setBoolPref(launchOnLoginPref, false);
// To reduce confusion when running multiple Gecko profiles, // Only remove registry key, not shortcut here as we can assume
// delete launch on login shortcuts and registry keys so that // if a user manually created a shortcut they want this behavior.
// users are not presented with the outdated profile selector await lazy.WindowsLaunchOnLogin.removeLaunchOnLoginRegistryKey();
// dialog.
lazy.WindowsLaunchOnLogin.removeLaunchOnLogin();
} }
break; break;
} }

View File

@@ -986,7 +986,7 @@ const BASE_MESSAGES = () => [
targeting: `source == 'newtab' targeting: `source == 'newtab'
&& 'browser.startup.windowsLaunchOnLogin.disableLaunchOnLoginPrompt'|preferenceValue == false && 'browser.startup.windowsLaunchOnLogin.disableLaunchOnLoginPrompt'|preferenceValue == false
&& 'browser.startup.windowsLaunchOnLogin.enabled'|preferenceValue == true && isDefaultBrowser && !activeNotifications && 'browser.startup.windowsLaunchOnLogin.enabled'|preferenceValue == true && isDefaultBrowser && !activeNotifications
&& !launchOnLoginEnabled`, && !launchOnLoginEnabled && !isMSIX`,
}, },
{ {
id: "INFOBAR_LAUNCH_ON_LOGIN_FINAL", id: "INFOBAR_LAUNCH_ON_LOGIN_FINAL",
@@ -1054,7 +1054,7 @@ const BASE_MESSAGES = () => [
&& messageImpressions.INFOBAR_LAUNCH_ON_LOGIN[messageImpressions.INFOBAR_LAUNCH_ON_LOGIN | length - 1] && messageImpressions.INFOBAR_LAUNCH_ON_LOGIN[messageImpressions.INFOBAR_LAUNCH_ON_LOGIN | length - 1]
&& messageImpressions.INFOBAR_LAUNCH_ON_LOGIN[messageImpressions.INFOBAR_LAUNCH_ON_LOGIN | length - 1] < && messageImpressions.INFOBAR_LAUNCH_ON_LOGIN[messageImpressions.INFOBAR_LAUNCH_ON_LOGIN | length - 1] <
currentDate|date - ${FOURTEEN_DAYS_IN_MS} currentDate|date - ${FOURTEEN_DAYS_IN_MS}
&& !launchOnLoginEnabled`, && !launchOnLoginEnabled && !isMSIX`,
}, },
{ {
id: "FOX_DOODLE_SET_DEFAULT", id: "FOX_DOODLE_SET_DEFAULT",

View File

@@ -439,7 +439,8 @@ var gMainPane = {
if ( if (
Cc["@mozilla.org/toolkit/profile-service;1"].getService( Cc["@mozilla.org/toolkit/profile-service;1"].getService(
Ci.nsIToolkitProfileService Ci.nsIToolkitProfileService
).startWithLastProfile ).startWithLastProfile &&
!Services.sysinfo.getProperty("hasWinPackageId", false)
) { ) {
NimbusFeatures.windowsLaunchOnLogin.recordExposureEvent({ NimbusFeatures.windowsLaunchOnLogin.recordExposureEvent({
once: true, once: true,
@@ -692,16 +693,12 @@ var gMainPane = {
let launchOnLoginCheckbox = document.getElementById( let launchOnLoginCheckbox = document.getElementById(
"windowsLaunchOnLogin" "windowsLaunchOnLogin"
); );
WindowsLaunchOnLogin.getLaunchOnLoginEnabled().then(enabled => { launchOnLoginCheckbox.checked =
launchOnLoginCheckbox.checked = enabled; WindowsLaunchOnLogin.getLaunchOnLoginEnabled();
}); let approvedByWindows = WindowsLaunchOnLogin.getLaunchOnLoginApproved();
WindowsLaunchOnLogin.getLaunchOnLoginApproved().then( launchOnLoginCheckbox.disabled = !approvedByWindows;
approvedByWindows => { document.getElementById("windowsLaunchOnLoginDisabledBox").hidden =
launchOnLoginCheckbox.disabled = !approvedByWindows; approvedByWindows;
document.getElementById("windowsLaunchOnLoginDisabledBox").hidden =
approvedByWindows;
}
);
// On Windows, the Application Update setting is an installation- // On Windows, the Application Update setting is an installation-
// specific preference, not a profile-specific one. Show a warning to // specific preference, not a profile-specific one. Show a warning to
@@ -1650,19 +1647,16 @@ var gMainPane = {
return; return;
} }
if (event.target.checked) { if (event.target.checked) {
// windowsLaunchOnLogin has been checked: create registry key or shortcut // windowsLaunchOnLogin has been checked: create registry key
// The shortcut is created with the same AUMID as Firefox itself. However, WindowsLaunchOnLogin.createLaunchOnLoginRegistryKey();
// this is not set during browser tests and the fallback of checking the
// registry fails. As such we pass an arbitrary AUMID for the purpose
// of testing.
await WindowsLaunchOnLogin.createLaunchOnLogin();
Services.prefs.setBoolPref( Services.prefs.setBoolPref(
"browser.startup.windowsLaunchOnLogin.disableLaunchOnLoginPrompt", "browser.startup.windowsLaunchOnLogin.disableLaunchOnLoginPrompt",
true true
); );
} else { } else {
// windowsLaunchOnLogin has been unchecked: delete registry key and shortcut // windowsLaunchOnLogin has been unchecked: delete registry key and shortcut
await WindowsLaunchOnLogin.removeLaunchOnLogin(); WindowsLaunchOnLogin.removeLaunchOnLoginRegistryKey();
await WindowsLaunchOnLogin.removeLaunchOnLoginShortcuts();
} }
}, },

View File

@@ -296,7 +296,4 @@ support-files = [
["browser_warning_permanent_private_browsing.js"] ["browser_warning_permanent_private_browsing.js"]
["browser_windows_launch_on_login.js"] ["browser_windows_launch_on_login.js"]
run-if = ["(os == 'win' && !msix)"] run-if = ["(os == 'win' && !msix)"] # Disabled for MSIX due to https://bugzilla.mozilla.org/show_bug.cgi?id=1888263
["browser_windows_launch_on_login_msix.js"]
run-if = ["(os == 'win' && msix)"]

View File

@@ -18,25 +18,7 @@ const { ExperimentFakes } = ChromeUtils.importESModule(
"resource://testing-common/NimbusTestUtils.sys.mjs" "resource://testing-common/NimbusTestUtils.sys.mjs"
); );
const { MockRegistry } = ChromeUtils.importESModule( add_task(async function test_check_checkbox() {
"resource://testing-common/MockRegistry.sys.mjs"
);
let registry = null;
add_setup(() => {
registry = new MockRegistry();
registry.setValue(
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
"",
""
);
registerCleanupFunction(() => {
registry.shutdown();
});
});
add_task(async function test_check_uncheck_checkbox() {
await ExperimentAPI.ready(); await ExperimentAPI.ready();
let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({ let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
featureId: "windowsLaunchOnLogin", featureId: "windowsLaunchOnLogin",
@@ -58,6 +40,25 @@ add_task(async function test_check_uncheck_checkbox() {
"Key exists" "Key exists"
); );
gBrowser.removeCurrentTab();
});
await doCleanup();
});
add_task(async function test_uncheck_checkbox() {
await ExperimentAPI.ready();
let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
featureId: "windowsLaunchOnLogin",
value: { enabled: true },
});
await WindowsLaunchOnLogin.withLaunchOnLoginRegistryKey(async wrk => {
// Open preferences to general pane
await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
leaveOpen: true,
});
let doc = gBrowser.contentDocument;
let launchOnLoginCheckbox = doc.getElementById("windowsLaunchOnLogin");
launchOnLoginCheckbox.click(); launchOnLoginCheckbox.click();
ok(!launchOnLoginCheckbox.checked, "Autostart checkbox unchecked"); ok(!launchOnLoginCheckbox.checked, "Autostart checkbox unchecked");
@@ -72,20 +73,12 @@ add_task(async function test_check_uncheck_checkbox() {
}); });
add_task(async function create_external_regkey() { add_task(async function create_external_regkey() {
if (Services.sysinfo.getProperty("hasWinPackageId")) {
return;
}
await ExperimentAPI.ready(); await ExperimentAPI.ready();
let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({ let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
featureId: "windowsLaunchOnLogin", featureId: "windowsLaunchOnLogin",
value: { enabled: true }, value: { enabled: true },
}); });
await WindowsLaunchOnLogin.withLaunchOnLoginRegistryKey(async wrk => { await WindowsLaunchOnLogin.withLaunchOnLoginRegistryKey(async wrk => {
// Delete any existing entries before testing
// Both functions are install specific so it's safe to run them
// like this.
wrk.removeValue(WindowsLaunchOnLogin.getLaunchOnLoginRegistryName());
await WindowsLaunchOnLogin.removeLaunchOnLoginShortcuts();
// Create registry key without using settings pane to check if // Create registry key without using settings pane to check if
// this is reflected in the settings // this is reflected in the settings
let autostartPath = let autostartPath =
@@ -115,9 +108,6 @@ add_task(async function create_external_regkey() {
}); });
add_task(async function delete_external_regkey() { add_task(async function delete_external_regkey() {
if (Services.sysinfo.getProperty("hasWinPackageId")) {
return;
}
await ExperimentAPI.ready(); await ExperimentAPI.ready();
let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({ let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
featureId: "windowsLaunchOnLogin", featureId: "windowsLaunchOnLogin",
@@ -146,7 +136,6 @@ add_task(async function delete_external_regkey() {
}); });
registerCleanupFunction(async function () { registerCleanupFunction(async function () {
await WindowsLaunchOnLogin.removeLaunchOnLoginShortcuts();
await WindowsLaunchOnLogin.withLaunchOnLoginRegistryKey(async wrk => { await WindowsLaunchOnLogin.withLaunchOnLoginRegistryKey(async wrk => {
let registryName = WindowsLaunchOnLogin.getLaunchOnLoginRegistryName(); let registryName = WindowsLaunchOnLogin.getLaunchOnLoginRegistryName();
if (wrk.hasValue(registryName)) { if (wrk.hasValue(registryName)) {

View File

@@ -1,101 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
ChromeUtils.defineESModuleGetters(this, {
BackgroundUpdate: "resource://gre/modules/BackgroundUpdate.sys.mjs",
MigrationUtils: "resource:///modules/MigrationUtils.sys.mjs",
PermissionTestUtils: "resource://testing-common/PermissionTestUtils.sys.mjs",
WindowsLaunchOnLogin: "resource://gre/modules/WindowsLaunchOnLogin.sys.mjs",
});
const { ExperimentAPI } = ChromeUtils.importESModule(
"resource://nimbus/ExperimentAPI.sys.mjs"
);
const { ExperimentFakes } = ChromeUtils.importESModule(
"resource://testing-common/NimbusTestUtils.sys.mjs"
);
add_task(async function test_check_uncheck_checkbox() {
await ExperimentAPI.ready();
let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
featureId: "windowsLaunchOnLogin",
value: { enabled: true },
});
// Open preferences to general pane
await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
leaveOpen: true,
});
let doc = gBrowser.contentDocument;
let launchOnLoginCheckbox = doc.getElementById("windowsLaunchOnLogin");
launchOnLoginCheckbox.click();
ok(launchOnLoginCheckbox.checked, "Autostart checkbox checked");
ok(
await WindowsLaunchOnLogin.getLaunchOnLoginEnabledMSIX(),
"Launch on login StartupTask enabled"
);
launchOnLoginCheckbox.click();
ok(!launchOnLoginCheckbox.checked, "Autostart checkbox unchecked");
ok(
await !WindowsLaunchOnLogin.getLaunchOnLoginEnabledMSIX(),
"Launch on login StartupTask disabled"
);
gBrowser.removeCurrentTab();
await doCleanup();
});
add_task(async function enable_external_startuptask() {
await ExperimentAPI.ready();
let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
featureId: "windowsLaunchOnLogin",
value: { enabled: true },
});
// Ensure the task is disabled before enabling it
await WindowsLaunchOnLogin.disableLaunchOnLoginMSIX();
let enabled = await WindowsLaunchOnLogin.enableLaunchOnLoginMSIX();
ok(enabled, "Task is enabled");
// Open preferences to general pane
await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
leaveOpen: true,
});
let doc = gBrowser.contentDocument;
let launchOnLoginCheckbox = doc.getElementById("windowsLaunchOnLogin");
ok(launchOnLoginCheckbox.checked, "Autostart checkbox automatically checked");
gBrowser.removeCurrentTab();
await doCleanup();
});
add_task(async function disable_external_startuptask() {
await ExperimentAPI.ready();
let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
featureId: "windowsLaunchOnLogin",
value: { enabled: true },
});
// Disable the startup task to ensure it's reflected in the settings
await WindowsLaunchOnLogin.disableLaunchOnLoginMSIX();
// Open preferences to general pane
await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
leaveOpen: true,
});
let doc = gBrowser.contentDocument;
let launchOnLoginCheckbox = doc.getElementById("windowsLaunchOnLogin");
ok(
!launchOnLoginCheckbox.checked,
"Launch on login checkbox automatically unchecked"
);
gBrowser.removeCurrentTab();
await doCleanup();
});

View File

@@ -75,93 +75,6 @@ interface nsIWindowsShellService : nsISupports
Array<AString> getLaunchOnLoginShortcuts(); Array<AString> getLaunchOnLoginShortcuts();
/*
* Disables the startup task corresponding to the provided taskId
* to launch upon OS login. The startup task is declared
* within the App Manifest.
*
* If the task was previously disabled by the user this function
* will not re-enable it.
*
* The APIs used within this function are MSIX only and
* will also not work on MINGW.
*
* @param aTaskId Target taskId to enable
*
* @return True if the application was successfully set up to
* launch on OS login.
*
* @throws NS_ERROR_NOT_AVAILABLE
* If used on a non-MSIX build
* @throws NS_ERROR_NOT_IMPLEMENTED
* If used on a MinGW build
* @throws NS_ERROR_NOT_SAME_THREAD
* If called off main thread
* @throws NS_ERROR_FAILURE
* For other types of failures
*/
[implicit_jscontext]
Promise enableLaunchOnLoginMSIXAsync(in AString aTaskId);
/*
* Disables the startup task corresponding to the provided taskId
* to launch upon OS login. The startup task is declared
* within the App Manifest.
*
* The APIs used within this function are MSIX only and
* will also not work on MINGW.
*
* @param aTaskId Target taskId to disable
*
* @return True if the application was successfully disabled from
* launching on OS login.
*
* @throws NS_ERROR_NOT_AVAILABLE
* If used on a non-MSIX build
* @throws NS_ERROR_NOT_IMPLEMENTED
* If used on a MinGW build
* @throws NS_ERROR_NOT_SAME_THREAD
* If called off main thread
* @throws NS_ERROR_FAILURE
* For other types of failures
*/
[implicit_jscontext]
Promise disableLaunchOnLoginMSIXAsync(in AString aTaskId);
/*
* Determines if the startup task corresponding to the provided taskId to
* launch upon OS login is enabled. The startup task is declared
* within the App Manifest. The APIs used within this function are MSIX
* only and will also not work on MINGW.
*
* If the user has disabled the application from launching on login, it
* cannot be re-enabled by the application.
*
* @param aTaskId Target taskId to check status of
*
* @return 0/1/2/3 if the application's OS launch on login is
disabled in settings / disabled / enabled / enabled by policy
*
* @throws NS_ERROR_NOT_AVAILABLE
* If used on a non-MSIX build
* @throws NS_ERROR_NOT_IMPLEMENTED
* If used on a MinGW build
* @throws NS_ERROR_NOT_SAME_THREAD
* If called off main thread
* @throws NS_ERROR_FAILURE
* For other types of failures
*/
cenum LaunchOnLoginEnabledEnumerator : 8 {
LAUNCH_ON_LOGIN_DISABLED_BY_SETTINGS = 0,
LAUNCH_ON_LOGIN_DISABLED = 1,
LAUNCH_ON_LOGIN_ENABLED = 2,
LAUNCH_ON_LOGIN_ENABLED_BY_POLICY = 3,
};
[implicit_jscontext]
Promise getLaunchOnLoginEnabledMSIXAsync(in AString aTaskId);
/* /*
* Pin the current app to the taskbar. If aPrivateBrowsing is true, the * Pin the current app to the taskbar. If aPrivateBrowsing is true, the
* Private Browsing version of the app (with a different icon and launch * Private Browsing version of the app (with a different icon and launch

View File

@@ -26,7 +26,6 @@
#include "nsDirectoryServiceDefs.h" #include "nsDirectoryServiceDefs.h"
#include "nsIWindowsRegKey.h" #include "nsIWindowsRegKey.h"
#include "nsUnicharUtils.h" #include "nsUnicharUtils.h"
#include "nsWindowsHelpers.h"
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#include "mozilla/WindowsVersion.h" #include "mozilla/WindowsVersion.h"
#include "mozilla/dom/Element.h" #include "mozilla/dom/Element.h"
@@ -55,14 +54,6 @@ PSSTDAPI PropVariantToString(REFPROPVARIANT propvar, PWSTR psz, UINT cch);
# define UNLEN 256 # define UNLEN 256
#else #else
# include <Lmcons.h> // For UNLEN # include <Lmcons.h> // For UNLEN
# include <wrl.h>
# include <windows.applicationmodel.activation.h>
# include <windows.foundation.h>
using namespace Microsoft::WRL;
using namespace ABI::Windows;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::ApplicationModel;
using namespace Microsoft::WRL::Wrappers;
#endif #endif
#include <comutil.h> #include <comutil.h>
@@ -1916,310 +1907,6 @@ nsWindowsShellService::IsCurrentAppPinnedToTaskbarAsync(
return NS_OK; return NS_OK;
} }
#ifndef __MINGW32__
# define RESOLVE_AND_RETURN(HOLDER, RESOLVE, RETURN) \
NS_DispatchToMainThread( \
NS_NewRunnableFunction(__func__, [promiseHolder = HOLDER] { \
promiseHolder.get()->get()->MaybeResolve(RESOLVE); \
})); \
return RETURN
# define REJECT_AND_RETURN(HOLDER, REJECT, RETURN) \
NS_DispatchToMainThread( \
NS_NewRunnableFunction(__func__, [promiseHolder = HOLDER] { \
promiseHolder.get()->get()->MaybeReject(REJECT); \
})); \
return RETURN
static void EnableLaunchOnLoginMSIXAsyncImpl(
const nsString& capturedTaskId,
const RefPtr<nsMainThreadPtrHolder<dom::Promise>> promiseHolder) {
ComPtr<IStartupTaskStatics> startupTaskStatics;
HRESULT hr = GetActivationFactory(
HStringReference(RuntimeClass_Windows_ApplicationModel_StartupTask).Get(),
&startupTaskStatics);
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, /* void */);
}
ComPtr<IAsyncOperation<StartupTask*>> getTaskOperation = nullptr;
hr = startupTaskStatics->GetAsync(
HStringReference(capturedTaskId.get()).Get(), &getTaskOperation);
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, /* void */);
}
auto getTaskCallback =
Callback<IAsyncOperationCompletedHandler<StartupTask*>>(
[promiseHolder](IAsyncOperation<StartupTask*>* operation,
AsyncStatus status) -> HRESULT {
if (status != AsyncStatus::Completed) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, E_FAIL);
}
ComPtr<IStartupTask> startupTask;
HRESULT hr = operation->GetResults(&startupTask);
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, E_FAIL);
}
ComPtr<IAsyncOperation<StartupTaskState>> enableOperation;
hr = startupTask->RequestEnableAsync(&enableOperation);
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, E_FAIL);
}
// Set another callback for enabling the startup task
auto enableHandler =
Callback<IAsyncOperationCompletedHandler<StartupTaskState>>(
[promiseHolder](
IAsyncOperation<StartupTaskState>* operation,
AsyncStatus status) -> HRESULT {
StartupTaskState resultState;
HRESULT hr = operation->GetResults(&resultState);
if (SUCCEEDED(hr) && status == AsyncStatus::Completed) {
RESOLVE_AND_RETURN(promiseHolder, true, S_OK);
}
RESOLVE_AND_RETURN(promiseHolder, false, S_OK);
});
hr = enableOperation->put_Completed(enableHandler.Get());
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, hr);
}
return hr;
});
hr = getTaskOperation->put_Completed(getTaskCallback.Get());
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, /* void */);
}
}
static void DisableLaunchOnLoginMSIXAsyncImpl(
const nsString& capturedTaskId,
const RefPtr<nsMainThreadPtrHolder<dom::Promise>> promiseHolder) {
ComPtr<IStartupTaskStatics> startupTaskStatics;
HRESULT hr = GetActivationFactory(
HStringReference(RuntimeClass_Windows_ApplicationModel_StartupTask).Get(),
&startupTaskStatics);
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, /* void */);
}
ComPtr<IAsyncOperation<StartupTask*>> getTaskOperation = nullptr;
hr = startupTaskStatics->GetAsync(
HStringReference(capturedTaskId.get()).Get(), &getTaskOperation);
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, /* void */);
}
auto getTaskCallback =
Callback<IAsyncOperationCompletedHandler<StartupTask*>>(
[promiseHolder](IAsyncOperation<StartupTask*>* operation,
AsyncStatus status) -> HRESULT {
if (status != AsyncStatus::Completed) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, E_FAIL);
}
ComPtr<IStartupTask> startupTask;
HRESULT hr = operation->GetResults(&startupTask);
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, E_FAIL);
}
hr = startupTask->Disable();
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, E_FAIL);
}
RESOLVE_AND_RETURN(promiseHolder, true, S_OK);
});
hr = getTaskOperation->put_Completed(getTaskCallback.Get());
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, /* void */);
}
}
static void GetLaunchOnLoginEnabledMSIXAsyncImpl(
const nsString& capturedTaskId,
const RefPtr<nsMainThreadPtrHolder<dom::Promise>> promiseHolder) {
ComPtr<IStartupTaskStatics> startupTaskStatics;
HRESULT hr = GetActivationFactory(
HStringReference(RuntimeClass_Windows_ApplicationModel_StartupTask).Get(),
&startupTaskStatics);
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, /* void */);
}
ComPtr<IAsyncOperation<StartupTask*>> getTaskOperation = nullptr;
hr = startupTaskStatics->GetAsync(
HStringReference(capturedTaskId.get()).Get(), &getTaskOperation);
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, /* void */);
}
auto getTaskCallback =
Callback<IAsyncOperationCompletedHandler<StartupTask*>>(
[promiseHolder](IAsyncOperation<StartupTask*>* operation,
AsyncStatus status) -> HRESULT {
if (status != AsyncStatus::Completed) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, E_FAIL);
}
ComPtr<IStartupTask> startupTask;
HRESULT hr = operation->GetResults(&startupTask);
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, E_FAIL);
}
StartupTaskState state;
hr = startupTask->get_State(&state);
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, E_FAIL);
}
switch (state) {
case StartupTaskState_EnabledByPolicy:
RESOLVE_AND_RETURN(
promiseHolder,
nsIWindowsShellService::LaunchOnLoginEnabledEnumerator::
LAUNCH_ON_LOGIN_ENABLED_BY_POLICY,
S_OK);
break;
case StartupTaskState_Enabled:
RESOLVE_AND_RETURN(
promiseHolder,
nsIWindowsShellService::LaunchOnLoginEnabledEnumerator::
LAUNCH_ON_LOGIN_ENABLED,
S_OK);
break;
case StartupTaskState_DisabledByUser:
case StartupTaskState_DisabledByPolicy:
RESOLVE_AND_RETURN(
promiseHolder,
nsIWindowsShellService::LaunchOnLoginEnabledEnumerator::
LAUNCH_ON_LOGIN_DISABLED_BY_SETTINGS,
S_OK);
break;
default:
RESOLVE_AND_RETURN(
promiseHolder,
nsIWindowsShellService::LaunchOnLoginEnabledEnumerator::
LAUNCH_ON_LOGIN_DISABLED,
S_OK);
}
});
hr = getTaskOperation->put_Completed(getTaskCallback.Get());
if (FAILED(hr)) {
REJECT_AND_RETURN(promiseHolder, NS_ERROR_FAILURE, /* void */);
}
}
NS_IMETHODIMP
nsWindowsShellService::EnableLaunchOnLoginMSIXAsync(
const nsAString& aTaskId, JSContext* aCx,
/* out */ dom::Promise** aPromise) {
if (!widget::WinUtils::HasPackageIdentity()) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!NS_IsMainThread()) {
return NS_ERROR_NOT_SAME_THREAD;
}
ErrorResult rv;
RefPtr<dom::Promise> promise =
dom::Promise::Create(xpc::CurrentNativeGlobal(aCx), rv);
if (MOZ_UNLIKELY(rv.Failed())) {
return rv.StealNSResult();
}
// A holder to pass the promise through the background task and back to
// the main thread when finished.
auto promiseHolder = MakeRefPtr<nsMainThreadPtrHolder<dom::Promise>>(
"EnableLaunchOnLoginMSIXAsync promise", promise);
NS_DispatchBackgroundTask(NS_NewRunnableFunction(
"EnableLaunchOnLoginMSIXAsync",
[taskId = nsString(aTaskId), promiseHolder] {
EnableLaunchOnLoginMSIXAsyncImpl(taskId, promiseHolder);
}));
promise.forget(aPromise);
return NS_OK;
}
NS_IMETHODIMP
nsWindowsShellService::DisableLaunchOnLoginMSIXAsync(
const nsAString& aTaskId, JSContext* aCx,
/* out */ dom::Promise** aPromise) {
if (!widget::WinUtils::HasPackageIdentity()) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!NS_IsMainThread()) {
return NS_ERROR_NOT_SAME_THREAD;
}
ErrorResult rv;
RefPtr<dom::Promise> promise =
dom::Promise::Create(xpc::CurrentNativeGlobal(aCx), rv);
if (MOZ_UNLIKELY(rv.Failed())) {
return rv.StealNSResult();
}
// A holder to pass the promise through the background task and back to
// the main thread when finished.
auto promiseHolder = MakeRefPtr<nsMainThreadPtrHolder<dom::Promise>>(
"DisableLaunchOnLoginMSIXAsync promise", promise);
NS_DispatchBackgroundTask(NS_NewRunnableFunction(
"DisableLaunchOnLoginMSIXAsync",
[taskId = nsString(aTaskId), promiseHolder] {
DisableLaunchOnLoginMSIXAsyncImpl(taskId, promiseHolder);
}));
promise.forget(aPromise);
return NS_OK;
}
NS_IMETHODIMP
nsWindowsShellService::GetLaunchOnLoginEnabledMSIXAsync(
const nsAString& aTaskId, JSContext* aCx,
/* out */ dom::Promise** aPromise) {
if (!widget::WinUtils::HasPackageIdentity()) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!NS_IsMainThread()) {
return NS_ERROR_NOT_SAME_THREAD;
}
ErrorResult rv;
RefPtr<dom::Promise> promise =
dom::Promise::Create(xpc::CurrentNativeGlobal(aCx), rv);
if (MOZ_UNLIKELY(rv.Failed())) {
return rv.StealNSResult();
}
// A holder to pass the promise through the background task and back to
// the main thread when finished.
auto promiseHolder = MakeRefPtr<nsMainThreadPtrHolder<dom::Promise>>(
"GetLaunchOnLoginEnabledMSIXAsync promise", promise);
NS_DispatchBackgroundTask(NS_NewRunnableFunction(
"GetLaunchOnLoginEnabledMSIXAsync",
[taskId = nsString(aTaskId), promiseHolder] {
GetLaunchOnLoginEnabledMSIXAsyncImpl(taskId, promiseHolder);
}));
promise.forget(aPromise);
return NS_OK;
}
#else
NS_IMETHODIMP
nsWindowsShellService::EnableLaunchOnLoginMSIXAsync(
const nsAString& aTaskId, JSContext* aCx,
/* out */ dom::Promise** aPromise) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsWindowsShellService::DisableLaunchOnLoginMSIXAsync(
const nsAString& aTaskId, JSContext* aCx,
/* out */ dom::Promise** aPromise) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsWindowsShellService::GetLaunchOnLoginEnabledMSIXAsync(
const nsAString& aTaskId, JSContext* aCx,
/* out */ dom::Promise** aPromise) {
return NS_ERROR_NOT_IMPLEMENTED;
}
#endif
NS_IMETHODIMP NS_IMETHODIMP
nsWindowsShellService::ClassifyShortcut(const nsAString& aPath, nsWindowsShellService::ClassifyShortcut(const nsAString& aPath,
nsAString& aResult) { nsAString& aResult) {

View File

@@ -10,10 +10,9 @@
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2" xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10" xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap uap2 uap3 uap5 uap10 rescap"> IgnorableNamespaces="uap uap2 uap3 uap10 rescap">
<Identity Name="@APPX_IDENTITY@" Publisher="@APPX_PUBLISHER@" Version="@APPX_VERSION@" ProcessorArchitecture="@APPX_ARCH@" /> <Identity Name="@APPX_IDENTITY@" Publisher="@APPX_PUBLISHER@" Version="@APPX_VERSION@" ProcessorArchitecture="@APPX_ARCH@" />
<Properties> <Properties>
@@ -103,16 +102,6 @@
</com:SurrogateServer> </com:SurrogateServer>
</com:ComServer> </com:ComServer>
</com:Extension> </com:Extension>
<uap5:Extension
Category="windows.startupTask"
Executable="VFS\ProgramFiles\@APPX_INSTDIR@\@MOZ_APP_NAME@.exe"
EntryPoint="Windows.FullTrustApplication"
uap10:Parameters="-os-autostart">
<uap5:StartupTask
TaskId="LaunchOnLogin"
Enabled="false"
DisplayName="@MOZ_APP_DISPLAYNAME@" />
</uap5:Extension>
<desktop:Extension Category="windows.toastNotificationActivation"> <desktop:Extension Category="windows.toastNotificationActivation">
<desktop:ToastNotificationActivation ToastActivatorCLSID="@MOZ_INOTIFICATIONACTIVATION_CLSID@" /> <desktop:ToastNotificationActivation ToastActivatorCLSID="@MOZ_INOTIFICATIONACTIVATION_CLSID@" />
</desktop:Extension> </desktop:Extension>

View File

@@ -457,7 +457,7 @@ export const SpecialMessageActions = {
const { WindowsLaunchOnLogin } = ChromeUtils.importESModule( const { WindowsLaunchOnLogin } = ChromeUtils.importESModule(
"resource://gre/modules/WindowsLaunchOnLogin.sys.mjs" "resource://gre/modules/WindowsLaunchOnLogin.sys.mjs"
); );
await WindowsLaunchOnLogin.createLaunchOnLogin(); await WindowsLaunchOnLogin.createLaunchOnLoginRegistryKey();
break; break;
case "PIN_CURRENT_TAB": case "PIN_CURRENT_TAB":
let tab = window.gBrowser.selectedTab; let tab = window.gBrowser.selectedTab;

View File

@@ -2,8 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const LAUNCH_ON_LOGIN_TASKID = "LaunchOnLogin";
/** /**
* "Launch on Login" is a Firefox feature automatically launches Firefox when the * "Launch on Login" is a Firefox feature automatically launches Firefox when the
* user logs in to Windows. The technical mechanism is simply writing a registry * user logs in to Windows. The technical mechanism is simply writing a registry
@@ -14,11 +12,6 @@ const LAUNCH_ON_LOGIN_TASKID = "LaunchOnLogin";
* When such keys are present, the launch on login feature should be considered * When such keys are present, the launch on login feature should be considered
* disabled and not available from within Firefox. This module provides the * disabled and not available from within Firefox. This module provides the
* functionality to access and modify these registry keys. * functionality to access and modify these registry keys.
*
* MSIX installs cannot write to the registry so we instead use the MSIX-exclusive
* Windows StartupTask APIs. The difference here is that the startup task is always
* "registered", we control whether it's enabled or disabled. As such some
* functions such as getLaunchOnLoginApproved() have different behavior on MSIX installs.
*/ */
export var WindowsLaunchOnLogin = { export var WindowsLaunchOnLogin = {
/** /**
@@ -70,33 +63,6 @@ export var WindowsLaunchOnLogin = {
} }
}, },
/**
* Either creates a Windows launch on login registry key on regular installs
* or enables the startup task within the app manifest due to
* restrictions on writing to the registry in MSIX.
*/
async createLaunchOnLogin() {
if (Services.sysinfo.getProperty("hasWinPackageId")) {
await this.enableLaunchOnLoginMSIX();
} else {
await this.createLaunchOnLoginRegistryKey();
}
},
/**
* Either deletes a Windows launch on login registry key and shortcut on
* regular installs or disables the startup task within the app manifest due
* to restrictions on writing to the registry in MSIX.
*/
async removeLaunchOnLogin() {
if (Services.sysinfo.getProperty("hasWinPackageId")) {
await this.disableLaunchOnLoginMSIX();
} else {
await this.removeLaunchOnLoginRegistryKey();
await this.removeLaunchOnLoginShortcuts();
}
},
/** /**
* Safely removes a Windows launch on login registry key * Safely removes a Windows launch on login registry key
*/ */
@@ -118,75 +84,6 @@ export var WindowsLaunchOnLogin = {
} }
}, },
/**
* Enables launch on login on MSIX installs by using the
* StartupTask APIs. A task called "LaunchOnLogin" exists
* in the packaged application manifest.
*
* @returns {Promise<bool>}
* Whether the enable operation was successful.
*/
async enableLaunchOnLoginMSIX() {
if (!Services.sysinfo.getProperty("hasWinPackageId")) {
throw Components.Exception(
"Called on non-MSIX build",
Cr.NS_ERROR_NOT_IMPLEMENTED
);
}
let shellService = Cc["@mozilla.org/browser/shell-service;1"].getService(
Ci.nsIWindowsShellService
);
return shellService.enableLaunchOnLoginMSIXAsync(LAUNCH_ON_LOGIN_TASKID);
},
/**
* Disables launch on login on MSIX installs by using the
* StartupTask APIs. A task called "LaunchOnLogin" exists
* in the packaged application manifest.
*
* @returns {Promise<bool>}
* Whether the disable operation was successful.
*/
async disableLaunchOnLoginMSIX() {
if (!Services.sysinfo.getProperty("hasWinPackageId")) {
throw Components.Exception(
"Called on non-MSIX build",
Cr.NS_ERROR_NOT_IMPLEMENTED
);
}
let shellService = Cc["@mozilla.org/browser/shell-service;1"].getService(
Ci.nsIWindowsShellService
);
return shellService.disableLaunchOnLoginMSIXAsync(LAUNCH_ON_LOGIN_TASKID);
},
/**
* Determines whether launch on login on MSIX is enabled by using the
* StartupTask APIs. A task called "LaunchOnLogin" exists
* in the packaged application manifest.
*
* @returns {Promise<bool>}
* Whether the startup task is enabled.
*/
async getLaunchOnLoginEnabledMSIX() {
if (!Services.sysinfo.getProperty("hasWinPackageId")) {
throw Components.Exception(
"Called on non-MSIX build",
Cr.NS_ERROR_NOT_IMPLEMENTED
);
}
let shellService = Cc["@mozilla.org/browser/shell-service;1"].getService(
Ci.nsIWindowsShellService
);
let state = await shellService.getLaunchOnLoginEnabledMSIXAsync(
LAUNCH_ON_LOGIN_TASKID
);
return (
state == shellService.LAUNCH_ON_LOGIN_ENABLED ||
state == shellService.LAUNCH_ON_LOGIN_ENABLED_BY_POLICY
);
},
/** /**
* Gets a list of all launch on login shortcuts in the * Gets a list of all launch on login shortcuts in the
* %USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup folder * %USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup folder
@@ -211,52 +108,12 @@ export var WindowsLaunchOnLogin = {
} }
}, },
/**
* If the state is set to disabled from the Windows UI our API calls to
* re-enable it will fail so we should say that it's not approved and
* provide users the link to the App Startup settings so they can
* re-enable it.
*
* @returns {Promise<bool>}
* If launch on login has not been disabled by Windows settings
* or enabled by policy.
*/
async getLaunchOnLoginApprovedMSIX() {
if (!Services.sysinfo.getProperty("hasWinPackageId")) {
throw Components.Exception(
"Called on non-MSIX build",
Cr.NS_ERROR_NOT_IMPLEMENTED
);
}
let shellService = Cc["@mozilla.org/browser/shell-service;1"].getService(
Ci.nsIWindowsShellService
);
let state = await shellService.getLaunchOnLoginEnabledMSIXAsync(
LAUNCH_ON_LOGIN_TASKID
);
return !(
state == shellService.LAUNCH_ON_LOGIN_DISABLED_BY_SETTINGS ||
state == shellService.LAUNCH_ON_LOGIN_ENABLED_BY_POLICY
);
},
/** /**
* Checks if Windows launch on login was independently enabled or disabled * Checks if Windows launch on login was independently enabled or disabled
* by the user in the Windows Startup Apps menu. The registry key that * by the user in the Windows Startup Apps menu. The registry key that
* stores this information should not be modified. * stores this information should not be modified.
*
* If the state is set to disabled from the Windows UI on MSIX our API calls to
* re-enable it will fail so report false.
*
* @returns {Promise<bool>}
* Report whether launch on login is allowed on Windows. On MSIX
* it's possible to set a startup app through policy making us
* unable to modify it so we should account for that here.
*/ */
async getLaunchOnLoginApproved() { getLaunchOnLoginApproved() {
if (Services.sysinfo.getProperty("hasWinPackageId")) {
return this.getLaunchOnLoginApprovedMSIX();
}
try { try {
let wrkApproved = Cc[ let wrkApproved = Cc[
"@mozilla.org/windows-registry-key;1" "@mozilla.org/windows-registry-key;1"
@@ -290,17 +147,8 @@ export var WindowsLaunchOnLogin = {
* Checks if Windows launch on login has an existing registry key or user-created shortcut in * Checks if Windows launch on login has an existing registry key or user-created shortcut in
* %USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup. The registry key that * %USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup. The registry key that
* stores this information should not be modified. * stores this information should not be modified.
*
* On MSIX installs we instead query whether the StartupTask is enabled or disabled
*
* @returns {Promise<bool>}
* Whether launch on login is enabled.
*/ */
async getLaunchOnLoginEnabled() { getLaunchOnLoginEnabled() {
if (Services.sysinfo.getProperty("hasWinPackageId")) {
return this.getLaunchOnLoginEnabledMSIX();
}
let registryName = this.getLaunchOnLoginRegistryName(); let registryName = this.getLaunchOnLoginRegistryName();
let regExists = false; let regExists = false;
let shortcutExists = false; let shortcutExists = false;