feat: add capabilities to app.getLoginItemSettings() and app.setLoginItemSettings() (#24494)
* fixed * semantic commit * add comments to browser.h Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
This commit is contained in:
		
					parent
					
						
							
								75372e933f
							
						
					
				
			
			
				commit
				
					
						1b175a0609
					
				
			
		
					 6 changed files with 326 additions and 16 deletions
				
			
		|  | @ -1216,6 +1216,13 @@ Returns `Object`: | ||||||
|   should restore the state from the previous session. This indicates that the |   should restore the state from the previous session. This indicates that the | ||||||
|   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 not available on [MAS builds][mas-builds]. |   closed. This setting is not available on [MAS builds][mas-builds]. | ||||||
|  | * `executableWillLaunchAtLogin` Boolean _Windows_ - `true` if app is set to open at login and its run key is not deactivated. This differs from `openAtLogin` as it ignores the `args` option, this property will be true if the given executable would be launched at login with **any** arguments. | ||||||
|  | * `launchItems` Object[] _Windows_ | ||||||
|  |   * `name` String _Windows_ - name value of a registry entry. | ||||||
|  |   * `path` String _Windows_ - The executable to an app that corresponds to a registry entry. | ||||||
|  |   * `args` String[] _Windows_ - the command-line arguments to pass to the executable. | ||||||
|  |   * `scope` String _Windows_ - one of `user` or `machine`. Indicates whether the registry entry is under `HKEY_CURRENT USER` or `HKEY_LOCAL_MACHINE`. | ||||||
|  |   * `enabled` Boolean _Windows_ - `true` if the app registry key is startup approved and therfore shows as `enabled` in Task Manager and Windows settings. | ||||||
| 
 | 
 | ||||||
| ### `app.setLoginItemSettings(settings)` _macOS_ _Windows_ | ### `app.setLoginItemSettings(settings)` _macOS_ _Windows_ | ||||||
| 
 | 
 | ||||||
|  | @ -1231,7 +1238,9 @@ Returns `Object`: | ||||||
|   * `args` String[] (optional) _Windows_ - The command-line arguments to pass to |   * `args` String[] (optional) _Windows_ - The command-line arguments to pass to | ||||||
|     the executable. Defaults to an empty array. Take care to wrap paths in |     the executable. Defaults to an empty array. Take care to wrap paths in | ||||||
|     quotes. |     quotes. | ||||||
| 
 |   * `enabled` Boolean (optional) _Windows_ - `true` will change the startup approved registry key and `enable / disable` the App in Task Manager and Windows Settings. | ||||||
|  |     Defaults to `true`. | ||||||
|  |   * `name` String (optional) _Windows_ - value name to write into registry. Defaults to the app's AppUserModelId(). | ||||||
| Set the app's login item settings. | Set the app's login item settings. | ||||||
| 
 | 
 | ||||||
| To work with Electron's `autoUpdater` on Windows, which uses [Squirrel][Squirrel-Windows], | To work with Electron's `autoUpdater` on Windows, which uses [Squirrel][Squirrel-Windows], | ||||||
|  |  | ||||||
|  | @ -334,6 +334,37 @@ struct Converter<JumpListResult> { | ||||||
| }; | }; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #if defined(OS_WIN) | ||||||
|  | template <> | ||||||
|  | struct Converter<Browser::LaunchItem> { | ||||||
|  |   static bool FromV8(v8::Isolate* isolate, | ||||||
|  |                      v8::Local<v8::Value> val, | ||||||
|  |                      Browser::LaunchItem* out) { | ||||||
|  |     gin_helper::Dictionary dict; | ||||||
|  |     if (!ConvertFromV8(isolate, val, &dict)) | ||||||
|  |       return false; | ||||||
|  | 
 | ||||||
|  |     dict.Get("name", &(out->name)); | ||||||
|  |     dict.Get("path", &(out->path)); | ||||||
|  |     dict.Get("args", &(out->args)); | ||||||
|  |     dict.Get("scope", &(out->scope)); | ||||||
|  |     dict.Get("enabled", &(out->enabled)); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, | ||||||
|  |                                    Browser::LaunchItem val) { | ||||||
|  |     gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate); | ||||||
|  |     dict.Set("name", val.name); | ||||||
|  |     dict.Set("path", val.path); | ||||||
|  |     dict.Set("args", val.args); | ||||||
|  |     dict.Set("scope", val.scope); | ||||||
|  |     dict.Set("enabled", val.enabled); | ||||||
|  |     return dict.GetHandle(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| template <> | template <> | ||||||
| struct Converter<Browser::LoginItemSettings> { | struct Converter<Browser::LoginItemSettings> { | ||||||
|   static bool FromV8(v8::Isolate* isolate, |   static bool FromV8(v8::Isolate* isolate, | ||||||
|  | @ -347,6 +378,10 @@ struct Converter<Browser::LoginItemSettings> { | ||||||
|     dict.Get("openAsHidden", &(out->open_as_hidden)); |     dict.Get("openAsHidden", &(out->open_as_hidden)); | ||||||
|     dict.Get("path", &(out->path)); |     dict.Get("path", &(out->path)); | ||||||
|     dict.Get("args", &(out->args)); |     dict.Get("args", &(out->args)); | ||||||
|  | #if defined(OS_WIN) | ||||||
|  |     dict.Get("enabled", &(out->enabled)); | ||||||
|  |     dict.Get("name", &(out->name)); | ||||||
|  | #endif | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -358,6 +393,11 @@ struct Converter<Browser::LoginItemSettings> { | ||||||
|     dict.Set("restoreState", val.restore_state); |     dict.Set("restoreState", val.restore_state); | ||||||
|     dict.Set("wasOpenedAtLogin", val.opened_at_login); |     dict.Set("wasOpenedAtLogin", val.opened_at_login); | ||||||
|     dict.Set("wasOpenedAsHidden", val.opened_as_hidden); |     dict.Set("wasOpenedAsHidden", val.opened_as_hidden); | ||||||
|  | #if defined(OS_WIN) | ||||||
|  |     dict.Set("launchItems", val.launch_items); | ||||||
|  |     dict.Set("executableWillLaunchAtLogin", | ||||||
|  |              val.executable_will_launch_at_login); | ||||||
|  | #endif | ||||||
|     return dict.GetHandle(); |     return dict.GetHandle(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -40,6 +40,12 @@ void RunQuitClosure(base::OnceClosure quit) { | ||||||
| 
 | 
 | ||||||
| }  // namespace
 | }  // namespace
 | ||||||
| 
 | 
 | ||||||
|  | #if defined(OS_WIN) | ||||||
|  | Browser::LaunchItem::LaunchItem() = default; | ||||||
|  | Browser::LaunchItem::~LaunchItem() = default; | ||||||
|  | Browser::LaunchItem::LaunchItem(const LaunchItem& other) = default; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| Browser::LoginItemSettings::LoginItemSettings() = default; | Browser::LoginItemSettings::LoginItemSettings() = default; | ||||||
| Browser::LoginItemSettings::~LoginItemSettings() = default; | Browser::LoginItemSettings::~LoginItemSettings() = default; | ||||||
| Browser::LoginItemSettings::LoginItemSettings(const LoginItemSettings& other) = | Browser::LoginItemSettings::LoginItemSettings(const LoginItemSettings& other) = | ||||||
|  |  | ||||||
|  | @ -110,6 +110,20 @@ class Browser : public WindowListObserver { | ||||||
|   bool SetBadgeCount(int count); |   bool SetBadgeCount(int count); | ||||||
|   int GetBadgeCount(); |   int GetBadgeCount(); | ||||||
| 
 | 
 | ||||||
|  | #if defined(OS_WIN) | ||||||
|  |   struct LaunchItem { | ||||||
|  |     base::string16 name; | ||||||
|  |     base::string16 path; | ||||||
|  |     base::string16 scope; | ||||||
|  |     std::vector<base::string16> args; | ||||||
|  |     bool enabled = true; | ||||||
|  | 
 | ||||||
|  |     LaunchItem(); | ||||||
|  |     ~LaunchItem(); | ||||||
|  |     LaunchItem(const LaunchItem&); | ||||||
|  |   }; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|   // Set/Get the login item settings of the app
 |   // Set/Get the login item settings of the app
 | ||||||
|   struct LoginItemSettings { |   struct LoginItemSettings { | ||||||
|     bool open_at_login = false; |     bool open_at_login = false; | ||||||
|  | @ -120,6 +134,16 @@ class Browser : public WindowListObserver { | ||||||
|     base::string16 path; |     base::string16 path; | ||||||
|     std::vector<base::string16> args; |     std::vector<base::string16> args; | ||||||
| 
 | 
 | ||||||
|  | #if defined(OS_WIN) | ||||||
|  |     // used in browser::setLoginItemSettings
 | ||||||
|  |     bool enabled = true; | ||||||
|  |     base::string16 name = base::string16(); | ||||||
|  | 
 | ||||||
|  |     // used in browser::getLoginItemSettings
 | ||||||
|  |     bool executable_will_launch_at_login = false; | ||||||
|  |     std::vector<LaunchItem> launch_items; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|     LoginItemSettings(); |     LoginItemSettings(); | ||||||
|     ~LoginItemSettings(); |     ~LoginItemSettings(); | ||||||
|     LoginItemSettings(const LoginItemSettings&); |     LoginItemSettings(const LoginItemSettings&); | ||||||
|  |  | ||||||
|  | @ -16,6 +16,7 @@ | ||||||
| #include "base/base_paths.h" | #include "base/base_paths.h" | ||||||
| #include "base/file_version_info.h" | #include "base/file_version_info.h" | ||||||
| #include "base/files/file_path.h" | #include "base/files/file_path.h" | ||||||
|  | #include "base/logging.h" | ||||||
| #include "base/path_service.h" | #include "base/path_service.h" | ||||||
| #include "base/strings/string_util.h" | #include "base/strings/string_util.h" | ||||||
| #include "base/strings/stringprintf.h" | #include "base/strings/stringprintf.h" | ||||||
|  | @ -183,6 +184,87 @@ bool FormatCommandLineString(base::string16* exe, | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Helper for GetLoginItemSettings().
 | ||||||
|  | // iterates over all the entries in a windows registry path and returns
 | ||||||
|  | // a list of launchItem with matching paths to our application.
 | ||||||
|  | // if a launchItem with a matching path also has a matching entry within the
 | ||||||
|  | // startup_approved_key_path, set executable_will_launch_at_login to be `true`
 | ||||||
|  | std::vector<Browser::LaunchItem> GetLoginItemSettingsHelper( | ||||||
|  |     base::win::RegistryValueIterator* it, | ||||||
|  |     boolean* executable_will_launch_at_login, | ||||||
|  |     base::string16 scope, | ||||||
|  |     const Browser::LoginItemSettings& options) { | ||||||
|  |   std::vector<Browser::LaunchItem> launch_items; | ||||||
|  | 
 | ||||||
|  |   while (it->Valid()) { | ||||||
|  |     base::string16 exe = options.path; | ||||||
|  |     if (FormatCommandLineString(&exe, options.args)) { | ||||||
|  |       // add launch item to vector if it has a matching path (case-insensitive)
 | ||||||
|  |       if ((base::CompareCaseInsensitiveASCII(it->Value(), exe.c_str())) == 0) { | ||||||
|  |         Browser::LaunchItem launch_item; | ||||||
|  |         base::string16 launch_path = options.path; | ||||||
|  |         if (!(launch_path.size() > 0)) { | ||||||
|  |           GetProcessExecPath(&launch_path); | ||||||
|  |         } | ||||||
|  |         launch_item.name = it->Name(); | ||||||
|  |         launch_item.path = launch_path; | ||||||
|  |         launch_item.args = options.args; | ||||||
|  |         launch_item.scope = scope; | ||||||
|  |         launch_item.enabled = true; | ||||||
|  | 
 | ||||||
|  |         // attempt to update launch_item.enabled if there is a matching key
 | ||||||
|  |         // value entry in the StartupApproved registry
 | ||||||
|  |         HKEY hkey; | ||||||
|  |         // StartupApproved registry path
 | ||||||
|  |         LPCTSTR path = TEXT( | ||||||
|  |             "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApp" | ||||||
|  |             "roved\\Run"); | ||||||
|  |         LONG res; | ||||||
|  |         if (scope == L"user") { | ||||||
|  |           res = | ||||||
|  |               RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_QUERY_VALUE, &hkey); | ||||||
|  |         } else { | ||||||
|  |           res = | ||||||
|  |               RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_QUERY_VALUE, &hkey); | ||||||
|  |         } | ||||||
|  |         if (res == ERROR_SUCCESS) { | ||||||
|  |           DWORD type, size; | ||||||
|  |           wchar_t startup_binary[12]; | ||||||
|  |           LONG result = | ||||||
|  |               RegQueryValueEx(hkey, it->Name(), nullptr, &type, | ||||||
|  |                               reinterpret_cast<BYTE*>(&startup_binary), | ||||||
|  |                               &(size = sizeof(startup_binary))); | ||||||
|  |           if (result == ERROR_SUCCESS) { | ||||||
|  |             if (type == REG_BINARY) { | ||||||
|  |               // any other binary other than this indicates that the program is
 | ||||||
|  |               // not set to launch at login
 | ||||||
|  |               wchar_t binary_accepted[12] = {0x00, 0x00, 0x00, 0x00, | ||||||
|  |                                              0x00, 0x00, 0x00, 0x00, | ||||||
|  |                                              0x00, 0x00, 0x00, 0x00}; | ||||||
|  |               wchar_t binary_accepted_alt[12] = {0x02, 0x00, 0x00, 0x00, | ||||||
|  |                                                  0x00, 0x00, 0x00, 0x00, | ||||||
|  |                                                  0x00, 0x00, 0x00, 0x00}; | ||||||
|  |               std::string reg_binary(reinterpret_cast<char*>(binary_accepted)); | ||||||
|  |               std::string reg_binary_alt( | ||||||
|  |                   reinterpret_cast<char*>(binary_accepted_alt)); | ||||||
|  |               std::string reg_startup_binary( | ||||||
|  |                   reinterpret_cast<char*>(startup_binary)); | ||||||
|  |               launch_item.enabled = (reg_binary == reg_startup_binary) || | ||||||
|  |                                     (reg_binary == reg_binary_alt); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         *executable_will_launch_at_login = | ||||||
|  |             *executable_will_launch_at_login || launch_item.enabled; | ||||||
|  |         launch_items.push_back(launch_item); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     it->operator++(); | ||||||
|  |   } | ||||||
|  |   return launch_items; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::unique_ptr<FileVersionInfo> FetchFileVersionInfo() { | std::unique_ptr<FileVersionInfo> FetchFileVersionInfo() { | ||||||
|   base::FilePath path; |   base::FilePath path; | ||||||
| 
 | 
 | ||||||
|  | @ -515,16 +597,46 @@ bool Browser::SetBadgeCount(int count) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Browser::SetLoginItemSettings(LoginItemSettings settings) { | void Browser::SetLoginItemSettings(LoginItemSettings settings) { | ||||||
|   base::string16 keyPath = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run"; |   base::string16 key_path = | ||||||
|   base::win::RegKey key(HKEY_CURRENT_USER, keyPath.c_str(), KEY_ALL_ACCESS); |       L"Software\\Microsoft\\Windows\\CurrentVersion\\Run"; | ||||||
|  |   base::win::RegKey key(HKEY_CURRENT_USER, key_path.c_str(), KEY_ALL_ACCESS); | ||||||
|  | 
 | ||||||
|  |   base::string16 startup_approved_key_path = | ||||||
|  |       L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApproved" | ||||||
|  |       L"\\Run"; | ||||||
|  |   base::win::RegKey startup_approved_key( | ||||||
|  |       HKEY_CURRENT_USER, startup_approved_key_path.c_str(), KEY_ALL_ACCESS); | ||||||
|  |   PCWSTR key_name = | ||||||
|  |       settings.name.size() > 0 ? settings.name.c_str() : GetAppUserModelID(); | ||||||
| 
 | 
 | ||||||
|   if (settings.open_at_login) { |   if (settings.open_at_login) { | ||||||
|     base::string16 exe = settings.path; |     base::string16 exe = settings.path; | ||||||
|     if (FormatCommandLineString(&exe, settings.args)) { |     if (FormatCommandLineString(&exe, settings.args)) { | ||||||
|       key.WriteValue(GetAppUserModelID(), exe.c_str()); |       key.WriteValue(key_name, exe.c_str()); | ||||||
|  | 
 | ||||||
|  |       if (settings.enabled) { | ||||||
|  |         startup_approved_key.DeleteValue(key_name); | ||||||
|  |       } else { | ||||||
|  |         HKEY hard_key; | ||||||
|  |         LPCTSTR path = TEXT( | ||||||
|  |             "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApp" | ||||||
|  |             "roved\\Run"); | ||||||
|  |         LONG res = | ||||||
|  |             RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_ALL_ACCESS, &hard_key); | ||||||
|  | 
 | ||||||
|  |         if (res == ERROR_SUCCESS) { | ||||||
|  |           UCHAR disable_startup_binary[] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |                                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||||||
|  |           RegSetValueEx(hard_key, key_name, 0, REG_BINARY, | ||||||
|  |                         reinterpret_cast<const BYTE*>(disable_startup_binary), | ||||||
|  |                         sizeof(disable_startup_binary)); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } else { |   } else { | ||||||
|     key.DeleteValue(GetAppUserModelID()); |     // if open at login is false, delete both values
 | ||||||
|  |     startup_approved_key.DeleteValue(key_name); | ||||||
|  |     key.DeleteValue(key_name); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -535,6 +647,7 @@ Browser::LoginItemSettings Browser::GetLoginItemSettings( | ||||||
|   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; | ||||||
| 
 | 
 | ||||||
|  |   // keep old openAtLogin behaviour
 | ||||||
|   if (!FAILED(key.ReadValue(GetAppUserModelID(), &keyVal))) { |   if (!FAILED(key.ReadValue(GetAppUserModelID(), &keyVal))) { | ||||||
|     base::string16 exe = options.path; |     base::string16 exe = options.path; | ||||||
|     if (FormatCommandLineString(&exe, options.args)) { |     if (FormatCommandLineString(&exe, options.args)) { | ||||||
|  | @ -542,6 +655,27 @@ Browser::LoginItemSettings Browser::GetLoginItemSettings( | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   // iterate over current user and machine registries and populate launch items
 | ||||||
|  |   // if there exists a launch entry with property enabled=='true',
 | ||||||
|  |   // set executable_will_launch_at_login to 'true'.
 | ||||||
|  |   boolean executable_will_launch_at_login = false; | ||||||
|  |   std::vector<Browser::LaunchItem> launch_items; | ||||||
|  |   base::win::RegistryValueIterator hkcu_iterator(HKEY_CURRENT_USER, | ||||||
|  |                                                  keyPath.c_str()); | ||||||
|  |   base::win::RegistryValueIterator hklm_iterator(HKEY_LOCAL_MACHINE, | ||||||
|  |                                                  keyPath.c_str()); | ||||||
|  | 
 | ||||||
|  |   launch_items = GetLoginItemSettingsHelper( | ||||||
|  |       &hkcu_iterator, &executable_will_launch_at_login, L"user", options); | ||||||
|  |   std::vector<Browser::LaunchItem> launch_items_hklm = | ||||||
|  |       GetLoginItemSettingsHelper(&hklm_iterator, | ||||||
|  |                                  &executable_will_launch_at_login, L"machine", | ||||||
|  |                                  options); | ||||||
|  |   launch_items.insert(launch_items.end(), launch_items_hklm.begin(), | ||||||
|  |                       launch_items_hklm.end()); | ||||||
|  | 
 | ||||||
|  |   settings.executable_will_launch_at_login = executable_will_launch_at_login; | ||||||
|  |   settings.launch_items = launch_items; | ||||||
|   return settings; |   return settings; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -619,7 +619,7 @@ describe('app module', () => { | ||||||
|       app.setLoginItemSettings({ openAtLogin: false, path: updateExe, args: processStartArgs }); |       app.setLoginItemSettings({ openAtLogin: false, path: updateExe, args: processStartArgs }); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('sets and returns the app as a login item', done => { |     ifit(process.platform !== 'win32')('sets and returns the app as a login item', function () { | ||||||
|       app.setLoginItemSettings({ openAtLogin: true }); |       app.setLoginItemSettings({ openAtLogin: true }); | ||||||
|       expect(app.getLoginItemSettings()).to.deep.equal({ |       expect(app.getLoginItemSettings()).to.deep.equal({ | ||||||
|         openAtLogin: true, |         openAtLogin: true, | ||||||
|  | @ -628,10 +628,28 @@ describe('app module', () => { | ||||||
|         wasOpenedAsHidden: false, |         wasOpenedAsHidden: false, | ||||||
|         restoreState: false |         restoreState: false | ||||||
|       }); |       }); | ||||||
|       done(); |  | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('adds a login item that loads in hidden mode', done => { |     ifit(process.platform === 'win32')('sets and returns the app as a login item (windows)', function () { | ||||||
|  |       app.setLoginItemSettings({ openAtLogin: true }); | ||||||
|  |       expect(app.getLoginItemSettings()).to.deep.equal({ | ||||||
|  |         openAtLogin: true, | ||||||
|  |         openAsHidden: false, | ||||||
|  |         wasOpenedAtLogin: false, | ||||||
|  |         wasOpenedAsHidden: false, | ||||||
|  |         restoreState: false, | ||||||
|  |         executableWillLaunchAtLogin: true, | ||||||
|  |         launchItems: [{ | ||||||
|  |           name: 'electron.app.Electron', | ||||||
|  |           path: process.execPath, | ||||||
|  |           args: [], | ||||||
|  |           scope: 'user', | ||||||
|  |           enabled: true | ||||||
|  |         }] | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     ifit(process.platform !== 'win32')('adds a login item that loads in hidden mode', function () { | ||||||
|       app.setLoginItemSettings({ openAtLogin: true, openAsHidden: true }); |       app.setLoginItemSettings({ openAtLogin: true, openAsHidden: true }); | ||||||
|       expect(app.getLoginItemSettings()).to.deep.equal({ |       expect(app.getLoginItemSettings()).to.deep.equal({ | ||||||
|         openAtLogin: true, |         openAtLogin: true, | ||||||
|  | @ -640,7 +658,25 @@ describe('app module', () => { | ||||||
|         wasOpenedAsHidden: false, |         wasOpenedAsHidden: false, | ||||||
|         restoreState: false |         restoreState: false | ||||||
|       }); |       }); | ||||||
|       done(); |     }); | ||||||
|  | 
 | ||||||
|  |     ifit(process.platform === 'win32')('adds a login item that loads in hidden mode (windows)', function () { | ||||||
|  |       app.setLoginItemSettings({ openAtLogin: true, openAsHidden: true }); | ||||||
|  |       expect(app.getLoginItemSettings()).to.deep.equal({ | ||||||
|  |         openAtLogin: true, | ||||||
|  |         openAsHidden: false, | ||||||
|  |         wasOpenedAtLogin: false, | ||||||
|  |         wasOpenedAsHidden: false, | ||||||
|  |         restoreState: false, | ||||||
|  |         executableWillLaunchAtLogin: true, | ||||||
|  |         launchItems: [{ | ||||||
|  |           name: 'electron.app.Electron', | ||||||
|  |           path: process.execPath, | ||||||
|  |           args: [], | ||||||
|  |           scope: 'user', | ||||||
|  |           enabled: true | ||||||
|  |         }] | ||||||
|  |       }); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('correctly sets and unsets the LoginItem', function () { |     it('correctly sets and unsets the LoginItem', function () { | ||||||
|  | @ -668,16 +704,77 @@ describe('app module', () => { | ||||||
|       expect(app.getLoginItemSettings().openAsHidden).to.equal(false); |       expect(app.getLoginItemSettings().openAsHidden).to.equal(false); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('allows you to pass a custom executable and arguments', function () { |     ifit(process.platform === 'win32')('allows you to pass a custom executable and arguments', function () { | ||||||
|       if (process.platform !== 'win32') this.skip(); |       app.setLoginItemSettings({ openAtLogin: true, path: updateExe, args: processStartArgs, enabled: true }); | ||||||
| 
 |  | ||||||
|       app.setLoginItemSettings({ openAtLogin: true, path: updateExe, args: processStartArgs }); |  | ||||||
| 
 |  | ||||||
|       expect(app.getLoginItemSettings().openAtLogin).to.equal(false); |       expect(app.getLoginItemSettings().openAtLogin).to.equal(false); | ||||||
|       expect(app.getLoginItemSettings({ |       const openAtLoginTrueEnabledTrue = app.getLoginItemSettings({ | ||||||
|         path: updateExe, |         path: updateExe, | ||||||
|         args: processStartArgs |         args: processStartArgs | ||||||
|       }).openAtLogin).to.equal(true); |       }); | ||||||
|  | 
 | ||||||
|  |       expect(openAtLoginTrueEnabledTrue.openAtLogin).to.equal(true); | ||||||
|  |       expect(openAtLoginTrueEnabledTrue.executableWillLaunchAtLogin).to.equal(true); | ||||||
|  | 
 | ||||||
|  |       app.setLoginItemSettings({ openAtLogin: true, path: updateExe, args: processStartArgs, enabled: false }); | ||||||
|  |       const openAtLoginTrueEnabledFalse = app.getLoginItemSettings({ | ||||||
|  |         path: updateExe, | ||||||
|  |         args: processStartArgs | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       expect(openAtLoginTrueEnabledFalse.openAtLogin).to.equal(true); | ||||||
|  |       expect(openAtLoginTrueEnabledFalse.executableWillLaunchAtLogin).to.equal(false); | ||||||
|  | 
 | ||||||
|  |       app.setLoginItemSettings({ openAtLogin: false, path: updateExe, args: processStartArgs, enabled: false }); | ||||||
|  |       const openAtLoginFalseEnabledFalse = app.getLoginItemSettings({ | ||||||
|  |         path: updateExe, | ||||||
|  |         args: processStartArgs | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       expect(openAtLoginFalseEnabledFalse.openAtLogin).to.equal(false); | ||||||
|  |       expect(openAtLoginFalseEnabledFalse.executableWillLaunchAtLogin).to.equal(false); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     ifit(process.platform === 'win32')('allows you to pass a custom name', function () { | ||||||
|  |       app.setLoginItemSettings({ openAtLogin: true }); | ||||||
|  |       app.setLoginItemSettings({ openAtLogin: true, name: 'additionalEntry', enabled: false }); | ||||||
|  |       expect(app.getLoginItemSettings()).to.deep.equal({ | ||||||
|  |         openAtLogin: true, | ||||||
|  |         openAsHidden: false, | ||||||
|  |         wasOpenedAtLogin: false, | ||||||
|  |         wasOpenedAsHidden: false, | ||||||
|  |         restoreState: false, | ||||||
|  |         executableWillLaunchAtLogin: true, | ||||||
|  |         launchItems: [{ | ||||||
|  |           name: 'additionalEntry', | ||||||
|  |           path: process.execPath, | ||||||
|  |           args: [], | ||||||
|  |           scope: 'user', | ||||||
|  |           enabled: false | ||||||
|  |         }, { | ||||||
|  |           name: 'electron.app.Electron', | ||||||
|  |           path: process.execPath, | ||||||
|  |           args: [], | ||||||
|  |           scope: 'user', | ||||||
|  |           enabled: true | ||||||
|  |         }] | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       app.setLoginItemSettings({ openAtLogin: false, name: 'additionalEntry' }); | ||||||
|  |       expect(app.getLoginItemSettings()).to.deep.equal({ | ||||||
|  |         openAtLogin: true, | ||||||
|  |         openAsHidden: false, | ||||||
|  |         wasOpenedAtLogin: false, | ||||||
|  |         wasOpenedAsHidden: false, | ||||||
|  |         restoreState: false, | ||||||
|  |         executableWillLaunchAtLogin: true, | ||||||
|  |         launchItems: [{ | ||||||
|  |           name: 'electron.app.Electron', | ||||||
|  |           path: process.execPath, | ||||||
|  |           args: [], | ||||||
|  |           scope: 'user', | ||||||
|  |           enabled: true | ||||||
|  |         }] | ||||||
|  |       }); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 George Xu
				George Xu