Index: src/mlx/gui/acars.py
===================================================================
--- src/mlx/gui/acars.py	(revision 649)
+++ src/mlx/gui/acars.py	(revision 649)
@@ -0,0 +1,36 @@
+
+from common import *
+
+from mlx.i18n import xstr
+import mlx.const as const
+
+import cef
+
+#------------------------------------------------------------------------------
+
+## @package mlx.gui.acars
+#
+# The ACARS tab.
+#
+# This module implements to \ref ACRS class, which displays the MAVA ACARS in a
+# browser window using CEF
+
+#------------------------------------------------------------------------------
+
+class ACARS(gtk.VBox):
+    """The flight info tab."""
+    # The URL of the ACARS map
+    URL = "http://virtualairlines.hu/acars2/show.html"
+
+    def __init__(self, gui):
+        """Construct the flight info tab."""
+        super(ACARS, self).__init__()
+        self._gui = gui
+
+    def start(self):
+        """Start the browser."""
+        container = cef.getContainer()
+
+        self.pack_start(container, True, True, 0)
+
+        cef.startInContainer(container, ACARS.URL)
Index: src/mlx/gui/cef.py
===================================================================
--- src/mlx/gui/cef.py	(revision 682)
+++ src/mlx/gui/cef.py	(revision 682)
@@ -0,0 +1,254 @@
+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
+import time
+import os
+import re
+import threading
+import tempfile
+import traceback
+
+#------------------------------------------------------------------------------
+
+## @package mlx.gui.cef
+#
+# Some helper stuff related to the Chrome Embedded Framework
+
+#------------------------------------------------------------------------------
+
+# Indicate if we should quit
+_toQuit = False
+
+# 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, _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 = {
+        "debug": True, # cefpython debug messages in console and in log_file
+        "log_severity": cefpython.LOGSEVERITY_VERBOSE, # LOGSEVERITY_VERBOSE
+        "log_file": "", # Set to "" to disable
+        "release_dcheck_enabled": True, # Enable only when debugging
+        # This directories must be set on Linux
+        "locales_dir_path": os.path.join(cefpython.GetModuleDirectory(), "locales"),
+        "resources_dir_path": cefpython.GetModuleDirectory(),
+        "browser_subprocess_path": "%s/%s" % \
+            (cefpython.GetModuleDirectory(), "subprocess"),
+    }
+
+    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()
+
+#------------------------------------------------------------------------------
+
+def getContainer():
+    """Get a container object suitable for running a browser instance
+    within."""
+    if os.name=="nt":
+        container = gtk.DrawingArea()
+        container.set_property("can-focus", True)
+        container.connect("size-allocate", _handleSizeAllocate)
+    else:
+        container = gtk.VBox(True, 0)
+
+    container.show()
+
+    return container
+
+#------------------------------------------------------------------------------
+
+def startInContainer(container, url, browserSettings = {}):
+    """Start a browser instance in the given container with the given URL."""
+    if os.name=="nt":
+        windowID = container.get_window().handle
+    else:
+        m = re.search("GtkVBox at 0x(\w+)", str(container))
+        hexID = m.group(1)
+        windowID = int(hexID, 16)
+
+    windowInfo = cefpython.WindowInfo()
+    windowInfo.SetAsChild(windowID)
+
+    return cefpython.CreateBrowserSync(windowInfo,
+                                       browserSettings = browserSettings,
+                                       navigateUrl = url)
+
+#------------------------------------------------------------------------------
+
+def finalize():
+    """Finalize the Chrome Embedded Framework."""
+    global _toQuit, _seleniumHandler
+    toQuit = True
+    _seleniumHandler.quit()
+    cefpython.Shutdown()
+
+#------------------------------------------------------------------------------
+
+def _handleTimeout():
+    """Handle the timeout by running the CEF message loop."""
+    if _toQuit:
+        return False
+    else:
+        cefpython.MessageLoopWork()
+        return True
+
+#------------------------------------------------------------------------------
+
+def _handleSizeAllocate(widget, sizeAlloc):
+    """Handle the size-allocate event."""
+    cefpython.WindowUtils.OnSize(widget.get_window().handle, 0, 0, 0)
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 620)
+++ src/mlx/gui/gui.py	(revision 682)
@@ -15,4 +15,6 @@
 from mlx.gui.pirep import PIREPViewer
 from mlx.gui.bugreport import BugReportDialog
+from mlx.gui.acars import ACARS
+import cef
 
 import mlx.const as const
@@ -102,6 +104,9 @@
         window.connect("delete-event", self.deleteMainWindow)
         window.connect("window-state-event", self._handleMainWindowState)
+        if os.name=="nt":
+            window.connect("leave-notify-event", self._handleLeaveNotify)
         accelGroup = gtk.AccelGroup()
         window.add_accel_group(accelGroup)
+        window.realize()
 
         mainVBox = gtk.VBox()
@@ -151,4 +156,9 @@
         self._notebook.append_page(self._fleetGateStatus, label)
 
+        self._acars = ACARS(self)
+        label = gtk.Label("ACARS")
+        label.set_use_underline(True)
+        self._notebook.append_page(self._acars, label)
+
         (self._debugLogWidget, self._debugLogView) = self._buildLogWidget()
         self._debugLogWidget.show_all()
@@ -170,4 +180,6 @@
 
         window.show_all()
+        if os.name=="nt":
+            window.get_window().focus()
 
         self._wizard.grabDefault()
@@ -427,11 +439,15 @@
             self._updater = Updater(self,
                                     self._programDirectory,
-                                    self.config.updateURL,
+                                    self.config.DEFAULT_UPDATE_URL,
                                     self._mainWindow)
             self._updater.start()
+
+        cef.initialize(self._programDirectory, self._cefInitialized)
 
         singleton.raiseCallback = self.raiseCallback
         gtk.main()
         singleton.raiseCallback = None
+
+        cef.finalize()
 
         self._disconnect()
@@ -687,4 +703,11 @@
              (event.new_window_state&WINDOW_STATE_ICONIFIED)==0:
             self._mainWindow.present()
+
+    def _handleLeaveNotify(self, widget, event):
+        """Handle the leave-notify event.
+
+        Here we reset the focus to the main window as CEF might have acquired
+        it earlier."""
+        self._mainWindow.get_window().focus()
 
     def raiseCallback(self):
@@ -1464,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."""
