Index: makeinst.bat
===================================================================
--- makeinst.bat	(revision 653)
+++ makeinst.bat	(revision 682)
@@ -2,7 +2,13 @@
 set GTKRTDIR=c:\Python27\Lib\site-packages\gtk-2.0\runtime
 set CEFDIR=c:\Python27\Lib\site-packages\cefpython3
+set CHROMEDRIVER=c:\tmp\chromedriver.exe
 set NSISDIR=C:\Program Files\NSIS
 
 python setup.py py2exe
 
+del dist\library\selenium\webdriver\chrome\service.pyc
+copy patches\library\selenium\webdriver\chrome\service.py dist\library\selenium\webdriver\chrome\service.py
+python -m compileall dist\library\selenium\webdriver\chrome\service.py
+del dist\library\selenium\webdriver\chrome\service.py
+
 "%NSISDIR%\makensis" mlx.nsi
Index: mlx_cef_caller.bat
===================================================================
--- mlx_cef_caller.bat	(revision 682)
+++ mlx_cef_caller.bat	(revision 682)
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+SET scriptdir=%~dp0
+scriptdir=`dirname $0`
+
+echo %* > %TEMP%\mlxcef.args.tmp
+move %TEMP%\mlxcef.args.tmp %TEMP%\mlxcef.args
Index: mlx_cef_caller.sh
===================================================================
--- mlx_cef_caller.sh	(revision 682)
+++ mlx_cef_caller.sh	(revision 682)
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+scriptdir=`dirname $0`
+
+echo "$@" > "/tmp/mlxcef.${LOGNAME}.args.tmp"
+mv "/tmp/mlxcef.${LOGNAME}.args.tmp" "/tmp/mlxcef.${LOGNAME}.args"
Index: mlx_cef_caller_secondary.bat
===================================================================
--- mlx_cef_caller_secondary.bat	(revision 682)
+++ mlx_cef_caller_secondary.bat	(revision 682)
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+SET scriptdir=%~dp0
+scriptdir=`dirname $0`
+
+echo %* > %TEMP%\mlxcef.args.secondary.tmp
+move %TEMP%\mlxcef.args.secondary.tmp %TEMP%\mlxcef.args.secondary
Index: mlx_cef_caller_secondary.sh
===================================================================
--- mlx_cef_caller_secondary.sh	(revision 682)
+++ mlx_cef_caller_secondary.sh	(revision 682)
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+scriptdir=`dirname $0`
+
+echo "$@" > "/tmp/mlxcef.${LOGNAME}.args.secondary.tmp"
+mv "/tmp/mlxcef.${LOGNAME}.args.secondary.tmp" "/tmp/mlxcef.${LOGNAME}.args.secondary"
Index: patches/library/selenium/webdriver/chrome/service.py
===================================================================
--- patches/library/selenium/webdriver/chrome/service.py	(revision 682)
+++ patches/library/selenium/webdriver/chrome/service.py	(revision 682)
@@ -0,0 +1,118 @@
+#!/usr/bin/python
+#
+# Copyright 2011 Webdriver_name committers
+# Copyright 2011 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import os
+import subprocess
+from subprocess import PIPE
+import time
+
+from selenium.common.exceptions import WebDriverException
+from selenium.webdriver.common import utils
+
+class Service(object):
+    """
+    Object that manages the starting and stopping of the ChromeDriver
+    """
+
+    def __init__(self, executable_path, port=0, service_args=None,
+                 log_path=None, env=None):
+        """
+        Creates a new instance of the Service
+
+        :Args:
+         - executable_path : Path to the ChromeDriver
+         - port : Port the service is running on
+         - service_args : List of args to pass to the chromedriver service
+         - log_path : Path for the chromedriver service to log to"""
+
+        self.port = port
+        self.path = executable_path
+        self.service_args = service_args or []
+        if log_path:
+          self.service_args.append('--log-path=%s' % log_path)
+        if self.port == 0:
+            self.port = utils.free_port()
+        self.env = env
+
+    def start(self):
+        """
+        Starts the ChromeDriver Service.
+
+        :Exceptions:
+         - WebDriverException : Raised either when it can't start the service
+           or when it can't connect to the service
+        """
+        env = self.env or os.environ
+        try:
+            startupInfo = subprocess.STARTUPINFO()
+            startupInfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+            self.process = subprocess.Popen([
+              self.path,
+              "--port=%d" % self.port] +
+              self.service_args, env=env, stdout=PIPE, stderr=PIPE,
+              startupinfo = startupInfo)
+        except:
+            raise WebDriverException(
+                "'" + os.path.basename(self.path) + "' executable needs to be \
+                available in the path. Please look at \
+                http://docs.seleniumhq.org/download/#thirdPartyDrivers \
+                and read up at \
+                http://code.google.com/p/selenium/wiki/ChromeDriver")
+        count = 0
+        while not utils.is_connectable(self.port):
+            count += 1
+            time.sleep(1)
+            if count == 30:
+                raise WebDriverException("Can not connect to the '" +
+                                         os.path.basename(self.path) + "'")
+
+    @property
+    def service_url(self):
+        """
+        Gets the url of the ChromeDriver Service
+        """
+        return "http://localhost:%d" % self.port
+
+    def stop(self):
+        """
+        Tells the ChromeDriver to stop and cleans up the process
+        """
+        #If its dead dont worry
+        if self.process is None:
+            return
+
+        #Tell the Server to die!
+        try:
+            from urllib import request as url_request
+        except ImportError:
+            import urllib2 as url_request
+
+        url_request.urlopen("http://127.0.0.1:%d/shutdown" % self.port)
+        count = 0
+        while utils.is_connectable(self.port):
+            if count == 30:
+               break
+            count += 1
+            time.sleep(1)
+
+        #Tell the Server to properly die in case
+        try:
+            if self.process:
+                self.process.kill()
+                self.process.wait()
+        except OSError:
+            # kill may not be available under windows environment
+            pass
Index: setup.py
===================================================================
--- setup.py	(revision 654)
+++ setup.py	(revision 682)
@@ -20,9 +20,16 @@
                                      "mlx.mo")]))
 data_files.append(("", ["logo.png",
-                        "conn_grey.png", "conn_red.png", "conn_green.png"]))
+                        "conn_grey.png", "conn_red.png", "conn_green.png",
+                        "mlx_cef_caller.sh", "mlx_cef_caller_secondary.sh",
+                        "mlx_cef_caller.bat", "mlx_cef_caller_secondary.bat"]))
+
 if os.name=="nt":
     import py2exe
 
     data_files.append(("", ["logo.ico"]))
+
+    chromedriver = os.environ.get("CHROMEDRIVER")
+    if chromedriver:
+        data_files.append(("", [chromedriver]))
 
     msvcrDir = os.environ["MSVCRDIR"] if "MSVCRDIR" in os.environ else None
@@ -61,4 +68,12 @@
             print >>f, '!define MLX_VERSION "%s"' % (mlx.const.VERSION)
             f.close()
+else:
+    for (dirpath, dirnames, filenames) in os.walk("patches"):
+        if filenames:
+            filenames = [os.path.join(dirpath, filename)
+                         for filename in filenames]
+            data_files.append((dirpath, filenames))
+
+
 
 long_description="""MAVA Logger X
Index: src/mlx/const.py
===================================================================
--- src/mlx/const.py	(revision 681)
+++ src/mlx/const.py	(revision 682)
@@ -11,5 +11,5 @@
 
 ## The version of the program
-VERSION="0.35.2"
+VERSION="0.35.2cef"
 
 #-------------------------------------------------------------------------------
Index: src/mlx/gui/cef.py
===================================================================
--- src/mlx/gui/cef.py	(revision 648)
+++ src/mlx/gui/cef.py	(revision 682)
@@ -1,11 +1,18 @@
 from common import *
+
+from mlx.util import secondaryInstallation
+
+from cefpython3 import cefpython
+from selenium import webdriver
+from selenium.webdriver.chrome.options import Options
 
 import platform
 import json
-
-from cefpython3 import cefpython
-
+import time
 import os
 import re
+import threading
+import tempfile
+import traceback
 
 #------------------------------------------------------------------------------
@@ -20,12 +27,140 @@
 _toQuit = False
 
-#------------------------------------------------------------------------------
-
-def initialize():
+# The Selenium thread
+_seleniumHandler = None
+
+#------------------------------------------------------------------------------
+
+def getArgsFilePath():
+    """Get the path of the argument file."""
+    if os.name=="nt":
+        return os.path.join(tempfile.gettempdir(),
+                            "mlxcef.args" +
+                            (".secondary" if secondaryInstallation else ""))
+    else:
+        import pwd
+        return os.path.join(tempfile.gettempdir(),
+                            "mlxcef." + pwd.getpwuid(os.getuid())[0] + ".args" +
+                            (".secondary" if secondaryInstallation else ""))
+
+#------------------------------------------------------------------------------
+
+class ArgsFileWaiter(threading.Thread):
+    """A thread to wait for the appearance of the arguments file."""
+    def __init__(self, initializedCallback):
+        """Construct the thread."""
+        threading.Thread.__init__(self)
+        self.daemon = True
+
+        self._initializedCallback = initializedCallback
+
+    def run(self):
+        """Repeatedly check for the existence of the arguments file.
+
+        If it is found, read it, extract the arguments and insert a job into
+        the GUI loop to perform the actual initialization of CEF."""
+        argsFilePath = getArgsFilePath()
+        print "Waiting for the arguments file '%s' to appear" % (argsFilePath,)
+
+        while not os.path.exists(argsFilePath):
+            time.sleep(0.1)
+
+        print "Got arguments, reading them."""
+
+        with open(argsFilePath, "rt") as f:
+            args = f.read().split()
+
+        gobject.idle_add(_initializeCEF, args, self._initializedCallback)
+
+#------------------------------------------------------------------------------
+
+class SeleniumHandler(threading.Thread):
+    """Thread to handle Selenium operations."""
+    def __init__(self, programDirectory):
+        """Construct the thread."""
+        threading.Thread.__init__(self)
+        self.daemon = False
+
+        self._programDirectory = programDirectory
+
+        self._commandsCondition = threading.Condition()
+        self._commands = []
+
+        self._toQuit = False
+
+    def run(self):
+        """Create the Selenium driver and the perform any operations
+        requested."""
+        scriptName = "mlx_cef_caller"
+        if secondaryInstallation:
+            scriptName += "_secondary"
+        scriptName += ".bat" if os.name=="nt" else ".sh"
+
+        scriptPath = os.path.join(self._programDirectory, scriptName)
+        print "Creating the Selenium driver to call script", scriptPath
+
+        options = Options()
+        options.binary_location = scriptPath
+        driver = webdriver.Chrome(chrome_options = options)
+        # try:
+        # except:
+        #     traceback.print_exc()
+
+        print "Created Selenium driver."
+        while not self._toQuit:
+            with self._commandsCondition:
+                while not self._commands:
+                    self._commandsCondition.wait()
+
+                command = self._commands[0]
+                del self._commands[0]
+
+            command()
+
+        driver.quit()
+
+    def quit(self):
+        """Instruct the thread to quit and then join it."""
+        self._enqueue(self._quit)
+        self.join()
+
+    def _enqueue(self, command):
+        """Enqueue the given command.
+
+        command should be a function to be executed in the thread."""
+        with self._commandsCondition:
+            self._commands.append(command)
+            self._commandsCondition.notify()
+
+    def _quit(self):
+        """Set the _toQuit member variable to indicate that the thread should
+        quit."""
+        self._toQuit = True
+
+#------------------------------------------------------------------------------
+
+def initialize(programDirectory, initializedCallback):
     """Initialize the Chrome Embedded Framework."""
-    global _toQuit
+    global _toQuit, _seleniumHandler
     _toQuit = False
 
     gobject.threads_init()
+
+    argsFilePath = getArgsFilePath()
+    try:
+        os.unlink(argsFilePath)
+    except:
+        pass
+
+    _seleniumHandler = SeleniumHandler(programDirectory)
+    _seleniumHandler.start()
+
+    ArgsFileWaiter(initializedCallback).start()
+
+#------------------------------------------------------------------------------
+
+def _initializeCEF(args, initializedCallback):
+    """Perform the actual initialization of CEF using the given arguments."""
+    print "Initializing CEF with args:", args
 
     settings = {
@@ -41,7 +176,22 @@
     }
 
-    cefpython.Initialize(settings, {})
+    switches={}
+    for arg in args:
+        if arg.startswith("--"):
+            if arg != "--enable-logging":
+                assignIndex = arg.find("=")
+                if assignIndex<0:
+                    switches[arg[2:]] = ""
+                else:
+                    switches[arg[2:assignIndex]] = arg[assignIndex+1:]
+        else:
+            print "Unhandled switch", arg
+
+    cefpython.Initialize(settings, switches)
 
     gobject.timeout_add(10, _handleTimeout)
+
+    print "Initialized, executing callback..."
+    initializedCallback()
 
 #------------------------------------------------------------------------------
@@ -83,6 +233,7 @@
 def finalize():
     """Finalize the Chrome Embedded Framework."""
-    global _toQuit
+    global _toQuit, _seleniumHandler
     toQuit = True
+    _seleniumHandler.quit()
     cefpython.Shutdown()
 
Index: src/mlx/gui/common.py
===================================================================
--- src/mlx/gui/common.py	(revision 604)
+++ src/mlx/gui/common.py	(revision 682)
@@ -32,4 +32,5 @@
     pygobject = False
     import pygtk
+    pygtk.require("2.0")
     import gtk.gdk as gdk
     import gtk
Index: src/mlx/gui/gui.py
===================================================================
--- src/mlx/gui/gui.py	(revision 652)
+++ src/mlx/gui/gui.py	(revision 682)
@@ -443,6 +443,5 @@
             self._updater.start()
 
-        cef.initialize()
-        self._acars.start()
+        cef.initialize(self._programDirectory, self._cefInitialized)
 
         singleton.raiseCallback = self.raiseCallback
@@ -1488,4 +1487,8 @@
                                       summary, description, email)
 
+    def _cefInitialized(self):
+        """Called when CEF has been initialized."""
+        self._acars.start()
+
     def _bugReportSentCallback(self, returned, result):
         """Callback function for the bug report sending result."""
