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:
@@ -1312,11 +1312,9 @@ BrowserGlue.prototype = {
|
||||
);
|
||||
}
|
||||
Services.prefs.setBoolPref(launchOnLoginPref, false);
|
||||
// To reduce confusion when running multiple Gecko profiles,
|
||||
// delete launch on login shortcuts and registry keys so that
|
||||
// users are not presented with the outdated profile selector
|
||||
// dialog.
|
||||
lazy.WindowsLaunchOnLogin.removeLaunchOnLogin();
|
||||
// Only remove registry key, not shortcut here as we can assume
|
||||
// if a user manually created a shortcut they want this behavior.
|
||||
await lazy.WindowsLaunchOnLogin.removeLaunchOnLoginRegistryKey();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -986,7 +986,7 @@ const BASE_MESSAGES = () => [
|
||||
targeting: `source == 'newtab'
|
||||
&& 'browser.startup.windowsLaunchOnLogin.disableLaunchOnLoginPrompt'|preferenceValue == false
|
||||
&& 'browser.startup.windowsLaunchOnLogin.enabled'|preferenceValue == true && isDefaultBrowser && !activeNotifications
|
||||
&& !launchOnLoginEnabled`,
|
||||
&& !launchOnLoginEnabled && !isMSIX`,
|
||||
},
|
||||
{
|
||||
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] <
|
||||
currentDate|date - ${FOURTEEN_DAYS_IN_MS}
|
||||
&& !launchOnLoginEnabled`,
|
||||
&& !launchOnLoginEnabled && !isMSIX`,
|
||||
},
|
||||
{
|
||||
id: "FOX_DOODLE_SET_DEFAULT",
|
||||
|
||||
@@ -439,7 +439,8 @@ var gMainPane = {
|
||||
if (
|
||||
Cc["@mozilla.org/toolkit/profile-service;1"].getService(
|
||||
Ci.nsIToolkitProfileService
|
||||
).startWithLastProfile
|
||||
).startWithLastProfile &&
|
||||
!Services.sysinfo.getProperty("hasWinPackageId", false)
|
||||
) {
|
||||
NimbusFeatures.windowsLaunchOnLogin.recordExposureEvent({
|
||||
once: true,
|
||||
@@ -692,16 +693,12 @@ var gMainPane = {
|
||||
let launchOnLoginCheckbox = document.getElementById(
|
||||
"windowsLaunchOnLogin"
|
||||
);
|
||||
WindowsLaunchOnLogin.getLaunchOnLoginEnabled().then(enabled => {
|
||||
launchOnLoginCheckbox.checked = enabled;
|
||||
});
|
||||
WindowsLaunchOnLogin.getLaunchOnLoginApproved().then(
|
||||
approvedByWindows => {
|
||||
launchOnLoginCheckbox.checked =
|
||||
WindowsLaunchOnLogin.getLaunchOnLoginEnabled();
|
||||
let approvedByWindows = WindowsLaunchOnLogin.getLaunchOnLoginApproved();
|
||||
launchOnLoginCheckbox.disabled = !approvedByWindows;
|
||||
document.getElementById("windowsLaunchOnLoginDisabledBox").hidden =
|
||||
approvedByWindows;
|
||||
}
|
||||
);
|
||||
|
||||
// On Windows, the Application Update setting is an installation-
|
||||
// specific preference, not a profile-specific one. Show a warning to
|
||||
@@ -1650,19 +1647,16 @@ var gMainPane = {
|
||||
return;
|
||||
}
|
||||
if (event.target.checked) {
|
||||
// windowsLaunchOnLogin has been checked: create registry key or shortcut
|
||||
// The shortcut is created with the same AUMID as Firefox itself. However,
|
||||
// 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();
|
||||
// windowsLaunchOnLogin has been checked: create registry key
|
||||
WindowsLaunchOnLogin.createLaunchOnLoginRegistryKey();
|
||||
Services.prefs.setBoolPref(
|
||||
"browser.startup.windowsLaunchOnLogin.disableLaunchOnLoginPrompt",
|
||||
true
|
||||
);
|
||||
} else {
|
||||
// windowsLaunchOnLogin has been unchecked: delete registry key and shortcut
|
||||
await WindowsLaunchOnLogin.removeLaunchOnLogin();
|
||||
WindowsLaunchOnLogin.removeLaunchOnLoginRegistryKey();
|
||||
await WindowsLaunchOnLogin.removeLaunchOnLoginShortcuts();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -296,7 +296,4 @@ support-files = [
|
||||
["browser_warning_permanent_private_browsing.js"]
|
||||
|
||||
["browser_windows_launch_on_login.js"]
|
||||
run-if = ["(os == 'win' && !msix)"]
|
||||
|
||||
["browser_windows_launch_on_login_msix.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
|
||||
|
||||
@@ -18,25 +18,7 @@ const { ExperimentFakes } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/NimbusTestUtils.sys.mjs"
|
||||
);
|
||||
|
||||
const { MockRegistry } = ChromeUtils.importESModule(
|
||||
"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() {
|
||||
add_task(async function test_check_checkbox() {
|
||||
await ExperimentAPI.ready();
|
||||
let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "windowsLaunchOnLogin",
|
||||
@@ -58,6 +40,25 @@ add_task(async function test_check_uncheck_checkbox() {
|
||||
"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();
|
||||
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() {
|
||||
if (Services.sysinfo.getProperty("hasWinPackageId")) {
|
||||
return;
|
||||
}
|
||||
await ExperimentAPI.ready();
|
||||
let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "windowsLaunchOnLogin",
|
||||
value: { enabled: true },
|
||||
});
|
||||
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
|
||||
// this is reflected in the settings
|
||||
let autostartPath =
|
||||
@@ -115,9 +108,6 @@ add_task(async function create_external_regkey() {
|
||||
});
|
||||
|
||||
add_task(async function delete_external_regkey() {
|
||||
if (Services.sysinfo.getProperty("hasWinPackageId")) {
|
||||
return;
|
||||
}
|
||||
await ExperimentAPI.ready();
|
||||
let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
|
||||
featureId: "windowsLaunchOnLogin",
|
||||
@@ -146,7 +136,6 @@ add_task(async function delete_external_regkey() {
|
||||
});
|
||||
|
||||
registerCleanupFunction(async function () {
|
||||
await WindowsLaunchOnLogin.removeLaunchOnLoginShortcuts();
|
||||
await WindowsLaunchOnLogin.withLaunchOnLoginRegistryKey(async wrk => {
|
||||
let registryName = WindowsLaunchOnLogin.getLaunchOnLoginRegistryName();
|
||||
if (wrk.hasValue(registryName)) {
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
@@ -75,93 +75,6 @@ interface nsIWindowsShellService : nsISupports
|
||||
|
||||
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
|
||||
* Private Browsing version of the app (with a different icon and launch
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsIWindowsRegKey.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
@@ -55,14 +54,6 @@ PSSTDAPI PropVariantToString(REFPROPVARIANT propvar, PWSTR psz, UINT cch);
|
||||
# define UNLEN 256
|
||||
#else
|
||||
# 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
|
||||
|
||||
#include <comutil.h>
|
||||
@@ -1916,310 +1907,6 @@ nsWindowsShellService::IsCurrentAppPinnedToTaskbarAsync(
|
||||
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
|
||||
nsWindowsShellService::ClassifyShortcut(const nsAString& aPath,
|
||||
nsAString& aResult) {
|
||||
|
||||
@@ -10,10 +10,9 @@
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
|
||||
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: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@" />
|
||||
<Properties>
|
||||
@@ -103,16 +102,6 @@
|
||||
</com:SurrogateServer>
|
||||
</com:ComServer>
|
||||
</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:ToastNotificationActivation ToastActivatorCLSID="@MOZ_INOTIFICATIONACTIVATION_CLSID@" />
|
||||
</desktop:Extension>
|
||||
|
||||
@@ -457,7 +457,7 @@ export const SpecialMessageActions = {
|
||||
const { WindowsLaunchOnLogin } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/WindowsLaunchOnLogin.sys.mjs"
|
||||
);
|
||||
await WindowsLaunchOnLogin.createLaunchOnLogin();
|
||||
await WindowsLaunchOnLogin.createLaunchOnLoginRegistryKey();
|
||||
break;
|
||||
case "PIN_CURRENT_TAB":
|
||||
let tab = window.gBrowser.selectedTab;
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const LAUNCH_ON_LOGIN_TASKID = "LaunchOnLogin";
|
||||
|
||||
/**
|
||||
* "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
|
||||
@@ -14,11 +12,6 @@ const LAUNCH_ON_LOGIN_TASKID = "LaunchOnLogin";
|
||||
* When such keys are present, the launch on login feature should be considered
|
||||
* disabled and not available from within Firefox. This module provides the
|
||||
* 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 = {
|
||||
/**
|
||||
@@ -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
|
||||
*/
|
||||
@@ -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
|
||||
* %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
|
||||
* by the user in the Windows Startup Apps menu. The registry key that
|
||||
* 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() {
|
||||
if (Services.sysinfo.getProperty("hasWinPackageId")) {
|
||||
return this.getLaunchOnLoginApprovedMSIX();
|
||||
}
|
||||
getLaunchOnLoginApproved() {
|
||||
try {
|
||||
let wrkApproved = Cc[
|
||||
"@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
|
||||
* %USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup. The registry key that
|
||||
* 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() {
|
||||
if (Services.sysinfo.getProperty("hasWinPackageId")) {
|
||||
return this.getLaunchOnLoginEnabledMSIX();
|
||||
}
|
||||
|
||||
getLaunchOnLoginEnabled() {
|
||||
let registryName = this.getLaunchOnLoginRegistryName();
|
||||
let regExists = false;
|
||||
let shortcutExists = false;
|
||||
|
||||
Reference in New Issue
Block a user