Skip to content

Commit

Permalink
Fix Edge Browser setText method
Browse files Browse the repository at this point in the history
This contribution fixes Edge browser for win32 to allow serving webpages using setText method where the source code may refer to local resources.

contributes to #213
  • Loading branch information
amartya4256 committed Aug 30, 2024
1 parent 66ae8a5 commit e8ad935
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
*******************************************************************************/
package org.eclipse.swt.browser;

import java.io.*;
import java.net.*;
import java.nio.charset.*;
import java.nio.file.*;
import java.nio.file.Path;
import java.time.*;
import java.util.*;
import java.util.function.*;
Expand All @@ -31,6 +34,18 @@ class Edge extends WebBrowser {
Library.loadLibrary("WebView2Loader");
}

static {
URI absolutePath;
try {
Path tempFile = Files.createTempFile("base", ".html");
absolutePath = tempFile.toUri();
tempFile.toFile().deleteOnExit();
} catch (IOException e) {
absolutePath = URI.create("about:blank");
}
URI_FOR_CUSTOM_TEXT_PAGE = absolutePath;
}

// WebView2Loader.dll compatible version. This is NOT the minimal required version.
static final String SDK_TARGET_VERSION = "99.0.1150.38";

Expand All @@ -43,6 +58,12 @@ class Edge extends WebBrowser {
static final String DATA_DIR_PROP = "org.eclipse.swt.browser.EdgeDataDir";
static final String LANGUAGE_PROP = "org.eclipse.swt.browser.EdgeLanguage";
static final String VERSIONT_PROP = "org.eclipse.swt.browser.EdgeVersion";
/**
* The URI_FOR_CUSTOM_TEXT_PAGE is the path to a temporary html file which is used
* by Edge browser to navigate to for setting html content in the
* DOM of the browser to enable it to load local resources.
*/
private static final URI URI_FOR_CUSTOM_TEXT_PAGE;

private record WebViewEnvironment(ICoreWebView2Environment environment, ArrayList<Edge> instances) {
public WebViewEnvironment(ICoreWebView2Environment environment) {
Expand All @@ -64,6 +85,8 @@ public WebViewEnvironment(ICoreWebView2Environment environment) {
boolean inNewWindow;
HashMap<Long, LocationEvent> navigations = new HashMap<>();

private String html;

static {
NativeClearSessions = () -> {
ICoreWebView2CookieManager manager = getCookieManager();
Expand Down Expand Up @@ -438,6 +461,8 @@ public void create(Composite parent, int style) {
handler.Release();
}

addProgressListener(ProgressListener.completedAdapter(__ -> writeToDefaultPathDOM()));

IUnknown hostDisp = newHostObject(this::handleCallJava);
long[] hostObj = { COM.VT_DISPATCH, hostDisp.getAddress(), 0 }; // VARIANT
webView.AddHostObjectToScript("swt\0".toCharArray(), hostObj);
Expand Down Expand Up @@ -542,7 +567,10 @@ String getJavaCallDeclaration() {

@Override
public String getText() {
return (String)evaluate("return document.documentElement.outerHTML;");
if (html == null) {
return (String)evaluate("return document.documentElement.outerHTML;");
}
return html;
}

@Override
Expand Down Expand Up @@ -907,21 +935,34 @@ public void stop() {
}

@Override
public boolean setText(String html, boolean trusted) {
char[] data = new char[html.length() + 1];
html.getChars(0, html.length(), data, 0);
return webView.NavigateToString(data) == COM.S_OK;
public URI getBaseUri() {
return URI_FOR_CUSTOM_TEXT_PAGE;
}

private void writeToDefaultPathDOM() {
if(html != null && browser.isLocationForCustomText(getUrl())) {
boolean test = jsEnabled;
jsEnabled = true;
execute("document.open(); document.write(`" + html + "`); document.close();");
jsEnabled = test;
this.html = null;
}
}

@Override
public boolean setUrl(String url, String postData, String[] headers) {
public boolean setText(String html, boolean trusted) {
return setWebpageData(URI_FOR_CUSTOM_TEXT_PAGE.toASCIIString(), null, null, html);
}

private boolean setWebpageData(String url, String postData, String[] headers, String html) {
// Feature in WebView2. Partial URLs like "www.example.com" are not accepted.
// Prepend the protocol if it's missing.
if (!url.matches("[a-z][a-z0-9+.-]*:.*")) {
url = "http://" + url;
}
int hr;
char[] pszUrl = stringToWstr(url);
this.html = html;
if (postData != null || headers != null) {
if (environment2 == null || webView_2 == null) {
SWT.error(SWT.ERROR_NOT_IMPLEMENTED, null, " [WebView2 version 88+ is required to set postData and headers]");
Expand Down Expand Up @@ -956,4 +997,9 @@ public boolean setUrl(String url, String postData, String[] headers) {
return hr == COM.S_OK;
}

@Override
public boolean setUrl(String url, String postData, String[] headers) {
return setWebpageData(url, postData, headers, null);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,6 @@ public void test_isSetUrlNotCustomTextUrlAfterSetText() {

@Test
public void test_isFirstSetTextURLStillCustomTextUrlAfterSetUrl() {
assumeFalse("behavior is not (yet) supported by Edge browser", isEdge); // Edge doesn't fire a changed event if the URL is the same as the previous location.
AtomicBoolean changed = new AtomicBoolean(false);
browser.addLocationListener(changedAdapter(event -> changed.set(true)));

Expand Down Expand Up @@ -602,7 +601,6 @@ public void test_isSetUrlNotCustomTextUrl() {

@Test
public void test_isLocationForCustomText() {
assumeFalse("behavior is not (yet) supported by Edge browser", isEdge); // Edge doesn't fire a changed event if the URL is the same as the previous location.
AtomicBoolean changed = new AtomicBoolean(false);
browser.addLocationListener(changedAdapter(e -> changed.set(true)));
shell.open();
Expand Down Expand Up @@ -1126,7 +1124,6 @@ public void test_TitleListener_event() {
assertTrue(errMsg, passed);
}


@Test
public void test_setText() {
String expectedTitle = "Website Title";
Expand Down Expand Up @@ -1233,16 +1230,16 @@ private void validateTitleChanged(String expectedTitle, Runnable browserSetFunc)
browserSetFunc.run();
shell.open();

boolean hasFinished = waitForPassCondition(() -> actualTitle.get().length() != 0
&& !actualTitle.get().contains("about:blank")); // Windows sometimes does 2 loads, one "about:blank", and one actual load.
boolean passed = hasFinished && actualTitle.get().equals(expectedTitle);
boolean passed = waitForPassCondition(() -> actualTitle.get().equals(expectedTitle));
String errMsg = "";
if (!hasFinished)
errMsg = "Test timed out. TitleListener not fired";
else if (!actualTitle.get().equals(expectedTitle)) {
errMsg = "\nExpected title and actual title do not match."
+ "\nExpected: " + expectedTitle
+ "\nActual: " + actualTitle;
if (!passed) {
if (actualTitle.get().length() == 0) {
errMsg = "Test timed out. TitleListener not fired";
} else {
errMsg = "\nExpected title and actual title do not match."
+ "\nExpected: " + expectedTitle
+ "\nActual: " + actualTitle;
}
}
assertTrue(errMsg + testLog.toString(), passed);
}
Expand Down

0 comments on commit e8ad935

Please sign in to comment.