<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to SdkTutorial</title><link>https://sourceforge.net/p/chromedevtools/wiki/SdkTutorial/</link><description>Recent changes to SdkTutorial</description><atom:link href="https://sourceforge.net/p/chromedevtools/wiki/SdkTutorial/feed" rel="self"/><language>en</language><lastBuildDate>Sat, 25 Apr 2015 13:43:51 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/chromedevtools/wiki/SdkTutorial/feed" rel="self" type="application/rss+xml"/><item><title>Discussion for SdkTutorial page</title><link>https://sourceforge.net/p/chromedevtools/wiki/SdkTutorial/</link><description>&lt;div class="markdown_content"&gt;&lt;p&gt;Originally posted by: &lt;a class="" href="http://code.google.com/u/112610498622514470706" rel="nofollow"&gt;peter.ry...@gmail.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Binod80, I suggest that you open a thread in ourmailing list so that we could discuss it there. Peter &lt;/p&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Anonymous</dc:creator><pubDate>Sat, 25 Apr 2015 13:43:51 -0000</pubDate><guid>https://sourceforge.netd783e24f6fadf9723cb75fde61c064f1ddcb59f4</guid></item><item><title>Discussion for SdkTutorial page</title><link>https://sourceforge.net/p/chromedevtools/wiki/SdkTutorial/</link><description>&lt;div class="markdown_content"&gt;&lt;p&gt;Originally posted by: &lt;a class="" href="http://code.google.com/u/101838308314394124329" rel="nofollow"&gt;bino...@gmail.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;How do I go beyond the &lt;/p&gt;
&lt;p&gt;WipBrowserTab&lt;a class="" href="/p/chromedevtools/w/edit/WipBrowserTab"&gt;?&lt;/a&gt; tab = browser.getTabs(backend).get(&amp;lt;choose your tab&amp;gt;).attach(listener); JavascriptVm&lt;a class="" href="/p/chromedevtools/w/edit/JavascriptVm"&gt;?&lt;/a&gt; javascriptVm = tab.getJavascriptVm() &lt;/p&gt;
&lt;p&gt;lines and actually start sending messages such as navigation etc to the browser? I tried to follow along the code, and all I could find was some message classes, but I did not see a documented way of using the debugger extension api methods. I am trying to build up a temporary Webdriver implementation for Chromium Embedded browser that my dev team is using, until the Webdriver full support for CEF is available &lt;/p&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Anonymous</dc:creator><pubDate>Sat, 25 Apr 2015 13:43:51 -0000</pubDate><guid>https://sourceforge.netc8575e7f5caf7e16c7affff2ddd0e1eea90e3bce</guid></item><item><title>SdkTutorial modified by Anonymous</title><link>https://sourceforge.net/p/chromedevtools/wiki/SdkTutorial/</link><description>&lt;div class="markdown_content"&gt;&lt;h1 id="chromedevtools-sdk-tutorial"&gt;ChromeDevTools &lt;a class="" href="/p/chromedevtools/wiki/ChromeDevToolsSdk"&gt;SDK&lt;/a&gt; Tutorial&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;ChromeDevTools Tutorial&lt;ul&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;Javadocs&lt;/li&gt;
&lt;li&gt;Getting started&lt;/li&gt;
&lt;li&gt;Attaching to JavaScript VM&lt;/li&gt;
&lt;li&gt;First steps&lt;/li&gt;
&lt;li&gt;DebugEventListener&lt;/li&gt;
&lt;li&gt;SDK Thread Model&lt;/li&gt;
&lt;li&gt;Blocking and non-blocking method.&lt;/li&gt;
&lt;li&gt;Recurring helper types: SyncCallback , RelayOk etc&lt;/li&gt;
&lt;li&gt;SyncCallback&lt;/li&gt;
&lt;li&gt;RelayOk&lt;/li&gt;
&lt;li&gt;MethodIsBlockingException&lt;/li&gt;
&lt;li&gt;Extensions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;SDK is a standalone Java library. It comes as a set of .jar files or as an Eclipse plugins. As of &lt;a class="" href="/p/chromedevtools/wiki/Release_0_3_0"&gt;0.3.0 version&lt;/a&gt; it supports '&lt;a class="" href="/p/chromedevtools/wiki/ChromeDevToolsProtocol"&gt;DevTools' protocol&lt;/a&gt;, native V8 protocol and &lt;a class="" href="/p/chromedevtools/wiki/WIP"&gt;WebKit Remote Debugging Protocol&lt;/a&gt;. They all are implemented with the common API and differs only in attach interfaces. &lt;/p&gt;
&lt;p&gt;WebKit Remote Debugging Protocol support is a new subproject called here “WIP” (stands historically for WebInspector Protocol). Several versions of WIP implementation are deployed simultaneously in modules called Wip Backends. Each of them corresponds to a particular version of WebKit Remote Debugging Protocol (see details in &lt;a class="" href="/p/chromedevtools/wiki/Release_0_3_0"&gt;release notes&lt;/a&gt;). As of 0.3.0 it is user's responsibility to choose the correct backend. &lt;/p&gt;
&lt;h3 id="javadocs"&gt;Javadocs&lt;/h3&gt;
&lt;p&gt;Generated documentation for the last release is available &lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/index.html" rel="nofollow"&gt;here&lt;/a&gt;. &lt;/p&gt;
&lt;h2 id="getting-started"&gt;Getting started&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Eclipse framework.&lt;/strong&gt; Install "ChromeDevTools SDK" and "ChromeDevTools SDK WIP Backends" features or manually install all org.chromium.sdk&lt;code&gt;*&lt;/code&gt; packages. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Non-Eclipse framework.&lt;/strong&gt; Get all .jar files of SDK. Put them in your classpath. Get WIP backend jars and put &lt;strong&gt;one&lt;/strong&gt; of them in your classpath. (You cannot put all backend jars in classpath, because they have conflicting class names. You can workaround it with several classloaders though.) &lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="attaching-to-javascript-vm"&gt;Attaching to JavaScript VM&lt;/h2&gt;
&lt;p&gt;Attachment is the part where SDK API is protocol-dependent. &lt;/p&gt;
&lt;h4 id="146-devtools-protocol"&gt;1. DevTools Protocol.&lt;/h4&gt;
&lt;p&gt;To connect by '&lt;a class="" href="/p/chromedevtools/wiki/ChromeDevToolsProtocol"&gt;DevTools&lt;/a&gt;' protocol, try the following code: &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="nx"&gt;Browser&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BrowserFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;InetSocketAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;localhost&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9222&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;TabFetcher&lt;/span&gt; &lt;span class="nx"&gt;tabFetcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTabFetcher&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;TabConnector&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;tabList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tabFetcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTabs&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;BrowserTab&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tabList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;choose&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Choose your tab somehow.&lt;/span&gt;
&lt;span class="nx"&gt;JavascriptVm&lt;/span&gt; &lt;span class="nx"&gt;javascriptVm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;tabFetcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dismiss&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// TabFecther is needed to accurately manage single shared connection to Browser.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="246-webkit-remote-debugging-protocol"&gt;2. WebKit Remote Debugging Protocol&lt;/h4&gt;
&lt;p&gt;To connect by &lt;a class="" href="/p/chromedevtools/wiki/WIP"&gt;WebKit Remote Debugging Protocol&lt;/a&gt; use WIP &lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/wip/package-summary.html" rel="nofollow"&gt;package&lt;/a&gt;: &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;WipBrowser&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WipBrowserFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INSTANCE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createBrowser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;InetSocketAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9222&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;WipBackend&lt;/span&gt; &lt;span class="n"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cp"&gt;#ifdef ECLIPSE&lt;/span&gt;
&lt;span class="n"&gt;backend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BackendRegistry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INSTANCE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getBackends&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;choose&lt;/span&gt; &lt;span class="n"&gt;your&lt;/span&gt; &lt;span class="n"&gt;backend&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="cp"&gt;#else&lt;/span&gt;
&lt;span class="n"&gt;WipBackendFactory&lt;/span&gt; &lt;span class="n"&gt;backendFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;WipBackendFactory&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Same class name in each backend .jar &lt;/span&gt;
&lt;span class="n"&gt;backend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;backendFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;span class="n"&gt;WipBrowserTab&lt;/span&gt; &lt;span class="n"&gt;tab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getTabs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;choose&lt;/span&gt; &lt;span class="n"&gt;your&lt;/span&gt; &lt;span class="n"&gt;tab&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;attach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;JavascriptVm&lt;/span&gt; &lt;span class="n"&gt;javascriptVm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getJavascriptVm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="346-standalone-javascript-vm"&gt;3. Standalone JavaScript VM&lt;/h4&gt;
&lt;p&gt;Standalone connection uses native &lt;a class="" href="http://code.google.com/p/v8/wiki/DebuggerProtocol" rel="nofollow"&gt;V8 protocol&lt;/a&gt; that is implemented by DebuggerAgent from V8 library. &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;StandaloneVm standaloneVm =
    BrowserFactory.getInstance().createStandalone(new InetSocketAddress(“localhost”, 9222), null);
standaloneVm.attach(listener);
JavascriptVm javascriptVm =  standaloneVm;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="first-steps"&gt;First steps&lt;/h2&gt;
&lt;p&gt;The API is pretty much straightforward. Once you got &lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/JavascriptVm.html" rel="nofollow"&gt;JavascriptVM&lt;/a&gt; object, you can make various requests. For example you can try to set a breakpoint: &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;javascriptVm.setBreakpoint(new Breakpoint.Target.ScriptName(“index.html”),
    5, // line
    1, // column
    true, null, null, null); // other parameters.
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Hopefully some time later the VM will pause on this breakpoint. Your program should learn about it from the DebugEventListener. &lt;/p&gt;
&lt;h2 id="debugeventlistener"&gt;DebugEventListener&lt;/h2&gt;
&lt;p&gt;What is called simply 'listener' in the previous code snippet is a central part of SDK API: &lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/DebugEventListener.html" rel="nofollow"&gt;DebugEventListener&lt;/a&gt;. That's how your program learns about new events in JavaScript VM. Once you attached, SDK will call your listener on each event in asynchronous manner. &lt;/p&gt;
&lt;p&gt;This asynchronism makes it difficult to simply play around with SDK, because your program becomes essentially multi-threaded. However, for the scripting purposes you can safely ignore most of the events except for 'suspended': &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="n"&gt;SimpleListener&lt;/span&gt; &lt;span class="n"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;DebugEventListener&lt;/span&gt; {
  &lt;span class="n"&gt;DebugContext&lt;/span&gt; &lt;span class="n"&gt;savedDebugContext&lt;/span&gt;;
  &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Semaphore&lt;/span&gt; &lt;span class="n"&gt;semaphore&lt;/span&gt; = &lt;span class="nb"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Semaphore&lt;/span&gt;(&lt;span class="mi"&gt;0&lt;/span&gt;); 
  &lt;span class="nv"&gt;@Override&lt;/span&gt; &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="nb"&gt;void&lt;/span&gt; &lt;span class="n"&gt;suspended&lt;/span&gt;(&lt;span class="n"&gt;DebugContext&lt;/span&gt; &lt;span class="n"&gt;debugContext&lt;/span&gt;) {
    &lt;span class="n"&gt;savedDebugContext&lt;/span&gt; = &lt;span class="n"&gt;debugContext&lt;/span&gt;;
    &lt;span class="n"&gt;semaphore&lt;/span&gt;.&lt;span class="n"&gt;release&lt;/span&gt;();
  }
  &lt;span class="nv"&gt;@Override&lt;/span&gt; &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="nb"&gt;void&lt;/span&gt; &lt;span class="n"&gt;scriptLoaded&lt;/span&gt;(&lt;span class="n"&gt;Script&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt;) {
    // &lt;span class="n"&gt;ignore&lt;/span&gt;
  }
  ...
}
&lt;span class="n"&gt;SimpleListener&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt; = &lt;span class="nb"&gt;new&lt;/span&gt; &lt;span class="n"&gt;SimpleListener&lt;/span&gt;();
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;in the main script: &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="c1"&gt;// Let's patiently wait for our breakpoint to hit.&lt;/span&gt;
&lt;span class="kr"&gt;boolean&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tryAcquire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TimeUnit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HOURS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RuntimeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;Bad&lt;/span&gt; &lt;span class="nx"&gt;luck&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;DebugContext&lt;/span&gt; &lt;span class="nx"&gt;debugContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;savedDebugContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Let's get stacktrace.&lt;/span&gt;
&lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;CallFrame&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;stackTrace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;debugContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getCallFrames&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Now let's iterate over local variables...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="sdk-thread-model"&gt;SDK Thread Model&lt;/h2&gt;
&lt;p&gt;SDK is multi-threaded library. It means that you can call its methods from different threads (with some reasonable limitations of course). &lt;/p&gt;
&lt;p&gt;Also it means that SDK itself will call you asynchronously from its own thread. Each JavascriptVm allocates a dedicated thread called Dispatch Thread. That's where you listener will be called from. The good news is that you can rely on the fact that all events are coming consequently from one thread. The bad news is that you should be careful and return from the callbacks promptly. In particular you cannot call certain blocking methods of API, because it's a certain deadlock (you cannot block the road and waiting for another car to come at the same time). &lt;/p&gt;
&lt;p&gt;All callbacks are called from either the Dispatch Thread or from your own thread (typically in some corner cases). &lt;/p&gt;
&lt;h2 id="blocking-and-non-blocking-method"&gt;Blocking and non-blocking method.&lt;/h2&gt;
&lt;p&gt;There are methods in API that work completely locally. For example &lt;code&gt;JavascriptVm.getVersion()&lt;/code&gt; will simply return a field. Other methods create requests, send them over wire to JavaScript VM and wait for the response that should (hopefully) come. This latter kind of methods could be implemented in 2 styles. In SDK you will find example of both styles: &lt;/p&gt;
&lt;p&gt;1. &lt;strong&gt;Blocking (Synchronous).&lt;/strong&gt; The method conveniently returns result to caller. For example &lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/JsObject.html#getProperties()" rel="nofollow"&gt;JsObject.getProperties()&lt;/a&gt; works like this. What may be inconvenient is that you have to wait for a result, which means that your thread is blocked for the time of entire operation. So several simultaneous operations you will need several threads. Plus you cannot call this methods from SDK callbacks and listeners, because you would stop the Dispatch Thread forever. &lt;/p&gt;
&lt;p&gt;2. &lt;strong&gt;Asynchronous (Non-blocking).&lt;/strong&gt; The method doesn't return result. Instead it starts work in some way (for example sends the corresponding request) and returns control to you. You have to provide a callback that will be notified some time in the future when result is there. This is more flexible comparing to Blocking approach, but is obviously less useful. E.g. see &lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/JavascriptVm.html#listBreakpoints(org.chromium.sdk.JavascriptVm.ListBreakpointsCallback,%20org.chromium.sdk.SyncCallback)" rel="nofollow"&gt;JavascriptVm.listBreakpoints&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;SDK combines both approaches optimized for the typical use cases: some methods are blocking, some asynchronous. Some methods come in 2 styles, like in &lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/JsEvaluateContext.html" rel="nofollow"&gt;JsEvaluateContext&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Some methods are blocking, but they still prefer to pass a result to callback. The possible reasons for this are: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;callback can accept both error and result, while (in Java) method can return only 1 type; &lt;/li&gt;
&lt;li&gt;SDK lets callback examine the result, holding all possible changes for the time of method work. &lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="recurring-helper-types-synccallback-relayok-etc"&gt;Recurring helper types: SyncCallback, RelayOk etc&lt;/h2&gt;
&lt;p&gt;There are certain patterns how methods are written in SDK API. All blocking methods throw &lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/util/MethodIsBlockingException.html" rel="nofollow"&gt;MethodIsBlockingException&lt;/a&gt;. All asynchronous methods return &lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/RelayOk.html" rel="nofollow"&gt;RelayOk&lt;/a&gt; and accept &lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/SyncCallback.html" rel="nofollow"&gt;SyncCallback&lt;/a&gt; parameter. In the first approach these types could be safely ignored. &lt;/p&gt;
&lt;p&gt;They are here to help writing more safe program. Java is a pretty safe language, however dealocks (and infinite loops) still remain an actual problem. There are 2 typical cases where you can get a deadlock with SDK: calling a blocking method from a callback and waiting for a callback that nobody's going to call. &lt;/p&gt;
&lt;h3 id="synccallback"&gt;SyncCallback&lt;/h3&gt;
&lt;p&gt;All asynchronous methods accept 2 callbacks. One is "logical", second one is "secure". It resembles try/finally structure, but for callbacks. The simple but vital actions should go into SyncCallback. It is guaranteed to be called one time when asynchronous operation finished either normally or with a failure. SyncCallback suits well for semaphore releasing and for resource deallocations. "Logical" callback is called first. It processes data, passes it into other callbacks and does other complex things. It's ok if it fails and strictly speaking SDK may also fail to call it (if something went wrong). &lt;/p&gt;
&lt;p&gt;There is a default implementation of SyncCallback that allows other thread to wait until callback is invoked: &lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/CallbackSemaphore.html" rel="nofollow"&gt;CallbackSemaphore&lt;/a&gt;. See how you can call asynchronous method &lt;code&gt;setBreakpoint&lt;/code&gt; and wait until it finishes. &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="nt"&gt;class&lt;/span&gt; &lt;span class="nt"&gt;LogicCallback&lt;/span&gt; &lt;span class="nt"&gt;implements&lt;/span&gt; &lt;span class="nt"&gt;BreakpointCallback&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Breakpoint&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;Override&lt;/span&gt; &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;void&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Breakpoint&lt;/span&gt; &lt;span class="n"&gt;breakpoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;breakpoint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;@Override&lt;/span&gt; &lt;span class="nt"&gt;public&lt;/span&gt; &lt;span class="nt"&gt;void&lt;/span&gt; &lt;span class="nt"&gt;failure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;String&lt;/span&gt; &lt;span class="nt"&gt;errorMessage&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;System&lt;/span&gt;&lt;span class="nc"&gt;.out.println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nt"&gt;Problem&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nt"&gt;errorMessage&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;LogicCallback&lt;/span&gt; &lt;span class="nt"&gt;callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;new&lt;/span&gt; &lt;span class="nt"&gt;LogicCallback&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;SyncCallback&lt;/span&gt; &lt;span class="nt"&gt;syncCallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;new&lt;/span&gt; &lt;span class="nt"&gt;CallbackSemaphore&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;RelayOk&lt;/span&gt; &lt;span class="nt"&gt;relayOk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;javascriptVm&lt;/span&gt;&lt;span class="nc"&gt;.setBreakpoint&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;new&lt;/span&gt; &lt;span class="nt"&gt;Breakpoint&lt;/span&gt;&lt;span class="nc"&gt;.Target.ScriptName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nt"&gt;index&lt;/span&gt;&lt;span class="nc"&gt;.html&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
    &lt;span class="nt"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;5&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;callback&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;syncCallback&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;Wait&lt;/span&gt; &lt;span class="nt"&gt;when&lt;/span&gt; &lt;span class="nt"&gt;for&lt;/span&gt; &lt;span class="nt"&gt;operation&lt;/span&gt; &lt;span class="nt"&gt;to&lt;/span&gt; &lt;span class="nt"&gt;finish&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="nt"&gt;syncCallback&lt;/span&gt;&lt;span class="nc"&gt;.acquireDefault&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;relayOk&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;Breakpoint&lt;/span&gt; &lt;span class="nt"&gt;createdBreakpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;callback&lt;/span&gt;&lt;span class="nc"&gt;.result&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="relayok"&gt;RelayOk&lt;/h3&gt;
&lt;p&gt;This a 'symbolic' type. It helps to track how asynchronous methods 'promises' to call SyncCallback. Initially all asynchronous methods returned &lt;code&gt;void&lt;/code&gt;. However the following incorrect code could easily be written with &lt;code&gt;void&lt;/code&gt; return type: &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;if (paramList.isEmpty()) {
  return;  // Hey, someone is waiting on SyncCallback, you promised to call it sooner or later.
} 
sendRequest(new Request(paramList), syncCallback);
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Also note in the snippet about SyncCallback how method acquireDefault doesn't let you forget to call asynchronous method first because of RelayOk symbolic value. &lt;/p&gt;
&lt;h3 id="methodisblockingexception"&gt;MethodIsBlockingException&lt;/h3&gt;
&lt;p&gt;This symbolic exception annotates all blocking methods in SDK. Tracking blocking methods is important, because you mustn't call them from callbacks. By default Java doesn't pay an attention to this exception, because it is unchecked (i.e. &lt;code&gt;extends RuntimeException&lt;/code&gt;). But if you manage to make it checked (edit sources or create a new class in IDE that override one from the jar file), the IDE and compiler would make you track this symbolic exception in your code. This way you would see where you actually call a blocking method even indirectly. &lt;/p&gt;
&lt;p&gt;Hint. You don't have to annotate all your program. At any point where you want to stop tracking a call chain, simply put a symbolic try/catch (this is cheap): &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;try {
  prepareAllProperties();
} catch (MethodIsBlockingException e) {
  // It's ok to call blocking code from here, because ...
}
&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="extensions"&gt;Extensions&lt;/h2&gt;
&lt;p&gt;Some features of SDK are optional. Depending on backend version or JavaScript VM version they may or may not be available. &lt;/p&gt;
&lt;p&gt;As of 0.3.0 there are following API extensions: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;'&lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/BreakpointTypeExtension.ScriptRegExpSupport.html" rel="nofollow"&gt;regexp' breakpoint target type&lt;/a&gt; (works everywhere except old V8 versions) &lt;/li&gt;
&lt;li&gt;'&lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/BreakpointTypeExtension.FunctionSupport.html" rel="nofollow"&gt;function' breakpoint target type&lt;/a&gt; (doesn't work in WIP) &lt;/li&gt;
&lt;li&gt;&lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/IgnoreCountBreakpointExtension.html" rel="nofollow"&gt;breakpoint 'ignore count' property&lt;/a&gt; (doesn't work in WIP) &lt;/li&gt;
&lt;li&gt;&lt;a class="" href="http://chromedevtools.googlecode.com/svn/trunk/plugins/org.chromium.sdk/javadocs/org/chromium/sdk/wip/EvaluateToMappingExtension.html" rel="nofollow"&gt;evaluate with 'target mapping' parameter&lt;/a&gt; (WIP only) &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All extensions are designed: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;to be fully separate from the standard API; &lt;/li&gt;
&lt;li&gt;as objects that are available as early as possible; for example IgnoreCountBreakpointExtension is available from JavascriptVM interface; this way you can prepare to 'ignore count' not being available (e.g. disable UI) before any breakpoint is actually created. &lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Anonymous</dc:creator><pubDate>Sat, 25 Apr 2015 13:43:51 -0000</pubDate><guid>https://sourceforge.netfc8b9670cb0246d8de81871b2c0e8f1ccfa82ebe</guid></item></channel></rss>