Merge pull request #8515 from electron/auto-launch-squirrel-support
Support custom launch path in app.setLoginItemSettings
This commit is contained in:
commit
18357512f3
8 changed files with 109 additions and 30 deletions
|
@ -12,7 +12,6 @@
|
||||||
#include "atom/browser/api/atom_api_web_contents.h"
|
#include "atom/browser/api/atom_api_web_contents.h"
|
||||||
#include "atom/browser/atom_browser_context.h"
|
#include "atom/browser/atom_browser_context.h"
|
||||||
#include "atom/browser/atom_browser_main_parts.h"
|
#include "atom/browser/atom_browser_main_parts.h"
|
||||||
#include "atom/browser/browser.h"
|
|
||||||
#include "atom/browser/login_handler.h"
|
#include "atom/browser/login_handler.h"
|
||||||
#include "atom/browser/relauncher.h"
|
#include "atom/browser/relauncher.h"
|
||||||
#include "atom/common/atom_command_line.h"
|
#include "atom/common/atom_command_line.h"
|
||||||
|
@ -298,6 +297,8 @@ struct Converter<Browser::LoginItemSettings> {
|
||||||
|
|
||||||
dict.Get("openAtLogin", &(out->open_at_login));
|
dict.Get("openAtLogin", &(out->open_at_login));
|
||||||
dict.Get("openAsHidden", &(out->open_as_hidden));
|
dict.Get("openAsHidden", &(out->open_as_hidden));
|
||||||
|
dict.Get("path", &(out->path));
|
||||||
|
dict.Get("args", &(out->args));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -746,6 +747,12 @@ bool App::IsAccessibilitySupportEnabled() {
|
||||||
return ax_state->IsAccessibleBrowser();
|
return ax_state->IsAccessibleBrowser();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Browser::LoginItemSettings App::GetLoginItemSettings(mate::Arguments* args) {
|
||||||
|
Browser::LoginItemSettings options;
|
||||||
|
args->GetNext(&options);
|
||||||
|
return Browser::Get()->GetLoginItemSettings(options);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(USE_NSS_CERTS)
|
#if defined(USE_NSS_CERTS)
|
||||||
void App::ImportCertificate(
|
void App::ImportCertificate(
|
||||||
const base::DictionaryValue& options,
|
const base::DictionaryValue& options,
|
||||||
|
@ -867,8 +874,7 @@ void App::BuildPrototype(
|
||||||
base::Bind(&Browser::RemoveAsDefaultProtocolClient, browser))
|
base::Bind(&Browser::RemoveAsDefaultProtocolClient, browser))
|
||||||
.SetMethod("setBadgeCount", base::Bind(&Browser::SetBadgeCount, browser))
|
.SetMethod("setBadgeCount", base::Bind(&Browser::SetBadgeCount, browser))
|
||||||
.SetMethod("getBadgeCount", base::Bind(&Browser::GetBadgeCount, browser))
|
.SetMethod("getBadgeCount", base::Bind(&Browser::GetBadgeCount, browser))
|
||||||
.SetMethod("getLoginItemSettings",
|
.SetMethod("getLoginItemSettings", &App::GetLoginItemSettings)
|
||||||
base::Bind(&Browser::GetLoginItemSettings, browser))
|
|
||||||
.SetMethod("setLoginItemSettings",
|
.SetMethod("setLoginItemSettings",
|
||||||
base::Bind(&Browser::SetLoginItemSettings, browser))
|
base::Bind(&Browser::SetLoginItemSettings, browser))
|
||||||
#if defined(OS_MACOSX)
|
#if defined(OS_MACOSX)
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "atom/browser/api/event_emitter.h"
|
#include "atom/browser/api/event_emitter.h"
|
||||||
#include "atom/browser/atom_browser_client.h"
|
#include "atom/browser/atom_browser_client.h"
|
||||||
|
#include "atom/browser/browser.h"
|
||||||
#include "atom/browser/browser_observer.h"
|
#include "atom/browser/browser_observer.h"
|
||||||
#include "atom/common/native_mate_converters/callback.h"
|
#include "atom/common/native_mate_converters/callback.h"
|
||||||
#include "chrome/browser/process_singleton.h"
|
#include "chrome/browser/process_singleton.h"
|
||||||
|
@ -123,6 +124,7 @@ class App : public AtomBrowserClient::Delegate,
|
||||||
bool Relaunch(mate::Arguments* args);
|
bool Relaunch(mate::Arguments* args);
|
||||||
void DisableHardwareAcceleration(mate::Arguments* args);
|
void DisableHardwareAcceleration(mate::Arguments* args);
|
||||||
bool IsAccessibilitySupportEnabled();
|
bool IsAccessibilitySupportEnabled();
|
||||||
|
Browser::LoginItemSettings GetLoginItemSettings(mate::Arguments* args);
|
||||||
#if defined(USE_NSS_CERTS)
|
#if defined(USE_NSS_CERTS)
|
||||||
void ImportCertificate(const base::DictionaryValue& options,
|
void ImportCertificate(const base::DictionaryValue& options,
|
||||||
const net::CompletionCallback& callback);
|
const net::CompletionCallback& callback);
|
||||||
|
|
|
@ -98,9 +98,11 @@ class Browser : public WindowListObserver {
|
||||||
bool restore_state = false;
|
bool restore_state = false;
|
||||||
bool opened_at_login = false;
|
bool opened_at_login = false;
|
||||||
bool opened_as_hidden = false;
|
bool opened_as_hidden = false;
|
||||||
|
base::string16 path;
|
||||||
|
std::vector<base::string16> args;
|
||||||
};
|
};
|
||||||
void SetLoginItemSettings(LoginItemSettings settings);
|
void SetLoginItemSettings(LoginItemSettings settings);
|
||||||
LoginItemSettings GetLoginItemSettings();
|
LoginItemSettings GetLoginItemSettings(LoginItemSettings options);
|
||||||
|
|
||||||
#if defined(OS_MACOSX)
|
#if defined(OS_MACOSX)
|
||||||
// Hide the application.
|
// Hide the application.
|
||||||
|
|
|
@ -63,7 +63,8 @@ bool Browser::SetBadgeCount(int count) {
|
||||||
void Browser::SetLoginItemSettings(LoginItemSettings settings) {
|
void Browser::SetLoginItemSettings(LoginItemSettings settings) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Browser::LoginItemSettings Browser::GetLoginItemSettings() {
|
Browser::LoginItemSettings Browser::GetLoginItemSettings(
|
||||||
|
LoginItemSettings options) {
|
||||||
return LoginItemSettings();
|
return LoginItemSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,8 @@ bool Browser::ContinueUserActivity(const std::string& type,
|
||||||
return prevent_default;
|
return prevent_default;
|
||||||
}
|
}
|
||||||
|
|
||||||
Browser::LoginItemSettings Browser::GetLoginItemSettings() {
|
Browser::LoginItemSettings Browser::GetLoginItemSettings(
|
||||||
|
LoginItemSettings options) {
|
||||||
LoginItemSettings settings;
|
LoginItemSettings settings;
|
||||||
settings.open_at_login = base::mac::CheckLoginItemStatus(
|
settings.open_at_login = base::mac::CheckLoginItemStatus(
|
||||||
&settings.open_as_hidden);
|
&settings.open_as_hidden);
|
||||||
|
|
|
@ -43,15 +43,19 @@ BOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GetProcessExecPath(base::string16* exe) {
|
||||||
|
base::FilePath path;
|
||||||
|
if (!PathService::Get(base::FILE_EXE, &path)) {
|
||||||
|
LOG(ERROR) << "Error getting app exe path";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*exe = path.value();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool GetProtocolLaunchPath(mate::Arguments* args, base::string16* exe) {
|
bool GetProtocolLaunchPath(mate::Arguments* args, base::string16* exe) {
|
||||||
// Executable Path
|
if (!args->GetNext(exe) && !GetProcessExecPath(exe)) {
|
||||||
if (!args->GetNext(exe)) {
|
return false;
|
||||||
base::FilePath path;
|
|
||||||
if (!PathService::Get(base::FILE_EXE, &path)) {
|
|
||||||
LOG(ERROR) << "Error getting app exe path";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*exe = path.value();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read in optional args arg
|
// Read in optional args arg
|
||||||
|
@ -65,6 +69,22 @@ bool GetProtocolLaunchPath(mate::Arguments* args, base::string16* exe) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FormatCommandLineString(base::string16* exe,
|
||||||
|
const std::vector<base::string16>& launch_args) {
|
||||||
|
if (exe->empty() && !GetProcessExecPath(exe)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!launch_args.empty()) {
|
||||||
|
base::string16 formatString = L"%s %s";
|
||||||
|
*exe = base::StringPrintf(formatString.c_str(),
|
||||||
|
exe->c_str(),
|
||||||
|
base::JoinString(launch_args, L" ").c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void Browser::Focus() {
|
void Browser::Focus() {
|
||||||
|
@ -257,34 +277,32 @@ void Browser::SetLoginItemSettings(LoginItemSettings settings) {
|
||||||
base::win::RegKey key(HKEY_CURRENT_USER, keyPath.c_str(), KEY_ALL_ACCESS);
|
base::win::RegKey key(HKEY_CURRENT_USER, keyPath.c_str(), KEY_ALL_ACCESS);
|
||||||
|
|
||||||
if (settings.open_at_login) {
|
if (settings.open_at_login) {
|
||||||
base::FilePath path;
|
base::string16 exe = settings.path;
|
||||||
if (PathService::Get(base::FILE_EXE, &path)) {
|
if (FormatCommandLineString(&exe, settings.args)) {
|
||||||
base::string16 exePath(path.value());
|
key.WriteValue(GetAppUserModelID(), exe.c_str());
|
||||||
key.WriteValue(GetAppUserModelID(), exePath.c_str());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
key.DeleteValue(GetAppUserModelID());
|
key.DeleteValue(GetAppUserModelID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Browser::LoginItemSettings Browser::GetLoginItemSettings() {
|
Browser::LoginItemSettings Browser::GetLoginItemSettings(
|
||||||
|
LoginItemSettings options) {
|
||||||
LoginItemSettings settings;
|
LoginItemSettings settings;
|
||||||
base::string16 keyPath = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
|
base::string16 keyPath = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
|
||||||
base::win::RegKey key(HKEY_CURRENT_USER, keyPath.c_str(), KEY_ALL_ACCESS);
|
base::win::RegKey key(HKEY_CURRENT_USER, keyPath.c_str(), KEY_ALL_ACCESS);
|
||||||
base::string16 keyVal;
|
base::string16 keyVal;
|
||||||
|
|
||||||
if (!FAILED(key.ReadValue(GetAppUserModelID(), &keyVal))) {
|
if (!FAILED(key.ReadValue(GetAppUserModelID(), &keyVal))) {
|
||||||
base::FilePath path;
|
base::string16 exe = options.path;
|
||||||
if (PathService::Get(base::FILE_EXE, &path)) {
|
if (FormatCommandLineString(&exe, options.args)) {
|
||||||
base::string16 exePath(path.value());
|
settings.open_at_login = keyVal == exe;
|
||||||
settings.open_at_login = keyVal == exePath;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PCWSTR Browser::GetAppUserModelID() {
|
PCWSTR Browser::GetAppUserModelID() {
|
||||||
if (app_user_model_id_.empty()) {
|
if (app_user_model_id_.empty()) {
|
||||||
SetAppUserModelID(base::ReplaceStringPlaceholders(
|
SetAppUserModelID(base::ReplaceStringPlaceholders(
|
||||||
|
|
|
@ -758,7 +758,16 @@ Returns `Integer` - The current value displayed in the counter badge.
|
||||||
|
|
||||||
Returns `Boolean` - Whether the current desktop environment is Unity launcher.
|
Returns `Boolean` - Whether the current desktop environment is Unity launcher.
|
||||||
|
|
||||||
### `app.getLoginItemSettings()` _macOS_ _Windows_
|
### `app.getLoginItemSettings([options])` _macOS_ _Windows_
|
||||||
|
|
||||||
|
* `options` Object (optional)
|
||||||
|
* `path` String (optional) _Windows_ - The executable path to compare against.
|
||||||
|
Defaults to `process.execPath`.
|
||||||
|
* `args` String[] (optional) _Windows_ - The command-line arguments to compare
|
||||||
|
against. Defaults to an empty array.
|
||||||
|
|
||||||
|
If you provided `path` and `args` options to `app.setLoginItemSettings` then you
|
||||||
|
need to pass the same arguments here for `openAtLogin` to be set correctly.
|
||||||
|
|
||||||
Returns `Object`:
|
Returns `Object`:
|
||||||
|
|
||||||
|
@ -775,10 +784,9 @@ Returns `Object`:
|
||||||
app should restore the windows that were open the last time the app was
|
app should restore the windows that were open the last time the app was
|
||||||
closed. This setting is only supported on macOS.
|
closed. This setting is only supported on macOS.
|
||||||
|
|
||||||
**Note:** This API has no effect on
|
**Note:** This API has no effect on [MAS builds][mas-builds].
|
||||||
[MAS builds][mas-builds].
|
|
||||||
|
|
||||||
### `app.setLoginItemSettings(settings)` _macOS_ _Windows_
|
### `app.setLoginItemSettings(settings[, path, args])` _macOS_ _Windows_
|
||||||
|
|
||||||
* `settings` Object
|
* `settings` Object
|
||||||
* `openAtLogin` Boolean (optional) - `true` to open the app at login, `false` to remove
|
* `openAtLogin` Boolean (optional) - `true` to open the app at login, `false` to remove
|
||||||
|
@ -788,11 +796,34 @@ Returns `Object`:
|
||||||
`app.getLoginItemStatus().wasOpenedAsHidden` should be checked when the app
|
`app.getLoginItemStatus().wasOpenedAsHidden` should be checked when the app
|
||||||
is opened to know the current value. This setting is only supported on
|
is opened to know the current value. This setting is only supported on
|
||||||
macOS.
|
macOS.
|
||||||
|
* `path` String (optional) _Windows_ - The executable to launch at login.
|
||||||
|
Defaults to `process.execPath`.
|
||||||
|
* `args` String[] (optional) _Windows_ - The command-line arguments to pass to
|
||||||
|
the executable. Defaults to an empty array. Take care to wrap paths in
|
||||||
|
quotes.
|
||||||
|
|
||||||
Set the app's login item settings.
|
Set the app's login item settings.
|
||||||
|
|
||||||
**Note:** This API has no effect on
|
To work with Electron's `autoUpdater` on Windows, which uses [Squirrel](Squirrel-Windows),
|
||||||
[MAS builds][mas-builds].
|
you'll want to set the launch path to Update.exe, and pass arguments that specify your
|
||||||
|
application name. For example:
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
const appFolder = path.dirname(process.execPath)
|
||||||
|
const updateExe = path.resolve(appFolder, '..', 'Update.exe')
|
||||||
|
const exeName = path.basename(process.execPath)
|
||||||
|
|
||||||
|
app.setLoginItemSettings({
|
||||||
|
openAtLogin: true,
|
||||||
|
path: updateExe,
|
||||||
|
args: [
|
||||||
|
'--processStart', `"${exeName}"`,
|
||||||
|
'--process-start-args', `"--hidden"`
|
||||||
|
]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** This API has no effect on [MAS builds][mas-builds].
|
||||||
|
|
||||||
### `app.isAccessibilitySupportEnabled()` _macOS_ _Windows_
|
### `app.isAccessibilitySupportEnabled()` _macOS_ _Windows_
|
||||||
|
|
||||||
|
@ -904,5 +935,6 @@ Sets the `image` associated with this dock icon.
|
||||||
[activity-type]: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType
|
[activity-type]: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType
|
||||||
[unity-requirement]: ../tutorial/desktop-environment-integration.md#unity-launcher-shortcuts-linux
|
[unity-requirement]: ../tutorial/desktop-environment-integration.md#unity-launcher-shortcuts-linux
|
||||||
[mas-builds]: ../tutorial/mac-app-store-submission-guide.md
|
[mas-builds]: ../tutorial/mac-app-store-submission-guide.md
|
||||||
|
[Squirrel-Windows]: https://github.com/Squirrel/Squirrel.Windows
|
||||||
[JumpListBeginListMSDN]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378398(v=vs.85).aspx
|
[JumpListBeginListMSDN]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378398(v=vs.85).aspx
|
||||||
[about-panel-options]: https://developer.apple.com/reference/appkit/nsapplication/1428479-orderfrontstandardaboutpanelwith?language=objc
|
[about-panel-options]: https://developer.apple.com/reference/appkit/nsapplication/1428479-orderfrontstandardaboutpanelwith?language=objc
|
||||||
|
|
|
@ -313,12 +313,20 @@ describe('app module', function () {
|
||||||
describe('app.get/setLoginItemSettings API', function () {
|
describe('app.get/setLoginItemSettings API', function () {
|
||||||
if (process.platform === 'linux') return
|
if (process.platform === 'linux') return
|
||||||
|
|
||||||
|
const updateExe = path.resolve(path.dirname(process.execPath), '..', 'Update.exe')
|
||||||
|
const processStartArgs = [
|
||||||
|
'--processStart', `"${path.basename(process.execPath)}"`,
|
||||||
|
'--process-start-args', `"--hidden"`
|
||||||
|
]
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
app.setLoginItemSettings({openAtLogin: false})
|
app.setLoginItemSettings({openAtLogin: false})
|
||||||
|
app.setLoginItemSettings({openAtLogin: false, path: updateExe, args: processStartArgs})
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
app.setLoginItemSettings({openAtLogin: false})
|
app.setLoginItemSettings({openAtLogin: false})
|
||||||
|
app.setLoginItemSettings({openAtLogin: false, path: updateExe, args: processStartArgs})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns the login item status of the app', function () {
|
it('returns the login item status of the app', function () {
|
||||||
|
@ -349,6 +357,15 @@ describe('app module', function () {
|
||||||
restoreState: false
|
restoreState: false
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('allows you to pass a custom executable and arguments', () => {
|
||||||
|
if (process.platform !== 'win32') return
|
||||||
|
|
||||||
|
app.setLoginItemSettings({openAtLogin: true, path: updateExe, args: processStartArgs})
|
||||||
|
|
||||||
|
assert.equal(app.getLoginItemSettings().openAtLogin, false)
|
||||||
|
assert.equal(app.getLoginItemSettings({path: updateExe, args: processStartArgs}).openAtLogin, true)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('isAccessibilitySupportEnabled API', function () {
|
describe('isAccessibilitySupportEnabled API', function () {
|
||||||
|
|
Loading…
Reference in a new issue