/
README.html
206 lines (203 loc) · 14.4 KB
/
README.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
<!--
~ The MIT License (MIT)
~ <p>
~ Copyright (c) 2018-2020 Vladimir Schneider (https://github.com/vsch)
~ <p>
~ Permission is hereby granted, free of charge, to any person obtaining a copy
~ of this software and associated documentation files (the "Software"), to deal
~ in the Software without restriction, including without limitation the rights
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
~ copies of the Software, and to permit persons to whom the Software is
~ furnished to do so, subject to the following conditions:
~ <p>
~ The above copyright notice and this permission notice shall be included in all
~ copies or substantial portions of the Software.
~ <p>
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
~ SOFTWARE
~
-->
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="layout-fx.css">
<style>
.container { width: 100%; }
</style>
<link rel="stylesheet" href="default-fx.css">
<link rel="stylesheet" href="github-collapse.css">
<title>README.md</title>
</head>
<body>
<div class="container">
<div id="readme" class="boxed-group">
<h3>
<a href="http://github.com/vsch/JavaFx-WebView-Debugger" name="markdown-page" id="markdown-page" class="page-anchor"><span class="bookicon octicon-book"></span>
</a> README.md
</h3>
<article class="markdown-body">
<h1 id="javafx-webview-debugger"><a href="#javafx-webview-debugger" name="javafx-webview-debugger" class="anchor"><span class="octicon octicon-link"></span></a>JavaFX WebView Debugger</h1>
<h5 id="via-websocket-connection-to-google-chrome-dev-tools"><a href="#via-websocket-connection-to-google-chrome-dev-tools" name="via-websocket-connection-to-google-chrome-dev-tools" class="anchor"><span class="octicon octicon-link"></span></a>Via WebSocket connection to Google Chrome Dev Tools</h5>
<p><a href="https://travis-ci.org/vsch/Javafx-WebView-Debugger"><img src="https://travis-ci.org/vsch/Javafx-WebView-Debugger.svg?branch=master" alt="Build status" /></a>
<a href="https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.vladsch.javafx-webview-debugger%22" class="local-only" title=" **Target file not on GitHub. Link will only resolve locally.**"><img src="https://img.shields.io/maven-central/v/com.vladsch.javafx-webview-debugger/javafx-webview-debugger.svg" alt="Maven Central status" /></a></p>
<p>Here is a teaser screenshot of dev tools running with JavaFX WebView, showing off the console
logging from scripts, with caller location for one click navigation to source:</p>
<p><img src="DevTools.png" alt="DevTools" /></p>
<h3 id="requirements"><a href="#requirements" name="requirements" class="anchor"><span class="octicon octicon-link"></span></a>Requirements</h3>
<ul>
<li>Java 8 (not tested with 9)</li>
<li>The project is on Maven: <code>com.vladsch.javafx-webview-debugger</code></li>
<li>dependencies:
<ul>
<li><code>org.glassfish:javax.json</code></li>
<li><code>org.jetbrains.annotations</code></li>
<li><code>com.vladsch.boxed-json</code></li>
<li><code>org.apache.log4j</code></li>
</ul>
</li>
</ul>
<h3 id="quick-start"><a href="#quick-start" name="quick-start" class="anchor"><span class="octicon octicon-link"></span></a>Quick Start</h3>
<p>Take a look at the <a href="https://github.com/vsch/WebViewDebugSample">Web View Debug Sample</a> application for a working example. You can play with
it and debug the embedded scripts before deciding whether you want to instrument your own
application for Chrome Dev Tools debugging.</p>
<p>For Maven:</p>
<pre><code class="xml"><dependency>
<groupId>com.vladsch.javafx-webview-debugger</groupId>
<artifactId>javafx-webview-debugger</artifactId>
<version>0.5.6</version>
</dependency>
</code></pre>
<h3 id="credit-where-credit-is-due"><a href="#credit-where-credit-is-due" name="credit-where-credit-is-due" class="anchor"><span class="octicon octicon-link"></span></a>Credit where credit is due</h3>
<p>I found out about the possibility of having any debugger for JavaFX WebView in
<a href="https://github.com/mohamnag/javafx_webview_debugger">mohamnag/javafx_webview_debugger</a>. That implementation in turn was based on the solution found
by Bosko Popovic.</p>
<p>I am grateful to Bosko Popovic for discovering the availability and to Mohammad Naghavi creating
an implementation of the solution. Without their original effort this solution would not be
possible.</p>
<h3 id="finally-real-debugging-for-javafx-webview"><a href="#finally-real-debugging-for-javafx-webview" name="finally-real-debugging-for-javafx-webview" class="anchor"><span class="octicon octicon-link"></span></a>Finally real debugging for JavaFX WebView</h3>
<p>Working with JavaScript code in WebView was a debugging nightmare that I tried to avoid. My
excitement about having a real debugger diminished when I saw how little was available with a
bare-bones implementation due to WebView’s lack of a full Dev Tools protocol. The console did
not work and none of the console api calls from scripts made it to the Dev Tools console. No
commandLineAPI for the same reason. Having to use logs for these is last century.</p>
<p>A proxy to get between Chrome Dev Tools and WebView solved most of the WebView debugging
protocol limitations. It also allowed to prevent conditions that caused WebView to crash and
bring the rest of the application with it. I don’t mean a Java exception. I mean a core dump and
sudden exit of the application. For my use cases this is not an acceptable option.</p>
<p>Now the console in the debugger works as expected, with completions, evaluations and console
logging from scripts, stepping in/out/over, break points, caller location one click away and
initialization debugging to allow pausing of the script before the JSBridge to JavaScript is
established. Having a real debugger makes minced meat of script initialization issues.</p>
<p>The current version is the the code I use in my <a href="http://www.jetbrains.com/idea">IntelliJ IDEA</a> plugin, <a href="http://vladsch.com/product/markdown-navigator">Markdown Navigator</a>.
With any functionality specific to my project added using the API of this library.</p>
<p>If you are working with JavaFX WebView scripts you need this functionality ASAP. Bugs that took
hours to figure out now take literally seconds to minutes without any recompilation or major log
reading. Take a look at the <a href="https://github.com/vsch/WebViewDebugSample">Web View Debug Sample</a> application to see what you get and how to
add it to your code.</p>
<h4 id="what-is-working"><a href="#what-is-working" name="what-is-working" class="anchor"><span class="octicon octicon-link"></span></a>What is working</h4>
<ul>
<li>all <code>console</code> functions: <code>assert</code>, <code>clear</code>, <code>count</code>, <code>debug</code>, <code>dir</code>, <code>dirxml</code>, <code>error</code>,
<code>exception</code>, <code>group</code>, <code>groupCollapsed</code>, <code>groupEnd</code>, <code>info</code>, <code>log</code>, <code>profile</code>, <code>profileEnd</code>,
<code>select</code>, <code>table</code>, <code>time</code>, <code>timeEnd</code>, <code>trace</code>, <code>warn</code>. With added extras to output to the Java
console: <code>print</code>, <code>println</code></li>
<li>all commandLineAPI functions implemented by JavaFX WebView: <code>$</code>, <code>$$</code>, <code>$x</code>, <code>dir</code>, <code>dirxml</code>,
<code>keys</code>, <code>values</code>, <code>profile</code>, <code>profileEnd</code>, <code>table</code>, <code>monitorEvents</code>, <code>unmonitorEvents</code>,
<code>inspect</code>, <code>copy</code>, <code>clear</code>, <code>getEventListeners</code>, <code>$0</code>, <code>$_</code>, <code>$exception</code>
<ul>
<li>Some limitations do exist because <code>Runtime.evaluate</code> is simulated. Otherwise, there was no
way to get the stack frame for any console log calls that would result from the evaluation.
Mainly, it caused the application to exit with a core dump more often than not. I figured it
was more important to have the caller location for console logs than for the commandLineAPI
calls.</li>
</ul>
</li>
<li>No longer necessary to instrument the page to have <code>JSBridge</code> support code working. Only
requires a page reload from WebView or Dev Tools.</li>
<li>Ability to debug break on page reload to debug scripts running before JSBridge is established</li>
<li>Safely stop debug session from Dev Tools or WebView side. This should have been easy but
turned out to be the hardest part to solve. Any wrong moves or dangling references would bring
down the whole application with a core-dump message.</li>
</ul>
<h4 id="in-progress"><a href="#in-progress" name="in-progress" class="anchor"><span class="octicon octicon-link"></span></a>In progress</h4>
<ul>
<li>highlighting of elements hovered over in the element tree of dev tools. Node resolution is
working. Kludged highlighting by setting a class on the element with translucent background
color defined instead of using an overlay element or the proper margin, borders, padding and
container size.</li>
</ul>
<h4 id="not-done"><a href="#not-done" name="not-done" class="anchor"><span class="octicon octicon-link"></span></a>Not done</h4>
<ul>
<li>Debugger paused overlay</li>
</ul>
<h4 id="probably-not-doable"><a href="#probably-not-doable" name="probably-not-doable" class="anchor"><span class="octicon octicon-link"></span></a>Probably not doable</h4>
<ul>
<li>profiling not available. Don’t know enough about what’s needed to say whether it is doable.</li>
</ul>
<h3 id="jsbridge-provided-debugging-support"><a href="#jsbridge-provided-debugging-support" name="jsbridge-provided-debugging-support" class="anchor"><span class="octicon octicon-link"></span></a>JSBridge Provided Debugging Support</h3>
<p>The missing functionality from the WebView debugger is implemented via a proxy that gets between
chrome dev tools and the debugger to fill in the blanks and to massage the conversation allowing
chrome dev tools to do their magic.</p>
<p>For this to work, some JavaScript and the <code>JSBridge</code> instance need to work together to provide
the essential glue. The implementation is confined to the initialization script. Most other
scripts can be oblivious to whether the <code>JSBridge</code> is established or not. Console log api is one
of the missing pieces in the WebView debugger, any console log calls made before the <code>JSBridge</code>
to Java is established <strong>will not have caller identification</strong> and will instead point to the
initialization code that played back the cached log calls generated before the connection was
established.</p>
<p>The <code>JSBridge</code> implementation also provides a mechanism for data persistence between page
reloads. It is generic enough if all the data you need to persist can be <code>JSON.stringify'd</code>
because the implementation does a call back to the WebView engine to serialize the passed in
state argument. This text will need to be inserted into the generated HTML page to allow scripts
access to their state before the <code>JSBridge</code> is hooked in. Scripts can also register for a
callback when the <code>JSBridge</code> is established.</p>
<p>The down side of the latter approach, is by the time this happens, WebView has already visually
updated the page. If the script is responsible for any visual modification of the page based on
persisted state then the unmodified version will flash on screen before the script is run.</p>
<p>Allowing scripts to get their state before <code>JSBridge</code> is established makes for smoother page
refresh.</p>
<h3 id="getting-full-featured-debugging"><a href="#getting-full-featured-debugging" name="getting-full-featured-debugging" class="anchor"><span class="octicon octicon-link"></span></a>Getting Full Featured Debugging</h3>
<p>This requires a little support from the Java to JavaScript bridge and the debug proxy. See the
<a href="https://github.com/vsch/WebViewDebugSample">Web View Debug Sample</a> application for an example.</p>
<p>I have not tried it with Java 9, and suspect that the debug protocol has changed and the proxy
may not work with it without modifications.</p>
<p>However, these are the instructions to compile for Java 9 WebView debugger access as given by
<a href="https://github.com/mohamnag/javafx_webview_debugger">mohamnag/javafx_webview_debugger</a>.</p>
<p><code>WebEngine.impl_getDebugger()</code> is an internal API and is subject to change which is happened in
Java 9. So if you are using Java 9, you need to use following code instead to start the debug
server:</p>
<pre><code class="java">Class webEngineClazz = WebEngine.class;
Field debuggerField = webEngineClazz.getDeclaredField("debugger");
debuggerField.setAccessible(true);
Debugger debugger = (Debugger) debuggerField.get(webView.getEngine());
DevToolsDebuggerServer devToolsDebuggerServer.startDebugServer(debugger, 51742, 1);
</code></pre>
<p>For this to work, you have to pass this parameter to Java compiler: <code>--add-exports javafx.web/com.sun.javafx.scene.web=ALL-UNNAMED</code>.</p>
<p>As examples, this can be done for Maven as follows:</p>
<pre><code class="xml"><plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>9</source>
<target>9</target>
<compilerArgs>
<arg>--add-exports</arg>
<arg>javafx.web/com.sun.javafx.scene.web=ALL-UNNAMED</arg>
</compilerArgs>
</configuration>
</plugin>
</code></pre>
<p>or for IntelliJ under <strong>Additional command line parameters</strong> in <strong>Preferences > Build,
Execution, Deployment > Compiler > Java Compiler</strong>.</p>
</article>
</div>
</div>
<script src="github-collapse-markdown.js"></script>
<script src="scroll-preview.js"></script>
</body>
</html>