Browse Source

refactor: JSify BrowserWindow unresponsive handling (#37902)

Jeremy Rose 1 year ago
parent
commit
67ba30402b

+ 23 - 0
lib/browser/api/browser-window.ts

@@ -36,6 +36,29 @@ BrowserWindow.prototype._init = function (this: BWT) {
     app.emit('browser-window-focus', event, this);
   });
 
+  let unresponsiveEvent: NodeJS.Timeout | null = null;
+  const emitUnresponsiveEvent = () => {
+    unresponsiveEvent = null;
+    if (!this.isDestroyed() && this.isEnabled()) { this.emit('unresponsive'); }
+  };
+  this.webContents.on('unresponsive', () => {
+    if (!unresponsiveEvent) { unresponsiveEvent = setTimeout(emitUnresponsiveEvent, 50); }
+  });
+  this.webContents.on('responsive', () => {
+    if (unresponsiveEvent) {
+      clearTimeout(unresponsiveEvent);
+      unresponsiveEvent = null;
+    }
+    this.emit('responsive');
+  });
+  this.on('close', () => {
+    if (!unresponsiveEvent) { unresponsiveEvent = setTimeout(emitUnresponsiveEvent, 5000); }
+  });
+  this.webContents.on('destroyed', () => {
+    if (unresponsiveEvent) clearTimeout(unresponsiveEvent);
+    unresponsiveEvent = null;
+  });
+
   // Subscribe to visibilityState changes and pass to renderer process.
   let isVisible = this.isVisible() && !this.isMinimized();
   const visibilityChanged = () => {

+ 0 - 46
shell/browser/api/electron_api_browser_window.cc

@@ -117,19 +117,6 @@ BrowserWindow::~BrowserWindow() {
 
 void BrowserWindow::BeforeUnloadDialogCancelled() {
   WindowList::WindowCloseCancelled(window());
-  // Cancel unresponsive event when window close is cancelled.
-  window_unresponsive_closure_.Cancel();
-}
-
-void BrowserWindow::OnRendererUnresponsive(content::RenderProcessHost*) {
-  // Schedule the unresponsive shortly later, since we may receive the
-  // responsive event soon. This could happen after the whole application had
-  // blocked for a while.
-  // Also notice that when closing this event would be ignored because we have
-  // explicitly started a close timeout counter. This is on purpose because we
-  // don't want the unresponsive event to be sent too early when user is closing
-  // the window.
-  ScheduleUnresponsiveEvent(50);
 }
 
 void BrowserWindow::WebContentsDestroyed() {
@@ -137,11 +124,6 @@ void BrowserWindow::WebContentsDestroyed() {
   CloseImmediately();
 }
 
-void BrowserWindow::OnRendererResponsive(content::RenderProcessHost*) {
-  window_unresponsive_closure_.Cancel();
-  Emit("responsive");
-}
-
 void BrowserWindow::OnSetContentBounds(const gfx::Rect& rect) {
   // window.resizeTo(...)
   // window.moveTo(...)
@@ -177,13 +159,6 @@ void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
   // first, and when the web page is closed the window will also be closed.
   *prevent_default = true;
 
-  // Assume the window is not responding if it doesn't cancel the close and is
-  // not closed in 5s, in this way we can quickly show the unresponsive
-  // dialog when the window is busy executing some script without waiting for
-  // the unresponsive timeout.
-  if (window_unresponsive_closure_.IsCancelled())
-    ScheduleUnresponsiveEvent(5000);
-
   // Already closed by renderer.
   if (!web_contents() || !api_web_contents_)
     return;
@@ -250,9 +225,6 @@ void BrowserWindow::CloseImmediately() {
   }
 
   BaseWindow::CloseImmediately();
-
-  // Do not sent "unresponsive" event after window is closed.
-  window_unresponsive_closure_.Cancel();
 }
 
 void BrowserWindow::Focus() {
@@ -362,24 +334,6 @@ void BrowserWindow::SetTitleBarOverlay(const gin_helper::Dictionary& options,
 }
 #endif
 
-void BrowserWindow::ScheduleUnresponsiveEvent(int ms) {
-  if (!window_unresponsive_closure_.IsCancelled())
-    return;
-
-  window_unresponsive_closure_.Reset(base::BindRepeating(
-      &BrowserWindow::NotifyWindowUnresponsive, GetWeakPtr()));
-  base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
-      FROM_HERE, window_unresponsive_closure_.callback(),
-      base::Milliseconds(ms));
-}
-
-void BrowserWindow::NotifyWindowUnresponsive() {
-  window_unresponsive_closure_.Cancel();
-  if (!window_->IsClosed() && window_->IsEnabled()) {
-    Emit("unresponsive");
-  }
-}
-
 void BrowserWindow::OnWindowShow() {
   web_contents()->WasShown();
   BaseWindow::OnWindowShow();

+ 0 - 13
shell/browser/api/electron_api_browser_window.h

@@ -43,9 +43,6 @@ class BrowserWindow : public BaseWindow,
 
   // content::WebContentsObserver:
   void BeforeUnloadDialogCancelled() override;
-  void OnRendererUnresponsive(content::RenderProcessHost*) override;
-  void OnRendererResponsive(
-      content::RenderProcessHost* render_process_host) override;
   void WebContentsDestroyed() override;
 
   // ExtendedWebContentsObserver:
@@ -84,16 +81,6 @@ class BrowserWindow : public BaseWindow,
  private:
   // Helpers.
 
-  // Schedule a notification unresponsive event.
-  void ScheduleUnresponsiveEvent(int ms);
-
-  // Dispatch unresponsive event to observers.
-  void NotifyWindowUnresponsive();
-
-  // Closure that would be called when window is unresponsive when closing,
-  // it should be cancelled when we can prove that the window is responsive.
-  base::CancelableRepeatingClosure window_unresponsive_closure_;
-
   v8::Global<v8::Value> web_contents_;
   v8::Global<v8::Value> web_contents_view_;
   base::WeakPtr<api::WebContents> api_web_contents_;