From e7796f38c4e09601c42beb9d643a28a3ea43679a Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Fri, 20 Sep 2024 17:08:40 +0200 Subject: [PATCH 1/2] Closing all Shells and the Display when browsertab is closed Closing all Shells results in dispose events, and allows for cleaning stuff up. Also-by: Ralf Schlesinger --- .../workbench/swt/PartRenderingEngine.java | 6 ++++ .../js/rwt/widgets/Browser.js | 24 +++++++++------ .../rwt/internal/lifecycle/RWTLifeCycle.java | 3 +- .../src/org/eclipse/swt/browser/Browser.java | 30 ++++++++++++++++++- .../org/eclipse/swt/browser/Browser_Test.java | 10 +++++-- 5 files changed, 59 insertions(+), 14 deletions(-) diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java index 15188dd244..7f413707d5 100644 --- a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java +++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java @@ -1130,6 +1130,12 @@ public void eventLoopException(Throwable exception) { advisor.eventLoopIdle(display); } } catch (ThreadDeath th) { + + for (Shell shell : display.getShells()) { + shell.close(); + } + display.close(); + throw th; } catch (Exception ex) { handle(ex, advisor); diff --git a/bundles/org.eclipse.rap.rwt/js/rwt/widgets/Browser.js b/bundles/org.eclipse.rap.rwt/js/rwt/widgets/Browser.js index ff60807174..b25d6ca36e 100644 --- a/bundles/org.eclipse.rap.rwt/js/rwt/widgets/Browser.js +++ b/bundles/org.eclipse.rap.rwt/js/rwt/widgets/Browser.js @@ -146,6 +146,7 @@ rwt.qx.Class.define( "rwt.widgets.Browser", { try { result = this._parseEvalResult( this._eval( script ) ); } catch( ex ) { + console.log(ex); success = false; } var connection = rwt.remote.Connection.getInstance(); @@ -198,7 +199,7 @@ rwt.qx.Class.define( "rwt.widgets.Browser", { // not accessible when it appears it should be // => user navigated to external site. this._throwSecurityException( true ); - } + } } }, @@ -215,21 +216,26 @@ rwt.qx.Class.define( "rwt.widgets.Browser", { }, _eval : function( script ) { - var win = this.getContentWindow(); - if( !win[ "eval" ] && win[ "execScript" ] ) { - // Workaround for IE bug, see: http://www.thismuchiknow.co.uk/?p=25 - win.execScript( "null;", "JScript" ); - } - return win[ "eval" ]( script ); + var win = this.getContentWindow(); + + if (win !== null) { + if( !win[ "eval" ] && win[ "execScript" ] ) { + // Workaround for IE bug, see: http://www.thismuchiknow.co.uk/?p=25 + win.execScript( "null;", "JScript" ); + } + return win[ "eval" ]( script ); + } else { + console.error("Window is null, can not execute scipts:\n" + script); + } }, _parseEvalResult : function( value ) { var result = null; var win = this.getContentWindow(); // NOTE: This mimics the behavior of the evaluate method in SWT: - if( value instanceof win.Function || value instanceof Function ) { + if( (win !== null && value instanceof win.Function) || value instanceof Function ) { result = this.toJSON( [ [] ] ); - } else if( value instanceof win.Array || value instanceof Array ) { + } else if( (win !== null && value instanceof win.Array) || value instanceof Array ) { result = this.toJSON( [ value ] ); } else if( typeof value !== "object" && typeof value !== "function" ) { // above: some browser say regular expressions of the type "function" diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/lifecycle/RWTLifeCycle.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/lifecycle/RWTLifeCycle.java index 641f7c7f1b..37825b8569 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/lifecycle/RWTLifeCycle.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/lifecycle/RWTLifeCycle.java @@ -302,7 +302,8 @@ public void run() { UISession uiSession = ContextProvider.getUISession(); uiSession.setAttribute( UI_THREAD_WAITING_FOR_TERMINATION, Boolean.TRUE ); // In any case: wait for the thread to be terminated by session timeout - uiThread.switchThread(); + // pw: no don't wait, because we cought that earlier and terminated normally + //uiThread.switchThread(); } } catch( @SuppressWarnings( "unused" ) UIThreadTerminatedError e ) { // If we get here, the session is being invalidated, see UIThread#terminateThread() diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java index d0e4148d4e..0719789bca 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java @@ -36,6 +36,7 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TypedListener; @@ -80,6 +81,7 @@ public class Browser extends Composite { private BrowserCallback browserCallback; private transient IBrowserAdapter browserAdapter; private final List functions; + private boolean clientInited = false; /** * Constructs a new instance of this class given its parent @@ -258,6 +260,33 @@ public boolean execute( String script ) { if( executeScript != null ) { throw new IllegalStateException( "Another script is already pending" ); } + + boolean showedShell = false; + Shell shell = getShell(); + + try { + // Show the shell, so that the browser is created in the browser + if (!clientInited && shell != null && !shell.getVisible()) { + showedShell = true; + //shell.setMinimized(true); + shell.setVisible(true); + internalExecute( "" ); + } + + internalExecute( script ); + } finally { + // if we showed it, we have to hide it again + if (showedShell) { + //shell.setMinimized(false); + shell.setVisible(false); + internalExecute( "" ); + } + clientInited = true; + } + return executeResult.booleanValue(); + } + + protected void internalExecute( String script ) { executeScript = script; executeResult = null; while( executeResult == null ) { @@ -268,7 +297,6 @@ public boolean execute( String script ) { } executeScript = null; executePending = false; - return executeResult.booleanValue(); } /** diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/browser/Browser_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/browser/Browser_Test.java index 5e80f3670f..b3f8099d7b 100644 --- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/browser/Browser_Test.java +++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/browser/Browser_Test.java @@ -34,6 +34,7 @@ import org.eclipse.rap.rwt.testfixture.TestContext; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTError; +import org.eclipse.swt.SWTException; import org.eclipse.swt.internal.browser.browserkit.BrowserLCA; import org.eclipse.swt.internal.events.EventTypes; import org.eclipse.swt.internal.widgets.IBrowserAdapter; @@ -356,9 +357,12 @@ public void run() { } } ); - boolean result = browser.execute( "var x = 2;" ); - - assertFalse( result ); + try { + boolean result = browser.execute( "var x = 2;" ); + fail(); + } catch( SWTException expected ) { + assertEquals( "Widget is disposed", expected.getMessage() ); + } } @Test From 75b3ebf01abb649de90c1727c900b238aa120d41 Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Tue, 24 Sep 2024 13:00:50 +0200 Subject: [PATCH 2/2] fixed merge error uiThread.switchThread() is needed, was removed in previous version Also-by: Ralf Schlesinger --- .../org/eclipse/rap/rwt/internal/lifecycle/RWTLifeCycle.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/lifecycle/RWTLifeCycle.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/lifecycle/RWTLifeCycle.java index 37825b8569..641f7c7f1b 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/lifecycle/RWTLifeCycle.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/lifecycle/RWTLifeCycle.java @@ -302,8 +302,7 @@ public void run() { UISession uiSession = ContextProvider.getUISession(); uiSession.setAttribute( UI_THREAD_WAITING_FOR_TERMINATION, Boolean.TRUE ); // In any case: wait for the thread to be terminated by session timeout - // pw: no don't wait, because we cought that earlier and terminated normally - //uiThread.switchThread(); + uiThread.switchThread(); } } catch( @SuppressWarnings( "unused" ) UIThreadTerminatedError e ) { // If we get here, the session is being invalidated, see UIThread#terminateThread()