org.chromium.debug.core/src/org/chromium/debug/core/model/JavascriptVmEmbedderFactory.java
changeset 2 e4420d2515f1
equal deleted inserted replaced
1:ef76fc2ac88c 2:e4420d2515f1
       
     1 package org.chromium.debug.core.model;
       
     2 
       
     3 import java.io.IOException;
       
     4 import java.net.InetSocketAddress;
       
     5 import java.net.SocketAddress;
       
     6 import java.text.MessageFormat;
       
     7 import java.util.HashMap;
       
     8 import java.util.Map;
       
     9 
       
    10 import org.chromium.debug.core.ChromiumDebugPlugin;
       
    11 import org.chromium.sdk.Browser;
       
    12 import org.chromium.sdk.BrowserFactory;
       
    13 import org.chromium.sdk.BrowserTab;
       
    14 import org.chromium.sdk.ConnectionLogger;
       
    15 import org.chromium.sdk.DebugEventListener;
       
    16 import org.chromium.sdk.JavascriptVm;
       
    17 import org.chromium.sdk.StandaloneVm;
       
    18 import org.chromium.sdk.TabDebugEventListener;
       
    19 import org.chromium.sdk.UnsupportedVersionException;
       
    20 import org.chromium.sdk.Browser.TabFetcher;
       
    21 import org.eclipse.core.runtime.CoreException;
       
    22 import org.eclipse.core.runtime.Status;
       
    23 
       
    24 
       
    25 public class JavascriptVmEmbedderFactory {
       
    26 
       
    27   private static final String LOCALHOST = "127.0.0.1"; //$NON-NLS-1$
       
    28 
       
    29   public static JavascriptVmEmbedder.ConnectionToRemote connectToChromeDevTools(int port,
       
    30       NamedConnectionLoggerFactory connectionLoggerFactory, final TabSelector tabSelector)
       
    31       throws CoreException {
       
    32 
       
    33     SocketAddress address = new InetSocketAddress(LOCALHOST, port);
       
    34     final Browser browser = browserCache.getOrCreateBrowser(address, connectionLoggerFactory);
       
    35 
       
    36     final TabFetcher tabFetcher;
       
    37     try {
       
    38       tabFetcher = browser.createTabFetcher();
       
    39     } catch (UnsupportedVersionException e) {
       
    40       throw newCoreException(e);
       
    41     } catch (IOException e) {
       
    42       throw newCoreException(e);
       
    43     }
       
    44 
       
    45     return new JavascriptVmEmbedder.ConnectionToRemote() {
       
    46       public JavascriptVmEmbedder.VmConnector selectVm() throws CoreException {
       
    47         Browser.TabConnector targetTabConnector;
       
    48         try {
       
    49           targetTabConnector = tabSelector.selectTab(tabFetcher);
       
    50         } catch (IOException e) {
       
    51           throw newCoreException("Failed to get tabs for debugging", e);
       
    52         }
       
    53         if (targetTabConnector == null) {
       
    54           return null;
       
    55         }
       
    56 
       
    57         return new EmbeddingTabConnector(targetTabConnector);
       
    58       }
       
    59 
       
    60       public void disposeConnection() {
       
    61         tabFetcher.dismiss();
       
    62       }
       
    63     };
       
    64   }
       
    65 
       
    66   private static final class EmbeddingTabConnector implements JavascriptVmEmbedder.VmConnector {
       
    67     private final Browser.TabConnector targetTabConnector;
       
    68 
       
    69     EmbeddingTabConnector(Browser.TabConnector targetTabConnector) {
       
    70       this.targetTabConnector = targetTabConnector;
       
    71     }
       
    72 
       
    73     public JavascriptVmEmbedder attach(final JavascriptVmEmbedder.Listener embedderListener,
       
    74         final DebugEventListener debugEventListener) throws CoreException {
       
    75       TabDebugEventListener tabDebugEventListener = new TabDebugEventListener() {
       
    76         public DebugEventListener getDebugEventListener() {
       
    77           return debugEventListener;
       
    78         }
       
    79         public void closed() {
       
    80           embedderListener.closed();
       
    81         }
       
    82         public void navigated(String newUrl) {
       
    83           embedderListener.reset();
       
    84         }
       
    85       };
       
    86       final BrowserTab browserTab;
       
    87       try {
       
    88         browserTab = targetTabConnector.attach(tabDebugEventListener);
       
    89       } catch (IOException e) {
       
    90         throw newCoreException("Failed to connect to browser tab", e);
       
    91       }
       
    92       return new JavascriptVmEmbedder() {
       
    93         public JavascriptVm getJavascriptVm() {
       
    94           return browserTab;
       
    95         }
       
    96 
       
    97         public String getTargetName() {
       
    98           return Messages.DebugTargetImpl_TargetName;
       
    99         }
       
   100 
       
   101         public String getThreadName() {
       
   102           return browserTab.getUrl();
       
   103         }
       
   104       };
       
   105     }
       
   106   }
       
   107 
       
   108   public static JavascriptVmEmbedder.ConnectionToRemote connectToStandalone(int port,
       
   109       NamedConnectionLoggerFactory connectionLoggerFactory) {
       
   110     SocketAddress address = new InetSocketAddress(LOCALHOST, port);
       
   111     ConnectionLogger connectionLogger =
       
   112       connectionLoggerFactory.createLogger(address.toString());
       
   113     final StandaloneVm standaloneVm = BrowserFactory.getInstance().createStandalone(address,
       
   114         connectionLogger);
       
   115 
       
   116     return new JavascriptVmEmbedder.ConnectionToRemote() {
       
   117       public JavascriptVmEmbedder.VmConnector selectVm() {
       
   118         return new JavascriptVmEmbedder.VmConnector() {
       
   119           public JavascriptVmEmbedder attach(JavascriptVmEmbedder.Listener embedderListener,
       
   120               DebugEventListener debugEventListener)
       
   121               throws CoreException {
       
   122             embedderListener = null;
       
   123             try {
       
   124               standaloneVm.attach(debugEventListener);
       
   125             } catch (IOException e) {
       
   126               throw newCoreException("Failed to connect to V8 VM", e);
       
   127             } catch (UnsupportedVersionException e) {
       
   128               throw newCoreException("Failed to connect to V8 VM", e);
       
   129             }
       
   130             return new JavascriptVmEmbedder() {
       
   131               public JavascriptVm getJavascriptVm() {
       
   132                 return standaloneVm;
       
   133               }
       
   134               public String getTargetName() {
       
   135                 String embedderName = standaloneVm.getEmbedderName();
       
   136                 String vmVersion = standaloneVm.getVmVersion();
       
   137                 String disconnectReason = standaloneVm.getDisconnectReason();
       
   138                 String targetTitle;
       
   139                 if (embedderName == null) {
       
   140                   targetTitle = ""; //$NON-NLS-1$
       
   141                 } else {
       
   142                   targetTitle = MessageFormat.format(
       
   143                       Messages.JavascriptVmEmbedderFactory_TargetName0, embedderName, vmVersion);
       
   144                 }
       
   145                 boolean isAttached = standaloneVm.isAttached();
       
   146                 if (!isAttached) {
       
   147                   String disconnectMessage;
       
   148                   if (disconnectReason == null) {
       
   149                     disconnectMessage = Messages.JavascriptVmEmbedderFactory_Terminated;
       
   150                   } else {
       
   151                     disconnectMessage = MessageFormat.format(
       
   152                         Messages.JavascriptVmEmbedderFactory_TerminatedWithReason,
       
   153                         disconnectReason);
       
   154                   }
       
   155                   targetTitle = "<" + disconnectMessage + "> " + targetTitle;
       
   156                 }
       
   157                 return targetTitle;
       
   158               }
       
   159               public String getThreadName() {
       
   160                 return ""; //$NON-NLS-1$
       
   161               }
       
   162             };
       
   163           }
       
   164         };
       
   165       }
       
   166 
       
   167       public void disposeConnection() {
       
   168         // Nothing to do. We do not take connection for ConnectionToRemote.
       
   169       }
       
   170     };
       
   171   }
       
   172 
       
   173   private static CoreException newCoreException(String message, Throwable cause) {
       
   174     return new CoreException(
       
   175         new Status(Status.ERROR, ChromiumDebugPlugin.PLUGIN_ID, message, cause));
       
   176   }
       
   177   private static CoreException newCoreException(Exception e) {
       
   178     return new CoreException(
       
   179         new Status(Status.ERROR, ChromiumDebugPlugin.PLUGIN_ID,
       
   180             "Failed to connect to the remote browser", e));
       
   181   }
       
   182 
       
   183   private static final BrowserCache browserCache = new BrowserCache();
       
   184   /**
       
   185    * Cache of browser instances.
       
   186    */
       
   187   private static class BrowserCache {
       
   188 
       
   189     /**
       
   190      * Tries to return already created instance of Browser connected to {@code address}
       
   191      * or create new instance.
       
   192      * However, it creates a new instance each time that {@code ConnectionLogger} is not null
       
   193      * (because you cannot add connection logger to existing connection).
       
   194      * @throws CoreException if browser can't be created because of conflict with connectionLogger
       
   195      */
       
   196     synchronized Browser getOrCreateBrowser(final SocketAddress address,
       
   197         final NamedConnectionLoggerFactory connectionLoggerFactory) throws CoreException {
       
   198       Browser result = address2Browser.get(address);
       
   199       if (result == null) {
       
   200 
       
   201         ConnectionLogger.Factory wrappedFactory = new ConnectionLogger.Factory() {
       
   202           public ConnectionLogger newConnectionLogger() {
       
   203             return connectionLoggerFactory.createLogger(address.toString());
       
   204           }
       
   205         };
       
   206         result = createBrowserImpl(address, wrappedFactory);
       
   207 
       
   208         address2Browser.put(address, result);
       
   209       }
       
   210       return result;
       
   211     }
       
   212     private Browser createBrowserImpl(SocketAddress address,
       
   213         ConnectionLogger.Factory connectionLoggerFactory) {
       
   214       return BrowserFactory.getInstance().create(address, connectionLoggerFactory);
       
   215     }
       
   216 
       
   217     private final Map<SocketAddress, Browser> address2Browser =
       
   218         new HashMap<SocketAddress, Browser>();
       
   219   }
       
   220 }