fix: prevent potential modal window close segfault (#22481)

This commit is contained in:
Shelley Vohr
2020-03-03 06:04:59 +00:00
committed by GitHub
parent c83dc5be92
commit 6e4690574d
2 changed files with 53 additions and 6 deletions

View File

@@ -592,7 +592,14 @@ void NativeWindowMac::SetContentView(views::View* view) {
void NativeWindowMac::Close() {
// When this is a sheet showing, performClose won't work.
if (is_modal() && parent() && IsVisible()) {
[parent()->GetNativeWindow().GetNativeNSWindow() endSheet:window_];
NSWindow* window = parent()->GetNativeWindow().GetNativeNSWindow();
if (NSWindow* sheetParent = [window sheetParent]) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(base::RetainBlock(^{
[sheetParent endSheet:window];
})));
}
// Manually emit close event (not triggered from close fn)
NotifyWindowCloseButtonClicked();
CloseImmediately();

View File

@@ -3050,15 +3050,53 @@ describe('BrowserWindow module', () => {
})
// The isEnabled API is not reliable on macOS.
ifdescribe(process.platform !== 'darwin')('modal option', () => {
it('disables parent window', () => {
describe('modal option', () => {
it('does not crash', async () => {
const parentWindow = new BrowserWindow()
const createTwo = async () => {
const two = new BrowserWindow({
width: 300,
height: 200,
parent: parentWindow,
modal: true,
show: false
})
const twoShown = emittedOnce(two, 'show')
two.show()
await twoShown
setTimeout(() => two.close(), 500)
await emittedOnce(two, 'closed')
}
const one = new BrowserWindow({
width: 600,
height: 400,
parent: parentWindow,
modal: true,
show: false
})
const oneShown = emittedOnce(one, 'show')
one.show()
await oneShown
setTimeout(() => one.destroy(), 500)
await emittedOnce(one, 'closed')
await createTwo()
})
ifit(process.platform !== 'darwin')('disables parent window', () => {
const w = new BrowserWindow({show: false})
const c = new BrowserWindow({ show: false, parent: w, modal: true })
expect(w.isEnabled()).to.be.true('w.isEnabled')
c.show()
expect(w.isEnabled()).to.be.false('w.isEnabled')
})
it('re-enables an enabled parent window when closed', (done) => {
ifit(process.platform !== 'darwin')('re-enables an enabled parent window when closed', (done) => {
const w = new BrowserWindow({show: false})
const c = new BrowserWindow({ show: false, parent: w, modal: true })
c.once('closed', () => {
@@ -3068,7 +3106,8 @@ describe('BrowserWindow module', () => {
c.show()
c.close()
})
it('does not re-enable a disabled parent window when closed', (done) => {
ifit(process.platform !== 'darwin')('does not re-enable a disabled parent window when closed', (done) => {
const w = new BrowserWindow({show: false})
const c = new BrowserWindow({ show: false, parent: w, modal: true })
c.once('closed', () => {
@@ -3079,7 +3118,8 @@ describe('BrowserWindow module', () => {
c.show()
c.close()
})
it('disables parent window recursively', () => {
ifit(process.platform !== 'darwin')('disables parent window recursively', () => {
const w = new BrowserWindow({show: false})
const c = new BrowserWindow({ show: false, parent: w, modal: true })
const c2 = new BrowserWindow({ show: false, parent: w, modal: true })