-
Notifications
You must be signed in to change notification settings - Fork 147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle local resource references in Edge#setText() #1395
Handle local resource references in Edge#setText() #1395
Conversation
Isn't this the same as #1378? |
9bfd013
to
daebdd1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't have time to test this again but the overall state of the code LGTM. All my comments from #1378 have been addressed and I see them addressed in this PR too.
I can't approve it though since I haven't had time to properly test this new PR and I can't know for sure if splitting the commits of #1378 had some side-effects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, it's great to see that with this fix Edge's setText()
works properly, so even Javadoc, Java element information, Welcome page etc. can be displayed.
My central concern is about the introduction of a public BASE_URI
as a replacement for the generally used about:blank
. Conceptually, I would like to have this hidden as an implementation detail of the browser. I.e., there should not be any magic URL used when setting custom contents via setText()
against which consumers compare (like they now do for about:blank
. From what I have seen so far, the information demand of consumers is to decide whether a page with some custom text is shown. To this end, the browser could provide an according interface providing the required information while hiding how this is implemented for a specific browser. For WebKit and IE that might be done with the about:blank
page, Edge might use a custom base URL, and that implementation detail may even be changed as desired or required without affecting consumers relying on that interface.
As a concrete proposal, some additional method for Browser
like an isLocationForCustomText(String location)
(may be called differently, accept a URL instead, ...) could be provided. This method could either match the provided location for some known strings (about:blank
, BASE_URI, starting with data:
or the like) or delegate the decision to the used WebBrowser
so that only the specific location for that browser implementation is considered.
Another benefit of that solution is that we could add such a method in a separate PR, adapt the known consumers to use that method, and then have this PR merged for adapting the Edge browser. That would avoid that merging this PR in the current state, Java element links in JDT would be broken when using Edge as the default browser until JDT is adapted to also match the new magic BASE_URI: https://github.com/eclipse-jdt/eclipse.jdt.ui/blob/caf5a4b29592e6d3911a2491aa6b811b52d66f74/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLinks.java#L599-L611
9e4e496
to
b4a5141
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to validate this solution, I've read the according Microsoft documentation for these use cases of Edge browser: https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/working-with-local-content
With that information, this still seems to be a proper solution for the problem. I only have some minor comments left.
....swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java
Outdated
Show resolved
Hide resolved
bd25311
to
1d273bc
Compare
8671b46
to
464a5d8
Compare
AFAIK all the other browsers consistently use That means:
And there are many many code pieces where 'about:blank' is checked. With this approach this would change, meaning that all consumers would have to adapt and do something like -if ("about:blank".equals(event.location)) {
+if (browser.isLocationForCustomText(event.location)) { I was wondering: To maximize compatibility, could we instead hide this fact and fake |
Interesting idea. I would expect that we have already considered that, but I am not sure anymore. This would of course also involve the location listeners to be provided with the faked location. @amartya4256, do you have any insights on this?
That's true. For some essential repos, there are already follow-up PRs to do this:
In my opinion, independent of whether the proposal of faking the URL behavior works or not, this adaptation should be done. Currently, all consumers rely on the usage of magic values, which will forever be unchangeable. Hiding this behind an API improves the design and makes the behavior exchangeable. |
I agree with @HeikoKlare. The decision to provide an API for this was taken upon the fact that it would abstract away the behaviour of browser, hiding the URLs that clients have to hard code at the moment which in my opinion is a bad practice. It also opens up possibilities for integrating browsers in the future which mgiht have a different behaviour. We can't expect every browser to behave the same, which we saw already between Edge and IE. Also, the way Webkit is implemented, it seems to force itself to comply with how IE behaves (Async to Sync, Open Window events, ABOUT_BLANK url, etc) and that should not be the case. We should have the API for such things where the web browsers can take decisions on their own or execute in their own fashion and provide the appropriate result accordingly. As mentioned, we already have the PRs to adapt the clients to use the API and new PRs would be following up for WebKit's internal usage of this API as well. As an idea, we can also do the same refactoring for IE. |
Maybe one can combine the approach having a constant for |
I agree. That's why I asked whether Sebastian's proposal is feasible, so that with that approach we might achieve an implementation of Edge browser that works with existing client implementations for now, but still provide a path to improve the design, i.e., migrate from comparison against magic value |
It is feasible, but only getUrl would not be enough. All the callbacks in Edge where the event contains a location needs to be validated and mutated if it is a custom text url |
6c0cd82
to
7189709
Compare
bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java
Outdated
Show resolved
Hide resolved
In general this looks good. Also, with this PR merged, my PR #1451 will become easier, since no more of those Regarding hiding the internal URL and exposing
There is one more corner case to consider: The application layer consumers will now only see That means, that this method now also needs to return I have one more general remark: |
Currently,
In my understanding, this file is not used at all. It is just an empty dummy that allows to provide WebView with custom contents of the document to display. The file is never written, so in my opinion it makes sense to share it across all WebView instances. |
bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java
Outdated
Show resolved
Hide resolved
Oh, right, I was confused by the same name of the private method in
Ah, right; we're only tricking Edge into thinking we are dealing with an actual HTML file on disk, but are then still manipulating the DOM via JavaScript. |
39cb207
to
30c745b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see all comments addressed and no outstanding complains with respect to this PR.
In case there are no objections, I plan to merge this by the end of the day to have it available for further testing in tomorrow's I-Build.
30c745b
to
0b067c9
Compare
This contribution allows Edge browser for win32 to serve webpages using setText method where the set html may refer to local resources. about:blank doesn't allow referencing local resources and hence, this contribution uses the URL to a temporary file to navigate to and serve the html allowing references to local resources. The temporary URL is not exposed to the clients and the APIs mimic about:blank in all the places where this URL is used to keep the consistency. contributes to eclipse-platform#213
0b067c9
to
6ab4c66
Compare
This change broke working with the DOM in Consider: public class Demo {
public static void main(String[] args) {
Display display = Display.getDefault();
Shell shell = new Shell();
shell.setLayout(new FillLayout());
Browser browser = new Browser(shell, SWT.EDGE);
browser.setText("""
<html>
<head>
<script src=\"file://c:/test.js\"></script>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>
""");
browser.addProgressListener(ProgressListener.completedAdapter(event -> {
String script = """
var h1s = document.getElementsByTagName("h1");
alert("Found h1s: " + h1s.length);
"""; //$NON-NLS-1$
browser.execute(script);
}));
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
} This should bring up a The debugging tools show:
Changing -execute("document.open(); document.write(`" + lastCustomText + "`); document.close();");
+execute("document.documentElement.innerHTML = `" + lastCustomText + "`;"); fixes the problem |
Separate the internal DOM manipulation from the processing of application code ProgressListeners. Wait until the DOM manipulation is fully processed and only then call the application layer ProgressListeners. Otherwise, the application layer code might not see the full up-to-date DOM. Follow-up on #1395.
Separate the internal DOM manipulation from the processing of application code ProgressListeners. Wait until the DOM manipulation is fully processed and only then call the application layer ProgressListeners. Otherwise, the application layer code might not see the full up-to-date DOM. Follow-up on #1395.
Separate the internal DOM manipulation from the processing of application code ProgressListeners. Wait until the DOM manipulation is fully processed and only then call the application layer ProgressListeners. Otherwise, the application layer code might not see the full up-to-date DOM. Follow-up on #1395.
Separate the internal DOM manipulation from the processing of application code ProgressListeners. Wait until the DOM manipulation is fully processed and only then call the application layer ProgressListeners. Otherwise, the application layer code might not see the full up-to-date DOM. Follow-up on #1395.
Separate the internal DOM manipulation from the processing of application code ProgressListeners. Wait until the DOM manipulation is fully processed and only then call the application layer ProgressListeners. Otherwise, the application layer code might not see the full up-to-date DOM. Follow-up on #1395.
Separate the internal DOM manipulation from the processing of application code ProgressListeners. Wait until the DOM manipulation is fully processed and only then call the application layer ProgressListeners. Otherwise, the application layer code might not see the full up-to-date DOM. Follow-up on #1395.
Separate the internal DOM manipulation from the processing of application code ProgressListeners. Wait until the DOM manipulation is fully processed and only then call the application layer ProgressListeners. Otherwise, the application layer code might not see the full up-to-date DOM. Follow-up on #1395.
Separate the internal DOM manipulation from the processing of application code ProgressListeners. Wait until the DOM manipulation is fully processed and only then call the application layer ProgressListeners. Otherwise, the application layer code might not see the full up-to-date DOM. Follow-up on #1395.
Separate the internal DOM manipulation from the processing of application code ProgressListeners. Wait until the DOM manipulation is fully processed and only then call the application layer ProgressListeners. Otherwise, the application layer code might not see the full up-to-date DOM. Follow-up on eclipse-platform#1395.
This contribution fixes Edge browser for win32 to allow serving webpages using setText method where the source code may refer to local resources.
The problem with setText in the modern browser is that webView2 navigates to a page "about:blank" (which is not the part of the intranet) [reference] and sets the html to the DOM. In case the html contains reference to local resource, the browsers throws error "can't load local resource" because of security reasons. This contribution fixes it by navigating edge to a temporary file created in the temporary folder of the OS and hence allowing it to load the local resources, and then sets the html to the DOM directly.
Note: We only need the file to get a concrete local address instead of "about:local" for setText method. We don't perform any I/O to the file itself.
To test the implementation, you need to set the default browser to Edge. To do it in the source code, change org.eclipse.swt.browser.BrowserFactory.createWebBrowser with the following source code:
return new Edge();
Scope not covered:
contributes to #213