Browse Source

fix: getLoginItemSettings() on windows (#26538)

* find by exe, detect taskmgr enable/disable

* tests

* revert

* oops

Co-authored-by: Jan Hannemann <[email protected]>
trop[bot] 4 years ago
parent
commit
b14c57e30c
2 changed files with 166 additions and 14 deletions
  1. 24 13
      shell/browser/browser_win.cc
  2. 142 1
      spec-main/api-app-spec.ts

+ 24 - 13
shell/browser/browser_win.cc

@@ -196,19 +196,30 @@ std::vector<Browser::LaunchItem> GetLoginItemSettingsHelper(
     const Browser::LoginItemSettings& options) {
   std::vector<Browser::LaunchItem> launch_items;
 
-  while (it->Valid()) {
-    base::string16 exe = options.path;
-    if (FormatCommandLineString(&exe, options.args)) {
+  base::FilePath lookup_exe_path;
+  if (options.path.empty()) {
+    base::string16 process_exe_path;
+    GetProcessExecPath(&process_exe_path);
+    lookup_exe_path =
+        base::CommandLine::FromString(process_exe_path).GetProgram();
+  } else {
+    lookup_exe_path = base::CommandLine::FromString(options.path).GetProgram();
+  }
+
+  if (!lookup_exe_path.empty()) {
+    while (it->Valid()) {
+      base::CommandLine registry_launch_cmd =
+          base::CommandLine::FromString(it->Value());
+      base::FilePath registry_launch_path = registry_launch_cmd.GetProgram();
+      bool exe_match = base::FilePath::CompareEqualIgnoreCase(
+          lookup_exe_path.value(), registry_launch_path.value());
+
       // add launch item to vector if it has a matching path (case-insensitive)
-      if ((base::CompareCaseInsensitiveASCII(it->Value(), exe.c_str())) == 0) {
+      if (exe_match) {
         Browser::LaunchItem launch_item;
-        base::string16 launch_path = options.path;
-        if (launch_path.empty()) {
-          GetProcessExecPath(&launch_path);
-        }
         launch_item.name = it->Name();
-        launch_item.path = launch_path;
-        launch_item.args = options.args;
+        launch_item.path = registry_launch_path.value();
+        launch_item.args = registry_launch_cmd.GetArgs();
         launch_item.scope = scope;
         launch_item.enabled = true;
 
@@ -249,8 +260,8 @@ std::vector<Browser::LaunchItem> GetLoginItemSettingsHelper(
                   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);
+              launch_item.enabled = (reg_startup_binary == reg_binary) ||
+                                    (reg_startup_binary == reg_binary_alt);
             }
           }
         }
@@ -259,8 +270,8 @@ std::vector<Browser::LaunchItem> GetLoginItemSettingsHelper(
             *executable_will_launch_at_login || launch_item.enabled;
         launch_items.push_back(launch_item);
       }
+      it->operator++();
     }
-    it->operator++();
   }
   return launch_items;
 }

+ 142 - 1
spec-main/api-app-spec.ts

@@ -604,6 +604,16 @@ describe('app module', () => {
       '--processStart', `"${path.basename(process.execPath)}"`,
       '--process-start-args', '"--hidden"'
     ];
+    const regAddArgs = [
+      'ADD',
+      'HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApproved\\Run',
+      '/v',
+      'additionalEntry',
+      '/t',
+      'REG_BINARY',
+      '/f',
+      '/d'
+    ];
 
     before(function () {
       if (process.platform === 'linux' || process.mas) this.skip();
@@ -612,11 +622,13 @@ describe('app module', () => {
     beforeEach(() => {
       app.setLoginItemSettings({ openAtLogin: false });
       app.setLoginItemSettings({ openAtLogin: false, path: updateExe, args: processStartArgs });
+      app.setLoginItemSettings({ name: 'additionalEntry', openAtLogin: false });
     });
 
     afterEach(() => {
       app.setLoginItemSettings({ openAtLogin: false });
       app.setLoginItemSettings({ openAtLogin: false, path: updateExe, args: processStartArgs });
+      app.setLoginItemSettings({ name: 'additionalEntry', openAtLogin: false });
     });
 
     ifit(process.platform !== 'win32')('sets and returns the app as a login item', function () {
@@ -631,7 +643,7 @@ describe('app module', () => {
     });
 
     ifit(process.platform === 'win32')('sets and returns the app as a login item (windows)', function () {
-      app.setLoginItemSettings({ openAtLogin: true });
+      app.setLoginItemSettings({ openAtLogin: true, enabled: true });
       expect(app.getLoginItemSettings()).to.deep.equal({
         openAtLogin: true,
         openAsHidden: false,
@@ -647,6 +659,24 @@ describe('app module', () => {
           enabled: true
         }]
       });
+
+      app.setLoginItemSettings({ openAtLogin: false });
+      app.setLoginItemSettings({ openAtLogin: true, enabled: false });
+      expect(app.getLoginItemSettings()).to.deep.equal({
+        openAtLogin: true,
+        openAsHidden: false,
+        wasOpenedAtLogin: false,
+        wasOpenedAsHidden: false,
+        restoreState: false,
+        executableWillLaunchAtLogin: false,
+        launchItems: [{
+          name: 'electron.app.Electron',
+          path: process.execPath,
+          args: [],
+          scope: 'user',
+          enabled: false
+        }]
+      });
     });
 
     ifit(process.platform !== 'win32')('adds a login item that loads in hidden mode', function () {
@@ -776,6 +806,117 @@ describe('app module', () => {
         }]
       });
     });
+
+    ifit(process.platform === 'win32')('finds launch items independent of args', function () {
+      app.setLoginItemSettings({ openAtLogin: true, args: ['arg1'] });
+      app.setLoginItemSettings({ openAtLogin: true, name: 'additionalEntry', enabled: false, args: ['arg2'] });
+      expect(app.getLoginItemSettings()).to.deep.equal({
+        openAtLogin: false,
+        openAsHidden: false,
+        wasOpenedAtLogin: false,
+        wasOpenedAsHidden: false,
+        restoreState: false,
+        executableWillLaunchAtLogin: true,
+        launchItems: [{
+          name: 'additionalEntry',
+          path: process.execPath,
+          args: ['arg2'],
+          scope: 'user',
+          enabled: false
+        }, {
+          name: 'electron.app.Electron',
+          path: process.execPath,
+          args: ['arg1'],
+          scope: 'user',
+          enabled: true
+        }]
+      });
+    });
+
+    ifit(process.platform === 'win32')('finds launch items independent of path quotation or casing', function () {
+      const expectation = {
+        openAtLogin: false,
+        openAsHidden: false,
+        wasOpenedAtLogin: false,
+        wasOpenedAsHidden: false,
+        restoreState: false,
+        executableWillLaunchAtLogin: true,
+        launchItems: [{
+          name: 'additionalEntry',
+          path: 'C:\\electron\\myapp.exe',
+          args: ['arg1'],
+          scope: 'user',
+          enabled: true
+        }]
+      };
+
+      app.setLoginItemSettings({ openAtLogin: true, name: 'additionalEntry', enabled: true, path: 'C:\\electron\\myapp.exe', args: ['arg1'] });
+      expect(app.getLoginItemSettings({ path: '"C:\\electron\\MYAPP.exe"' })).to.deep.equal(expectation);
+
+      app.setLoginItemSettings({ openAtLogin: false, name: 'additionalEntry' });
+      app.setLoginItemSettings({ openAtLogin: true, name: 'additionalEntry', enabled: true, path: '"C:\\electron\\MYAPP.exe"', args: ['arg1'] });
+      expect(app.getLoginItemSettings({ path: 'C:\\electron\\myapp.exe' })).to.deep.equal({
+        ...expectation,
+        launchItems: [
+          {
+            name: 'additionalEntry',
+            path: 'C:\\electron\\MYAPP.exe',
+            args: ['arg1'],
+            scope: 'user',
+            enabled: true
+          }
+        ]
+      });
+    });
+
+    ifit(process.platform === 'win32')('detects disabled by TaskManager', async function () {
+      app.setLoginItemSettings({ openAtLogin: true, name: 'additionalEntry', enabled: true, args: ['arg1'] });
+      const appProcess = cp.spawn('reg', [...regAddArgs, '030000000000000000000000']);
+      await emittedOnce(appProcess, 'exit');
+      expect(app.getLoginItemSettings()).to.deep.equal({
+        openAtLogin: false,
+        openAsHidden: false,
+        wasOpenedAtLogin: false,
+        wasOpenedAsHidden: false,
+        restoreState: false,
+        executableWillLaunchAtLogin: false,
+        launchItems: [{
+          name: 'additionalEntry',
+          path: process.execPath,
+          args: ['arg1'],
+          scope: 'user',
+          enabled: false
+        }]
+      });
+    });
+
+    ifit(process.platform === 'win32')('detects enabled by TaskManager', async function () {
+      const expectation = {
+        openAtLogin: false,
+        openAsHidden: false,
+        wasOpenedAtLogin: false,
+        wasOpenedAsHidden: false,
+        restoreState: false,
+        executableWillLaunchAtLogin: true,
+        launchItems: [{
+          name: 'additionalEntry',
+          path: process.execPath,
+          args: ['arg1'],
+          scope: 'user',
+          enabled: true
+        }]
+      };
+
+      app.setLoginItemSettings({ openAtLogin: true, name: 'additionalEntry', enabled: false, args: ['arg1'] });
+      let appProcess = cp.spawn('reg', [...regAddArgs, '020000000000000000000000']);
+      await emittedOnce(appProcess, 'exit');
+      expect(app.getLoginItemSettings()).to.deep.equal(expectation);
+
+      app.setLoginItemSettings({ openAtLogin: true, name: 'additionalEntry', enabled: false, args: ['arg1'] });
+      appProcess = cp.spawn('reg', [...regAddArgs, '000000000000000000000000']);
+      await emittedOnce(appProcess, 'exit');
+      expect(app.getLoginItemSettings()).to.deep.equal(expectation);
+    });
   });
 
   ifdescribe(process.platform !== 'linux')('accessibilitySupportEnabled property', () => {