From 6fc2a2a051712ec063e52543e124f0e6c108d0ad Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Fri, 12 Oct 2018 15:19:27 -0700 Subject: [PATCH] fix: natively implement LoginItem functions (#15010) --- atom/browser/browser_mac.mm | 64 +++++++++++++++++++++++++++++++++++-- spec/api-app-spec.js | 15 +++++++++ vsts.yml | 17 ++++------ 3 files changed, 84 insertions(+), 12 deletions(-) diff --git a/atom/browser/browser_mac.mm b/atom/browser/browser_mac.mm index 27e347ecceb..735e07b2f3b 100644 --- a/atom/browser/browser_mac.mm +++ b/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 login_items( + LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL)); + if (!login_items.get()) { + LOG(ERROR) << "Couldn't get a Login Items list."; + return NULL; + } + base::scoped_nsobject 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(login_items_array[i]); + CFURLRef item_url_ref = NULL; + if (LSSharedFileListItemResolve(item, 0, &item_url_ref, NULL) == noErr && + item_url_ref) { + base::ScopedCFTypeRef item_url(item_url_ref); + if (CFEqual(item_url, url)) { + CFRetain(item); + return item; + } + } + } + return NULL; +} + +void RemoveFromLoginItems() { + base::ScopedCFTypeRef list( + LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL)); + if (!list) { + LOG(ERROR) << "Unable to access shared file list"; + return; + } + + if (GetLoginItemForApp() != NULL) { + base::scoped_nsobject 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(login_items_array[i]); + CFURLRef url_ref = NULL; + if (LSSharedFileListItemResolve(item, 0, &url_ref, NULL) == noErr && + item) { + base::ScopedCFTypeRef 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 } diff --git a/spec/api-app-spec.js b/spec/api-app-spec.js index caa3ae27e71..21f50a37ad5 100644 --- a/spec/api-app-spec.js +++ b/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. diff --git a/vsts.yml b/vsts.yml index 5e939d06b88..05861775b70 100644 --- a/vsts.yml +++ b/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