diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 11176b54a6f38..9f4153a49b1d2 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -130,10 +130,6 @@ Corresponds to the points in time when the spinner of the tab stopped spinning. #### Event: 'dom-ready' -Returns: - -* `event` Event - Emitted when the document in the top-level frame is loaded. #### Event: 'page-title-updated' @@ -156,6 +152,18 @@ Returns: Emitted when page receives favicon urls. +#### Event: 'content-bounds-updated' + +Returns: + +* `event` Event +* `bounds` [Rectangle](structures/rectangle.md) - requested new content bounds + +Emitted when the page calls `window.moveTo`, `window.resizeTo` or related APIs. + +By default, this will move the window. To prevent that behavior, call +`event.preventDefault()`. + #### Event: 'did-create-window' Returns: diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index ebf009112155d..fe5380654170c 100755 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -1180,8 +1180,9 @@ void WebContents::BeforeUnloadFired(content::WebContents* tab, void WebContents::SetContentsBounds(content::WebContents* source, const gfx::Rect& rect) { - for (ExtendedWebContentsObserver& observer : observers_) - observer.OnSetContentBounds(rect); + if (!Emit("content-bounds-updated", rect)) + for (ExtendedWebContentsObserver& observer : observers_) + observer.OnSetContentBounds(rect); } void WebContents::CloseContents(content::WebContents* source) { diff --git a/spec/api-web-contents-spec.ts b/spec/api-web-contents-spec.ts index 3ceb081c76c9b..98251ac79035f 100644 --- a/spec/api-web-contents-spec.ts +++ b/spec/api-web-contents-spec.ts @@ -2132,4 +2132,62 @@ describe('webContents module', () => { expect(params.y).to.be.a('number'); }); }); + + describe('content-bounds-updated event', () => { + afterEach(closeAllWindows); + it('emits when moveTo is called', async () => { + const w = new BrowserWindow({ show: false }); + w.loadURL('about:blank'); + w.webContents.executeJavaScript('window.moveTo(100, 100)', true); + const [, rect] = await emittedOnce(w.webContents, 'content-bounds-updated'); + const { width, height } = w.getBounds(); + expect(rect).to.deep.equal({ + x: 100, + y: 100, + width, + height + }); + await new Promise(setImmediate); + expect(w.getBounds().x).to.equal(100); + expect(w.getBounds().y).to.equal(100); + }); + + it('emits when resizeTo is called', async () => { + const w = new BrowserWindow({ show: false }); + w.loadURL('about:blank'); + w.webContents.executeJavaScript('window.resizeTo(100, 100)', true); + const [, rect] = await emittedOnce(w.webContents, 'content-bounds-updated'); + const { x, y } = w.getBounds(); + expect(rect).to.deep.equal({ + x, + y, + width: 100, + height: 100 + }); + await new Promise(setImmediate); + expect({ + width: w.getBounds().width, + height: w.getBounds().height + }).to.deep.equal(process.platform === 'win32' ? { + // The width is reported as being larger on Windows? I'm not sure why + // this is. + width: 136, + height: 100 + } : { + width: 100, + height: 100 + }); + }); + + it('does not change window bounds if cancelled', async () => { + const w = new BrowserWindow({ show: false }); + const { width, height } = w.getBounds(); + w.loadURL('about:blank'); + w.webContents.once('content-bounds-updated', e => e.preventDefault()); + await w.webContents.executeJavaScript('window.resizeTo(100, 100)', true); + await new Promise(setImmediate); + expect(w.getBounds().width).to.equal(width); + expect(w.getBounds().height).to.equal(height); + }); + }); });