plugins/org.symbian.tools.tmw.debug/src/org/symbian/tools/tmw/debug/internal/launch/ChromeInstancesManager.java
changeset 471 06589bf52fa7
child 472 bd9f2d7c64a6
equal deleted inserted replaced
470:d4809db37847 471:06589bf52fa7
       
     1 /*******************************************************************************
       
     2  * Copyright (c) 2009 Symbian Foundation and/or its subsidiary(-ies).
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of the License "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Symbian Foundation - initial contribution.
       
    11  * Contributors:
       
    12  * Description:
       
    13  * Overview:
       
    14  * Details:
       
    15  * Platforms/Drives/Compatibility:
       
    16  * Assumptions/Requirement/Pre-requisites:
       
    17  * Failures and causes:
       
    18  *******************************************************************************/
       
    19 package org.symbian.tools.tmw.debug.internal.launch;
       
    20 
       
    21 import java.io.File;
       
    22 import java.io.FileFilter;
       
    23 import java.io.IOException;
       
    24 import java.text.MessageFormat;
       
    25 import java.util.Collections;
       
    26 import java.util.HashMap;
       
    27 import java.util.Map;
       
    28 
       
    29 import org.eclipse.core.resources.ResourcesPlugin;
       
    30 import org.eclipse.core.runtime.CoreException;
       
    31 import org.eclipse.core.runtime.IPath;
       
    32 import org.eclipse.core.runtime.IStatus;
       
    33 import org.eclipse.core.runtime.Path;
       
    34 import org.eclipse.core.runtime.Status;
       
    35 import org.symbian.tools.tmw.debug.internal.Activator;
       
    36 import org.symbian.tools.tmw.debug.internal.ChromeDebugUtils;
       
    37 import org.symbian.tools.wrttools.util.CoreUtil;
       
    38 
       
    39 public class ChromeInstancesManager {
       
    40     private static final String[] CHROME_ARGS = { "%s", "--remote-shell-port=%d", // Here we will set port
       
    41             "--user-data-dir=%s", // Here we will set profile folder so user settings have no effect
       
    42             "--disk-cache-dir=%s", // We don't care
       
    43             "--disable-web-security", // Widgets can use network now
       
    44             "--disable-extenions", // Use standard UI, should also improve speed and stability
       
    45             "--activate-on-launch", // Bring to front on Mac
       
    46             "--disable-geolocation", // Use our own Geolocation (needed to emulate Geolocation in phonegap) 
       
    47             "--disable-local-storage", // Disable local storage (needed to emulate Geolocation in phonegap) 
       
    48             "--disable-session-storage", // Disable local storage (needed to emulate Geolocation in phonegap) 
       
    49             "--no-default-browser-check", // Our users don't need this nagging
       
    50             "--disable-hang-monitor", // Fix for Bug 2682 - The debugger should disable "unresponsive" error message from chrome
       
    51             "--no-first-run", // We don't care
       
    52             "--app=%s" // Here we will have widget URI as --app argument
       
    53     };
       
    54     private final Map<Object, Process> chromes = Collections.synchronizedMap(new HashMap<Object, Process>());
       
    55 
       
    56     private static final int EXECUTIBLE_INDEX = 0;
       
    57     private static final int PORT_INDEX = 1;
       
    58     private static final int USER_DATA_INDEX = 2;
       
    59     private static final int CACHE_INDEX = 3;
       
    60     private static final int URL_INDEX = CHROME_ARGS.length - 1;
       
    61 
       
    62     private int profileNum = 0;
       
    63 
       
    64     public void startChrome(final Object key, int port, final String url) throws CoreException {
       
    65         final String browserExecutable = ChromeDebugUtils.getChromeExecutible();
       
    66         if (browserExecutable == null) {
       
    67             throw createCoreException("No Chrome browser available", null);
       
    68         }
       
    69 
       
    70         String[] commandline = new String[CHROME_ARGS.length];
       
    71         System.arraycopy(CHROME_ARGS, 0, commandline, 0, CHROME_ARGS.length);
       
    72         commandline[EXECUTIBLE_INDEX] = String.format(CHROME_ARGS[EXECUTIBLE_INDEX], browserExecutable);
       
    73         commandline[PORT_INDEX] = String.format(CHROME_ARGS[PORT_INDEX], port);
       
    74         commandline[USER_DATA_INDEX] = String.format(CHROME_ARGS[USER_DATA_INDEX], getChromeProfilePath());
       
    75         commandline[CACHE_INDEX] = String.format(CHROME_ARGS[CACHE_INDEX], getChromeCachePath());
       
    76         commandline[URL_INDEX] = String.format(CHROME_ARGS[URL_INDEX], url);
       
    77         
       
    78         // 2. Start Chrome
       
    79         try {
       
    80             Process process = Runtime.getRuntime().exec(commandline);
       
    81             chromes.put(key, process);
       
    82         } catch (IOException e) {
       
    83             StringBuilder builder = new StringBuilder();
       
    84             for (String string : commandline) {
       
    85                 builder.append(" ").append(string);
       
    86             }
       
    87             throw createCoreException("Cannot execute: {0}", builder.toString().trim(), e);
       
    88         }
       
    89 
       
    90     }
       
    91 
       
    92     private String getChromeCachePath() {
       
    93         return getChromeSpecialDir(".chromecache");
       
    94     }
       
    95 
       
    96     /**
       
    97      * Terminate Chrome instance associated with given key.
       
    98      */
       
    99     public synchronized void stopChrome(final Object key) {
       
   100 
       
   101     }
       
   102 
       
   103     public synchronized void forgetChrome(final Object key) {
       
   104 
       
   105     }
       
   106 
       
   107     public synchronized void shutdown() {
       
   108         String dir = getChromeSpecialDir("");
       
   109         File directory = new File(dir);
       
   110         File[] files = directory.listFiles(new FileFilter() {
       
   111             public boolean accept(File pathname) {
       
   112                 return pathname.isDirectory() && pathname.getName().matches("\\.chr\\d{3}")
       
   113                         && !isChromeRunning(pathname);
       
   114             }
       
   115         });
       
   116         boolean removedAll = true;
       
   117         for (File file : files) {
       
   118             removedAll = delete(file) && removedAll;
       
   119         }
       
   120         if (removedAll) {
       
   121             String cachePath = getChromeCachePath();
       
   122             delete(new File(cachePath));
       
   123         }
       
   124 
       
   125     }
       
   126 
       
   127     private boolean delete(File file) {
       
   128         if (!file.exists()) {
       
   129             return true;
       
   130         } else if (file.isDirectory()) {
       
   131             File[] files = file.listFiles();
       
   132             for (File f : files) {
       
   133                 if (!delete(f)) {
       
   134                     return false;
       
   135                 }
       
   136             }
       
   137         }
       
   138         return file.delete();
       
   139     }
       
   140 
       
   141     private CoreException createCoreException(String pattern, String arg, Throwable exeption) {
       
   142         return createCoreException(MessageFormat.format(pattern, arg), exeption);
       
   143     }
       
   144 
       
   145     private CoreException createCoreException(String message, Throwable exeption) {
       
   146         return new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, message, exeption));
       
   147     }
       
   148 
       
   149     private String getChromeProfilePath() {
       
   150         while (true) {
       
   151             String dir = getChromeSpecialDir(String.format(".chr%03d", profileNum++));
       
   152             if (!new File(dir).exists()) {
       
   153                 return dir;
       
   154             }
       
   155         }
       
   156     }
       
   157 
       
   158     private boolean isChromeRunning(File pathname) {
       
   159         File file = new File(pathname, "Default/Cookies");
       
   160         try {
       
   161             // Note: it is ok to delete cookies file - if it can be deleted then Chrome is not running.
       
   162             // If Chrome is running then we will not be able to delete the file.
       
   163             // We do not need to preserve state between launches. So it is ok to delete coockies.
       
   164             return file.exists() && !file.delete();
       
   165         } catch (Exception e) {
       
   166             Activator.log(e);
       
   167             return true;
       
   168         }
       
   169     }
       
   170 
       
   171     private String getChromeSpecialDir(String subdir) {
       
   172         IPath location = ResourcesPlugin.getWorkspace().getRoot().getLocation();
       
   173         if (CoreUtil.isLinux() && location.toString().length() > 50) {
       
   174             location = new Path(System.getProperty("user.home")).append(".wrtdebug");
       
   175         }
       
   176         return location.append(subdir).toOSString();
       
   177     }
       
   178 }