org.chromium.debug.core/src/org/chromium/debug/core/model/JavascriptVmEmbedderFactory.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/JavascriptVmEmbedderFactory.java Wed Dec 23 17:13:18 2009 -0800
@@ -0,0 +1,220 @@
+package org.chromium.debug.core.model;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.chromium.debug.core.ChromiumDebugPlugin;
+import org.chromium.sdk.Browser;
+import org.chromium.sdk.BrowserFactory;
+import org.chromium.sdk.BrowserTab;
+import org.chromium.sdk.ConnectionLogger;
+import org.chromium.sdk.DebugEventListener;
+import org.chromium.sdk.JavascriptVm;
+import org.chromium.sdk.StandaloneVm;
+import org.chromium.sdk.TabDebugEventListener;
+import org.chromium.sdk.UnsupportedVersionException;
+import org.chromium.sdk.Browser.TabFetcher;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Status;
+
+
+public class JavascriptVmEmbedderFactory {
+
+ private static final String LOCALHOST = "127.0.0.1"; //$NON-NLS-1$
+
+ public static JavascriptVmEmbedder.ConnectionToRemote connectToChromeDevTools(int port,
+ NamedConnectionLoggerFactory connectionLoggerFactory, final TabSelector tabSelector)
+ throws CoreException {
+
+ SocketAddress address = new InetSocketAddress(LOCALHOST, port);
+ final Browser browser = browserCache.getOrCreateBrowser(address, connectionLoggerFactory);
+
+ final TabFetcher tabFetcher;
+ try {
+ tabFetcher = browser.createTabFetcher();
+ } catch (UnsupportedVersionException e) {
+ throw newCoreException(e);
+ } catch (IOException e) {
+ throw newCoreException(e);
+ }
+
+ return new JavascriptVmEmbedder.ConnectionToRemote() {
+ public JavascriptVmEmbedder.VmConnector selectVm() throws CoreException {
+ Browser.TabConnector targetTabConnector;
+ try {
+ targetTabConnector = tabSelector.selectTab(tabFetcher);
+ } catch (IOException e) {
+ throw newCoreException("Failed to get tabs for debugging", e);
+ }
+ if (targetTabConnector == null) {
+ return null;
+ }
+
+ return new EmbeddingTabConnector(targetTabConnector);
+ }
+
+ public void disposeConnection() {
+ tabFetcher.dismiss();
+ }
+ };
+ }
+
+ private static final class EmbeddingTabConnector implements JavascriptVmEmbedder.VmConnector {
+ private final Browser.TabConnector targetTabConnector;
+
+ EmbeddingTabConnector(Browser.TabConnector targetTabConnector) {
+ this.targetTabConnector = targetTabConnector;
+ }
+
+ public JavascriptVmEmbedder attach(final JavascriptVmEmbedder.Listener embedderListener,
+ final DebugEventListener debugEventListener) throws CoreException {
+ TabDebugEventListener tabDebugEventListener = new TabDebugEventListener() {
+ public DebugEventListener getDebugEventListener() {
+ return debugEventListener;
+ }
+ public void closed() {
+ embedderListener.closed();
+ }
+ public void navigated(String newUrl) {
+ embedderListener.reset();
+ }
+ };
+ final BrowserTab browserTab;
+ try {
+ browserTab = targetTabConnector.attach(tabDebugEventListener);
+ } catch (IOException e) {
+ throw newCoreException("Failed to connect to browser tab", e);
+ }
+ return new JavascriptVmEmbedder() {
+ public JavascriptVm getJavascriptVm() {
+ return browserTab;
+ }
+
+ public String getTargetName() {
+ return Messages.DebugTargetImpl_TargetName;
+ }
+
+ public String getThreadName() {
+ return browserTab.getUrl();
+ }
+ };
+ }
+ }
+
+ public static JavascriptVmEmbedder.ConnectionToRemote connectToStandalone(int port,
+ NamedConnectionLoggerFactory connectionLoggerFactory) {
+ SocketAddress address = new InetSocketAddress(LOCALHOST, port);
+ ConnectionLogger connectionLogger =
+ connectionLoggerFactory.createLogger(address.toString());
+ final StandaloneVm standaloneVm = BrowserFactory.getInstance().createStandalone(address,
+ connectionLogger);
+
+ return new JavascriptVmEmbedder.ConnectionToRemote() {
+ public JavascriptVmEmbedder.VmConnector selectVm() {
+ return new JavascriptVmEmbedder.VmConnector() {
+ public JavascriptVmEmbedder attach(JavascriptVmEmbedder.Listener embedderListener,
+ DebugEventListener debugEventListener)
+ throws CoreException {
+ embedderListener = null;
+ try {
+ standaloneVm.attach(debugEventListener);
+ } catch (IOException e) {
+ throw newCoreException("Failed to connect to V8 VM", e);
+ } catch (UnsupportedVersionException e) {
+ throw newCoreException("Failed to connect to V8 VM", e);
+ }
+ return new JavascriptVmEmbedder() {
+ public JavascriptVm getJavascriptVm() {
+ return standaloneVm;
+ }
+ public String getTargetName() {
+ String embedderName = standaloneVm.getEmbedderName();
+ String vmVersion = standaloneVm.getVmVersion();
+ String disconnectReason = standaloneVm.getDisconnectReason();
+ String targetTitle;
+ if (embedderName == null) {
+ targetTitle = ""; //$NON-NLS-1$
+ } else {
+ targetTitle = MessageFormat.format(
+ Messages.JavascriptVmEmbedderFactory_TargetName0, embedderName, vmVersion);
+ }
+ boolean isAttached = standaloneVm.isAttached();
+ if (!isAttached) {
+ String disconnectMessage;
+ if (disconnectReason == null) {
+ disconnectMessage = Messages.JavascriptVmEmbedderFactory_Terminated;
+ } else {
+ disconnectMessage = MessageFormat.format(
+ Messages.JavascriptVmEmbedderFactory_TerminatedWithReason,
+ disconnectReason);
+ }
+ targetTitle = "<" + disconnectMessage + "> " + targetTitle;
+ }
+ return targetTitle;
+ }
+ public String getThreadName() {
+ return ""; //$NON-NLS-1$
+ }
+ };
+ }
+ };
+ }
+
+ public void disposeConnection() {
+ // Nothing to do. We do not take connection for ConnectionToRemote.
+ }
+ };
+ }
+
+ private static CoreException newCoreException(String message, Throwable cause) {
+ return new CoreException(
+ new Status(Status.ERROR, ChromiumDebugPlugin.PLUGIN_ID, message, cause));
+ }
+ private static CoreException newCoreException(Exception e) {
+ return new CoreException(
+ new Status(Status.ERROR, ChromiumDebugPlugin.PLUGIN_ID,
+ "Failed to connect to the remote browser", e));
+ }
+
+ private static final BrowserCache browserCache = new BrowserCache();
+ /**
+ * Cache of browser instances.
+ */
+ private static class BrowserCache {
+
+ /**
+ * Tries to return already created instance of Browser connected to {@code address}
+ * or create new instance.
+ * However, it creates a new instance each time that {@code ConnectionLogger} is not null
+ * (because you cannot add connection logger to existing connection).
+ * @throws CoreException if browser can't be created because of conflict with connectionLogger
+ */
+ synchronized Browser getOrCreateBrowser(final SocketAddress address,
+ final NamedConnectionLoggerFactory connectionLoggerFactory) throws CoreException {
+ Browser result = address2Browser.get(address);
+ if (result == null) {
+
+ ConnectionLogger.Factory wrappedFactory = new ConnectionLogger.Factory() {
+ public ConnectionLogger newConnectionLogger() {
+ return connectionLoggerFactory.createLogger(address.toString());
+ }
+ };
+ result = createBrowserImpl(address, wrappedFactory);
+
+ address2Browser.put(address, result);
+ }
+ return result;
+ }
+ private Browser createBrowserImpl(SocketAddress address,
+ ConnectionLogger.Factory connectionLoggerFactory) {
+ return BrowserFactory.getInstance().create(address, connectionLoggerFactory);
+ }
+
+ private final Map<SocketAddress, Browser> address2Browser =
+ new HashMap<SocketAddress, Browser>();
+ }
+}