Browse Source

fix: natively implement LoginItem functions (#15010)

Shelley Vohr 6 years ago
parent
commit
6fc2a2a051
3 changed files with 84 additions and 12 deletions
  1. 62 2
      atom/browser/browser_mac.mm
  2. 15 0
      spec/api-app-spec.js
  3. 7 10
      vsts.yml

+ 62 - 2
atom/browser/browser_mac.mm

@@ -217,14 +217,74 @@ Browser::LoginItemSettings Browser::GetLoginItemSettings(
   return settings;
 }
 
+// copied from GetLoginItemForApp in base/mac/mac_util.mm
+LSSharedFileListItemRef GetLoginItemForApp() {
+  base::ScopedCFTypeRef<LSSharedFileListRef> login_items(
+      LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL));
+  if (!login_items.get()) {
+    LOG(ERROR) << "Couldn't get a Login Items list.";
+    return NULL;
+  }
+  base::scoped_nsobject<NSArray> login_items_array(
+      base::mac::CFToNSCast(LSSharedFileListCopySnapshot(login_items, NULL)));
+  NSURL* url = [NSURL fileURLWithPath:[base::mac::MainBundle() bundlePath]];
+  for (NSUInteger i = 0; i < [login_items_array count]; ++i) {
+    LSSharedFileListItemRef item =
+        reinterpret_cast<LSSharedFileListItemRef>(login_items_array[i]);
+    CFURLRef item_url_ref = NULL;
+    if (LSSharedFileListItemResolve(item, 0, &item_url_ref, NULL) == noErr &&
+        item_url_ref) {
+      base::ScopedCFTypeRef<CFURLRef> item_url(item_url_ref);
+      if (CFEqual(item_url, url)) {
+        CFRetain(item);
+        return item;
+      }
+    }
+  }
+  return NULL;
+}
+
+void RemoveFromLoginItems() {
+  base::ScopedCFTypeRef<LSSharedFileListRef> list(
+      LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL));
+  if (!list) {
+    LOG(ERROR) << "Unable to access shared file list";
+    return;
+  }
+
+  if (GetLoginItemForApp() != NULL) {
+    base::scoped_nsobject<NSArray> login_items_array(
+        base::mac::CFToNSCast(LSSharedFileListCopySnapshot(list, NULL)));
+
+    if (!login_items_array) {
+      LOG(ERROR) << "No items in list of auto-loaded apps";
+      return;
+    }
+
+    for (NSUInteger i = 0; i < [login_items_array count]; ++i) {
+      LSSharedFileListItemRef item =
+          reinterpret_cast<LSSharedFileListItemRef>(login_items_array[i]);
+      CFURLRef url_ref = NULL;
+      if (LSSharedFileListItemResolve(item, 0, &url_ref, NULL) == noErr &&
+          item) {
+        base::ScopedCFTypeRef<CFURLRef> url(url_ref);
+        if ([[base::mac::CFToNSCast(url.get()) path]
+                hasPrefix:[[NSBundle mainBundle] bundlePath]])
+          LSSharedFileListItemRemove(list, item);
+      }
+    }
+  }
+}
+
 void Browser::SetLoginItemSettings(LoginItemSettings settings) {
 #if defined(MAS_BUILD)
   platform_util::SetLoginItemEnabled(settings.open_at_login);
 #else
   if (settings.open_at_login)
     base::mac::AddToLoginItems(settings.open_as_hidden);
-  else
-    base::mac::RemoveFromLoginItems();
+  else {
+    RemoveFromLoginItems();
+  }
 #endif
 }
 

+ 15 - 0
spec/api-app-spec.js

@@ -466,6 +466,21 @@ describe('app module', () => {
       }, delay)
     })
 
+    it('correctly sets and unsets the LoginItem as hidden', function () {
+      if (process.platform !== 'darwin' || process.mas) this.skip()
+
+      expect(app.getLoginItemSettings().openAtLogin).to.be.false()
+      expect(app.getLoginItemSettings().openAsHidden).to.be.false()
+
+      app.setLoginItemSettings({ openAtLogin: true, openAsHidden: true })
+      expect(app.getLoginItemSettings().openAtLogin).to.be.true()
+      expect(app.getLoginItemSettings().openAsHidden).to.be.true()
+
+      app.setLoginItemSettings({ openAtLogin: true, openAsHidden: false })
+      expect(app.getLoginItemSettings().openAtLogin).to.be.true()
+      expect(app.getLoginItemSettings().openAsHidden).to.be.false()
+    })
+
     it('allows you to pass a custom executable and arguments', function () {
       if (process.platform !== 'win32') {
         // FIXME(alexeykuzmin): Skip the test.

+ 7 - 10
vsts.yml

@@ -208,10 +208,8 @@ jobs:
   # Run this job only if we are supposed to run the tests,
   # and we have an Electron built either in the previous job or in a different job, defined by a user.
   condition: and(eq(variables['RUN_TESTS'], '1'), or(succeeded(), ne(variables['Custom.UseArtifacts.BuildId'], '')))
-# TODO(alexeykuzmin): Run on Microsoft-hosted agents
-# once https://github.com/electron/electron/issues/15041 is fixed.
-#  pool:
-#    vmImage: 'macOS-10.13'
+  pool:
+    vmImage: 'macOS-10.13'
   timeoutInMinutes: 20
   variables:
     CI: true
@@ -269,12 +267,11 @@ jobs:
       destinationFolder: src/out/Default/gen
     timeoutInMinutes: 1
 
-#  TODO(alexeykuzmin): Install Node when tests are run on Microsoft-hosted agents.
-#  - task: NodeTool@0
-#    displayName: Install Node.js 10.x
-#    inputs:
-#      versionSpec: '10.x'
-#    timeoutInMinutes: 2  # Should take less than a minute.
+  - task: NodeTool@0
+    displayName: Install Node.js 10.x
+    inputs:
+      versionSpec: '10.x'
+    timeoutInMinutes: 2  # Should take less than a minute.
 
   - bash: |
       cd src/electron