fix: natively implement LoginItems methods (#15128)

* fix: natively implement LoginItems methods

* fix flaky spec on MAS builds
This commit is contained in:
Shelley Vohr 2018-10-12 20:50:03 -07:00 committed by GitHub
parent 9bb3701f7e
commit f6b7f547bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 90 additions and 23 deletions

View file

@ -217,6 +217,65 @@ Browser::LoginItemSettings Browser::GetLoginItemSettings(
return settings; 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) { void Browser::SetLoginItemSettings(LoginItemSettings settings) {
#if defined(MAS_BUILD) #if defined(MAS_BUILD)
platform_util::SetLoginItemEnabled(settings.open_at_login); platform_util::SetLoginItemEnabled(settings.open_at_login);
@ -224,7 +283,7 @@ void Browser::SetLoginItemSettings(LoginItemSettings settings) {
if (settings.open_at_login) if (settings.open_at_login)
base::mac::AddToLoginItems(settings.open_as_hidden); base::mac::AddToLoginItems(settings.open_as_hidden);
else else
base::mac::RemoveFromLoginItems(); RemoveFromLoginItems();
#endif #endif
} }

View file

@ -455,8 +455,11 @@ describe('app module', () => {
app.setLoginItemSettings({openAtLogin: false, path: updateExe, args: processStartArgs}) app.setLoginItemSettings({openAtLogin: false, path: updateExe, args: processStartArgs})
}) })
it('returns the login item status of the app', done => { it('sets and returns the app as a login item', done => {
app.setLoginItemSettings({ openAtLogin: true }) app.setLoginItemSettings({ openAtLogin: true })
// Wait because login item settings are not applied immediately in MAS build
const delay = process.mas ? 150 : 0
setTimeout(() => {
expect(app.getLoginItemSettings()).to.deep.equal({ expect(app.getLoginItemSettings()).to.deep.equal({
openAtLogin: true, openAtLogin: true,
openAsHidden: false, openAsHidden: false,
@ -464,7 +467,11 @@ describe('app module', () => {
wasOpenedAsHidden: false, wasOpenedAsHidden: false,
restoreState: false restoreState: false
}) })
done()
}, delay)
})
it('adds a login item that loads in hidden mode', () => {
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,
@ -473,20 +480,21 @@ describe('app module', () => {
wasOpenedAsHidden: false, wasOpenedAsHidden: false,
restoreState: false restoreState: false
}) })
app.setLoginItemSettings({})
// Wait because login item settings are not applied immediately in MAS build
const delay = process.mas ? 100 : 0
setTimeout(() => {
expect(app.getLoginItemSettings()).to.deep.equal({
openAtLogin: false,
openAsHidden: false,
wasOpenedAtLogin: false,
wasOpenedAsHidden: false,
restoreState: false
}) })
done()
}, 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 () { it('allows you to pass a custom executable and arguments', function () {