Browse Source

feat: expose content-bounds-updated event (#35533)

Jeremy Rose 2 years ago
parent
commit
9f97c3e50a

+ 12 - 4
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:

+ 3 - 2
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) {

+ 58 - 0
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);
+    });
+  });
 });