changeset 278:93409d9838c5

Commit more browser/xpcom updates, including still uncoverted source.
author John Reimer<terminal.node@gmail.com>
date Thu, 31 Jul 2008 19:17:51 -0700
parents 687f261028b8
children 88f81e22e0ee
files dsss.conf dwt/browser/AppFileLocProvider.d dwt/browser/Browser.d dwt/browser/CloseWindowListener.d dwt/browser/Download.d dwt/browser/DownloadFactory.d dwt/browser/DownloadFactory_1_8.d dwt/browser/Download_1_8.d dwt/browser/FilePicker.d dwt/browser/FilePickerFactory.d dwt/browser/FilePickerFactory_1_8.d dwt/browser/FilePicker_1_8.d dwt/browser/HelperAppLauncherDialog.d dwt/browser/HelperAppLauncherDialogFactory.d dwt/browser/InputStream.d dwt/browser/LocationAdapter.d dwt/browser/LocationEvent.d dwt/browser/LocationListener.d dwt/browser/Mozilla.d dwt/browser/MozillaDelegate.d dwt/browser/OpenWindowListener.d dwt/browser/ProgressAdapter.d dwt/browser/ProgressEvent.d dwt/browser/ProgressListener.d dwt/browser/PromptDialog.d dwt/browser/PromptService2.d dwt/browser/PromptService2Factory.d dwt/browser/SimpleEnumerator.d dwt/browser/StatusTextEvent.d dwt/browser/StatusTextListener.d dwt/browser/TitleEvent.d dwt/browser/TitleListener.d dwt/browser/VisibilityWindowAdapter.d dwt/browser/VisibilityWindowListener.d dwt/browser/WebBrowser.d dwt/browser/WindowCreator2.d dwt/browser/WindowEvent.d dwt/internal/mozilla/nsEmbedString.d dwt/internal/mozilla/nsEmbedString2.d dwt/internal/mozilla/nsIInputStream.d dwt/internal/mozilla/nsILocalFile.d dwt/internal/mozilla/nsISupports.d dwt/internal/mozilla/nsStringAPI.d dwt/internal/mozilla/nsXPCOM.d
diffstat 44 files changed, 9694 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/dsss.conf	Sat Jul 26 14:37:23 2008 +0200
+++ b/dsss.conf	Thu Jul 31 19:17:51 2008 -0700
@@ -1,4 +1,8 @@
-
 [dwt]
 type=library
 
+# These directories are excluded for now
+# until browser/xpcom is ported
+
+exclude=dwt/internal/mozilla
+exclude=dwt/browser
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/AppFileLocProvider.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,287 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+  * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+
+module dwt.browser.AppFileLocProvider;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.Compatibility;
+
+import dwt.internal.mozilla.nsEmbedString;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIDirectoryService;
+import dwt.internal.mozilla.nsIFile;
+import dwt.internal.mozilla.nsILocalFile;
+import dwt.internal.mozilla.nsISupports;
+
+class AppFileLocProvider : nsISupports, nsIDirectoryServiceProvider2 
+{
+    // XPCOMObject supports;
+    // XPCOMObject directoryServiceProvider;
+    // XPCOMObject directoryServiceProvider2;  
+    nsrefcnt _refCount = 0;
+    String   mozillaPath, profilePath;
+    String[] pluginDirs;
+    bool     isXULRunner;
+    
+    static String SEPARATOR_OS = System.getProperty ("file.separator"); //$NON-NLS-1$
+    static String CHROME_DIR = "chrome"; //$NON-NLS-1$
+    static String COMPONENTS_DIR = "components"; //$NON-NLS-1$
+    static String HISTORY_FILE = "history.dat"; //$NON-NLS-1$
+    static String LOCALSTORE_FILE = "localstore.rdf"; //$NON-NLS-1$
+    static String MIMETYPES_FILE = "mimeTypes.rdf"; //$NON-NLS-1$
+    static String PLUGINS_DIR = "plugins"; //$NON-NLS-1$
+    static String USER_PLUGINS_DIR = ".mozilla" + SEPARATOR_OS + "plugins"; //$NON-NLS-1$ //$NON-NLS-2$
+    static String PREFERENCES_FILE = "prefs.js"; //$NON-NLS-1$
+    
+AppFileLocProvider (String path) {
+    mozillaPath = path + SEPARATOR_OS;
+    createCOMInterfaces ();
+}
+
+    int AddRef () 
+    {
+        refCount++;
+        return refCount;
+    }
+
+    nsresult QueryInterface ( nsIID* riid, void** ppvObject) 
+    {
+        if (riid is null || ppvObject is null) 
+            return NS_ERROR_NO_INTERFACE;
+
+        if (riid == nsISupports.IID) 
+        {
+            *ppvObject =cast(void*)cast(nsISupports)this;
+            AddRef ();
+            return NS_OK;
+        }
+
+        if (riid == nsIDirectoryServiceProvider.IID) 
+        {
+            *ppvObject = cast(void*)cast(nsIDirectoryServiceProvider)this;
+            AddRef ();
+            return NS_OK;
+        }
+
+        if (riid == nsDirectoryServiceProvider2.IID) {
+            *ppvObject = cast(void*)cast(nsIDirectoryServiceProvider2)this;
+            AddRef ();
+            return NS_OK;
+        }
+    
+        *ppvObject = null;
+        return NS_ERROR_NO_INTERFACE;
+    } 
+
+    nsrefcnt Release () 
+    {
+        _refCount--;
+        if (_refCount is 0) 
+            return 0;
+        return _refCount;
+    }
+
+void setProfilePath (String path) {
+    profilePath = path;
+    if (!Compatibility.fileExists (path, "")) { //$NON-NLS-1$
+        int /*long*/[] result = new int /*long*/[1];
+        nsEmbedString pathString = new nsEmbedString (path);
+        int rc = XPCOM.NS_NewLocalFile (pathString.getAddress (), 1, result);
+        if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+        if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
+        pathString.dispose ();
+
+        nsILocalFile file = new nsILocalFile (result [0]);
+        rc = file.Create (nsILocalFile.DIRECTORY_TYPE, 0700);
+        if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+        file.Release ();
+    }
+}
+
+/* nsIDirectoryServiceProvider2 */
+
+int getFiles (int /*long*/ prop, int /*long*/ _retval) {
+    int size = XPCOM.strlen (prop);
+    byte[] bytes = new byte[size];
+    XPCOM.memmove (bytes, prop, size);
+    String propertyName = new String (MozillaDelegate.mbcsToWcs (null, bytes));
+    String[] propertyValues = null;
+
+    if (propertyName.equals (XPCOM.NS_APP_PLUGINS_DIR_LIST)) {
+        if (pluginDirs is null) {
+            int index = 0;
+            /* set the first value(s) to the MOZ_PLUGIN_PATH environment variable value if it's defined */
+            int /*long*/ ptr = C.getenv (MozillaDelegate.wcsToMbcs (null, XPCOM.MOZILLA_PLUGIN_PATH, true));
+            if (ptr !is 0) {
+                int length = C.strlen (ptr);
+                byte[] buffer = new byte[length];
+                C.memmove (buffer, ptr, length);
+                String value = new String (MozillaDelegate.mbcsToWcs (null, buffer));
+                if (value.length () > 0) {
+                    String separator = System.getProperty ("path.separator"); // $NON-NLS-1$
+                    Vector segments = new Vector ();
+                    int start, end = -1;
+                    do {
+                        start = end + 1;
+                        end = value.indexOf (separator, start);
+                        String segment;
+                        if (end is -1) {
+                            segment = value.substring (start);
+                        } else {
+                            segment = value.substring (start, end);
+                        }
+                        if (segment.length () > 0) segments.addElement (segment);
+                    } while (end !is -1);
+                    int segmentsSize = segments.size ();
+                    pluginDirs = new String [segmentsSize + 2];
+                    for (index = 0; index < segmentsSize; index++) {
+                        pluginDirs[index] = (String)segments.elementAt (index);
+                    }
+                }
+            }
+            if (pluginDirs is null) {
+                pluginDirs = new String[2];
+            }
+
+            /* set the next value to the GRE path + "plugins" */
+            pluginDirs[index++] = mozillaPath + PLUGINS_DIR;
+
+            /* set the next value to the home directory + "/.mozilla/plugins" */
+            pluginDirs[index++] = System.getProperty("user.home") + SEPARATOR_OS + USER_PLUGINS_DIR;
+        }
+        propertyValues = pluginDirs;
+    }
+
+    XPCOM.memmove(_retval, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    if (propertyValues !is null) {
+        int /*long*/[] result = new int /*long*/[1];
+        nsISupports[] files = new nsISupports [propertyValues.length];
+        int index = 0;
+        for (int i = 0; i < propertyValues.length; i++) {
+            nsEmbedString pathString = new nsEmbedString (propertyValues[i]);
+            int rc = XPCOM.NS_NewLocalFile (pathString.getAddress (), 1, result);
+            if (rc !is XPCOM.NS_ERROR_FILE_UNRECOGNIZED_PATH) {
+                /* value appears to be a valid pathname */
+                if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+                if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
+
+                nsILocalFile localFile = new nsILocalFile (result[0]);
+                result[0] = 0;
+                rc = localFile.QueryInterface (nsIFile.NS_IFILE_IID, result); 
+                if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+                if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE);
+                localFile.Release ();
+
+                nsIFile file = new nsIFile (result[0]);
+                files[index++] = file;
+            }
+            pathString.dispose ();
+            result[0] = 0;
+        }
+
+        if (index < propertyValues.length) {
+            /* there were some invalid values so remove the trailing empty array slots */
+            nsISupports[] temp = new nsISupports [index];
+            System.arraycopy (files, 0, temp, 0, index);
+            files = temp;
+        }
+
+        SimpleEnumerator enumerator = new SimpleEnumerator (files);
+        enumerator.AddRef ();
+        XPCOM.memmove (_retval, new int /*long*/[] {enumerator.getAddress ()}, C.PTR_SIZEOF);
+        return XPCOM.NS_OK;
+    }
+
+    return XPCOM.NS_ERROR_FAILURE;
+}   
+    
+/* nsIDirectoryServiceProvider implementation */
+
+int getFile(int /*long*/ prop, int /*long*/ persistent, int /*long*/ _retval) {
+    int size = XPCOM.strlen (prop);
+    byte[] bytes = new byte[size];
+    XPCOM.memmove (bytes, prop, size);
+    String propertyName = new String (MozillaDelegate.mbcsToWcs (null, bytes));
+    String propertyValue = null;
+
+    if (propertyName.equals (XPCOM.NS_APP_HISTORY_50_FILE)) {
+        propertyValue = profilePath + HISTORY_FILE;
+    } else if (propertyName.equals (XPCOM.NS_APP_USER_MIMETYPES_50_FILE)) {
+        propertyValue = profilePath + MIMETYPES_FILE;
+    } else if (propertyName.equals (XPCOM.NS_APP_PREFS_50_FILE)) {
+        propertyValue = profilePath + PREFERENCES_FILE;
+    } else if (propertyName.equals (XPCOM.NS_APP_PREFS_50_DIR)) {
+        propertyValue = profilePath;
+    } else if (propertyName.equals (XPCOM.NS_APP_USER_CHROME_DIR)) {
+        propertyValue = profilePath + CHROME_DIR;
+    } else if (propertyName.equals (XPCOM.NS_APP_USER_PROFILE_50_DIR)) {
+        propertyValue = profilePath;
+    } else if (propertyName.equals (XPCOM.NS_APP_LOCALSTORE_50_FILE)) {
+        propertyValue = profilePath + LOCALSTORE_FILE;
+    } else if (propertyName.equals (XPCOM.NS_APP_CACHE_PARENT_DIR)) {
+        propertyValue = profilePath;
+    } else if (propertyName.equals (XPCOM.NS_OS_HOME_DIR)) {
+        propertyValue = System.getProperty("user.home");    //$NON-NLS-1$
+    } else if (propertyName.equals (XPCOM.NS_OS_TEMP_DIR)) {
+        propertyValue = System.getProperty("java.io.tmpdir");   //$NON-NLS-1$
+    } else if (propertyName.equals (XPCOM.NS_GRE_DIR)) {
+        propertyValue = mozillaPath;
+    } else if (propertyName.equals (XPCOM.NS_GRE_COMPONENT_DIR)) {
+        propertyValue = mozillaPath + COMPONENTS_DIR;
+    } else if (propertyName.equals (XPCOM.NS_XPCOM_INIT_CURRENT_PROCESS_DIR)) {
+        propertyValue = mozillaPath;
+    } else if (propertyName.equals (XPCOM.NS_OS_CURRENT_PROCESS_DIR)) {
+        propertyValue = mozillaPath;
+    } else if (propertyName.equals (XPCOM.NS_XPCOM_COMPONENT_DIR)) {
+        propertyValue = mozillaPath + COMPONENTS_DIR;
+    } else if (propertyName.equals (XPCOM.NS_XPCOM_CURRENT_PROCESS_DIR)) {
+        propertyValue = mozillaPath;
+    } else if (propertyName.equals (XPCOM.NS_APP_PREF_DEFAULTS_50_DIR)) {
+        /*
+        * Answering a value for this property causes problems in Mozilla versions
+        * < 1.7.  Unfortunately this property is queried early enough in the
+        * Browser creation process that the Mozilla version being used is not
+        * yet determined.  However it is known if XULRunner is being used or not.
+        * 
+        * For now answer a value for this property iff XULRunner is the GRE.
+        * If the range of Mozilla versions supported by the Browser is changed
+        * in the future to be >= 1.7 then this value can always be answered.  
+        */
+        if (isXULRunner) propertyValue = profilePath;
+    }
+
+    XPCOM.memmove (persistent, new int[] {1}, 4); /* PRBool */
+    XPCOM.memmove (_retval, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    if (propertyValue !is null && propertyValue.length () > 0) {
+        int /*long*/[] result = new int /*long*/[1];
+        nsEmbedString pathString = new nsEmbedString (propertyValue);
+        int rc = XPCOM.NS_NewLocalFile (pathString.getAddress (), 1, result);
+        if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+        if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
+        pathString.dispose ();
+        
+        nsILocalFile localFile = new nsILocalFile (result [0]);
+        result[0] = 0;
+        rc = localFile.QueryInterface (nsIFile.NS_IFILE_IID, result); 
+        if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+        if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+        XPCOM.memmove (_retval, new int /*long*/[] {result[0]}, C.PTR_SIZEOF);
+        localFile.Release ();
+        return XPCOM.NS_OK;
+    }
+
+    return XPCOM.NS_ERROR_FAILURE;
+}       
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/Browser.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,782 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.Browser;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.DWTError;
+import dwt.DWTException;
+import dwt.widgets.Composite;
+import dwt.widgets.Display;
+import dwt.widgets.Widget;
+
+/**
+ * Instances of this class implement the browser user interface
+ * metaphor.  It allows the user to visualize and navigate through
+ * HTML documents.
+ * <p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to set a layout on it.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>MOZILLA</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>CloseWindowListener, LocationListener, OpenWindowListener, ProgressListener, StatusTextListener, TitleListener, VisibilityWindowListener</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ * 
+ * @since 3.0
+ */
+
+public class Browser extends Composite {
+    WebBrowser webBrowser;
+    int userStyle;
+
+    static final String PACKAGE_PREFIX = "dwt.browser."; //$NON-NLS-1$
+    static final String NO_INPUT_METHOD = "dwt.internal.gtk.noInputMethod"; //$NON-NLS-1$
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>DWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together 
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>DWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ * @exception DWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for browser creation</li>
+ * </ul>
+ * 
+ * @see Widget#getStyle
+ * 
+ * @since 3.0
+ */
+public Browser (Composite parent, int style) {
+    super (checkParent (parent), checkStyle (style));
+    userStyle = style;
+
+    String platform = DWT.getPlatform ();
+    Display display = parent.getDisplay ();
+    if ("gtk".equals (platform)) display.setData (NO_INPUT_METHOD, null); //$NON-NLS-1$
+    String className = null;
+    if ((style & DWT.MOZILLA) !is 0) {
+        className = "dwt.browser.Mozilla"; //$NON-NLS-1$
+    } else {
+        if ("win32".equals (platform) || "wpf".equals (platform)) { //$NON-NLS-1$ $NON-NLS-2$
+            className = "dwt.browser.IE"; //$NON-NLS-1$
+        } else if ("motif".equals (platform)) { //$NON-NLS-1$
+            className = "dwt.browser.Mozilla"; //$NON-NLS-1$
+        } else if ("gtk".equals (platform)) { //$NON-NLS-1$
+            className = "dwt.browser.Mozilla"; //$NON-NLS-1$
+        } else if ("carbon".equals (platform) || "cocoa".equals (platform)) { //$NON-NLS-1$
+            className = "dwt.browser.Safari"; //$NON-NLS-1$
+        } else if ("photon".equals (platform)) { //$NON-NLS-1$
+            className = "dwt.browser.Voyager"; //$NON-NLS-1$
+        } else {
+            dispose ();
+            DWT.error (DWT.ERROR_NO_HANDLES);
+        }
+    }
+
+    try {
+        Class clazz = Class.forName (className);
+        webBrowser = (WebBrowser)clazz.newInstance ();
+    } catch (ClassNotFoundException e) {
+    } catch (IllegalAccessException e) {
+    } catch (InstantiationException e) {
+    }
+    if (webBrowser is null) {
+        dispose ();
+        DWT.error (DWT.ERROR_NO_HANDLES);
+    }
+
+    webBrowser.setBrowser (this);
+    webBrowser.create (parent, style);
+}
+
+static Composite checkParent (Composite parent) {
+    String platform = DWT.getPlatform ();
+    if (!"gtk".equals (platform)) return parent; //$NON-NLS-1$
+
+    /*
+    * Note.  Mozilla provides all IM support needed for text input in web pages.
+    * If DWT creates another input method context for the widget it will cause
+    * indeterminate results to happen (hangs and crashes). The fix is to prevent 
+    * DWT from creating an input method context for the  Browser widget.
+    */
+    if (parent !is null && !parent.isDisposed ()) {
+        Display display = parent.getDisplay ();
+        if (display !is null) {
+            if (display.getThread () is Thread.currentThread ()) {
+                display.setData (NO_INPUT_METHOD, "true"); //$NON-NLS-1$
+            }
+        }
+    }
+    return parent;
+}
+
+static int checkStyle(int style) {
+    String platform = DWT.getPlatform ();
+    if ((style & DWT.MOZILLA) !is 0) {
+        if ("carbon".equals (platform)) return style | DWT.EMBEDDED; //$NON-NLS-1$
+        if ("motif".equals (platform)) return style | DWT.EMBEDDED; //$NON-NLS-1$
+        return style;
+    }
+
+    if ("win32".equals (platform)) { //$NON-NLS-1$
+        /*
+        * For IE on win32 the border is supplied by the embedded browser, so remove
+        * the style so that the parent Composite will not draw a second border.
+        */
+        return style & ~DWT.BORDER;
+    } else if ("motif".equals (platform)) { //$NON-NLS-1$
+        return style | DWT.EMBEDDED;
+    }
+    return style;
+}
+
+/**
+ * Clears all session cookies from all current Browser instances.
+ * 
+ * @since 3.2
+ */
+public static void clearSessions () {
+    WebBrowser.clearSessions ();
+}
+
+/**  
+ * Adds the listener to the collection of listeners who will be
+ * notified when the window hosting the receiver should be closed.
+ * <p>
+ * This notification occurs when a javascript command such as
+ * <code>window.close</code> gets executed by a <code>Browser</code>.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void addCloseWindowListener (CloseWindowListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.addCloseWindowListener (listener);
+}
+
+/**  
+ * Adds the listener to the collection of listeners who will be
+ * notified when the current location has changed or is about to change.
+ * <p>
+ * This notification typically occurs when the application navigates
+ * to a new location with {@link #setUrl(String)} or when the user
+ * activates a hyperlink.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void addLocationListener (LocationListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.addLocationListener (listener);
+}
+
+/**  
+ * Adds the listener to the collection of listeners who will be
+ * notified when a new window needs to be created.
+ * <p>
+ * This notification occurs when a javascript command such as
+ * <code>window.open</code> gets executed by a <code>Browser</code>.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void addOpenWindowListener (OpenWindowListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.addOpenWindowListener (listener);
+}
+
+/**  
+ * Adds the listener to the collection of listeners who will be
+ * notified when a progress is made during the loading of the current 
+ * URL or when the loading of the current URL has been completed.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void addProgressListener (ProgressListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.addProgressListener (listener);
+}
+
+/**  
+ * Adds the listener to the collection of listeners who will be
+ * notified when the status text is changed.
+ * <p>
+ * The status text is typically displayed in the status bar of
+ * a browser application.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void addStatusTextListener (StatusTextListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.addStatusTextListener (listener);
+}
+
+/**  
+ * Adds the listener to the collection of listeners who will be
+ * notified when the title of the current document is available
+ * or has changed.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void addTitleListener (TitleListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.addTitleListener (listener);
+}
+
+/**  
+ * Adds the listener to the collection of listeners who will be
+ * notified when a window hosting the receiver needs to be displayed
+ * or hidden.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void addVisibilityWindowListener (VisibilityWindowListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.addVisibilityWindowListener (listener);
+}
+
+/**
+ * Navigate to the previous session history item.
+ *
+ * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @see #forward
+ * 
+ * @since 3.0
+ */
+public bool back () {
+    checkWidget();
+    return webBrowser.back ();
+}
+
+protected void checkSubclass () {
+    String name = getClass ().getName ();
+    int index = name.lastIndexOf ('.');
+    if (!name.substring (0, index + 1).equals (PACKAGE_PREFIX)) {
+        DWT.error (DWT.ERROR_INVALID_SUBCLASS);
+    }
+}
+
+/**
+ * Execute the specified script.
+ *
+ * <p>
+ * Execute a script containing javascript commands in the context of the current document. 
+ * 
+ * @param script the script with javascript commands
+ *  
+ * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the script is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public bool execute (String script) {
+    checkWidget();
+    if (script is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    return webBrowser.execute (script);
+}
+
+/**
+ * Navigate to the next session history item.
+ *
+ * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ * 
+ * @see #back
+ * 
+ * @since 3.0
+ */
+public bool forward () {
+    checkWidget();
+    return webBrowser.forward ();
+}
+
+public int getStyle () {
+    /*
+    * If DWT.BORDER was specified at creation time then getStyle() should answer
+    * it even though it is removed for IE on win32 in checkStyle().
+    */
+    return super.getStyle () | (userStyle & DWT.BORDER);
+}
+
+/**
+ * Returns a string with HTML that represents the content of the current page.
+ *
+ * @return HTML representing the current page or an empty <code>String</code>
+ * if this is empty
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public String getText () {
+    checkWidget();
+    return webBrowser.getText ();
+}
+
+/**
+ * Returns the current URL.
+ *
+ * @return the current URL or an empty <code>String</code> if there is no current URL
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @see #setUrl
+ * 
+ * @since 3.0
+ */
+public String getUrl () {
+    checkWidget();
+    return webBrowser.getUrl ();
+}
+
+/**
+ * Returns the JavaXPCOM <code>nsIWebBrowser</code> for the receiver, or <code>null</code>
+ * if it is not available.  In order for an <code>nsIWebBrowser</code> to be returned all
+ * of the following must be true: <ul>
+ *    <li>the receiver's style must be <code>DWT.MOZILLA</code></li>
+ *    <li>the classes from JavaXPCOM &gt;= 1.8.1.2 must be resolvable at runtime</li>
+ *    <li>the version of the underlying XULRunner must be &gt;= 1.8.1.2</li>
+ * </ul> 
+ *
+ * @return the receiver's JavaXPCOM <code>nsIWebBrowser</code> or <code>null</code>
+ * 
+ * @since 3.3
+ */
+public Object getWebBrowser () {
+    checkWidget();
+    return webBrowser.getWebBrowser ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver can navigate to the 
+ * previous session history item, and <code>false</code> otherwise.
+ *
+ * @return the receiver's back command enabled state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ * 
+ * @see #back
+ */
+public bool isBackEnabled () {
+    checkWidget();
+    return webBrowser.isBackEnabled ();
+}
+
+public bool isFocusControl () {
+    checkWidget();
+    if (webBrowser.isFocusControl ()) return true;
+    return super.isFocusControl ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver can navigate to the 
+ * next session history item, and <code>false</code> otherwise.
+ *
+ * @return the receiver's forward command enabled state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ * 
+ * @see #forward
+ */
+public bool isForwardEnabled () {
+    checkWidget();
+    return webBrowser.isForwardEnabled ();
+}
+
+/**
+ * Refresh the current page.
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void refresh () {
+    checkWidget();
+    webBrowser.refresh ();
+}
+
+/**  
+ * Removes the listener from the collection of listeners who will
+ * be notified when the window hosting the receiver should be closed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ * 
+ * @since 3.0
+ */
+public void removeCloseWindowListener (CloseWindowListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.removeCloseWindowListener (listener);
+}
+
+/**  
+ * Removes the listener from the collection of listeners who will
+ * be notified when the current location is changed or about to be changed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ * 
+ * @since 3.0
+ */
+public void removeLocationListener (LocationListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.removeLocationListener (listener);
+}
+
+/**  
+ * Removes the listener from the collection of listeners who will
+ * be notified when a new window needs to be created.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ * 
+ * @since 3.0
+ */
+public void removeOpenWindowListener (OpenWindowListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.removeOpenWindowListener (listener);
+}
+
+/**  
+ * Removes the listener from the collection of listeners who will
+ * be notified when a progress is made during the loading of the current 
+ * URL or when the loading of the current URL has been completed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ * 
+ * @since 3.0
+ */
+public void removeProgressListener (ProgressListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.removeProgressListener (listener);
+}
+
+/**  
+ * Removes the listener from the collection of listeners who will
+ * be notified when the status text is changed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ * 
+ * @since 3.0
+ */
+public void removeStatusTextListener (StatusTextListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.removeStatusTextListener (listener);
+}
+
+/**  
+ * Removes the listener from the collection of listeners who will
+ * be notified when the title of the current document is available
+ * or has changed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ * 
+ * @since 3.0
+ */
+public void removeTitleListener (TitleListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.removeTitleListener (listener);
+}
+
+/**  
+ * Removes the listener from the collection of listeners who will
+ * be notified when a window hosting the receiver needs to be displayed
+ * or hidden.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ * 
+ * @since 3.0
+ */
+public void removeVisibilityWindowListener (VisibilityWindowListener listener) {
+    checkWidget();
+    if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    webBrowser.removeVisibilityWindowListener (listener);
+}
+
+/**
+ * Renders HTML.
+ * 
+ * <p>
+ * The html parameter is Unicode encoded since it is a java <code>String</code>.
+ * As a result, the HTML meta tag charset should not be set. The charset is implied
+ * by the <code>String</code> itself.
+ * 
+ * @param html the HTML content to be rendered
+ *
+ * @return true if the operation was successful and false otherwise.
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the html is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *  
+ * @see #setUrl
+ * 
+ * @since 3.0
+ */
+public bool setText (String html) {
+    checkWidget();
+    if (html is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    return webBrowser.setText (html);
+}
+
+/**
+ * Loads a URL.
+ * 
+ * @param url the URL to be loaded
+ *
+ * @return true if the operation was successful and false otherwise.
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the url is null</li>
+ * </ul>
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *  
+ * @see #getUrl
+ * 
+ * @since 3.0
+ */
+public bool setUrl (String url) {
+    checkWidget();
+    if (url is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
+    return webBrowser.setUrl (url);
+}
+
+/**
+ * Stop any loading and rendering activity.
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void stop () {
+    checkWidget();
+    webBrowser.stop ();
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/CloseWindowListener.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.CloseWindowListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * a {@link WindowEvent} notification when a {@link Browser} is 
+ * about to be closed and when its host window should be closed
+ * by the application.
+ * 
+ * @see Browser#addCloseWindowListener(CloseWindowListener)
+ * @see Browser#removeCloseWindowListener(CloseWindowListener)
+ * @see OpenWindowListener
+ * @see VisibilityWindowListener
+ * 
+ * @since 3.0
+ */
+public interface CloseWindowListener : DWTEventListener {
+
+/**
+ * This method is called when the window hosting a {@link Browser} should be closed.
+ * Application would typically close the {@link dwt.widgets.Shell} that
+ * hosts the <code>Browser</code>. The <code>Browser</code> is disposed after this
+ * notification.
+ *
+ * <p>The following fields in the <code>WindowEvent</code> apply:
+ * <ul>
+ * <li>(in) widget the <code>Browser</code> that is going to be disposed
+ * </ul></p>
+ *
+ * @param event the <code>WindowEvent</code> that specifies the <code>Browser</code>
+ * that is going to be disposed
+ * 
+ * @see dwt.widgets.Shell#close()
+ * 
+ * @since 3.0
+ */ 
+    public void close(WindowEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/Download.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,388 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+module dwt.browser.Download;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.internal.C;
+import dwt.internal.Compatibility;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIDownload;
+import dwt.internal.mozilla.nsIHelperAppLauncher;
+import dwt.internal.mozilla.nsILocalFile;
+import dwt.internal.mozilla.nsIProgressDialog;
+import dwt.internal.mozilla.nsISupports;
+import dwt.internal.mozilla.nsIURI;
+import dwt.internal.mozilla.nsIWebProgressListener;
+import dwt.layout.GridData;
+import dwt.layout.GridLayout;
+import dwt.widgets.Button;
+import dwt.widgets.Event;
+import dwt.widgets.Label;
+import dwt.widgets.Listener;
+import dwt.widgets.Shell;
+
+class Download {
+    XPCOMObject supports;
+    XPCOMObject download;
+    XPCOMObject progressDialog;
+    XPCOMObject webProgressListener;
+    nsIHelperAppLauncher helperAppLauncher;
+    int refCount = 0;
+
+    Shell shell;
+    Label status;
+    Button cancel;
+    
+Download () {
+    createCOMInterfaces ();
+}
+
+int AddRef () {
+    refCount++;
+    return refCount;
+}
+
+void createCOMInterfaces () {
+    /* Create each of the interfaces that this object implements */
+    supports = new XPCOMObject (new int[] {2, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+    };
+    
+    download = new XPCOMObject (new int[] {2, 0, 0, 7, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return Init (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return GetSource (args[0]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return GetTarget (args[0]);}
+        public int /*long*/ method6 (int /*long*/[] args) {return GetPersist (args[0]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return GetPercentComplete (args[0]);}
+        public int /*long*/ method8 (int /*long*/[] args) {return GetDisplayName (args[0]);}
+        public int /*long*/ method9 (int /*long*/[] args) {return SetDisplayName (args[0]);}
+        public int /*long*/ method10 (int /*long*/[] args) {return GetStartTime (args[0]);}
+        public int /*long*/ method11 (int /*long*/[] args) {return GetMIMEInfo (args[0]);}
+        public int /*long*/ method12 (int /*long*/[] args) {return GetListener (args[0]);}
+        public int /*long*/ method13 (int /*long*/[] args) {return SetListener (args[0]);}
+        public int /*long*/ method14 (int /*long*/[] args) {return GetObserver (args[0]);}
+        public int /*long*/ method15 (int /*long*/[] args) {return SetObserver (args[0]);}
+    };
+    
+    progressDialog = new XPCOMObject (new int[] {2, 0, 0, 7, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return Init (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return GetSource (args[0]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return GetTarget (args[0]);}
+        public int /*long*/ method6 (int /*long*/[] args) {return GetPersist (args[0]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return GetPercentComplete (args[0]);}
+        public int /*long*/ method8 (int /*long*/[] args) {return GetDisplayName (args[0]);}
+        public int /*long*/ method9 (int /*long*/[] args) {return SetDisplayName (args[0]);}
+        public int /*long*/ method10 (int /*long*/[] args) {return GetStartTime (args[0]);}
+        public int /*long*/ method11 (int /*long*/[] args) {return GetMIMEInfo (args[0]);}
+        public int /*long*/ method12 (int /*long*/[] args) {return GetListener (args[0]);}
+        public int /*long*/ method13 (int /*long*/[] args) {return SetListener (args[0]);}
+        public int /*long*/ method14 (int /*long*/[] args) {return GetObserver (args[0]);}
+        public int /*long*/ method15 (int /*long*/[] args) {return SetObserver (args[0]);}
+        public int /*long*/ method16 (int /*long*/[] args) {return Open (args[0]);}
+        public int /*long*/ method17 (int /*long*/[] args) {return GetCancelDownloadOnClose (args[0]);}
+        public int /*long*/ method18 (int /*long*/[] args) {return SetCancelDownloadOnClose ((int)/*64*/args[0]);}
+        public int /*long*/ method19 (int /*long*/[] args) {return GetDialog (args[0]);}
+        public int /*long*/ method20 (int /*long*/[] args) {return SetDialog (args[0]);}
+    };
+    
+    webProgressListener = new XPCOMObject (new int[] {2, 0, 0, 4, 6, 3, 4, 3}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return OnStateChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return OnProgressChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4], (int)/*64*/args[5]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return OnLocationChange (args[0], args[1], args[2]);}
+        public int /*long*/ method6 (int /*long*/[] args) {return OnStatusChange (args[0], args[1], (int)/*64*/args[2], args[3]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return OnSecurityChange (args[0], args[1], (int)/*64*/args[2]);}
+    };
+}
+
+void disposeCOMInterfaces () {
+    if (supports !is null) {
+        supports.dispose ();
+        supports = null;
+    }   
+    if (download !is null) {
+        download.dispose ();
+        download = null;    
+    }
+    if (progressDialog !is null) {
+        progressDialog.dispose ();
+        progressDialog = null;
+    }
+    if (webProgressListener !is null) {
+        webProgressListener.dispose ();
+        webProgressListener = null;
+    }
+}
+
+int /*long*/ getAddress () {
+    return progressDialog.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+    if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+    nsID guid = new nsID ();
+    XPCOM.memmove (guid, riid, nsID.sizeof);
+
+    if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+        AddRef();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIDownload.NS_IDOWNLOAD_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {download.getAddress ()}, C.PTR_SIZEOF);
+        AddRef();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIProgressDialog.NS_IPROGRESSDIALOG_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {progressDialog.getAddress ()}, C.PTR_SIZEOF);
+        AddRef();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {webProgressListener.getAddress ()}, C.PTR_SIZEOF);
+        AddRef();
+        return XPCOM.NS_OK;
+    }
+    XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+            
+int Release () {
+    refCount--;
+    if (refCount is 0) disposeCOMInterfaces ();
+    return refCount;
+}
+
+/* nsIDownload */
+
+/* Note. The argument startTime is defined as a PRInt64. This translates into two java ints. */
+int Init (int /*long*/ aSource, int /*long*/ aTarget, int /*long*/ aDisplayName, int /*long*/ aMIMEInfo, int /*long*/ startTime1, int /*long*/ startTime2, int /*long*/ aPersist) {
+    nsIURI source = new nsIURI (aSource);
+    int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
+    int rc = source.GetHost (aSpec);
+    if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+    int length = XPCOM.nsEmbedCString_Length (aSpec);
+    int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
+    byte[] dest = new byte[length];
+    XPCOM.memmove (dest, buffer, length);
+    XPCOM.nsEmbedCString_delete (aSpec);
+    String url = new String (dest);
+
+    /*
+    * As of mozilla 1.7 the second argument of the nsIDownload interface's 
+    * Init function changed from nsILocalFile to nsIURI.  Detect which of
+    * these interfaces the second argument implements and act accordingly.  
+    */
+    String filename = null;
+    nsISupports supports = new nsISupports (aTarget);
+    int /*long*/[] result = new int /*long*/[1];
+    rc = supports.QueryInterface (nsIURI.NS_IURI_IID, result);
+    if (rc is 0) {  /* >= 1.7 */
+        nsIURI target = new nsIURI (result[0]);
+        result[0] = 0;
+        int /*long*/ aPath = XPCOM.nsEmbedCString_new ();
+        rc = target.GetPath (aPath);
+        if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+        length = XPCOM.nsEmbedCString_Length (aPath);
+        buffer = XPCOM.nsEmbedCString_get (aPath);
+        dest = new byte[length];
+        XPCOM.memmove (dest, buffer, length);
+        XPCOM.nsEmbedCString_delete (aPath);
+        filename = new String (dest);
+        int separator = filename.lastIndexOf (System.getProperty ("file.separator"));   //$NON-NLS-1$
+        filename = filename.substring (separator + 1);
+        target.Release ();
+    } else {    /* < 1.7 */
+        nsILocalFile target = new nsILocalFile (aTarget);
+        int /*long*/ aNativeTarget = XPCOM.nsEmbedCString_new ();
+        rc = target.GetNativeLeafName (aNativeTarget);
+        if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+        length = XPCOM.nsEmbedCString_Length (aNativeTarget);
+        buffer = XPCOM.nsEmbedCString_get (aNativeTarget);
+        dest = new byte[length];
+        XPCOM.memmove (dest, buffer, length);
+        XPCOM.nsEmbedCString_delete (aNativeTarget);
+        filename = new String (dest);
+    }
+
+    Listener listener = new Listener () {
+        public void handleEvent (Event event) {
+            if (event.widget is cancel) {
+                shell.close ();
+            }
+            if (helperAppLauncher !is null) {
+                helperAppLauncher.Cancel ();
+                helperAppLauncher.Release ();
+            }
+            shell = null;
+            helperAppLauncher = null;
+        }
+    };
+    shell = new Shell (DWT.DIALOG_TRIM);
+    String msg = Compatibility.getMessage ("SWT_Download_File", new Object[] {filename}); //$NON-NLS-1$
+    shell.setText (msg);
+    GridLayout gridLayout = new GridLayout ();
+    gridLayout.marginHeight = 15;
+    gridLayout.marginWidth = 15;
+    gridLayout.verticalSpacing = 20;
+    shell.setLayout(gridLayout);
+    msg = Compatibility.getMessage ("SWT_Download_Location", new Object[] {filename, url}); //$NON-NLS-1$
+    new Label (shell, DWT.SIMPLE).setText (msg);
+    status = new Label (shell, DWT.SIMPLE);
+    msg = Compatibility.getMessage ("SWT_Download_Started"); //$NON-NLS-1$
+    status.setText (msg);
+    GridData data = new GridData ();
+    data.grabExcessHorizontalSpace = true;
+    data.grabExcessVerticalSpace = true;
+    status.setLayoutData (data);
+
+    cancel = new Button (shell, DWT.PUSH);
+    cancel.setText (DWT.getMessage ("SWT_Cancel")); //$NON-NLS-1$
+    data = new GridData ();
+    data.horizontalAlignment = GridData.CENTER;
+    cancel.setLayoutData (data);
+    cancel.addListener (DWT.Selection, listener);
+    shell.addListener (DWT.Close, listener);
+    shell.pack ();
+    shell.open ();
+    return XPCOM.NS_OK;
+}
+
+int GetSource (int /*long*/ aSource) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetTarget (int /*long*/ aTarget) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetPersist (int /*long*/ aPersist) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetPercentComplete (int /*long*/ aPercentComplete) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetDisplayName (int /*long*/ aDisplayName) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetDisplayName (int /*long*/ aDisplayName) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetStartTime (int /*long*/ aStartTime) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetMIMEInfo (int /*long*/ aMIMEInfo) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetListener (int /*long*/ aListener) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetListener (int /*long*/ aListener) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetObserver (int /*long*/ aObserver) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetObserver (int /*long*/ aObserver) {
+    if (aObserver !is 0) {
+        nsISupports supports = new nsISupports (aObserver);
+        int /*long*/[] result = new int /*long*/[1];
+        int rc = supports.QueryInterface (nsIHelperAppLauncher.NS_IHELPERAPPLAUNCHER_IID, result);
+        if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+        if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE);
+        helperAppLauncher = new nsIHelperAppLauncher (result[0]);
+    }
+    return XPCOM.NS_OK;
+}
+
+/* nsIProgressDialog */
+int Open (int /*long*/ aParent) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetCancelDownloadOnClose (int /*long*/ aCancelDownloadOnClose) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetCancelDownloadOnClose (int aCancelDownloadOnClose) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetDialog (int /*long*/ aDialog) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetDialog (int /*long*/ aDialog) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIWebProgressListener */
+
+int OnStateChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStateFlags, int aStatus) {
+    if ((aStateFlags & nsIWebProgressListener.STATE_STOP) !is 0) {
+        if (helperAppLauncher !is null) helperAppLauncher.Release ();
+        helperAppLauncher = null;
+        if (shell !is null && !shell.isDisposed ()) shell.dispose ();
+        shell = null;
+    }
+    return XPCOM.NS_OK;
+}
+
+int OnProgressChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aCurSelfProgress, int aMaxSelfProgress, int aCurTotalProgress, int aMaxTotalProgress) {
+    int currentKBytes = aCurTotalProgress / 1024;
+    int totalKBytes = aMaxTotalProgress / 1024;
+    if (shell !is null && !shell.isDisposed ()) {
+        Object[] arguments = {new Integer (currentKBytes), new Integer (totalKBytes)};
+        String statusMsg = Compatibility.getMessage ("SWT_Download_Status", arguments); //$NON-NLS-1$
+        status.setText (statusMsg);
+        shell.layout (true);
+        shell.getDisplay ().update ();
+    }
+    return XPCOM.NS_OK;
+}
+
+int OnLocationChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int /*long*/ aLocation) {
+    return XPCOM.NS_OK;
+}
+
+int OnStatusChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStatus, int /*long*/ aMessage) {
+    return XPCOM.NS_OK;
+}
+
+int OnSecurityChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int state) {
+    return XPCOM.NS_OK;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/DownloadFactory.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+module dwt.browser.DownloadFactory;
+
+import dwt.dwthelper.utils;
+
+import dwt.browser.Download;
+
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIFactory;
+import dwt.internal.mozilla.nsISupports;
+
+class DownloadFactory : nsIFactory
+{
+    int _refCount = 0;
+
+    nsrefcnt AddRef () 
+    {
+        _refCount++;
+        return _refCount;
+    }
+
+    int QueryInterface ( ref nsIID riid, void** ppvObject) 
+    {
+        if (riid is null || ppvObject is null) 
+            return NS_ERROR_NO_INTERFACE;
+        
+        if ( riid == nsISupports.IID) 
+        {
+            *ppvObject = cast(void*)cast(nsISupports)this;
+            AddRef ();
+            return NS_OK;
+        }
+
+        if ( riid == nsIFactory.IID) 
+        {
+            *ppvObject = cast(void*)cast(nsIFactory)this;
+            AddRef ();
+            return NS_OK;
+        }
+    
+        *ppvObject = null;
+        return NS_ERROR_NO_INTERFACE;
+    }
+            
+    nsrefcnt Release () 
+    {
+        _refCount--;
+        if (_refCount is 0) 
+            _refCount = 0;
+    return _refCount;
+    }
+    
+/* nsIFactory */
+
+    nsresult CreateInstance ( nsISupports aOuter, nsIID* iid, void** result) 
+    {
+        Download download = new Download ();
+        download.AddRef ();
+        nsresult rv = download.QueryInterface( iid, result );
+        return rv;
+    }
+
+    nsresult LockFactory (int lock) 
+    {
+        return NS_OK;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/DownloadFactory_1_8.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.DownloadFactory_1_8;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIFactory;
+import dwt.internal.mozilla.nsISupports;
+
+class DownloadFactory_1_8 {
+    XPCOMObject supports;
+    XPCOMObject factory;
+    int refCount = 0;
+
+DownloadFactory_1_8 () {
+    createCOMInterfaces ();
+}
+
+int AddRef () {
+    refCount++;
+    return refCount;
+}
+
+void createCOMInterfaces () {
+    /* Create each of the interfaces that this object implements */
+    supports = new XPCOMObject (new int[] {2, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+    };
+    
+    factory = new XPCOMObject (new int[] {2, 0, 0, 3, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return CreateInstance (args[0], args[1], args[2]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return LockFactory ((int)/*64*/args[0]);}
+    };
+}
+
+void disposeCOMInterfaces () {
+    if (supports !is null) {
+        supports.dispose ();
+        supports = null;
+    }   
+    if (factory !is null) {
+        factory.dispose ();
+        factory = null; 
+    }
+}
+
+int /*long*/ getAddress () {
+    return factory.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+    if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+    nsID guid = new nsID ();
+    XPCOM.memmove (guid, riid, nsID.sizeof);
+    
+    if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIFactory.NS_IFACTORY_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {factory.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    
+    XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+            
+int Release () {
+    refCount--;
+    if (refCount is 0) disposeCOMInterfaces ();
+    return refCount;
+}
+
+/* nsIFactory */
+
+int CreateInstance (int /*long*/ aOuter, int /*long*/ iid, int /*long*/ result) {
+    Download_1_8 download = new Download_1_8 ();
+    download.AddRef ();
+    XPCOM.memmove (result, new int /*long*/[] {download.getAddress ()}, C.PTR_SIZEOF);
+    return XPCOM.NS_OK;
+}
+
+int LockFactory (int lock) {
+    return XPCOM.NS_OK;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/Download_1_8.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,407 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.Download_1_8;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.internal.C;
+import dwt.internal.Compatibility;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsICancelable;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIDownload_1_8;
+import dwt.internal.mozilla.nsIProgressDialog_1_8;
+import dwt.internal.mozilla.nsISupports;
+import dwt.internal.mozilla.nsIURI;
+import dwt.internal.mozilla.nsIWebProgressListener;
+import dwt.layout.GridData;
+import dwt.layout.GridLayout;
+import dwt.widgets.Button;
+import dwt.widgets.Event;
+import dwt.widgets.Label;
+import dwt.widgets.Listener;
+import dwt.widgets.Shell;
+
+class Download_1_8 {
+    XPCOMObject supports;
+    XPCOMObject download;
+    XPCOMObject progressDialog;
+    XPCOMObject webProgressListener;
+    nsICancelable cancelable;
+    int refCount = 0;
+
+    Shell shell;
+    Label status;
+    Button cancel;
+
+    static final bool is32 = C.PTR_SIZEOF is 4;
+
+Download_1_8 () {
+    createCOMInterfaces ();
+}
+
+int AddRef () {
+    refCount++;
+    return refCount;
+}
+
+void createCOMInterfaces () {
+    /* Create each of the interfaces that this object implements */
+    supports = new XPCOMObject (new int[] {2, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+    };
+
+    download = new XPCOMObject (new int[] {2, 0, 0, 4, 6, 3, 4, 3, is32 ? 10 : 6, is32 ? 8 : 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return OnStateChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return OnProgressChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4], (int)/*64*/args[5]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return OnLocationChange (args[0], args[1], args[2]);}
+        public int /*long*/ method6 (int /*long*/[] args) {return OnStatusChange (args[0], args[1], (int)/*64*/args[2], args[3]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return OnSecurityChange (args[0], args[1], (int)/*64*/args[2]);}
+        public int /*long*/ method8 (int /*long*/[] args) {
+            if (args.length is 10) {
+                return OnProgressChange64_32 (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
+            } else {
+                return OnProgressChange64 (args[0], args[1], args[2], args[3], args[4], args[5]);
+            }
+        }
+        public int /*long*/ method9 (int /*long*/[] args) {
+            if (args.length is 8) {
+                return Init_32 (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+            } else {
+                return Init (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+            }
+        }
+        public int /*long*/ method10 (int /*long*/[] args) {return GetTargetFile (args[0]);}
+        public int /*long*/ method11 (int /*long*/[] args) {return GetPercentComplete (args[0]);}
+        public int /*long*/ method12 (int /*long*/[] args) {return GetAmountTransferred (args[0]);}
+        public int /*long*/ method13 (int /*long*/[] args) {return GetSize (args[0]);}
+        public int /*long*/ method14 (int /*long*/[] args) {return GetSource (args[0]);}
+        public int /*long*/ method15 (int /*long*/[] args) {return GetTarget (args[0]);}
+        public int /*long*/ method16 (int /*long*/[] args) {return GetCancelable (args[0]);}
+        public int /*long*/ method17 (int /*long*/[] args) {return GetDisplayName (args[0]);}
+        public int /*long*/ method18 (int /*long*/[] args) {return GetStartTime (args[0]);}
+        public int /*long*/ method19 (int /*long*/[] args) {return GetMIMEInfo (args[0]);}
+    };
+
+    progressDialog = new XPCOMObject (new int[] {2, 0, 0, 4, 6, 3, 4, 3, is32 ? 10 : 6, is32 ? 8 : 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return OnStateChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return OnProgressChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4], (int)/*64*/args[5]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return OnLocationChange (args[0], args[1], args[2]);}
+        public int /*long*/ method6 (int /*long*/[] args) {return OnStatusChange (args[0], args[1], (int)/*64*/args[2], args[3]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return OnSecurityChange (args[0], args[1], (int)/*64*/args[2]);}
+        public int /*long*/ method8 (int /*long*/[] args) {
+            if (args.length is 10) {
+                return OnProgressChange64_32 (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
+            } else {
+                return OnProgressChange64 (args[0], args[1], args[2], args[3], args[4], args[5]);
+            }
+        }
+        public int /*long*/ method9 (int /*long*/[] args) {
+            if (args.length is 8) {
+                return Init_32 (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+            } else {
+                return Init (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+            }
+        }
+        public int /*long*/ method10 (int /*long*/[] args) {return GetTargetFile (args[0]);}
+        public int /*long*/ method11 (int /*long*/[] args) {return GetPercentComplete (args[0]);}
+        public int /*long*/ method12 (int /*long*/[] args) {return GetAmountTransferred (args[0]);}
+        public int /*long*/ method13 (int /*long*/[] args) {return GetSize (args[0]);}
+        public int /*long*/ method14 (int /*long*/[] args) {return GetSource (args[0]);}
+        public int /*long*/ method15 (int /*long*/[] args) {return GetTarget (args[0]);}
+        public int /*long*/ method16 (int /*long*/[] args) {return GetCancelable (args[0]);}
+        public int /*long*/ method17 (int /*long*/[] args) {return GetDisplayName (args[0]);}
+        public int /*long*/ method18 (int /*long*/[] args) {return GetStartTime (args[0]);}
+        public int /*long*/ method19 (int /*long*/[] args) {return GetMIMEInfo (args[0]);}
+        public int /*long*/ method20 (int /*long*/[] args) {return Open (args[0]);}
+        public int /*long*/ method21 (int /*long*/[] args) {return GetCancelDownloadOnClose (args[0]);}
+        public int /*long*/ method22 (int /*long*/[] args) {return SetCancelDownloadOnClose ((int)/*64*/args[0]);}
+        public int /*long*/ method23 (int /*long*/[] args) {return GetObserver (args[0]);}
+        public int /*long*/ method24 (int /*long*/[] args) {return SetObserver (args[0]);}
+        public int /*long*/ method25 (int /*long*/[] args) {return GetDialog (args[0]);}
+        public int /*long*/ method26 (int /*long*/[] args) {return SetDialog (args[0]);}
+    };
+
+    webProgressListener = new XPCOMObject (new int[] {2, 0, 0, 4, 6, 3, 4, 3}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return OnStateChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return OnProgressChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4], (int)/*64*/args[5]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return OnLocationChange (args[0], args[1], args[2]);}
+        public int /*long*/ method6 (int /*long*/[] args) {return OnStatusChange (args[0], args[1], (int)/*64*/args[2], args[3]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return OnSecurityChange (args[0], args[1], (int)/*64*/args[2]);}
+    };
+}
+
+void disposeCOMInterfaces() {
+    if (supports !is null) {
+        supports.dispose ();
+        supports = null;
+    }   
+    if (download !is null) {
+        download.dispose ();
+        download = null;    
+    }
+    if (progressDialog !is null) {
+        progressDialog.dispose ();
+        progressDialog = null;  
+    }
+    if (webProgressListener !is null) {
+        webProgressListener.dispose ();
+        webProgressListener = null; 
+    }
+}
+
+int /*long*/ getAddress () {
+    return progressDialog.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+    if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+    nsID guid = new nsID ();
+    XPCOM.memmove (guid, riid, nsID.sizeof);
+
+    if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+        AddRef();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIDownload_1_8.NS_IDOWNLOAD_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {download.getAddress ()}, C.PTR_SIZEOF);
+        AddRef();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIProgressDialog_1_8.NS_IPROGRESSDIALOG_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {progressDialog.getAddress ()}, C.PTR_SIZEOF);
+        AddRef();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {webProgressListener.getAddress ()}, C.PTR_SIZEOF);
+        AddRef();
+        return XPCOM.NS_OK;
+    }
+    XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+    refCount--;
+    if (refCount is 0) disposeCOMInterfaces ();
+    return refCount;
+}
+
+/* nsIDownload */
+
+/* Note. The argument startTime is defined as a PRInt64. This translates into two java ints. */
+int Init_32 (int /*long*/ aSource, int /*long*/ aTarget, int /*long*/ aDisplayName, int /*long*/ aMIMEInfo, int /*long*/ startTime1, int /*long*/ startTime2, int /*long*/ aTempFile, int /*long*/ aCancelable) {
+    long startTime = (startTime2 << 32) + startTime1;
+    return Init (aSource, aTarget, aDisplayName, aMIMEInfo, startTime, aTempFile, aCancelable);
+}
+
+int Init (int /*long*/ aSource, int /*long*/ aTarget, int /*long*/ aDisplayName, int /*long*/ aMIMEInfo, long startTime, int /*long*/ aTempFile, int /*long*/ aCancelable) {
+    cancelable = new nsICancelable (aCancelable);
+    nsIURI source = new nsIURI (aSource);
+    int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
+    int rc = source.GetHost (aSpec);
+    if (rc !is XPCOM.NS_OK) Mozilla.error(rc);
+    int length = XPCOM.nsEmbedCString_Length (aSpec);
+    int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
+    byte[] dest = new byte[length];
+    XPCOM.memmove (dest, buffer, length);
+    XPCOM.nsEmbedCString_delete (aSpec);
+    String url = new String (dest);
+
+    nsIURI target = new nsIURI (aTarget);
+    int /*long*/ aPath = XPCOM.nsEmbedCString_new ();
+    rc = target.GetPath (aPath);
+    if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+    length = XPCOM.nsEmbedCString_Length (aPath);
+    buffer = XPCOM.nsEmbedCString_get (aPath);
+    dest = new byte[length];
+    XPCOM.memmove (dest, buffer, length);
+    XPCOM.nsEmbedCString_delete (aPath);
+    String filename = new String (dest);
+    int separator = filename.lastIndexOf (System.getProperty ("file.separator"));   //$NON-NLS-1$
+    filename = filename.substring (separator + 1);
+
+    Listener listener = new Listener() {
+        public void handleEvent (Event event) {
+            if (event.widget is cancel) {
+                shell.close ();
+            }
+            if (cancelable !is null) {
+                int rc = cancelable.Cancel (XPCOM.NS_BINDING_ABORTED);
+                if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+            }
+            shell = null;
+            cancelable = null;
+        }
+    };
+    shell = new Shell (DWT.DIALOG_TRIM);
+    String msg = Compatibility.getMessage ("SWT_Download_File", new Object[] {filename}); //$NON-NLS-1$
+    shell.setText (msg);
+    GridLayout gridLayout = new GridLayout ();
+    gridLayout.marginHeight = 15;
+    gridLayout.marginWidth = 15;
+    gridLayout.verticalSpacing = 20;
+    shell.setLayout (gridLayout);
+    msg = Compatibility.getMessage ("SWT_Download_Location", new Object[] {filename, url}); //$NON-NLS-1$
+    new Label (shell, DWT.SIMPLE).setText (msg);
+    status = new Label (shell, DWT.SIMPLE);
+    msg = Compatibility.getMessage ("SWT_Download_Started"); //$NON-NLS-1$
+    status.setText (msg);
+    GridData data = new GridData ();
+    data.grabExcessHorizontalSpace = true;
+    data.grabExcessVerticalSpace = true;
+    status.setLayoutData (data);
+    
+    cancel = new Button (shell, DWT.PUSH);
+    cancel.setText (DWT.getMessage ("SWT_Cancel")); //$NON-NLS-1$
+    data = new GridData ();
+    data.horizontalAlignment = GridData.CENTER;
+    cancel.setLayoutData (data);
+    cancel.addListener (DWT.Selection, listener);
+    shell.addListener (DWT.Close, listener);
+    shell.pack ();
+    shell.open ();
+    return XPCOM.NS_OK;
+}
+
+int GetAmountTransferred (int /*long*/ arg0) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetCancelable (int /*long*/ arg0) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetDisplayName (int /*long*/ aDisplayName) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetMIMEInfo (int /*long*/ aMIMEInfo) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetPercentComplete (int /*long*/ aPercentComplete) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetSize (int /*long*/ arg0) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetSource (int /*long*/ aSource) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetStartTime (int /*long*/ aStartTime) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetTarget (int /*long*/ aTarget) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetTargetFile (int /*long*/ arg0) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIProgressDialog */
+int GetCancelDownloadOnClose (int /*long*/ aCancelDownloadOnClose) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetDialog (int /*long*/ aDialog) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetObserver (int /*long*/ aObserver) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int Open (int /*long*/ aParent) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetCancelDownloadOnClose (int aCancelDownloadOnClose) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetDialog (int /*long*/ aDialog) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetObserver (int /*long*/ aObserver) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIWebProgressListener */
+
+int OnLocationChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int /*long*/ aLocation) {
+    return XPCOM.NS_OK;
+}
+
+int OnProgressChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aCurSelfProgress, int aMaxSelfProgress, int aCurTotalProgress, int aMaxTotalProgress) {
+    return OnProgressChange64 (aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
+}
+
+/* Note. The last 4 args in the original interface are defined as PRInt64. These each translate into two java ints. */
+int OnProgressChange64_32 (int /*long*/ aWebProgress, int /*long*/ aRequest, int /*long*/ aCurSelfProgress1, int /*long*/ aCurSelfProgress2, int /*long*/ aMaxSelfProgress1, int /*long*/ aMaxSelfProgress2, int /*long*/ aCurTotalProgress1, int /*long*/ aCurTotalProgress2, int /*long*/ aMaxTotalProgress1, int /*long*/ aMaxTotalProgress2) {
+    long aCurSelfProgress = (aCurSelfProgress2 << 32) + aCurSelfProgress1;
+    long aMaxSelfProgress = (aMaxSelfProgress2 << 32) + aMaxSelfProgress1;
+    long aCurTotalProgress = (aCurTotalProgress2 << 32) + aCurTotalProgress1;
+    long aMaxTotalProgress = (aMaxTotalProgress2 << 32) + aMaxTotalProgress1;
+    return OnProgressChange64 (aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
+}
+
+int OnProgressChange64 (int /*long*/ aWebProgress, int /*long*/ aRequest, long aCurSelfProgress, long aMaxSelfProgress, long aCurTotalProgress, long aMaxTotalProgress) {
+    long currentKBytes = aCurTotalProgress / 1024;
+    long totalKBytes = aMaxTotalProgress / 1024;
+    if (shell !is null && !shell.isDisposed ()) {
+        Object[] arguments = {new Long (currentKBytes), new Long (totalKBytes)};
+        String statusMsg = Compatibility.getMessage ("SWT_Download_Status", arguments); //$NON-NLS-1$
+        status.setText (statusMsg);
+        shell.layout (true);
+        shell.getDisplay ().update ();
+    }
+    return XPCOM.NS_OK;
+}
+
+int OnSecurityChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int state) {
+    return XPCOM.NS_OK;
+}
+
+int OnStateChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStateFlags, int aStatus) {
+    if ((aStateFlags & nsIWebProgressListener.STATE_STOP) !is 0) {
+        cancelable = null;
+        if (shell !is null && !shell.isDisposed ()) shell.dispose ();
+        shell = null;
+    }
+    return XPCOM.NS_OK;
+}   
+
+int OnStatusChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStatus, int /*long*/ aMessage) {
+    return XPCOM.NS_OK;
+}       
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/FilePicker.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,453 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+
+module dwt.browser.FilePicker;
+
+import tango.io.model.IFile;
+import Utf = tango.text.convert.Utf;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+
+import XPCOM = dwt.internal.mozilla.nsXPCOM;
+
+import dwt.browser.Mozilla;
+import dwt.browser.MozillaDelegate;
+
+import dwt.internal.mozilla.nsEmbedString;
+import dwt.internal.mozilla.nsIDOMWindow;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIFilePicker;
+import dwt.internal.mozilla.nsILocalFile;
+import dwt.internal.mozilla.nsISupports;
+import dwt.internal.mozilla.nsSimpleEnumerator;
+import dwt.internal.mozilla.nsStringAPI;
+import dwt.internal.mozilla.nsError;
+
+import dwt.widgets.DirectoryDialog;
+import dwt.widgets.Display;
+import dwt.widgets.FileDialog;
+import dwt.widgets.Shell;
+
+
+class FilePicker : nsISupports, nsIFilePicker 
+{
+    /**************************************************************************
+
+    **************************************************************************/
+    
+    private 
+    {
+        int      _refCount = 0;
+        short    _mode;
+
+        nsIDOMWindow _parent;
+
+        String[] _files;
+        String   _masks;
+        String   _defaultFilename, 
+                 _directory, 
+                 _title;
+    }
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static final String SEPARATOR = FileConst.FileSeparatorChar;
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    this () 
+    {
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsrefcnt AddRef () 
+    {
+        _refCount++;
+        return _refCount;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult QueryInterface ( inout nsID riid, void** ppvObject) 
+    {   
+        if (riid is null || ppvObject is null) 
+            return NS_ERROR_NO_INTERFACE;
+    
+        if (riid == nsISupports.IID) 
+        {
+            *ppvObject = cast(void*)cast(nsISupports) this;
+            AddRef ();
+            return NS_OK;
+        }
+    
+        if (riid == nsIFilePicker.IID)) 
+        {
+            *ppvObject = cast(void*)cast(nsIFilePicker) this;
+            AddRef ();
+            return NS_OK;
+        }
+    
+        if (riid == nsIFilePicker_1_8.IID) 
+        {
+            *ppvObject = cast(void*)cast(nsIFilePicker_1_8) this;
+            AddRef ();
+            return NS_OK;
+        }
+
+        *ppvObject = null; 
+        return NS_ERROR_NO_INTERFACE;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsrefcnt Release () 
+    {
+        _refCount--;
+        
+        if (_refCount is 0) 
+            // No big deal here; just allow the GC to reap this object
+            // once all references are expired. -JJR
+            // delete this;
+            return 0;
+        
+        return _refCount;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    /* SWT Comment:
+     *
+     * As of Mozilla 1.8 some of nsIFilePicker's string arguments changed type.  This method
+     * answers a java string based on the type of string that is appropriate for the Mozilla
+     * version being used.
+     */
+
+    override String parseAString (nsEmbedString str) 
+    {
+        return null;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    /* nsIFilePicker */
+
+    nsresult Init (nsIDOMWindow parent, nsAString* title, PRInt16 mode) 
+    {
+        _parent = parent;
+        _mode = mode;
+        _title = parseAString (title);
+        return XPCOM;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult Show (PRUint32* retval) 
+    {
+        if (_mode is nsIFilePicker.modeGetFolder) 
+        {
+            /* picking a directory */
+            int result = this.showDirectoryPicker ();
+            *retval = result;
+            return NS_OK;
+        }
+
+        /* picking a file */
+        int style = _mode is nsIFilePicker.modeSave ? DWT.SAVE : DWT.OPEN;
+
+        if (_mode is nsIFilePicker.modeOpenMultiple) 
+            style |= DWT.MULTI;
+
+        Display display = Display.getCurrent ();
+        Shell parent = null; // TODO compute parent
+
+        if (parent is null) 
+        {
+            parent = new Shell (display);
+        }
+
+        FileDialog dialog = new FileDialog (parent, style);
+        
+        if (_title !is null) 
+            dialog.setText (_title);
+        
+        if (_directory !is null) 
+            dialog.setFilterPath (_directory);
+        
+        if (_masks !is null) {
+            String[] str ~= _masks;
+            dialog.setFilterExtensions ( str );
+        }
+        
+        if (_defaultFilename !is null) 
+            dialog.setFileName (_defaultFilename);
+        
+        String filename = dialog.open ();
+        files = dialog.getFileNames ();
+        _directory = dialog.getFilterPath ();
+        _title = _defaultFilename = null;
+        _masks = null;
+        int result = filename is null ? nsIFilePicker.returnCancel : nsIFilePicker.returnOK; 
+        *retval = result;
+        return NS_OK;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    int showDirectoryPicker () 
+    {
+        Display display = Display.getCurrent ();
+        Shell parent = null; // TODO compute parent
+        
+        if (parent is null) 
+        {
+            parent = new Shell (display);
+        }
+        
+        DirectoryDialog dialog = new DirectoryDialog (parent, DWT.NONE);
+        
+        if (_title !is null) 
+            dialog.setText (_title);
+        if (_directory !is null) 
+            dialog.setFilterPath (_directory);
+        _directory = dialog.open ();
+        _title = _defaultFilename = null;
+        _files = _masks = null;
+        return _directory is null ? nsIFilePicker.returnCancel : nsIFilePicker.returnOK;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult GetFiles ( nsISimpleEnumerator* aFiles) 
+    {
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult GetFileURL (nsIFileURL aFileURL) 
+    {
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult GetFile (nsILocalFile* aFile) 
+    {
+        String filename = "";   //$NON-NLS-1$
+        
+        if (_directory !is null) 
+            filename ~= _directory ~ SEPARATOR;
+        if (_files !is null && _files.length > 0) 
+            filename ~= _files[0];
+        
+        // Create a nsEmbedString which will be automatically disposed 
+        // at the end of scope.
+        scope auto path = new nsEmbedString( filename );
+        
+        nsresult rc = XPCOM.NS_NewLocalFile ( cast(nsAString*)path, 1, aFile);
+
+        if (rc !is NS_OK) 
+            Mozilla.error (rc);
+        if (aFile is null) 
+            Mozilla.error (NS_ERROR_NULL_POINTER);
+
+        return NS_OK;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult SetDisplayDirectory (nsILocalFile aDisplayDirectory) 
+    {
+        if (aDisplayDirectory is null) 
+            return NS_OK;
+        
+        scope auto pathname = new nsEmbedCString;
+        aDisplayDirectory.GetNativePath ( cast(nsACString*)pathname );
+        // TODO: CHECK IF THIS DOES CORRECT STRING CONVERSION -JJR
+        char[] buffer = pathname.toString();
+        char[] chars = MozillaDelegate.mbcsToWcs (null, buffer);
+        // "buffer" contains a dup'ed string so we can safely reuse
+        // it's memory for the _directory member. -JJR
+        _directory = buffer;
+        return NS_OK;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult GetDisplayDirectory (nsILocalFile* aDisplayDirectory) 
+    {
+        String directoryName = _directory !is null ? _directory : ""; //$NON-NLS-1$
+        scope auto path = new nsEmbedString (directoryName);
+        nsresult rc = XPCOM.NS_NewLocalFile ( cast(nsAString*)path, 1, aDisplayDirectory);
+        
+        if (rc !is NS_OK) 
+            Mozilla.error (rc);
+        if (aDisplayDirectory is null) 
+            Mozilla.error (NS_ERROR_NULL_POINTER);
+        return NS_OK;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult SetFilterIndex (PRInt32 aFilterIndex) 
+    {
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nresult GetFilterIndex (PRInt32* aFilterIndex) 
+    {
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    int SetDefaultExtension (nsAString* aDefaultExtension) 
+    {
+        /* note that the type of argument 1 changed as of Mozilla 1.8 */
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    int GetDefaultExtension (nsAString* aDefaultExtension) 
+    {
+        /* note that the type of argument 1 changed as of Mozilla 1.8 */
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nresult SetDefaultString (nsAString* aDefaultString) 
+    {
+        defaultFilename = parseAString (aDefaultString);
+        return NS_OK;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nresult GetDefaultString (nsAString* aDefaultString) 
+    {
+        /* note that the type of argument 1 changed as of Mozilla 1.8 */
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nresult AppendFilter (nsAString* title, nsAString* filter)
+    {
+        /* note that the type of arguments 1 and 2 changed as of Mozilla 1.8 */
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nresult AppendFilters (PRInt32 filterMask) 
+    {
+        String addFilters;
+        
+        switch (filterMask) 
+        {
+            case nsIFilePicker.filterAll:
+            case nsIFilePicker.filterApps:
+                _masks = null;           /* this is equivalent to no filter */
+                break;
+            case nsIFilePicker.filterHTML:
+                addFilters = "*.htm;*.html" ;
+                break;
+            case nsIFilePicker.filterImages:
+                addFilters = "*.gif;*.jpeg;*.jpg;*.png";
+                break;
+            case nsIFilePicker.filterText:
+                addFilters = "*.txt";
+                break;
+            case nsIFilePicker.filterXML:
+                addFilters = "*.xml";
+                break;
+            case nsIFilePicker.filterXUL:
+                addFilters = "*.xul";
+                break;
+        }
+    
+        if (_masks is null) 
+        {
+            _masks = addFilters;
+        } else {
+            if (addFilters !is null)
+                _masks ~= addFilters;
+        }
+        return NS_OK;
+    }
+
+/******************************************************************************
+
+    FilePicker for Mozilla Version 1.8
+
+******************************************************************************/
+
+class FilePicker_1_8 : FilePicker
+{
+    String parseAString (nsEmbedString str) 
+    {
+        if (str is null) 
+            return null;
+        return Utf.toString( str.toString16() );
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/FilePickerFactory.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+
+module dwt.browser.FilePickerFactory;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.
+import dwt.internal.mozilla.nsIFactory;
+import dwt.internal.mozilla.nsISupports;
+
+class FilePickerFactory : nsISupports, nsIFactory 
+{
+
+    /**************************************************************************
+
+    **************************************************************************/
+    
+    int _refCount = 0;
+    
+    /**************************************************************************
+
+    **************************************************************************/
+
+    this () 
+    {
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsrefcnt AddRef () 
+    {
+        _refCount++;
+        return _refCount;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    int QueryInterface ( ref nsID riid, void** ppvObject)
+    {
+        if (riid is null || ppvObject is null) 
+            return NS_ERROR_NO_INTERFACE;
+        
+        if (guid == nsISupports.IID)) 
+        {
+            *ppvObject = cast(void*)cast(nsISupports) this; 
+            AddRef ();
+            return NS_OK;
+        }
+    
+        if (guid == nsIFactory.IID) 
+        {
+            *ppvObject = cast(void*)cast(nsIFactory) this;
+            AddRef ();
+            return NS_OK;
+        }
+    
+        *ppvObject = null;
+        return NS_ERROR_NO_INTERFACE;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsrefcnt Release () 
+    {
+        _refCount--;
+        if (_refCount is 0) 
+            return 0;
+        return _refCount;
+    }
+    
+    /**************************************************************************
+
+    **************************************************************************/
+
+    /* nsIFactory */
+
+    nsresult CreateInstance (nsISupports aOuter, nsIID* iid, void** result) 
+    {
+        if (result is null)
+            return NS_ERROR_INVALID_ARG;
+
+        FilePicker picker = new FilePicker ();
+        picker.AddRef ();
+
+        nsresult rv = picker.QueryInterface( iid, result );
+        
+        // TODO: If the query fails, the error should be checked and the 
+        //       newly created object deleted. In C++, this is done
+        //       like so:
+        //
+        //      if (NS_FAILED(rv)) {
+        //          *result = nsnull;
+        //          delete picker;
+        //      }
+        //
+        // Deletion of the object really isn't critical here for D, but
+        // it may be considered "good habit" to do anyway for XPCOM objects.
+        // For now, just return the rv value.  NS_FAILED needs to be
+        // ported first. -JJR
+
+        return rv;
+    }
+
+    nsresult LockFactory (int lock) 
+    {
+        return NS_OK;
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/FilePickerFactory_1_8.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.FilePickerFactory_1_8;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+
+class FilePickerFactory_1_8 extends FilePickerFactory {
+
+void createCOMInterfaces () {
+    /* Create each of the interfaces that this object implements */
+    supports = new XPCOMObject (new int[] {2, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+    };
+    
+    factory = new XPCOMObject (new int[] {2, 0, 0, 3, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return CreateInstance (args[0], args[1], args[2]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return LockFactory ((int)/*64*/args[0]);}
+    };
+}
+
+/* nsIFactory */
+
+int CreateInstance (int /*long*/ aOuter, int /*long*/ iid, int /*long*/ result) {
+    FilePicker_1_8 picker = new FilePicker_1_8 ();
+    picker.AddRef ();
+    XPCOM.memmove (result, new int /*long*/[] {picker.getAddress ()}, C.PTR_SIZEOF);
+    return XPCOM.NS_OK;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/FilePicker_1_8.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.FilePicker_1_8;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+
+class FilePicker_1_8 extends FilePicker {
+
+void createCOMInterfaces () {
+    /* Create each of the interfaces that this object implements */
+    supports = new XPCOMObject (new int[] {2, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+    };
+
+    filePicker = new XPCOMObject (new int[] {2, 0, 0, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return Init (args[0], args[1], (short)args[2]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return AppendFilters ((int)/*64*/args[0]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return AppendFilter (args[0], args[1]);}
+        public int /*long*/ method6 (int /*long*/[] args) {return GetDefaultString (args[0]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return SetDefaultString (args[0]);}
+        public int /*long*/ method8 (int /*long*/[] args) {return GetDefaultExtension (args[0]);}
+        public int /*long*/ method9 (int /*long*/[] args) {return SetDefaultExtension (args[0]);}
+        public int /*long*/ method10 (int /*long*/[] args) {return GetFilterIndex (args[0]);}
+        public int /*long*/ method11 (int /*long*/[] args) {return SetFilterIndex ((int)/*64*/args[0]);}
+        public int /*long*/ method12 (int /*long*/[] args) {return GetDisplayDirectory (args[0]);}
+        public int /*long*/ method13 (int /*long*/[] args) {return SetDisplayDirectory (args[0]);}
+        public int /*long*/ method14 (int /*long*/[] args) {return GetFile (args[0]);}
+        public int /*long*/ method15 (int /*long*/[] args) {return GetFileURL (args[0]);}
+        public int /*long*/ method16 (int /*long*/[] args) {return GetFiles (args[0]);}
+        public int /*long*/ method17 (int /*long*/[] args) {return Show (args[0]);}
+    };
+}
+
+/*
+ * As of Mozilla 1.8 some of nsIFilePicker's string arguments changed type.  This method
+ * answers a java string based on the type of string that is appropriate for the Mozilla
+ * version being used.
+ */
+String parseAString (int /*long*/ string) {
+    if (string is 0) return null;
+    int length = XPCOM.nsEmbedString_Length (string);
+    int /*long*/ buffer = XPCOM.nsEmbedString_get (string);
+    char[] chars = new char[length];
+    XPCOM.memmove (chars, buffer, length * 2);
+    return new String (chars);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/HelperAppLauncherDialog.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.HelperAppLauncherDialog;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsEmbedString;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIHelperAppLauncher;
+import dwt.internal.mozilla.nsIHelperAppLauncherDialog;
+import dwt.internal.mozilla.nsIHelperAppLauncher_1_8;
+import dwt.internal.mozilla.nsIHelperAppLauncher_1_9;
+import dwt.internal.mozilla.nsISupports;
+import dwt.widgets.FileDialog;
+import dwt.widgets.Shell;
+
+class HelperAppLauncherDialog {
+    XPCOMObject supports;
+    XPCOMObject helperAppLauncherDialog;
+    int refCount = 0;
+
+HelperAppLauncherDialog () {
+    createCOMInterfaces ();
+}
+
+int AddRef () {
+    refCount++;
+    return refCount;
+}
+
+void createCOMInterfaces () {
+    /* Create each of the interfaces that this object implements */
+    supports = new XPCOMObject (new int[] {2, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+    };
+    
+    helperAppLauncherDialog = new XPCOMObject (new int[] {2, 0, 0, 3, 5}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return Show (args[0], args[1], (int)/*64*/args[2]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return PromptForSaveToFile (args[0], args[1], args[2], args[3], args[4]);}
+    };      
+}
+
+void disposeCOMInterfaces () {
+    if (supports !is null) {
+        supports.dispose ();
+        supports = null;
+    }   
+    if (helperAppLauncherDialog !is null) {
+        helperAppLauncherDialog.dispose ();
+        helperAppLauncherDialog = null; 
+    }
+}
+
+int /*long*/ getAddress () {
+    return helperAppLauncherDialog.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+    if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+    nsID guid = new nsID ();
+    XPCOM.memmove (guid, riid, nsID.sizeof);
+    
+    if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIHelperAppLauncherDialog.NS_IHELPERAPPLAUNCHERDIALOG_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {helperAppLauncherDialog.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    
+    XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+            
+int Release () {
+    refCount--;
+    /*
+    * Note.  This instance lives as long as the download it is binded to.
+    * Its reference count is expected to go down to 0 when the download
+    * has completed or when it has been cancelled. E.g. when the user
+    * cancels the File Dialog, cancels or closes the Download Dialog
+    * and when the Download Dialog goes away after the download is completed.
+    */
+    if (refCount is 0) disposeCOMInterfaces ();
+    return refCount;
+}
+
+/* nsIHelperAppLauncherDialog */
+
+int Show (int /*long*/ aLauncher, int /*long*/ aContext, int aReason) {
+    /*
+    * The interface for nsIHelperAppLauncher changed in GRE versions 1.8 and 1.9.  Query for
+    * each of these interfaces in turn until one is found.
+    */
+    nsISupports supports = new nsISupports (aLauncher);
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = supports.QueryInterface (nsIHelperAppLauncher_1_9.NS_IHELPERAPPLAUNCHER_IID, result);
+    if (rc is 0) {
+        nsIHelperAppLauncher_1_9 helperAppLauncher = new nsIHelperAppLauncher_1_9 (aLauncher);
+        rc = helperAppLauncher.SaveToDisk (0, 0);
+        helperAppLauncher.Release ();
+        return rc;
+    }
+
+    result[0] = 0;
+    rc = supports.QueryInterface (nsIHelperAppLauncher_1_8.NS_IHELPERAPPLAUNCHER_IID, result);
+    if (rc is 0) {
+        nsIHelperAppLauncher_1_8 helperAppLauncher = new nsIHelperAppLauncher_1_8 (aLauncher);
+        rc = helperAppLauncher.SaveToDisk (0, 0);
+        helperAppLauncher.Release ();
+        return rc;
+    }
+
+    nsIHelperAppLauncher helperAppLauncher = new nsIHelperAppLauncher (aLauncher);  /* < 1.8 */
+    return helperAppLauncher.SaveToDisk (0, 0);
+}
+
+int PromptForSaveToFile (int /*long*/ arg0, int /*long*/ arg1, int /*long*/ arg2, int /*long*/ arg3, int /*long*/ arg4) {
+    int /*long*/ aDefaultFile, aSuggestedFileExtension, _retval;
+    bool hasLauncher = false;
+
+    /*
+    * The interface for nsIHelperAppLauncherDialog changed as of mozilla 1.5 when an
+    * extra argument was added to the PromptForSaveToFile method (this resulted in all
+    * subsequent arguments shifting right).  The workaround is to provide an XPCOMObject 
+    * that fits the newer API, and to use the first argument's type to infer whether
+    * the old or new nsIHelperAppLauncherDialog interface is being used (and by extension
+    * the ordering of the arguments).  In mozilla >= 1.5 the first argument is an
+    * nsIHelperAppLauncher. 
+    */
+    /*
+     * The interface for nsIHelperAppLauncher changed as of mozilla 1.8, so the first
+     * argument must be queried for both the old and new nsIHelperAppLauncher interfaces. 
+     */
+    bool using_1_8 = false, using_1_9 = false;
+    nsISupports support = new nsISupports (arg0);
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = support.QueryInterface (nsIHelperAppLauncher_1_8.NS_IHELPERAPPLAUNCHER_IID, result);
+    if (rc is 0) {
+        using_1_8 = true;
+        hasLauncher = true;
+        new nsISupports (result[0]).Release ();
+    } else {
+        result[0] = 0;
+        rc = support.QueryInterface (nsIHelperAppLauncher_1_9.NS_IHELPERAPPLAUNCHER_IID, result);
+        if (rc is 0) {
+            using_1_9 = true;
+            hasLauncher = true;
+            new nsISupports (result[0]).Release ();
+        } else {
+            result[0] = 0;
+            rc = support.QueryInterface (nsIHelperAppLauncher.NS_IHELPERAPPLAUNCHER_IID, result);
+            if (rc is 0) {
+                hasLauncher = true;
+                new nsISupports (result[0]).Release ();
+            }
+        }
+    }
+    result[0] = 0;
+
+    if (hasLauncher) {  /* >= 1.5 */
+        aDefaultFile = arg2;
+        aSuggestedFileExtension = arg3;
+        _retval = arg4;
+    } else {            /* 1.4 */
+        aDefaultFile = arg1;
+        aSuggestedFileExtension = arg2;
+        _retval = arg3;
+    }
+
+    int length = XPCOM.strlen_PRUnichar (aDefaultFile);
+    char[] dest = new char[length];
+    XPCOM.memmove (dest, aDefaultFile, length * 2);
+    String defaultFile = new String (dest);
+
+    length = XPCOM.strlen_PRUnichar (aSuggestedFileExtension);
+    dest = new char[length];
+    XPCOM.memmove (dest, aSuggestedFileExtension, length * 2);
+    String suggestedFileExtension = new String (dest);
+
+    Shell shell = new Shell ();
+    FileDialog fileDialog = new FileDialog (shell, DWT.SAVE);
+    fileDialog.setFileName (defaultFile);
+    fileDialog.setFilterExtensions (new String[] {suggestedFileExtension});
+    String name = fileDialog.open ();
+    shell.close ();
+    if (name is null) {
+        if (hasLauncher) {
+            if (using_1_8) {
+                nsIHelperAppLauncher_1_8 launcher = new nsIHelperAppLauncher_1_8 (arg0);
+                rc = launcher.Cancel (XPCOM.NS_BINDING_ABORTED);
+            } else if (using_1_9) {
+                nsIHelperAppLauncher_1_9 launcher = new nsIHelperAppLauncher_1_9 (arg0);
+                rc = launcher.Cancel (XPCOM.NS_BINDING_ABORTED);
+            } else {
+                nsIHelperAppLauncher launcher = new nsIHelperAppLauncher (arg0);
+                rc = launcher.Cancel ();
+            }
+            if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+            return XPCOM.NS_OK;
+        }
+        return XPCOM.NS_ERROR_FAILURE;
+    }
+    nsEmbedString path = new nsEmbedString (name);
+    rc = XPCOM.NS_NewLocalFile (path.getAddress (), 1, result);
+    path.dispose ();
+    if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+    if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
+    /* Our own nsIDownload has been registered during the Browser initialization. It will be invoked by Mozilla. */
+    XPCOM.memmove (_retval, result, C.PTR_SIZEOF);  
+    return XPCOM.NS_OK;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/HelperAppLauncherDialogFactory.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.HelperAppLauncherDialogFactory;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIFactory;
+import dwt.internal.mozilla.nsISupports;
+
+class HelperAppLauncherDialogFactory {
+    XPCOMObject supports;
+    XPCOMObject factory;
+    int refCount = 0;
+
+HelperAppLauncherDialogFactory () {
+    createCOMInterfaces ();
+}
+
+int AddRef () {
+    refCount++;
+    return refCount;
+}
+
+void createCOMInterfaces () {
+    /* Create each of the interfaces that this object implements */
+    supports = new XPCOMObject (new int[] {2, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+    };
+    
+    factory = new XPCOMObject (new int[] {2, 0, 0, 3, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return CreateInstance (args[0], args[1], args[2]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return LockFactory ((int)/*64*/args[0]);}
+    };
+}
+
+void disposeCOMInterfaces () {
+    if (supports !is null) {
+        supports.dispose ();
+        supports = null;
+    }   
+    if (factory !is null) {
+        factory.dispose ();
+        factory = null; 
+    }
+}
+
+int /*long*/ getAddress () {
+    return factory.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+    if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+    nsID guid = new nsID ();
+    XPCOM.memmove (guid, riid, nsID.sizeof);
+    
+    if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIFactory.NS_IFACTORY_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {factory.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    
+    XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+            
+int Release () {
+    refCount--;
+    if (refCount is 0) disposeCOMInterfaces ();
+    return refCount;
+}
+    
+/* nsIFactory */
+
+int CreateInstance (int /*long*/ aOuter, int /*long*/ iid, int /*long*/ result) {
+    HelperAppLauncherDialog helperAppLauncherDialog = new HelperAppLauncherDialog ();
+    helperAppLauncherDialog.AddRef ();
+    XPCOM.memmove (result, new int /*long*/[] {helperAppLauncherDialog.getAddress ()}, C.PTR_SIZEOF);
+    return XPCOM.NS_OK;
+}
+
+int LockFactory (int lock) {
+    return XPCOM.NS_OK;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/InputStream.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+
+module dwt.browser.InputStream;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.mozilla.nsError;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIInputStream;
+import dwt.internal.mozilla.nsISupports;
+
+import Math = tango.math.Math;
+
+/******************************************************************************
+
+    COMMENTS: SWT implements this class as a replacement for the XPCOM 
+    implementation; it may be possible to use the XPCOM one instead 
+    (which also may be safer for D), but for now we'll follow SWT's example 
+    and use this reimplementation of InputStream. It should be trivial to
+    move over to strict XPCOM implementation should the need arise. It appears 
+    that the Java SWT source uses many workarounds in order to use the XPCOM 
+    interface. For D, I remove much of the Java layered callback
+    approach since it is no longer necessary.  -JJR
+
+******************************************************************************/
+
+class InputStream : nsIInputStream
+{
+    int     _refCount = 0;
+    int     _index     = 0;
+    byte[]  _buffer;
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    this (byte[] buffer) 
+    {
+        this._buffer = buffer;
+        index = 0;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsrefcnt AddRef () 
+    {
+        _refCount++;
+        return _refCount;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult QueryInterface ( inout nsID riid, void** ppvObject) 
+    {
+        if (riid is null || ppvObject is null) 
+            return NS_ERROR_NO_INTERFACE;
+        
+        nsID guid = riid;
+    
+        if (guid == nsISupports.NS_ISUPPORTS_IID) 
+        {
+            *ppvObject = cast(void*)cast(nsISupports) this;
+            this.AddRef ();
+            return NS_OK;
+        }
+
+        if (guid == nsIInputStream.NS_IINPUTSTREAM_IID) 
+        {
+            *ppvObject = cast(void*)cast(nsIInputStream) this;
+            this.AddRef ();
+            return NS_OK;
+        }   
+    
+        *ppvObject = null;
+        return NS_ERROR_NO_INTERFACE;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsrefcnt Release () 
+    {
+        _refCount--;
+        if (_refCount is 0) 
+            return 0 
+           // delete this;
+        return _refCount;
+    }
+    
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult Close () 
+    {
+        _buffer = null;
+        _index = 0;
+        return NS_OK;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult Available ( PRUint32* retval) 
+    {
+        PRUint32 available = buffer is null ? 0 : buffer.length - _index;
+        *retval = available;
+        return NS_OK;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult Read(byte* aBuf, PRUint32 aCount, PRUint32* retval) 
+    {
+        int max = Math.min (aCount, _buffer is null ? 0 : _buffer.length - _index);
+        
+        if (max > 0) 
+        {
+            aBuf[0..max] = _buffer[_index..$];
+            _index += max;
+        }
+
+        *retval = max;
+        return NS_OK;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult ReadSegments (nsWriteSegmentFun aWriter, void* aClosure, PRUint32 aCount, PRUint32*  retval) 
+    {
+        int      max = Math.min (aCount, buffer is null ? 0 : buffer.length - _index);
+        PRUint32 cnt = max;
+        
+        while (cnt > 0) 
+        {
+            PRUint32 aWriteCount;
+            nsresult rc = aWriter ( cast(nsIInputStream)this, aClosure, buffer.ptr, _index, cnt, &aWriteCount);
+            if (rc !is NS_OK) break;
+            _index += aWriteCount;
+            cnt -= aWriteCount;
+        }
+
+        *retval = (max - cnt);
+        return NS_OK;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    nsresult IsNonBlocking ( PRUint32* retval) 
+    {
+        *retval = 0;
+        return NS_OK;
+    } 
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/LocationAdapter.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+module dwt.browser.LocationAdapter;
+
+import dwt.browser.LocationListener;
+import dwt.browser.LocationEvent;
+import dwt.dwthelper.utils;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the {@link LocationListener} interface.
+ * <p>
+ * Classes that wish to deal with {@link LocationEvent}'s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ * 
+ * @since 3.0
+ */
+public abstract class LocationAdapter : LocationListener {
+
+    public void changing(LocationEvent event) {
+    }
+
+    public void changed(LocationEvent event) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/LocationEvent.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+module dwt.browser.LocationEvent;
+
+import dwt.dwthelper.utils;
+
+import dwt.events.TypedEvent;
+import dwt.widgets.Widget;
+
+/**
+ * A <code>LocationEvent</code> is sent by a {@link Browser} to
+ * {@link LocationListener}'s when the <code>Browser</code>
+ * navigates to a different URL. This notification typically 
+ * occurs when the application navigates to a new location with 
+ * {@link Browser#setUrl(String)} or when the user activates a
+ * hyperlink.
+ * 
+ * @since 3.0
+ */
+public class LocationEvent : TypedEvent {
+    /** current location */
+    public String location;
+    
+    /**
+     * A flag indicating whether the location opens in the top frame
+     * or not.
+     */
+    public bool top;
+    
+    /**
+     * A flag indicating whether the location loading should be allowed.
+     * Setting this field to <code>false</code> will cancel the operation.
+     */
+    public bool doit;
+
+    static final long serialVersionUID = 3906644198244299574L;
+    
+LocationEvent(Widget w) {
+    super(w);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public String toString() {
+    String string = super.toString ();
+    return string.substring (0, string.length() - 1) // remove trailing '}'
+        + " location=" + location
+        + " top=" + top
+        + " doit=" + doit
+        + "}";
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/LocationListener.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.LocationListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * a {@link LocationEvent} notification when a {@link Browser}
+ * navigates to a different URL.
+ * 
+ * @see Browser#addLocationListener(LocationListener)
+ * @see Browser#removeLocationListener(LocationListener)
+ * 
+ * @since 3.0
+ */
+public interface LocationListener extends DWTEventListener {
+
+/**
+ * This method is called when the current location is about to be changed.
+ * <p>
+ *
+ * <p>The following fields in the <code>LocationEvent</code> apply:
+ * <ul>
+ * <li>(in) location the location to be loaded
+ * <li>(in) widget the <code>Browser</code> whose location is changing
+ * <li>(in/out) doit can be set to <code>false</code> to prevent the location
+ * from being loaded 
+ * </ul>
+ * 
+ * @param event the <code>LocationEvent</code> that specifies the location
+ * to be loaded by a <code>Browser</code>
+ * 
+ * @since 3.0
+ */ 
+public void changing(LocationEvent event);
+
+/**
+ * This method is called when the current location is changed.
+ * <p>
+ *
+ * <p>The following fields in the <code>LocationEvent</code> apply:
+ * <ul>
+ * <li>(in) location the current location
+ * <li>(in) top <code>true</code> if the location opens in the top frame or
+ * <code>false</code> otherwise
+ * <li>(in) widget the <code>Browser</code> whose location has changed
+ * </ul>
+ * 
+ * @param event the <code>LocationEvent</code> that specifies  the new
+ * location of a <code>Browser</code>
+ * 
+ * @since 3.0
+ */ 
+public void changed(LocationEvent event);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/Mozilla.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,3222 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+module dwt.browser.Mozilla;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.DWTError;
+import dwt.graphics.Device;
+import dwt.graphics.Point;
+import dwt.graphics.Rectangle;
+
+import dwt.internal.Compatibility;
+import dwt.internal.LONG;
+import dwt.internal.Library;
+
+import dwt.internal.mozilla.nsEmbedString;
+import dwt.internal.mozilla.nsError;
+
+import dwt.internal.mozilla.nsIAppShell;
+import dwt.internal.mozilla.nsIBaseWindow;
+import dwt.internal.mozilla.nsICategoryManager;
+import dwt.internal.mozilla.nsIComponentManager;
+import dwt.internal.mozilla.nsIComponentRegistrar;
+import dwt.internal.mozilla.nsIContextMenuListener;
+import dwt.internal.mozilla.nsICookie;
+import dwt.internal.mozilla.nsICookieManager;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIDOMEvent;
+import dwt.internal.mozilla.nsIDOMEventTarget;
+import dwt.internal.mozilla.nsIDOMKeyEvent;
+import dwt.internal.mozilla.nsIDOMMouseEvent;
+import dwt.internal.mozilla.nsIDOMSerializer;
+import dwt.internal.mozilla.nsIDOMSerializer_1_7;
+import dwt.internal.mozilla.nsIDOMWindow;
+import dwt.internal.mozilla.nsIDOMWindowCollection;
+import dwt.internal.mozilla.nsIDirectoryService;
+import dwt.internal.mozilla.nsIDocShell;
+import dwt.internal.mozilla.nsIDocShell_1_8;
+import dwt.internal.mozilla.nsIDocShell_1_9;
+import dwt.internal.mozilla.nsIEmbeddingSiteWindow;
+import dwt.internal.mozilla.nsIFile;
+import dwt.internal.mozilla.nsIIOService;
+import dwt.internal.mozilla.nsIInterfaceRequestor;
+import dwt.internal.mozilla.nsIJSContextStack;
+import dwt.internal.mozilla.nsILocalFile;
+import dwt.internal.mozilla.nsIObserverService;
+import dwt.internal.mozilla.nsIPrefBranch;
+import dwt.internal.mozilla.nsIPrefLocalizedString;
+import dwt.internal.mozilla.nsIPrefService;
+import dwt.internal.mozilla.nsIProperties;
+import dwt.internal.mozilla.nsIServiceManager;
+import dwt.internal.mozilla.nsISimpleEnumerator;
+import dwt.internal.mozilla.nsISupports;
+import dwt.internal.mozilla.nsISupportsWeakReference;
+import dwt.internal.mozilla.nsITooltipListener;
+import dwt.internal.mozilla.nsIURI;
+import dwt.internal.mozilla.nsIURIContentListener;
+import dwt.internal.mozilla.nsIWeakReference;
+import dwt.internal.mozilla.nsIWebBrowser;
+import dwt.internal.mozilla.nsIWebBrowserChrome;
+import dwt.internal.mozilla.nsIWebBrowserChromeFocus;
+import dwt.internal.mozilla.nsIWebBrowserFocus;
+import dwt.internal.mozilla.nsIWebNavigation;
+import dwt.internal.mozilla.nsIWebNavigationInfo;
+import dwt.internal.mozilla.nsIWebProgress;
+import dwt.internal.mozilla.nsIWebProgressListener;
+import dwt.internal.mozilla.nsIWindowWatcher;
+
+import dwt.layout.FillLayout;
+import dwt.widgets.Composite;
+import dwt.widgets.Display;
+import dwt.widgets.Event;
+import dwt.widgets.Label;
+import dwt.widgets.Listener;
+import dwt.widgets.Menu;
+import dwt.widgets.Shell;
+
+class Mozilla : nsIWebBrowser, nsIWeakReference, 
+                nsIWebProgressListener, nsIWebBrowserChrome,
+                nsIWebBrowserChromeFocus, nsIEmbeddingSiteWindow,
+                nsIInterfaceRequestor, nsISupportsWeakReference,
+                nsIContextMenuListener, nsIUriContentListener,
+                nsIToolTipListener, nsIDOMEventListener
+{
+    int /*long*/    embedHandle;
+    nsIWebBrowser   webBrowser;
+    Object          webBrowserObject;
+    MozillaDelegate mozDelegate;
+
+    int chromeFlags = nsIWebBrowserChrome.CHROME_DEFAULT;
+    int refCount, lastKeyCode, lastCharCode;
+    int /*long*/ request;
+    Point location, size;
+    bool visible, isChild, ignoreDispose, awaitingNavigate;
+    Shell tip = null;
+    Listener listener;
+
+    // replace with appropriate D/Tango data structure
+    Vector unhookedDOMWindows = new Vector ();
+
+    static nsIAppShell AppShell;
+    static AppFileLocProvider LocationProvider;
+    static WindowCreator2 WindowCreator;
+    static int BrowserCount;
+    static bool Initialized, IsPre_1_8, PerformedVersionCheck, XPCOMWasGlued, XPCOMInitWasGlued;
+
+    /* XULRunner detect constants */
+    static final String GRERANGE_LOWER = "1.8.1.2"; //$NON-NLS-1$
+    static final String GRERANGE_LOWER_FALLBACK = "1.8"; //$NON-NLS-1$
+    static final bool LowerRangeInclusive = true;
+    static final String GRERANGE_UPPER = "1.9.*"; //$NON-NLS-1$
+    static final bool UpperRangeInclusive = true;
+
+    static final int MAX_PORT = 65535;
+    static final String SEPARATOR_OS = System.getProperty ("file.separator"); //$NON-NLS-1$
+    static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
+    static final String DISPOSE_LISTENER_HOOKED = "dwt.browser.Mozilla.disposeListenerHooked"; //$NON-NLS-1$
+    static final String PREFIX_JAVASCRIPT = "javascript:"; //$NON-NLS-1$
+    static final String PREFERENCE_CHARSET = "intl.charset.default"; //$NON-NLS-1$
+    static final String PREFERENCE_DISABLEOPENDURINGLOAD = "dom.disable_open_during_load"; //$NON-NLS-1$
+    static final String PREFERENCE_DISABLEWINDOWSTATUSCHANGE = "dom.disable_window_status_change"; //$NON-NLS-1$
+    static final String PREFERENCE_LANGUAGES = "intl.accept_languages"; //$NON-NLS-1$
+    static final String PREFERENCE_PROXYHOST_FTP = "network.proxy.ftp"; //$NON-NLS-1$
+    static final String PREFERENCE_PROXYPORT_FTP = "network.proxy.ftp_port"; //$NON-NLS-1$
+    static final String PREFERENCE_PROXYHOST_HTTP = "network.proxy.http"; //$NON-NLS-1$
+    static final String PREFERENCE_PROXYPORT_HTTP = "network.proxy.http_port"; //$NON-NLS-1$
+    static final String PREFERENCE_PROXYHOST_SSL = "network.proxy.ssl"; //$NON-NLS-1$
+    static final String PREFERENCE_PROXYPORT_SSL = "network.proxy.ssl_port"; //$NON-NLS-1$
+    static final String PREFERENCE_PROXYTYPE = "network.proxy.type"; //$NON-NLS-1$
+    static final String PROFILE_AFTER_CHANGE = "profile-after-change"; //$NON-NLS-1$
+    static final String PROFILE_BEFORE_CHANGE = "profile-before-change"; //$NON-NLS-1$
+    static final String PROFILE_DIR = SEPARATOR_OS + "eclipse" + SEPARATOR_OS; //$NON-NLS-1$
+    static final String PROFILE_DO_CHANGE = "profile-do-change"; //$NON-NLS-1$
+    static final String PROPERTY_PROXYPORT = "network.proxy_port"; //$NON-NLS-1$
+    static final String PROPERTY_PROXYHOST = "network.proxy_host"; //$NON-NLS-1$
+    static final String SEPARATOR_LOCALE = "-"; //$NON-NLS-1$
+    static final String SHUTDOWN_PERSIST = "shutdown-persist"; //$NON-NLS-1$
+    static final String STARTUP = "startup"; //$NON-NLS-1$
+    static final String TOKENIZER_LOCALE = ","; //$NON-NLS-1$
+    static final String URI_FROMMEMORY = "file:///"; //$NON-NLS-1$
+    static final String XULRUNNER_PATH = "dwt.browser.XULRunnerPath"; //$NON-NLS-1$
+
+    // TEMPORARY CODE
+    static final String GRE_INITIALIZED = "dwt.browser.XULRunnerInitialized"; //$NON-NLS-1$
+
+    static {
+        MozillaClearSessions = new Runnable () {
+            public void run () {
+                if (!Initialized) return;
+                int /*long*/[] result = new int /*long*/[1];
+                int rc = XPCOM.NS_GetServiceManager (result);
+                if (rc !is XPCOM.NS_OK) error (rc);
+                if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+                nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+                result[0] = 0;
+                byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_COOKIEMANAGER_CONTRACTID, true);
+                rc = serviceManager.GetServiceByContractID (aContractID, nsICookieManager.NS_ICOOKIEMANAGER_IID, result);
+                if (rc !is XPCOM.NS_OK) error (rc);
+                if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+                serviceManager.Release ();
+
+                nsICookieManager manager = new nsICookieManager (result[0]);
+                result[0] = 0;
+                rc = manager.GetEnumerator (result);
+                if (rc !is XPCOM.NS_OK) error (rc);
+                manager.Release ();
+
+                nsISimpleEnumerator enumerator = new nsISimpleEnumerator (result[0]);
+                int[] moreElements = new int[1]; /* PRBool */
+                rc = enumerator.HasMoreElements (moreElements);
+                if (rc !is XPCOM.NS_OK) error (rc);
+                while (moreElements[0] !is 0) {
+                    result[0] = 0;
+                    rc = enumerator.GetNext (result);
+                    if (rc !is XPCOM.NS_OK) error (rc);
+                    nsICookie cookie = new nsICookie (result[0]);
+                    long[] expires = new long[1];
+                    rc = cookie.GetExpires (expires);
+                    if (expires[0] is 0) {
+                        /* indicates a session cookie */
+                        int /*long*/ domain = XPCOM.nsEmbedCString_new ();
+                        int /*long*/ name = XPCOM.nsEmbedCString_new ();
+                        int /*long*/ path = XPCOM.nsEmbedCString_new ();
+                        cookie.GetHost (domain);
+                        cookie.GetName (name);
+                        cookie.GetPath (path);
+                        rc = manager.Remove (domain, name, path, 0);
+                        XPCOM.nsEmbedCString_delete (domain);
+                        XPCOM.nsEmbedCString_delete (name);
+                        XPCOM.nsEmbedCString_delete (path);
+                        if (rc !is XPCOM.NS_OK) error (rc);
+                    }
+                    cookie.Release ();
+                    rc = enumerator.HasMoreElements (moreElements);
+                    if (rc !is XPCOM.NS_OK) error (rc);
+                }
+                enumerator.Release ();
+            }
+        };
+    }
+
+public void create (Composite parent, int style) {
+    mozDelegate = new MozillaDelegate (browser);
+    Display display = parent.getDisplay ();
+
+    int /*long*/[] result = new int /*long*/[1];
+    if (!Initialized) {
+        bool initLoaded = false;
+        bool IsXULRunner = false;
+
+        String greInitialized = System.getProperty (GRE_INITIALIZED); 
+        if ("true".equals (greInitialized)) { //$NON-NLS-1$
+            /* 
+             * Another browser has already initialized xulrunner in this process,
+             * so just bind to it instead of trying to initialize a new one.
+             */
+            Initialized = true;
+        }
+        String mozillaPath = System.getProperty (XULRUNNER_PATH);
+        if (mozillaPath is null) {
+            try {
+                String libName = mozDelegate.getSWTInitLibraryName ();
+                Library.loadLibrary (libName);
+                initLoaded = true;
+            } catch (UnsatisfiedLinkError e) {
+                /* 
+                * If this library failed to load then do not attempt to detect a
+                * xulrunner to use.  The Browser may still be usable if MOZILLA_FIVE_HOME
+                * points at a GRE. 
+                */
+            }
+        } else {
+            mozillaPath += SEPARATOR_OS + mozDelegate.getLibraryName ();
+            IsXULRunner = true;
+        }
+
+        if (initLoaded) {
+            /* attempt to discover a XULRunner to use as the GRE */
+            GREVersionRange range = new GREVersionRange ();
+            byte[] bytes = MozillaDelegate.wcsToMbcs (null, GRERANGE_LOWER, true);
+            int /*long*/ lower = C.malloc (bytes.length);
+            C.memmove (lower, bytes, bytes.length);
+            range.lower = lower;
+            range.lowerInclusive = LowerRangeInclusive;
+
+            bytes = MozillaDelegate.wcsToMbcs (null, GRERANGE_UPPER, true);
+            int /*long*/ upper = C.malloc (bytes.length);
+            C.memmove (upper, bytes, bytes.length);
+            range.upper = upper;
+            range.upperInclusive = UpperRangeInclusive;
+
+            int length = XPCOMInit.PATH_MAX;
+            int /*long*/ greBuffer = C.malloc (length);
+            int /*long*/ propertiesPtr = C.malloc (2 * C.PTR_SIZEOF);
+            int rc = XPCOMInit.GRE_GetGREPathWithProperties (range, 1, propertiesPtr, 0, greBuffer, length);
+
+            /*
+             * A XULRunner was not found that supports wrapping of XPCOM handles as JavaXPCOM objects.
+             * Drop the lower version bound and try to detect an earlier XULRunner installation.
+             */
+            if (rc !is XPCOM.NS_OK) {
+                C.free (lower);
+                bytes = MozillaDelegate.wcsToMbcs (null, GRERANGE_LOWER_FALLBACK, true);
+                lower = C.malloc (bytes.length);
+                C.memmove (lower, bytes, bytes.length);
+                range.lower = lower;
+                rc = XPCOMInit.GRE_GetGREPathWithProperties (range, 1, propertiesPtr, 0, greBuffer, length);
+            }
+
+            C.free (lower);
+            C.free (upper);
+            C.free (propertiesPtr);
+            if (rc is XPCOM.NS_OK) {
+                /* indicates that a XULRunner was found */
+                length = C.strlen (greBuffer);
+                bytes = new byte[length];
+                C.memmove (bytes, greBuffer, length);
+                mozillaPath = new String (MozillaDelegate.mbcsToWcs (null, bytes));
+                IsXULRunner = mozillaPath.length () > 0;
+
+                /*
+                 * Test whether the detected XULRunner can be used as the GRE before loading swt's
+                 * XULRunner library.  If it cannot be used then fall back to attempting to use
+                 * the GRE pointed to by MOZILLA_FIVE_HOME.
+                 * 
+                 * One case where this will fail is attempting to use a 64-bit xulrunner while swt
+                 * is running in 32-bit mode, or vice versa.
+                 */
+                if (IsXULRunner) {
+                    byte[] path = MozillaDelegate.wcsToMbcs (null, mozillaPath, true);
+                    rc = XPCOMInit.XPCOMGlueStartup (path);
+                    if (rc !is XPCOM.NS_OK) {
+                        IsXULRunner = false;    /* failed */
+                        mozillaPath = mozillaPath.substring (0, mozillaPath.lastIndexOf (SEPARATOR_OS));
+                        if (Device.DEBUG) System.out.println ("cannot use detected XULRunner: " + mozillaPath); //$NON-NLS-1$
+                    } else {
+                        XPCOMInitWasGlued = true;
+                    }
+                }
+            }
+            C.free (greBuffer);
+        }
+
+        if (IsXULRunner) {
+            if (Device.DEBUG) System.out.println ("XULRunner path: " + mozillaPath); //$NON-NLS-1$
+            try {
+                Library.loadLibrary ("swt-xulrunner"); //$NON-NLS-1$
+            } catch (UnsatisfiedLinkError e) {
+                DWT.error (DWT.ERROR_NO_HANDLES, e);
+            }
+            byte[] path = MozillaDelegate.wcsToMbcs (null, mozillaPath, true);
+            int rc = XPCOM.XPCOMGlueStartup (path);
+            if (rc !is XPCOM.NS_OK) {
+                browser.dispose ();
+                error (rc);
+            }
+            XPCOMWasGlued = true;
+
+            /*
+             * Remove the trailing xpcom lib name from mozillaPath because the
+             * Mozilla.initialize and NS_InitXPCOM2 invocations require a directory name only.
+             */ 
+            mozillaPath = mozillaPath.substring (0, mozillaPath.lastIndexOf (SEPARATOR_OS));
+        } else {
+            if ((style & DWT.MOZILLA) !is 0) {
+                browser.dispose ();
+                String errorString = (mozillaPath !is null && mozillaPath.length () > 0) ?
+                    " [Failed to use detected XULRunner: " + mozillaPath + "]" :
+                    " [Could not detect registered XULRunner to use]";  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                DWT.error (DWT.ERROR_NO_HANDLES, null, errorString);
+            }
+
+            /* attempt to use the GRE pointed at by MOZILLA_FIVE_HOME */
+            int /*long*/ ptr = C.getenv (MozillaDelegate.wcsToMbcs (null, XPCOM.MOZILLA_FIVE_HOME, true));
+            if (ptr !is 0) {
+                int length = C.strlen (ptr);
+                byte[] buffer = new byte[length];
+                C.memmove (buffer, ptr, length);
+                mozillaPath = new String (MozillaDelegate.mbcsToWcs (null, buffer));
+            } else {
+                browser.dispose ();
+                DWT.error (DWT.ERROR_NO_HANDLES, null, " [Unknown Mozilla path (MOZILLA_FIVE_HOME not set)]"); //$NON-NLS-1$
+            }
+            if (Device.DEBUG) System.out.println ("Mozilla path: " + mozillaPath); //$NON-NLS-1$
+
+            /*
+            * Note.  Embedding a Mozilla GTK1.2 causes a crash.  The workaround
+            * is to check the version of GTK used by Mozilla by looking for
+            * the libwidget_gtk.so library used by Mozilla GTK1.2. Mozilla GTK2
+            * uses the libwidget_gtk2.so library.   
+            */
+            if (Compatibility.fileExists (mozillaPath, "components/libwidget_gtk.so")) { //$NON-NLS-1$
+                browser.dispose ();
+                DWT.error (DWT.ERROR_NO_HANDLES, null, " [Mozilla GTK2 required (GTK1.2 detected)]"); //$NON-NLS-1$                         
+            }
+
+            try {
+                Library.loadLibrary ("swt-mozilla"); //$NON-NLS-1$
+            } catch (UnsatisfiedLinkError e) {
+                try {
+                    /* 
+                     * The initial loadLibrary attempt may have failed as a result of the user's
+                     * system not having libstdc++.so.6 installed, so try to load the alternate
+                     * swt mozilla library that depends on libswtc++.so.5 instead.
+                     */
+                    Library.loadLibrary ("swt-mozilla-gcc3"); //$NON-NLS-1$
+                } catch (UnsatisfiedLinkError ex) {
+                    browser.dispose ();
+                    /*
+                     * Print the error from the first failed attempt since at this point it's
+                     * known that the failure was not due to the libstdc++.so.6 dependency.
+                     */
+                    DWT.error (DWT.ERROR_NO_HANDLES, e, " [MOZILLA_FIVE_HOME='" + mozillaPath + "']"); //$NON-NLS-1$ //$NON-NLS-2$
+                }
+            }
+        }
+
+        if (!Initialized) {
+            int /*long*/[] retVal = new int /*long*/[1];
+            nsEmbedString pathString = new nsEmbedString (mozillaPath);
+            int rc = XPCOM.NS_NewLocalFile (pathString.getAddress (), 1, retVal);
+            pathString.dispose ();
+            if (rc !is XPCOM.NS_OK) {
+                browser.dispose ();
+                error (rc);
+            }
+            if (retVal[0] is 0) {
+                browser.dispose ();
+                error (XPCOM.NS_ERROR_NULL_POINTER);
+            }
+
+            LocationProvider = new AppFileLocProvider (mozillaPath);
+            LocationProvider.AddRef ();
+
+            nsIFile localFile = new nsILocalFile (retVal[0]);
+            rc = XPCOM.NS_InitXPCOM2 (0, localFile.getAddress(), LocationProvider.getAddress ());
+            localFile.Release ();
+            if (rc !is XPCOM.NS_OK) {
+                browser.dispose ();
+                DWT.error (DWT.ERROR_NO_HANDLES, null, " [MOZILLA_FIVE_HOME may not point at an embeddable GRE] [NS_InitEmbedding " + mozillaPath + " error " + rc + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+            }
+            System.setProperty (GRE_INITIALIZED, "true"); //$NON-NLS-1$
+            if (IsXULRunner) {
+                System.setProperty (XULRUNNER_PATH, mozillaPath);
+            }
+        }
+
+        /* If JavaXPCOM is detected then attempt to initialize it with the XULRunner being used */
+        if (IsXULRunner) {
+            try {
+                Class clazz = Class.forName ("org.mozilla.xpcom.Mozilla"); //$NON-NLS-1$
+                Method method = clazz.getMethod ("getInstance", new Class[0]); //$NON-NLS-1$
+                Object mozilla = method.invoke (null, new Object[0]);
+                method = clazz.getMethod ("getComponentManager", new Class[0]); //$NON-NLS-1$
+                try {
+                    method.invoke (mozilla, new Object[0]);
+                } catch (InvocationTargetException e) {
+                    /* indicates that JavaXPCOM has not been initialized yet */
+                    Class fileClass = Class.forName ("java.io.File"); //$NON-NLS-1$
+                    method = clazz.getMethod ("initialize", new Class[] {fileClass}); //$NON-NLS-1$
+                    Constructor constructor = fileClass.getDeclaredConstructor (new Class[] {String.class});
+                    Object argument = constructor.newInstance (new Object[] {mozillaPath});
+                    method.invoke (mozilla, new Object[] {argument});
+                }
+            } catch (ClassNotFoundException e) {
+                /* JavaXPCOM is not on the classpath */
+            } catch (NoSuchMethodException e) {
+                /* the JavaXPCOM on the classpath does not implement initialize() */
+            } catch (IllegalArgumentException e) {
+            } catch (IllegalAccessException e) {
+            } catch (InvocationTargetException e) {
+            } catch (InstantiationException e) {
+            }
+        }
+
+        int rc = XPCOM.NS_GetComponentManager (result);
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+        if (result[0] is 0) {
+            browser.dispose ();
+            error (XPCOM.NS_NOINTERFACE);
+        }
+        
+        nsIComponentManager componentManager = new nsIComponentManager (result[0]);
+        result[0] = 0;
+        if (mozDelegate.needsSpinup ()) {
+            /* nsIAppShell is discontinued as of xulrunner 1.9, so do not fail if it is not found */
+            rc = componentManager.CreateInstance (XPCOM.NS_APPSHELL_CID, 0, nsIAppShell.NS_IAPPSHELL_IID, result);
+            if (rc !is XPCOM.NS_ERROR_NO_INTERFACE) {
+                if (rc !is XPCOM.NS_OK) {
+                    browser.dispose ();
+                    error (rc);
+                }
+                if (result[0] is 0) {
+                    browser.dispose ();
+                    error (XPCOM.NS_NOINTERFACE);
+                }
+    
+                AppShell = new nsIAppShell (result[0]);
+                rc = AppShell.Create (0, null);
+                if (rc !is XPCOM.NS_OK) {
+                    browser.dispose ();
+                    error (rc);
+                }
+                rc = AppShell.Spinup ();
+                if (rc !is XPCOM.NS_OK) {
+                    browser.dispose ();
+                    error (rc);
+                }
+            }
+            result[0] = 0;
+        }
+
+        WindowCreator = new WindowCreator2 ();
+        WindowCreator.AddRef ();
+        
+        rc = XPCOM.NS_GetServiceManager (result);
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+        if (result[0] is 0) {
+            browser.dispose ();
+            error (XPCOM.NS_NOINTERFACE);
+        }
+        
+        nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+        result[0] = 0;      
+        byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_WINDOWWATCHER_CONTRACTID, true);
+        rc = serviceManager.GetServiceByContractID (aContractID, nsIWindowWatcher.NS_IWINDOWWATCHER_IID, result);
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+        if (result[0] is 0) {
+            browser.dispose ();
+            error (XPCOM.NS_NOINTERFACE);       
+        }
+
+        nsIWindowWatcher windowWatcher = new nsIWindowWatcher (result[0]);
+        result[0] = 0;
+        rc = windowWatcher.SetWindowCreator (WindowCreator.getAddress());
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+        windowWatcher.Release ();
+
+        /* compute the profile directory and set it on the AppFileLocProvider */
+        if (LocationProvider !is null) {
+            byte[] buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DIRECTORYSERVICE_CONTRACTID, true);
+            rc = serviceManager.GetServiceByContractID (buffer, nsIDirectoryService.NS_IDIRECTORYSERVICE_IID, result);
+            if (rc !is XPCOM.NS_OK) {
+                browser.dispose ();
+                error (rc);
+            }
+            if (result[0] is 0) {
+                browser.dispose ();
+                error (XPCOM.NS_NOINTERFACE);
+            }
+
+            nsIDirectoryService directoryService = new nsIDirectoryService (result[0]);
+            result[0] = 0;
+            rc = directoryService.QueryInterface (nsIProperties.NS_IPROPERTIES_IID, result);
+            if (rc !is XPCOM.NS_OK) {
+                browser.dispose ();
+                error (rc);
+            }
+            if (result[0] is 0) {
+                browser.dispose ();
+                error (XPCOM.NS_NOINTERFACE);
+            }
+            directoryService.Release ();
+
+            nsIProperties properties = new nsIProperties (result[0]);
+            result[0] = 0;
+            buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_APP_APPLICATION_REGISTRY_DIR, true);
+            rc = properties.Get (buffer, nsIFile.NS_IFILE_IID, result);
+            if (rc !is XPCOM.NS_OK) {
+                browser.dispose ();
+                error (rc);
+            }
+            if (result[0] is 0) {
+                browser.dispose ();
+                error (XPCOM.NS_NOINTERFACE);
+            }
+            properties.Release ();
+
+            nsIFile profileDir = new nsIFile (result[0]);
+            result[0] = 0;
+            int /*long*/ path = XPCOM.nsEmbedCString_new ();
+            rc = profileDir.GetNativePath (path);
+            if (rc !is XPCOM.NS_OK) {
+                browser.dispose ();
+                error (rc);
+            }
+            int length = XPCOM.nsEmbedCString_Length (path);
+            int /*long*/ ptr = XPCOM.nsEmbedCString_get (path);
+            buffer = new byte [length];
+            XPCOM.memmove (buffer, ptr, length);
+            String profilePath = new String (MozillaDelegate.mbcsToWcs (null, buffer)) + PROFILE_DIR;
+            LocationProvider.setProfilePath (profilePath);
+            LocationProvider.isXULRunner = IsXULRunner;
+            XPCOM.nsEmbedCString_delete (path);
+            profileDir.Release ();
+
+            /* notify observers of a new profile directory being used */
+            buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_OBSERVER_CONTRACTID, true);
+            rc = serviceManager.GetServiceByContractID (buffer, nsIObserverService.NS_IOBSERVERSERVICE_IID, result);
+            if (rc !is XPCOM.NS_OK) {
+                browser.dispose ();
+                error (rc);
+            }
+            if (result[0] is 0) {
+                browser.dispose ();
+                error (XPCOM.NS_NOINTERFACE);
+            }
+
+            nsIObserverService observerService = new nsIObserverService (result[0]);
+            result[0] = 0;
+            buffer = MozillaDelegate.wcsToMbcs (null, PROFILE_DO_CHANGE, true);
+            length = STARTUP.length ();
+            char[] chars = new char [length + 1];
+            STARTUP.getChars (0, length, chars, 0);
+            rc = observerService.NotifyObservers (0, buffer, chars);
+            if (rc !is XPCOM.NS_OK) {
+                browser.dispose ();
+                error (rc);
+            }
+            buffer = MozillaDelegate.wcsToMbcs (null, PROFILE_AFTER_CHANGE, true);
+            rc = observerService.NotifyObservers (0, buffer, chars);
+            if (rc !is XPCOM.NS_OK) {
+                browser.dispose ();
+                error (rc);
+            }
+            observerService.Release ();
+        }
+
+        /*
+         * As a result of using a common profile the user cannot change their locale
+         * and charset.  The fix for this is to set mozilla's locale and charset
+         * preference values according to the user's current locale and charset.
+         */
+        aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFSERVICE_CONTRACTID, true);
+        rc = serviceManager.GetServiceByContractID (aContractID, nsIPrefService.NS_IPREFSERVICE_IID, result);
+        serviceManager.Release ();
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+        if (result[0] is 0) {
+            browser.dispose ();
+            error (XPCOM.NS_NOINTERFACE);
+        }
+
+        nsIPrefService prefService = new nsIPrefService (result[0]);
+        result[0] = 0;
+        byte[] buffer = new byte[1];
+        rc = prefService.GetBranch (buffer, result);    /* empty buffer denotes root preference level */
+        prefService.Release ();
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+        if (result[0] is 0) {
+            browser.dispose ();
+            error (XPCOM.NS_NOINTERFACE);
+        }
+
+        nsIPrefBranch prefBranch = new nsIPrefBranch (result[0]);
+        result[0] = 0;
+
+        /* get Mozilla's current locale preference value */
+        String prefLocales = null;
+        nsIPrefLocalizedString localizedString = null;
+        buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_LANGUAGES, true);
+        rc = prefBranch.GetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
+        /* 
+         * Feature of Debian.  For some reason attempting to query for the current locale
+         * preference fails on Debian.  The workaround for this is to assume a value of
+         * "en-us,en" since this is typically the default value when mozilla is used without
+         * a profile.
+         */
+        if (rc !is XPCOM.NS_OK) {
+            prefLocales = "en-us,en" + TOKENIZER_LOCALE;    //$NON-NLS-1$
+        } else {
+            if (result[0] is 0) {
+                browser.dispose ();
+                error (XPCOM.NS_NOINTERFACE);
+            }
+            localizedString = new nsIPrefLocalizedString (result[0]);
+            result[0] = 0;
+            rc = localizedString.ToString (result);
+            if (rc !is XPCOM.NS_OK) {
+                browser.dispose ();
+                error (rc);
+            }
+            if (result[0] is 0) {
+                browser.dispose ();
+                error (XPCOM.NS_NOINTERFACE);
+            }
+            int length = XPCOM.strlen_PRUnichar (result[0]);
+            char[] dest = new char[length];
+            XPCOM.memmove (dest, result[0], length * 2);
+            prefLocales = new String (dest) + TOKENIZER_LOCALE;
+        }
+        result[0] = 0;
+
+        /*
+         * construct the new locale preference value by prepending the
+         * user's current locale and language to the original value 
+         */
+        Locale locale = Locale.getDefault ();
+        String language = locale.getLanguage ();
+        String country = locale.getCountry ();
+        StringBuffer stringBuffer = new StringBuffer (language);
+        stringBuffer.append (SEPARATOR_LOCALE);
+        stringBuffer.append (country.toLowerCase ());
+        stringBuffer.append (TOKENIZER_LOCALE);
+        stringBuffer.append (language);
+        stringBuffer.append (TOKENIZER_LOCALE);
+        String newLocales = stringBuffer.toString ();
+
+        int start, end = -1;
+        do {
+            start = end + 1;
+            end = prefLocales.indexOf (TOKENIZER_LOCALE, start);
+            String token;
+            if (end is -1) {
+                token = prefLocales.substring (start);
+            } else {
+                token = prefLocales.substring (start, end);
+            }
+            if (token.length () > 0) {
+                token = (token + TOKENIZER_LOCALE).trim ();
+                /* ensure that duplicate locale values are not added */
+                if (newLocales.indexOf (token) is -1) {
+                    stringBuffer.append (token);
+                }
+            }
+        } while (end !is -1);
+        newLocales = stringBuffer.toString ();
+        if (!newLocales.equals (prefLocales)) {
+            /* write the new locale value */
+            newLocales = newLocales.substring (0, newLocales.length () - TOKENIZER_LOCALE.length ()); /* remove trailing tokenizer */
+            int length = newLocales.length ();
+            char[] charBuffer = new char[length + 1];
+            newLocales.getChars (0, length, charBuffer, 0);
+            if (localizedString is null) {
+                byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID, true);
+                rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
+                if (rc !is XPCOM.NS_OK) {
+                    browser.dispose ();
+                    error (rc);
+                }
+                if (result[0] is 0) {
+                    browser.dispose ();
+                    error (XPCOM.NS_NOINTERFACE);
+                }
+                localizedString = new nsIPrefLocalizedString (result[0]);
+                result[0] = 0;
+            }
+            localizedString.SetDataWithLength (length, charBuffer);
+            rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress());
+        }
+        if (localizedString !is null) {
+            localizedString.Release ();
+            localizedString = null;
+        }
+
+        /* get Mozilla's current charset preference value */
+        String prefCharset = null;
+        buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_CHARSET, true);
+        rc = prefBranch.GetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
+        /* 
+         * Feature of Debian.  For some reason attempting to query for the current charset
+         * preference fails on Debian.  The workaround for this is to assume a value of
+         * "ISO-8859-1" since this is typically the default value when mozilla is used
+         * without a profile.
+         */
+        if (rc !is XPCOM.NS_OK) {
+            prefCharset = "ISO-8859-1"; //$NON_NLS-1$
+        } else {
+            if (result[0] is 0) {
+                browser.dispose ();
+                error (XPCOM.NS_NOINTERFACE);
+            }
+            localizedString = new nsIPrefLocalizedString (result[0]);
+            result[0] = 0;
+            rc = localizedString.ToString (result);
+            if (rc !is XPCOM.NS_OK) {
+                browser.dispose ();
+                error (rc);
+            }
+            if (result[0] is 0) {
+                browser.dispose ();
+                error (XPCOM.NS_NOINTERFACE);
+            }
+            int length = XPCOM.strlen_PRUnichar (result[0]);
+            char[] dest = new char[length];
+            XPCOM.memmove (dest, result[0], length * 2);
+            prefCharset = new String (dest);
+        }
+        result[0] = 0;
+
+        String newCharset = System.getProperty ("file.encoding");   // $NON-NLS-1$
+        if (!newCharset.equals (prefCharset)) {
+            /* write the new charset value */
+            int length = newCharset.length ();
+            char[] charBuffer = new char[length + 1];
+            newCharset.getChars (0, length, charBuffer, 0);
+            if (localizedString is null) {
+                byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID, true);
+                rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
+                if (rc !is XPCOM.NS_OK) {
+                    browser.dispose ();
+                    error (rc);
+                }
+                if (result[0] is 0) {
+                    browser.dispose ();
+                    error (XPCOM.NS_NOINTERFACE);
+                }
+                localizedString = new nsIPrefLocalizedString (result[0]);
+                result[0] = 0;
+            }
+            localizedString.SetDataWithLength (length, charBuffer);
+            rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ());
+        }
+        if (localizedString !is null) localizedString.Release ();
+
+        /*
+        * Check for proxy values set as documented java properties and update mozilla's
+        * preferences with these values if needed.
+        */
+        String proxyHost = System.getProperty (PROPERTY_PROXYHOST);
+        String proxyPortString = System.getProperty (PROPERTY_PROXYPORT);
+
+        int port = -1;
+        if (proxyPortString !is null) {
+            try {
+                int value = Integer.valueOf (proxyPortString).intValue ();
+                if (0 <= value && value <= MAX_PORT) port = value;
+            } catch (NumberFormatException e) {
+                /* do nothing, java property has non-integer value */
+            }
+        }
+
+        if (proxyHost !is null) {
+            byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID, true);
+            rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+            localizedString = new nsIPrefLocalizedString (result[0]);
+            result[0] = 0;
+            int length = proxyHost.length ();
+            char[] charBuffer = new char[length + 1];
+            proxyHost.getChars (0, length, charBuffer, 0);
+            rc = localizedString.SetDataWithLength (length, charBuffer);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYHOST_FTP, true);
+            rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ());
+            if (rc !is XPCOM.NS_OK) error (rc);
+            buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYHOST_HTTP, true);
+            rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ());
+            if (rc !is XPCOM.NS_OK) error (rc);
+            buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYHOST_SSL, true);
+            rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ());
+            if (rc !is XPCOM.NS_OK) error (rc);
+            localizedString.Release ();
+        }
+
+        if (port !is -1) {
+            buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYPORT_FTP, true);
+            rc = prefBranch.SetIntPref (buffer, port);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYPORT_HTTP, true);
+            rc = prefBranch.SetIntPref (buffer, port);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYPORT_SSL, true);
+            rc = prefBranch.SetIntPref (buffer, port);
+            if (rc !is XPCOM.NS_OK) error (rc);
+        }
+
+        if (proxyHost !is null || port !is -1) {
+            buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYTYPE, true);
+            rc = prefBranch.SetIntPref (buffer, 1);
+            if (rc !is XPCOM.NS_OK) error (rc);
+        }
+
+        /*
+        * Ensure that windows that are shown during page loads are not blocked.  Firefox may
+        * try to block these by default since such windows are often unwelcome, but this
+        * assumption should not be made in the Browser's context.  Since the Browser client
+        * is responsible for creating the new Browser and Shell in an OpenWindowListener,
+        * they should decide whether the new window is unwelcome or not and act accordingly. 
+        */
+        buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_DISABLEOPENDURINGLOAD, true);
+        rc = prefBranch.SetBoolPref (buffer, 0);
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+
+        /* Ensure that the status text can be set through means like javascript */ 
+        buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_DISABLEWINDOWSTATUSCHANGE, true);
+        rc = prefBranch.SetBoolPref (buffer, 0);
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+
+        prefBranch.Release ();
+
+        PromptService2Factory factory = new PromptService2Factory ();
+        factory.AddRef ();
+
+        rc = componentManager.QueryInterface (nsIComponentRegistrar.NS_ICOMPONENTREGISTRAR_IID, result);
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+        if (result[0] is 0) {
+            browser.dispose ();
+            error (XPCOM.NS_NOINTERFACE);
+        }
+        
+        nsIComponentRegistrar componentRegistrar = new nsIComponentRegistrar (result[0]);
+        result[0] = 0;
+        aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PROMPTSERVICE_CONTRACTID, true); 
+        byte[] aClassName = MozillaDelegate.wcsToMbcs (null, "Prompt Service", true); //$NON-NLS-1$
+        rc = componentRegistrar.RegisterFactory (XPCOM.NS_PROMPTSERVICE_CID, aClassName, aContractID, factory.getAddress ());
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+        factory.Release ();
+        
+        HelperAppLauncherDialogFactory dialogFactory = new HelperAppLauncherDialogFactory ();
+        dialogFactory.AddRef ();
+        aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_HELPERAPPLAUNCHERDIALOG_CONTRACTID, true);
+        aClassName = MozillaDelegate.wcsToMbcs (null, "Helper App Launcher Dialog", true); //$NON-NLS-1$
+        rc = componentRegistrar.RegisterFactory (XPCOM.NS_HELPERAPPLAUNCHERDIALOG_CID, aClassName, aContractID, dialogFactory.getAddress ());
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+        dialogFactory.Release ();
+
+        /*
+        * This Download factory will be used if the GRE version is < 1.8.
+        * If the GRE version is 1.8.x then the Download factory that is registered later for
+        *   contract "Transfer" will be used.
+        * If the GRE version is >= 1.9 then no Download factory is registered because this
+        *   functionality is provided by the GRE.
+        */
+        DownloadFactory downloadFactory = new DownloadFactory ();
+        downloadFactory.AddRef ();
+        aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DOWNLOAD_CONTRACTID, true);
+        aClassName = MozillaDelegate.wcsToMbcs (null, "Download", true); //$NON-NLS-1$
+        rc = componentRegistrar.RegisterFactory (XPCOM.NS_DOWNLOAD_CID, aClassName, aContractID, downloadFactory.getAddress ());
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+        downloadFactory.Release ();
+
+        FilePickerFactory pickerFactory = IsXULRunner ? new FilePickerFactory_1_8 () : new FilePickerFactory ();
+        pickerFactory.AddRef ();
+        aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_FILEPICKER_CONTRACTID, true);
+        aClassName = MozillaDelegate.wcsToMbcs (null, "FilePicker", true); //$NON-NLS-1$
+        rc = componentRegistrar.RegisterFactory (XPCOM.NS_FILEPICKER_CID, aClassName, aContractID, pickerFactory.getAddress ());
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (rc);
+        }
+        pickerFactory.Release ();
+
+        componentRegistrar.Release ();
+        componentManager.Release ();
+
+        Initialized = true;
+    }
+
+    if (display.getData (DISPOSE_LISTENER_HOOKED) is null) {
+        display.setData (DISPOSE_LISTENER_HOOKED, DISPOSE_LISTENER_HOOKED);
+        display.addListener (DWT.Dispose, new Listener () {
+            public void handleEvent (Event event) {
+                if (BrowserCount > 0) return; /* another display is still active */
+
+                int /*long*/[] result = new int /*long*/[1];
+                int rc = XPCOM.NS_GetServiceManager (result);
+                if (rc !is XPCOM.NS_OK) error (rc);
+                if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+                nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+                result[0] = 0;      
+                byte[] buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_OBSERVER_CONTRACTID, true);
+                rc = serviceManager.GetServiceByContractID (buffer, nsIObserverService.NS_IOBSERVERSERVICE_IID, result);
+                if (rc !is XPCOM.NS_OK) error (rc);
+                if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+                nsIObserverService observerService = new nsIObserverService (result[0]);
+                result[0] = 0;
+                buffer = MozillaDelegate.wcsToMbcs (null, PROFILE_BEFORE_CHANGE, true);
+                int length = SHUTDOWN_PERSIST.length ();
+                char[] chars = new char [length + 1];
+                SHUTDOWN_PERSIST.getChars (0, length, chars, 0);
+                rc = observerService.NotifyObservers (0, buffer, chars);
+                if (rc !is XPCOM.NS_OK) error (rc);
+                observerService.Release ();
+
+                if (LocationProvider !is null) {
+                    String prefsLocation = LocationProvider.profilePath + AppFileLocProvider.PREFERENCES_FILE;
+                    nsEmbedString pathString = new nsEmbedString (prefsLocation);
+                    rc = XPCOM.NS_NewLocalFile (pathString.getAddress (), 1, result);
+                    if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+                    if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
+                    pathString.dispose ();
+
+                    nsILocalFile localFile = new nsILocalFile (result [0]);
+                    result[0] = 0;
+                    rc = localFile.QueryInterface (nsIFile.NS_IFILE_IID, result); 
+                    if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+                    if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE);
+                    localFile.Release ();
+
+                    nsIFile prefFile = new nsIFile (result[0]);
+                    result[0] = 0;
+
+                    buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFSERVICE_CONTRACTID, true);
+                    rc = serviceManager.GetServiceByContractID (buffer, nsIPrefService.NS_IPREFSERVICE_IID, result);
+                    if (rc !is XPCOM.NS_OK) error (rc);
+                    if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+                    nsIPrefService prefService = new nsIPrefService (result[0]);
+                    result[0] = 0;
+                    rc = prefService.SavePrefFile(prefFile.getAddress ());
+                    prefService.Release ();
+                    prefFile.Release ();
+                }
+                serviceManager.Release ();
+
+                if (XPCOMWasGlued) {
+                    XPCOM.XPCOMGlueShutdown ();
+                    XPCOMWasGlued = false;
+                }
+                if (XPCOMInitWasGlued) {
+                    XPCOMInit.XPCOMGlueShutdown ();
+                    XPCOMInitWasGlued = false;
+                }
+                Initialized = false;
+            }
+        });
+    }
+
+    BrowserCount++;
+    int rc = XPCOM.NS_GetComponentManager (result);
+    if (rc !is XPCOM.NS_OK) {
+        browser.dispose ();
+        error (rc);
+    }
+    if (result[0] is 0) {
+        browser.dispose ();
+        error (XPCOM.NS_NOINTERFACE);
+    }
+    
+    nsIComponentManager componentManager = new nsIComponentManager (result[0]);
+    result[0] = 0;
+    nsID NS_IWEBBROWSER_CID = new nsID ("F1EAC761-87E9-11d3-AF80-00A024FFC08C"); //$NON-NLS-1$
+    rc = componentManager.CreateInstance (NS_IWEBBROWSER_CID, 0, nsIWebBrowser.NS_IWEBBROWSER_IID, result);
+    if (rc !is XPCOM.NS_OK) {
+        browser.dispose ();
+        error (rc);
+    }
+    if (result[0] is 0) {
+        browser.dispose ();
+        error (XPCOM.NS_NOINTERFACE);   
+    }
+    
+    webBrowser = new nsIWebBrowser (result[0]);
+    result[0] = 0;
+
+    createCOMInterfaces ();
+    AddRef ();
+
+    rc = webBrowser.SetContainerWindow (webBrowserChrome.getAddress());
+    if (rc !is XPCOM.NS_OK) {
+        browser.dispose ();
+        error (rc);
+    }
+            
+    rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
+    if (rc !is XPCOM.NS_OK) {
+        browser.dispose ();
+        error (rc);
+    }
+    if (result[0] is 0) {
+        browser.dispose ();
+        error (XPCOM.NS_ERROR_NO_INTERFACE);
+    }
+    
+    nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
+    result[0] = 0;
+    Rectangle rect = browser.getClientArea ();
+    if (rect.isEmpty ()) {
+        rect.width = 1;
+        rect.height = 1;
+    }
+
+    embedHandle = mozDelegate.getHandle ();
+
+    rc = baseWindow.InitWindow (embedHandle, 0, 0, 0, rect.width, rect.height);
+    if (rc !is XPCOM.NS_OK) {
+        browser.dispose ();
+        error (XPCOM.NS_ERROR_FAILURE);
+    }
+    rc = baseWindow.Create ();
+    if (rc !is XPCOM.NS_OK) {
+        browser.dispose ();
+        error (XPCOM.NS_ERROR_FAILURE);
+    }
+    rc = baseWindow.SetVisibility (1);
+    if (rc !is XPCOM.NS_OK) {
+        browser.dispose ();
+        error (XPCOM.NS_ERROR_FAILURE);
+    }
+    baseWindow.Release ();
+
+    if (!PerformedVersionCheck) {
+        PerformedVersionCheck = true;
+
+        /*
+        * Check for the availability of the pre-1.8 implementation of nsIDocShell
+        * to determine if the GRE's version is < 1.8.
+        */
+        rc = webBrowser.QueryInterface (nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID, result);
+        if (rc !is XPCOM.NS_OK) {
+            browser.dispose ();
+            error (XPCOM.NS_ERROR_FAILURE);
+        }
+        if (result[0] is 0) {
+            browser.dispose ();
+            error (XPCOM.NS_ERROR_NO_INTERFACE);
+        }
+        nsIInterfaceRequestor interfaceRequestor = new nsIInterfaceRequestor (result[0]);
+        result[0] = 0;
+
+        rc = interfaceRequestor.GetInterface (nsIDocShell.NS_IDOCSHELL_IID, result);
+        if (rc is XPCOM.NS_OK && result[0] !is 0) {
+            IsPre_1_8 = true;
+            new nsISupports (result[0]).Release ();
+        }
+        result[0] = 0;
+
+        /*
+        * A Download factory for contract "Transfer" must be registered iff the GRE's version is 1.8.x.
+        *   Check for the availability of the 1.8 implementation of nsIDocShell to determine if the
+        *   GRE's version is 1.8.x.
+        * If the GRE version is < 1.8 then the previously-registered Download factory for contract
+        *   "Download" will be used.
+        * If the GRE version is >= 1.9 then no Download factory is registered because this
+        *   functionality is provided by the GRE.
+        */
+        if (!IsPre_1_8) {
+            rc = interfaceRequestor.GetInterface (nsIDocShell_1_8.NS_IDOCSHELL_IID, result);
+            if (rc is XPCOM.NS_OK && result[0] !is 0) { /* 1.8 */
+                new nsISupports (result[0]).Release ();
+                result[0] = 0;
+                rc = componentManager.QueryInterface (nsIComponentRegistrar.NS_ICOMPONENTREGISTRAR_IID, result);
+                if (rc !is XPCOM.NS_OK) {
+                    browser.dispose ();
+                    error (rc);
+                }
+                if (result[0] is 0) {
+                    browser.dispose ();
+                    error (XPCOM.NS_NOINTERFACE);
+                }
+
+                nsIComponentRegistrar componentRegistrar = new nsIComponentRegistrar (result[0]);
+                DownloadFactory_1_8 downloadFactory_1_8 = new DownloadFactory_1_8 ();
+                downloadFactory_1_8.AddRef ();
+                byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_TRANSFER_CONTRACTID, true);
+                byte[] aClassName = MozillaDelegate.wcsToMbcs (null, "Transfer", true); //$NON-NLS-1$
+                rc = componentRegistrar.RegisterFactory (XPCOM.NS_DOWNLOAD_CID, aClassName, aContractID, downloadFactory_1_8.getAddress ());
+                if (rc !is XPCOM.NS_OK) {
+                    browser.dispose ();
+                    error (rc);
+                }
+                downloadFactory_1_8.Release ();
+                componentRegistrar.Release ();
+            } else { /* >= 1.9 */
+                /*
+                 * Bug in XULRunner 1.9.  Mozilla no longer clears its background before initial content has
+                 * been set.  As a result embedders appear broken if they do not immediately navigate to a url.
+                 * The workaround for this is to navigate to about:blank immediately so that the background is
+                 * cleared, but do not fire any corresponding events or allow Browser API calls to reveal this.
+                 * Once the client does a proper navigate with either setUrl() or setText() then resume as
+                 * normal.  The Mozilla bug for this is https://bugzilla.mozilla.org/show_bug.cgi?id=415789.
+                 */
+                awaitingNavigate = true;
+                rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+                if (rc !is XPCOM.NS_OK) {
+                    browser.dispose ();
+                    error (rc);
+                }
+                if (result[0] is 0) {
+                    browser.dispose ();
+                    error (XPCOM.NS_ERROR_NO_INTERFACE);
+                }
+                nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+                char[] uri = new char[ABOUT_BLANK.length () + 1];
+                ABOUT_BLANK.getChars (0, ABOUT_BLANK.length (), uri, 0);
+                rc = webNavigation.LoadURI (uri, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0);
+                webNavigation.Release ();
+            }
+        }
+        result[0] = 0;
+        interfaceRequestor.Release ();
+    }
+    componentManager.Release ();
+
+    rc = webBrowser.AddWebBrowserListener (weakReference.getAddress (), nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID);
+    if (rc !is XPCOM.NS_OK) {
+        browser.dispose ();
+        error (rc);
+    }
+
+    rc = webBrowser.SetParentURIContentListener (uriContentListener.getAddress ());
+    if (rc !is XPCOM.NS_OK) {
+        browser.dispose ();
+        error (rc);
+    }
+
+    mozDelegate.init ();
+
+    listener = new Listener () {
+        public void handleEvent (Event event) {
+            switch (event.type) {
+                case DWT.Dispose: {
+                    /* make this handler run after other dispose listeners */
+                    if (ignoreDispose) {
+                        ignoreDispose = false;
+                        break;
+                    }
+                    ignoreDispose = true;
+                    browser.notifyListeners (event.type, event);
+                    event.type = DWT.NONE;
+                    onDispose (event.display);
+                    break;
+                }
+                case DWT.Resize: onResize (); break;
+                case DWT.FocusIn: Activate (); break;
+                case DWT.Activate: Activate (); break;
+                case DWT.Deactivate: {
+                    Display display = event.display;
+                    if (Mozilla.this.browser is display.getFocusControl ()) Deactivate ();
+                    break;
+                }
+                case DWT.Show: {
+                    /*
+                    * Feature in GTK Mozilla.  Mozilla does not show up when
+                    * its container (a GTK fixed handle) is made visible
+                    * after having been hidden.  The workaround is to reset
+                    * its size after the container has been made visible. 
+                    */
+                    Display display = event.display;
+                    display.asyncExec(new Runnable () {
+                        public void run() {
+                            if (browser.isDisposed ()) return;
+                            onResize ();
+                        }
+                    });
+                    break;
+                }
+            }
+        }
+    };  
+    int[] folderEvents = new int[] {
+        DWT.Dispose,
+        DWT.Resize,  
+        DWT.FocusIn,
+        DWT.Activate,
+        DWT.Deactivate,
+        DWT.Show,
+        DWT.KeyDown     // needed to make browser traversable
+    };
+    for (int i = 0; i < folderEvents.length; i++) {
+        browser.addListener (folderEvents[i], listener);
+    }
+}
+
+public bool back () {
+    if (awaitingNavigate) return false;
+
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    
+    nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);          
+    rc = webNavigation.GoBack ();   
+    webNavigation.Release ();
+    return rc is XPCOM.NS_OK;
+}
+
+void createCOMInterfaces () {
+    // Create each of the interfaces that this object implements
+    supports = new XPCOMObject (new int[] {2, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+    };
+    
+    weakReference = new XPCOMObject (new int[] {2, 0, 0, 2}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return QueryReferent (args[0], args[1]);}
+    };
+
+    webProgressListener = new XPCOMObject (new int[] {2, 0, 0, 4, 6, 3, 4, 3}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return OnStateChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return OnProgressChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4], (int)/*64*/args[5]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return OnLocationChange (args[0], args[1], args[2]);}
+        public int /*long*/ method6 (int /*long*/[] args) {return OnStatusChange (args[0], args[1], (int)/*64*/args[2], args[3]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return OnSecurityChange (args[0], args[1], (int)/*64*/args[2]);}
+    };
+    
+    webBrowserChrome = new XPCOMObject (new int[] {2, 0, 0, 2, 1, 1, 1, 1, 0, 2, 0, 1, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return SetStatus ((int)/*64*/args[0], args[1]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return GetWebBrowser (args[0]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return SetWebBrowser (args[0]);}
+        public int /*long*/ method6 (int /*long*/[] args) {return GetChromeFlags (args[0]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return SetChromeFlags ((int)/*64*/args[0]);}
+        public int /*long*/ method8 (int /*long*/[] args) {return DestroyBrowserWindow ();}
+        public int /*long*/ method9 (int /*long*/[] args) {return SizeBrowserTo ((int)/*64*/args[0], (int)/*64*/args[1]);}
+        public int /*long*/ method10 (int /*long*/[] args) {return ShowAsModal ();}
+        public int /*long*/ method11 (int /*long*/[] args) {return IsWindowModal (args[0]);}
+        public int /*long*/ method12 (int /*long*/[] args) {return ExitModalEventLoop ((int)/*64*/args[0]);}
+    };
+    
+    webBrowserChromeFocus = new XPCOMObject (new int[] {2, 0, 0, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return FocusNextElement ();}
+        public int /*long*/ method4 (int /*long*/[] args) {return FocusPrevElement ();}
+    };
+        
+    embeddingSiteWindow = new XPCOMObject (new int[] {2, 0, 0, 5, 5, 0, 1, 1, 1, 1, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return SetDimensions ((int)/*64*/args[0], (int)/*64*/args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return GetDimensions ((int)/*64*/args[0], args[1], args[2], args[3], args[4]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return SetFocus ();}
+        public int /*long*/ method6 (int /*long*/[] args) {return GetVisibility (args[0]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return SetVisibility ((int)/*64*/args[0]);}
+        public int /*long*/ method8 (int /*long*/[] args) {return GetTitle (args[0]);}
+        public int /*long*/ method9 (int /*long*/[] args) {return SetTitle (args[0]);}
+        public int /*long*/ method10 (int /*long*/[] args) {return GetSiteWindow (args[0]);}
+    };
+    
+    interfaceRequestor = new XPCOMObject (new int[] {2, 0, 0, 2} ){
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return GetInterface (args[0], args[1]);}
+    };
+        
+    supportsWeakReference = new XPCOMObject (new int[] {2, 0, 0, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return GetWeakReference (args[0]);}
+    };
+    
+    contextMenuListener = new XPCOMObject (new int[] {2, 0, 0, 3}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return OnShowContextMenu ((int)/*64*/args[0], args[1], args[2]);}
+    };
+    
+    uriContentListener = new XPCOMObject (new int[] {2, 0, 0, 2, 5, 3, 4, 1, 1, 1, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return OnStartURIOpen (args[0], args[1]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return DoContent (args[0], (int)/*64*/args[1], args[2], args[3], args[4]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return IsPreferred (args[0], args[1], args[2]);}
+        public int /*long*/ method6 (int /*long*/[] args) {return CanHandleContent (args[0], (int)/*64*/args[1], args[2], args[3]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return GetLoadCookie (args[0]);}
+        public int /*long*/ method8 (int /*long*/[] args) {return SetLoadCookie (args[0]);}
+        public int /*long*/ method9 (int /*long*/[] args) {return GetParentContentListener (args[0]);}
+        public int /*long*/ method10 (int /*long*/[] args) {return SetParentContentListener (args[0]);}     
+    };
+    
+    tooltipListener = new XPCOMObject (new int[] {2, 0, 0, 3, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return OnShowTooltip ((int)/*64*/args[0], (int)/*64*/args[1], args[2]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return OnHideTooltip ();}        
+    };
+
+    domEventListener = new XPCOMObject (new int[] {2, 0, 0, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return HandleEvent (args[0]);}
+    };
+}
+
+void disposeCOMInterfaces () {
+    if (supports !is null) {
+        supports.dispose ();
+        supports = null;
+    }   
+    if (weakReference !is null) {
+        weakReference.dispose ();
+        weakReference = null;   
+    }
+    if (webProgressListener !is null) {
+        webProgressListener.dispose ();
+        webProgressListener = null;
+    }
+    if (webBrowserChrome !is null) {
+        webBrowserChrome.dispose ();
+        webBrowserChrome = null;
+    }
+    if (webBrowserChromeFocus !is null) {
+        webBrowserChromeFocus.dispose ();
+        webBrowserChromeFocus = null;
+    }
+    if (embeddingSiteWindow !is null) {
+        embeddingSiteWindow.dispose ();
+        embeddingSiteWindow = null;
+    }
+    if (interfaceRequestor !is null) {
+        interfaceRequestor.dispose ();
+        interfaceRequestor = null;
+    }       
+    if (supportsWeakReference !is null) {
+        supportsWeakReference.dispose ();
+        supportsWeakReference = null;
+    }   
+    if (contextMenuListener !is null) {
+        contextMenuListener.dispose ();
+        contextMenuListener = null;
+    }
+    if (uriContentListener !is null) {
+        uriContentListener.dispose ();
+        uriContentListener = null;
+    }
+    if (tooltipListener !is null) {
+        tooltipListener.dispose ();
+        tooltipListener = null;
+    }
+    if (domEventListener !is null) {
+        domEventListener.dispose ();
+        domEventListener = null;
+    }
+}
+
+public bool execute (String script) {
+    if (awaitingNavigate) return false;
+
+    String url = PREFIX_JAVASCRIPT + script + ";void(0);";  //$NON-NLS-1$
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+    nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+    char[] arg = url.toCharArray (); 
+    char[] c = new char[arg.length+1];
+    System.arraycopy (arg, 0, c, 0, arg.length);
+    rc = webNavigation.LoadURI (c, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0);
+    webNavigation.Release ();
+    return rc is XPCOM.NS_OK;
+}
+
+static Browser findBrowser (int /*long*/ handle) {
+    return MozillaDelegate.findBrowser (handle);
+}
+
+public bool forward () {
+    if (awaitingNavigate) return false;
+
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    
+    nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+    rc = webNavigation.GoForward ();
+    webNavigation.Release ();
+
+    return rc is XPCOM.NS_OK;
+}
+
+public String getText () {
+    if (awaitingNavigate) return ""; //$NON-NLS-1$
+
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.GetContentDOMWindow (result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+    nsIDOMWindow window = new nsIDOMWindow (result[0]);
+    result[0] = 0;
+    rc = window.GetDocument (result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+    window.Release ();
+
+    int /*long*/ document = result[0];
+    result[0] = 0;
+    rc = XPCOM.NS_GetComponentManager (result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+    nsIComponentManager componentManager = new nsIComponentManager (result[0]);
+    result[0] = 0;
+    byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DOMSERIALIZER_CONTRACTID, true);
+    char[] chars = null;
+
+    rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIDOMSerializer_1_7.NS_IDOMSERIALIZER_IID, result);
+    if (rc is XPCOM.NS_OK) {    /* mozilla >= 1.7 */
+        if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+        nsIDOMSerializer_1_7 serializer = new nsIDOMSerializer_1_7 (result[0]);
+        result[0] = 0;
+        int /*long*/ string = XPCOM.nsEmbedString_new ();
+        rc = serializer.SerializeToString (document, string);
+        serializer.Release ();
+
+        int length = XPCOM.nsEmbedString_Length (string);
+        int /*long*/ buffer = XPCOM.nsEmbedString_get (string);
+        chars = new char[length];
+        XPCOM.memmove (chars, buffer, length * 2);
+        XPCOM.nsEmbedString_delete (string);
+    } else {    /* mozilla < 1.7 */
+        rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIDOMSerializer.NS_IDOMSERIALIZER_IID, result);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+        nsIDOMSerializer serializer = new nsIDOMSerializer (result[0]);
+        result[0] = 0;
+        rc = serializer.SerializeToString (document, result);
+        serializer.Release ();
+
+        int length = XPCOM.strlen_PRUnichar (result[0]);
+        chars = new char[length];
+        XPCOM.memmove (chars, result[0], length * 2);
+    }
+
+    componentManager.Release ();
+    new nsISupports (document).Release ();
+    return new String (chars);
+}
+
+public String getUrl () {
+    if (awaitingNavigate) return ""; //$NON-NLS-1$
+
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+    nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+    int /*long*/[] aCurrentURI = new int /*long*/[1];
+    rc = webNavigation.GetCurrentURI (aCurrentURI);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    webNavigation.Release ();
+
+    byte[] dest = null;
+    if (aCurrentURI[0] !is 0) {
+        nsIURI uri = new nsIURI (aCurrentURI[0]);
+        int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
+        rc = uri.GetSpec (aSpec);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        int length = XPCOM.nsEmbedCString_Length (aSpec);
+        int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
+        dest = new byte[length];
+        XPCOM.memmove (dest, buffer, length);
+        XPCOM.nsEmbedCString_delete (aSpec);
+        uri.Release ();
+    }
+    if (dest is null) return ""; //$NON-NLS-1$
+
+    String location = new String (dest);
+    /*
+     * If the URI indicates that the page is being rendered from memory
+     * (via setText()) then set it to about:blank to be consistent with IE.
+     */
+    if (location.equals (URI_FROMMEMORY)) location = ABOUT_BLANK;
+    return location;
+}
+
+public Object getWebBrowser () {
+    if ((browser.getStyle () & DWT.MOZILLA) is 0) return null;
+    if (webBrowserObject !is null) return webBrowserObject;
+
+    try {
+        Class clazz = Class.forName ("org.mozilla.xpcom.Mozilla"); //$NON-NLS-1$
+        Method method = clazz.getMethod ("getInstance", new Class[0]); //$NON-NLS-1$
+        Object mozilla = method.invoke (null, new Object[0]);
+        method = clazz.getMethod ("wrapXPCOMObject", new Class[] {Long.TYPE, String.class}); //$NON-NLS-1$
+        webBrowserObject = method.invoke (mozilla, new Object[] {new Long (webBrowser.getAddress ()), nsIWebBrowser.NS_IWEBBROWSER_IID_STR});
+        /*
+         * The following AddRef() is needed to offset the automatic Release() that
+         * will be performed by JavaXPCOM when webBrowserObject is finalized.
+         */
+        webBrowser.AddRef ();
+        return webBrowserObject;
+    } catch (ClassNotFoundException e) {
+    } catch (NoSuchMethodException e) {
+    } catch (IllegalArgumentException e) {
+    } catch (IllegalAccessException e) {
+    } catch (InvocationTargetException e) {
+    }
+    return null;
+}
+
+public bool isBackEnabled () {
+    if (awaitingNavigate) return false;
+
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    
+    nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+    int[] aCanGoBack = new int[1]; /* PRBool */
+    rc = webNavigation.GetCanGoBack (aCanGoBack);   
+    webNavigation.Release ();
+    return aCanGoBack[0] !is 0;
+}
+
+public bool isForwardEnabled () {
+    if (awaitingNavigate) return false;
+
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    
+    nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+    int[] aCanGoForward = new int[1]; /* PRBool */
+    rc = webNavigation.GetCanGoForward (aCanGoForward);
+    webNavigation.Release ();
+    return aCanGoForward[0] !is 0;
+}
+
+static String error (int code) {
+    throw new DWTError ("XPCOM error " + code); //$NON-NLS-1$
+}
+
+void onDispose (Display display) {
+    int rc = webBrowser.RemoveWebBrowserListener (weakReference.getAddress (), nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID);
+    if (rc !is XPCOM.NS_OK) error (rc);
+
+    rc = webBrowser.SetParentURIContentListener (0);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    
+    unhookDOMListeners ();
+    if (listener !is null) {
+        int[] folderEvents = new int[] {
+            DWT.Dispose,
+            DWT.Resize,  
+            DWT.FocusIn,
+            DWT.Activate,
+            DWT.Deactivate,
+            DWT.Show,
+            DWT.KeyDown,
+        };
+        for (int i = 0; i < folderEvents.length; i++) {
+            browser.removeListener (folderEvents[i], listener);
+        }
+        listener = null;
+    }
+
+    int /*long*/[] result = new int /*long*/[1];
+    rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+    nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
+    rc = baseWindow.Destroy ();
+    if (rc !is XPCOM.NS_OK) error (rc);
+    baseWindow.Release ();
+
+    Release ();
+    webBrowser.Release ();
+    webBrowser = null;
+    webBrowserObject = null;
+
+    if (tip !is null && !tip.isDisposed ()) tip.dispose ();
+    tip = null;
+    location = size = null;
+
+    Enumeration elements = unhookedDOMWindows.elements ();
+    while (elements.hasMoreElements ()) {
+        LONG ptrObject = (LONG)elements.nextElement ();
+        new nsISupports (ptrObject.value).Release ();
+    }
+    unhookedDOMWindows = null;
+
+    mozDelegate.onDispose (embedHandle);
+    mozDelegate = null;
+
+    embedHandle = 0;
+    BrowserCount--;
+}
+
+void Activate () {
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIWebBrowserFocus.NS_IWEBBROWSERFOCUS_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    
+    nsIWebBrowserFocus webBrowserFocus = new nsIWebBrowserFocus (result[0]);
+    rc = webBrowserFocus.Activate ();
+    if (rc !is XPCOM.NS_OK) error (rc);
+    webBrowserFocus.Release ();
+}
+    
+void Deactivate () {
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIWebBrowserFocus.NS_IWEBBROWSERFOCUS_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    
+    nsIWebBrowserFocus webBrowserFocus = new nsIWebBrowserFocus (result[0]);
+    rc = webBrowserFocus.Deactivate ();
+    if (rc !is XPCOM.NS_OK) error (rc);
+    webBrowserFocus.Release ();
+}
+
+void onResize () {
+    Rectangle rect = browser.getClientArea ();
+    int width = Math.max (1, rect.width);
+    int height = Math.max (1, rect.height);
+
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+    mozDelegate.setSize (embedHandle, width, height);
+    nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
+    rc = baseWindow.SetPositionAndSize (0, 0, width, height, 1);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    baseWindow.Release ();
+}
+
+public void refresh () {
+    if (awaitingNavigate) return;
+
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+    if (rc !is XPCOM.NS_OK) error(rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    
+    nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);          
+    rc = webNavigation.Reload (nsIWebNavigation.LOAD_FLAGS_NONE);
+    webNavigation.Release ();
+    if (rc is XPCOM.NS_OK) return;
+    /*
+    * Feature in Mozilla.  Reload returns an error code NS_ERROR_INVALID_POINTER
+    * when it is called immediately after a request to load a new document using
+    * LoadURI.  The workaround is to ignore this error code.
+    *
+    * Feature in Mozilla.  Attempting to reload a file that no longer exists
+    * returns an error code of NS_ERROR_FILE_NOT_FOUND.  This is equivalent to
+    * attempting to load a non-existent local url, which is not a Browser error,
+    * so this error code should be ignored. 
+    */
+    if (rc !is XPCOM.NS_ERROR_INVALID_POINTER && rc !is XPCOM.NS_ERROR_FILE_NOT_FOUND) error (rc);
+}
+
+public bool setText (String html) {
+    /*
+    *  Feature in Mozilla.  The focus memory of Mozilla must be 
+    *  properly managed through the nsIWebBrowserFocus interface.
+    *  In particular, nsIWebBrowserFocus.deactivate must be called
+    *  when the focus moves from the browser (or one of its children
+    *  managed by Mozilla to another widget.  We currently do not
+    *  get notified when a widget takes focus away from the Browser.
+    *  As a result, deactivate is not properly called. This causes
+    *  Mozilla to retake focus the next time a document is loaded.
+    *  This breaks the case where the HTML loaded in the Browser 
+    *  varies while the user enters characters in a text widget. The text
+    *  widget loses focus every time new content is loaded.
+    *  The current workaround is to call deactivate everytime if 
+    *  the browser currently does not have focus. A better workaround
+    *  would be to have a way to call deactivate when the Browser
+    *  or one of its children loses focus.
+    */
+    if (browser !is browser.getDisplay ().getFocusControl ()) Deactivate ();
+    
+    /* convert the String containing HTML to an array of bytes with UTF-8 data */
+    byte[] data = null;
+    try {
+        data = html.getBytes ("UTF-8"); //$NON-NLS-1$
+    } catch (UnsupportedEncodingException e) {
+        return false;
+    }
+
+    awaitingNavigate = false;
+
+    byte[] contentTypeBuffer = MozillaDelegate.wcsToMbcs (null, "text/html", true); // $NON-NLS-1$
+    int /*long*/ aContentType = XPCOM.nsEmbedCString_new (contentTypeBuffer, contentTypeBuffer.length);
+    byte[] contentCharsetBuffer = MozillaDelegate.wcsToMbcs (null, "UTF-8", true);  //$NON-NLS-1$
+    int /*long*/ aContentCharset = XPCOM.nsEmbedCString_new (contentCharsetBuffer, contentCharsetBuffer.length);
+
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = XPCOM.NS_GetServiceManager (result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+    nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+    result[0] = 0;
+    rc = serviceManager.GetService (XPCOM.NS_IOSERVICE_CID, nsIIOService.NS_IIOSERVICE_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+    serviceManager.Release ();
+
+    nsIIOService ioService = new nsIIOService (result[0]);
+    result[0] = 0;
+    /*
+    * Note.  Mozilla ignores LINK tags used to load CSS stylesheets
+    * when the URI protocol for the nsInputStreamChannel
+    * is about:blank.  The fix is to specify the file protocol.
+    */
+    byte[] aString = MozillaDelegate.wcsToMbcs (null, URI_FROMMEMORY, false);
+    int /*long*/ aSpec = XPCOM.nsEmbedCString_new (aString, aString.length);
+    rc = ioService.NewURI (aSpec, null, 0, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+    XPCOM.nsEmbedCString_delete (aSpec);
+    ioService.Release ();
+
+    nsIURI uri = new nsIURI (result[0]);
+    result[0] = 0;
+
+    rc = webBrowser.QueryInterface (nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    nsIInterfaceRequestor interfaceRequestor = new nsIInterfaceRequestor (result[0]);
+    result[0] = 0;
+
+    /*
+    * Feature in Mozilla. LoadStream invokes the nsIInputStream argument
+    * through a different thread.  The callback mechanism must attach 
+    * a non java thread to the JVM otherwise the nsIInputStream Read and
+    * Close methods never get called.
+    */
+    InputStream inputStream = new InputStream (data);
+    inputStream.AddRef ();
+
+    rc = interfaceRequestor.GetInterface (nsIDocShell_1_9.NS_IDOCSHELL_IID, result);
+    if (rc is XPCOM.NS_OK) {
+        if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+        nsIDocShell_1_9 docShell = new nsIDocShell_1_9 (result[0]);
+        rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType,  aContentCharset, 0);
+        docShell.Release ();
+    } else {
+        result[0] = 0;
+        rc = interfaceRequestor.GetInterface (nsIDocShell_1_8.NS_IDOCSHELL_IID, result);
+        if (rc is XPCOM.NS_OK) {    
+            if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+            nsIDocShell_1_8 docShell = new nsIDocShell_1_8 (result[0]);
+            rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType,  aContentCharset, 0);
+            docShell.Release ();
+        } else {
+            result[0] = 0;
+            rc = interfaceRequestor.GetInterface (nsIDocShell.NS_IDOCSHELL_IID, result);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+            nsIDocShell docShell = new nsIDocShell (result[0]);
+            rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType,  aContentCharset, 0);
+            docShell.Release ();
+        }
+    }
+    if (rc !is XPCOM.NS_OK) error (rc);
+    result[0] = 0;
+
+    inputStream.Release ();
+    interfaceRequestor.Release ();
+    uri.Release ();
+    XPCOM.nsEmbedCString_delete (aContentCharset);
+    XPCOM.nsEmbedCString_delete (aContentType);
+    return true;
+}
+
+public bool setUrl (String url) {
+    awaitingNavigate = false;
+
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+    nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+    char[] uri = new char[url.length () + 1];
+    url.getChars (0, url.length (), uri, 0);
+    rc = webNavigation.LoadURI (uri, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0);
+    webNavigation.Release ();
+    return rc is XPCOM.NS_OK;
+}
+
+public void stop () {
+    if (awaitingNavigate) return;
+
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    
+    nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);      
+    rc = webNavigation.Stop (nsIWebNavigation.STOP_ALL);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    webNavigation.Release ();
+}
+
+void hookDOMListeners (nsIDOMEventTarget target, bool isTop) {
+    nsEmbedString string = new nsEmbedString (XPCOM.DOMEVENT_FOCUS);
+    target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_UNLOAD);
+    target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDOWN);
+    target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEUP);
+    target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEMOVE);
+    target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEWHEEL);
+    target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDRAG);
+    target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+
+    /*
+    * Only hook mouseover and mouseout if the target is a top-level frame, so that mouse moves
+    * between frames will not generate events.
+    */
+    if (isTop && mozDelegate.hookEnterExit ()) {
+        string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOVER);
+        target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+        string.dispose ();
+        string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOUT);
+        target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+        string.dispose ();
+    }
+
+    string = new nsEmbedString (XPCOM.DOMEVENT_KEYDOWN);
+    target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_KEYPRESS);
+    target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_KEYUP);
+    target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+}
+
+void unhookDOMListeners () {
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.GetContentDOMWindow (result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+    nsIDOMWindow window = new nsIDOMWindow (result[0]);
+    result[0] = 0;
+    rc = window.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+    nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]);
+    result[0] = 0;
+    unhookDOMListeners (target);
+    target.Release ();
+
+    /* Listeners must be unhooked in pages contained in frames */
+    rc = window.GetFrames (result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    nsIDOMWindowCollection frames = new nsIDOMWindowCollection (result[0]);
+    result[0] = 0;
+    int[] frameCount = new int[1];
+    rc = frames.GetLength (frameCount); /* PRUint32 */
+    if (rc !is XPCOM.NS_OK) error (rc);
+    int count = frameCount[0];
+
+    if (count > 0) {
+        for (int i = 0; i < count; i++) {
+            rc = frames.Item (i, result);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+            nsIDOMWindow frame = new nsIDOMWindow (result[0]);
+            result[0] = 0;
+            rc = frame.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+            target = new nsIDOMEventTarget (result[0]);
+            result[0] = 0;
+            unhookDOMListeners (target);
+            target.Release ();
+            frame.Release ();
+        }
+    }
+    frames.Release ();
+    window.Release ();
+}
+
+void unhookDOMListeners (nsIDOMEventTarget target) {
+    nsEmbedString string = new nsEmbedString (XPCOM.DOMEVENT_FOCUS);
+    target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_UNLOAD);
+    target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDOWN);
+    target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEUP);
+    target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEMOVE);
+    target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEWHEEL);
+    target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDRAG);
+    target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOVER);
+    target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOUT);
+    target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_KEYDOWN);
+    target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_KEYPRESS);
+    target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+    string = new nsEmbedString (XPCOM.DOMEVENT_KEYUP);
+    target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+    string.dispose ();
+}
+
+/* nsISupports */
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+    if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+
+    nsID guid = new nsID ();
+    XPCOM.memmove (guid, riid, nsID.sizeof);
+
+    if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIWeakReference.NS_IWEAKREFERENCE_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {weakReference.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {webProgressListener.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIWebBrowserChrome.NS_IWEBBROWSERCHROME_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {webBrowserChrome.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIWebBrowserChromeFocus.NS_IWEBBROWSERCHROMEFOCUS_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {webBrowserChromeFocus.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIEmbeddingSiteWindow.NS_IEMBEDDINGSITEWINDOW_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {embeddingSiteWindow.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {interfaceRequestor.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsISupportsWeakReference.NS_ISUPPORTSWEAKREFERENCE_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {supportsWeakReference.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIContextMenuListener.NS_ICONTEXTMENULISTENER_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {contextMenuListener.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIURIContentListener.NS_IURICONTENTLISTENER_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {uriContentListener.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsITooltipListener.NS_ITOOLTIPLISTENER_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {tooltipListener.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int AddRef () {
+    refCount++;
+    return refCount;
+}
+
+int Release () {
+    refCount--;
+    if (refCount is 0) disposeCOMInterfaces ();
+    return refCount;
+}
+
+/* nsIWeakReference */  
+    
+int QueryReferent (int /*long*/ riid, int /*long*/ ppvObject) {
+    return QueryInterface (riid, ppvObject);
+}
+
+/* nsIInterfaceRequestor */
+
+int GetInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+    if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+    nsID guid = new nsID ();
+    XPCOM.memmove (guid, riid, nsID.sizeof);
+    if (guid.Equals (nsIDOMWindow.NS_IDOMWINDOW_IID)) {
+        int /*long*/[] aContentDOMWindow = new int /*long*/[1];
+        int rc = webBrowser.GetContentDOMWindow (aContentDOMWindow);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        if (aContentDOMWindow[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+        XPCOM.memmove (ppvObject, aContentDOMWindow, C.PTR_SIZEOF);
+        return rc;
+    }
+    return QueryInterface (riid, ppvObject);
+}
+
+int GetWeakReference (int /*long*/ ppvObject) {
+    XPCOM.memmove (ppvObject, new int /*long*/[] {weakReference.getAddress ()}, C.PTR_SIZEOF);
+    AddRef ();
+    return XPCOM.NS_OK;
+}
+
+/* nsIWebProgressListener */
+
+int OnStateChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStateFlags, int aStatus) {
+    if ((aStateFlags & nsIWebProgressListener.STATE_IS_DOCUMENT) is 0) return XPCOM.NS_OK;
+    if ((aStateFlags & nsIWebProgressListener.STATE_START) !is 0) {
+        if (request is 0) request = aRequest;
+
+        if (!awaitingNavigate) {
+            /*
+             * Add the page's nsIDOMWindow to the collection of windows that will
+             * have DOM listeners added to them later on in the page loading
+             * process.  These listeners cannot be added yet because the
+             * nsIDOMWindow is not ready to take them at this stage.
+             */
+            int /*long*/[] result = new int /*long*/[1];
+            nsIWebProgress progress = new nsIWebProgress (aWebProgress);
+            int rc = progress.GetDOMWindow (result);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+            unhookedDOMWindows.addElement (new LONG (result[0]));
+        }
+    } else if ((aStateFlags & nsIWebProgressListener.STATE_REDIRECTING) !is 0) {
+        if (request is aRequest) request = 0;
+    } else if ((aStateFlags & nsIWebProgressListener.STATE_STOP) !is 0) {
+        /*
+        * If this page's nsIDOMWindow handle is still in unhookedDOMWindows then
+        * add its DOM listeners now.  It's possible for this to happen since
+        * there is no guarantee that a STATE_TRANSFERRING state change will be
+        * received for every window in a page, which is when these listeners
+        * are typically added.
+        */
+        int /*long*/[] result = new int /*long*/[1];
+        nsIWebProgress progress = new nsIWebProgress (aWebProgress);
+        int rc = progress.GetDOMWindow (result);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+        nsIDOMWindow domWindow = new nsIDOMWindow (result[0]);
+
+        LONG ptrObject = new LONG (result[0]);
+        result[0] = 0;
+        int index = unhookedDOMWindows.indexOf (ptrObject);
+        if (index !is -1) {
+            rc = webBrowser.GetContentDOMWindow (result);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+            bool isTop = result[0] is domWindow.getAddress ();
+            new nsISupports (result[0]).Release ();
+            result[0] = 0;
+
+            rc = domWindow.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+            nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]);
+            result[0] = 0;
+            hookDOMListeners (target, isTop);
+            target.Release ();
+
+            /*
+            * Remove and unreference the nsIDOMWindow from the collection of windows
+            * that are waiting to have DOM listeners hooked on them. 
+            */
+            unhookedDOMWindows.remove (ptrObject);
+            new nsISupports (ptrObject.value).Release ();
+        }
+        domWindow.Release ();
+
+        /*
+        * Feature in Mozilla.  When a request is redirected (STATE_REDIRECTING),
+        * it never reaches the state STATE_STOP and it is replaced with a new request.
+        * The new request is received when it is in the state STATE_STOP.
+        * To handle this case,  the variable request is set to 0 when the corresponding
+        * request is redirected. The following request received with the state STATE_STOP
+        * - the new request resulting from the redirection - is used to send
+        * the ProgressListener.completed event.
+        */
+        if (request is aRequest || request is 0) {
+            request = 0;
+            if (!awaitingNavigate) {
+                StatusTextEvent event = new StatusTextEvent (browser);
+                event.display = browser.getDisplay ();
+                event.widget = browser;
+                event.text = ""; //$NON-NLS-1$
+                for (int i = 0; i < statusTextListeners.length; i++) {
+                    statusTextListeners[i].changed (event);
+                }
+                ProgressEvent event2 = new ProgressEvent (browser);
+                event2.display = browser.getDisplay ();
+                event2.widget = browser;
+                for (int i = 0; i < progressListeners.length; i++) {
+                    progressListeners[i].completed (event2);
+                }
+            }
+        }
+    } else if ((aStateFlags & nsIWebProgressListener.STATE_TRANSFERRING) !is 0) {
+        /*
+        * Hook DOM listeners to the page's nsIDOMWindow here because this is
+        * the earliest opportunity to do so.    
+        */
+        int /*long*/[] result = new int /*long*/[1];
+        nsIWebProgress progress = new nsIWebProgress (aWebProgress);
+        int rc = progress.GetDOMWindow (result);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+        nsIDOMWindow domWindow = new nsIDOMWindow (result[0]);
+
+        LONG ptrObject = new LONG (result[0]);
+        result[0] = 0;
+        int index = unhookedDOMWindows.indexOf (ptrObject);
+        if (index !is -1) {
+            rc = webBrowser.GetContentDOMWindow (result);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+            bool isTop = result[0] is domWindow.getAddress ();
+            new nsISupports (result[0]).Release ();
+            result[0] = 0;
+
+            rc = domWindow.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+            nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]);
+            result[0] = 0;
+            hookDOMListeners (target, isTop);
+            target.Release ();
+
+            /*
+            * Remove and unreference the nsIDOMWindow from the collection of windows
+            * that are waiting to have DOM listeners hooked on them. 
+            */
+            unhookedDOMWindows.remove (ptrObject);
+            new nsISupports (ptrObject.value).Release ();
+        }
+        domWindow.Release ();
+    }
+    return XPCOM.NS_OK;
+}
+
+int OnProgressChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aCurSelfProgress, int aMaxSelfProgress, int aCurTotalProgress, int aMaxTotalProgress) {
+    if (awaitingNavigate || progressListeners.length is 0) return XPCOM.NS_OK;
+    ProgressEvent event = new ProgressEvent (browser);
+    event.display = browser.getDisplay ();
+    event.widget = browser;
+    event.current = aCurTotalProgress;
+    event.total = aMaxTotalProgress;
+    for (int i = 0; i < progressListeners.length; i++) {
+        progressListeners[i].changed (event);
+    }
+    return XPCOM.NS_OK;
+}
+
+int OnLocationChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int /*long*/ aLocation) {
+    /*
+    * Feature in Mozilla.  When a page is loaded via setText before a previous
+    * setText page load has completed, the expected OnStateChange STATE_STOP for the
+    * original setText never arrives because it gets replaced by the OnStateChange
+    * STATE_STOP for the new request.  This results in the request field never being
+    * cleared because the original request's OnStateChange STATE_STOP is still expected
+    * (but never arrives).  To handle this case, the request field is updated to the new
+    * overriding request since its OnStateChange STATE_STOP will be received next.
+    */
+    if (request !is 0 && request !is aRequest) request = aRequest;
+
+    if (awaitingNavigate || locationListeners.length is 0) return XPCOM.NS_OK;
+
+    nsIWebProgress webProgress = new nsIWebProgress (aWebProgress);
+    int /*long*/[] aDOMWindow = new int /*long*/[1];
+    int rc = webProgress.GetDOMWindow (aDOMWindow);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (aDOMWindow[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    
+    nsIDOMWindow domWindow = new nsIDOMWindow (aDOMWindow[0]);
+    int /*long*/[] aTop = new int /*long*/[1];
+    rc = domWindow.GetTop (aTop);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (aTop[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    domWindow.Release ();
+    
+    nsIDOMWindow topWindow = new nsIDOMWindow (aTop[0]);
+    topWindow.Release ();
+    
+    nsIURI location = new nsIURI (aLocation);
+    int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
+    location.GetSpec (aSpec);
+    int length = XPCOM.nsEmbedCString_Length (aSpec);
+    int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
+    byte[] dest = new byte[length];
+    XPCOM.memmove (dest, buffer, length);
+    XPCOM.nsEmbedCString_delete (aSpec);
+    String url = new String (dest);
+
+    /*
+     * As of Mozilla 1.8, the first time that a page is displayed, regardless of
+     * whether it's via Browser.setURL() or Browser.setText(), the GRE navigates
+     * to about:blank and fires the corresponding navigation events.  Do not send
+     * this event on to the user since it is not expected.
+     */
+    if (!IsPre_1_8 && aRequest is 0 && url.startsWith (ABOUT_BLANK)) return XPCOM.NS_OK;
+
+    LocationEvent event = new LocationEvent (browser);
+    event.display = browser.getDisplay ();
+    event.widget = browser;
+    event.location = url;
+    /*
+     * If the URI indicates that the page is being rendered from memory
+     * (via setText()) then set it to about:blank to be consistent with IE.
+     */
+    if (event.location.equals (URI_FROMMEMORY)) event.location = ABOUT_BLANK;
+    event.top = aTop[0] is aDOMWindow[0];
+    for (int i = 0; i < locationListeners.length; i++) {
+        locationListeners[i].changed (event);
+    }
+    return XPCOM.NS_OK;
+}
+
+int OnStatusChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStatus, int /*long*/ aMessage) {
+    if (awaitingNavigate || statusTextListeners.length is 0) return XPCOM.NS_OK;
+    StatusTextEvent event = new StatusTextEvent (browser);
+    event.display = browser.getDisplay ();
+    event.widget = browser;
+    int length = XPCOM.strlen_PRUnichar (aMessage);
+    char[] dest = new char[length];
+    XPCOM.memmove (dest, aMessage, length * 2);
+    event.text = new String (dest);
+    for (int i = 0; i < statusTextListeners.length; i++) {
+        statusTextListeners[i].changed (event);
+    }
+    return XPCOM.NS_OK;
+}       
+
+int OnSecurityChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int state) {
+    return XPCOM.NS_OK;
+}
+
+/* nsIWebBrowserChrome */
+
+int SetStatus (int statusType, int /*long*/ status) {
+    if (awaitingNavigate || statusTextListeners.length is 0) return XPCOM.NS_OK;
+    StatusTextEvent event = new StatusTextEvent (browser);
+    event.display = browser.getDisplay ();
+    event.widget = browser;
+    int length = XPCOM.strlen_PRUnichar (status);
+    char[] dest = new char[length];
+    XPCOM.memmove (dest, status, length * 2);
+    String string = new String (dest);
+    event.text = string;
+    for (int i = 0; i < statusTextListeners.length; i++) {
+        statusTextListeners[i].changed (event);
+    }
+    return XPCOM.NS_OK;
+}
+
+int GetWebBrowser (int /*long*/ aWebBrowser) {
+    int /*long*/[] ret = new int /*long*/[1];   
+    if (webBrowser !is null) {
+        webBrowser.AddRef ();
+        ret[0] = webBrowser.getAddress ();  
+    }
+    XPCOM.memmove (aWebBrowser, ret, C.PTR_SIZEOF);
+    return XPCOM.NS_OK;
+}
+
+int SetWebBrowser (int /*long*/ aWebBrowser) {
+    if (webBrowser !is null) webBrowser.Release ();
+    webBrowser = aWebBrowser !is 0 ? new nsIWebBrowser (aWebBrowser) : null;                
+    return XPCOM.NS_OK;
+}
+   
+int GetChromeFlags (int /*long*/ aChromeFlags) {
+    int[] ret = new int[1];
+    ret[0] = chromeFlags;
+    XPCOM.memmove (aChromeFlags, ret, 4); /* PRUint32 */
+    return XPCOM.NS_OK;
+}
+
+int SetChromeFlags (int aChromeFlags) {
+    chromeFlags = aChromeFlags;
+    return XPCOM.NS_OK;
+}
+
+int DestroyBrowserWindow () {
+    WindowEvent newEvent = new WindowEvent (browser);
+    newEvent.display = browser.getDisplay ();
+    newEvent.widget = browser;
+    for (int i = 0; i < closeWindowListeners.length; i++) {
+        closeWindowListeners[i].close (newEvent);
+    }
+    /*
+    * Note on Mozilla.  The DestroyBrowserWindow notification cannot be cancelled.
+    * The browser widget cannot be used after this notification has been received.
+    * The application is advised to close the window hosting the browser widget.
+    * The browser widget must be disposed in all cases.
+    */
+    browser.dispose ();
+    return XPCOM.NS_OK;
+}
+    
+int SizeBrowserTo (int aCX, int aCY) {
+    size = new Point (aCX, aCY);
+    bool isChrome = (chromeFlags & nsIWebBrowserChrome.CHROME_OPENAS_CHROME) !is 0;
+    if (isChrome) {
+        Shell shell = browser.getShell ();
+        shell.setSize (shell.computeSize (size.x, size.y));
+    }
+    return XPCOM.NS_OK;
+}
+
+int ShowAsModal () {
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = XPCOM.NS_GetServiceManager (result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+    nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+    result[0] = 0;
+    byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_CONTEXTSTACK_CONTRACTID, true);
+    rc = serviceManager.GetServiceByContractID (aContractID, nsIJSContextStack.NS_IJSCONTEXTSTACK_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+    serviceManager.Release ();
+
+    nsIJSContextStack stack = new nsIJSContextStack (result[0]);
+    result[0] = 0;
+    rc = stack.Push (0);
+    if (rc !is XPCOM.NS_OK) error (rc);
+
+    Shell shell = browser.getShell ();
+    Display display = browser.getDisplay ();
+    while (!shell.isDisposed ()) {
+        if (!display.readAndDispatch ()) display.sleep ();
+    }
+
+    rc = stack.Pop (result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    stack.Release ();
+    return XPCOM.NS_OK;
+}
+
+int IsWindowModal (int /*long*/ retval) {
+    int result = (chromeFlags & nsIWebBrowserChrome.CHROME_MODAL) !is 0 ? 1 : 0;
+    XPCOM.memmove (retval, new int[] {result}, 4); /* PRBool */
+    return XPCOM.NS_OK;
+}
+   
+int ExitModalEventLoop (int aStatus) {
+    return XPCOM.NS_OK;
+}
+
+/* nsIEmbeddingSiteWindow */ 
+
+int SetDimensions (int flags, int x, int y, int cx, int cy) {
+    if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_POSITION) !is 0) {
+        location = new Point (x, y);
+        browser.getShell ().setLocation (x, y);
+    }
+    if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_INNER) !is 0) {
+        browser.setSize (cx, cy);
+    }
+    if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_OUTER) !is 0) {
+        browser.getShell ().setSize (cx, cy);
+    }
+    return XPCOM.NS_OK;
+}
+
+int GetDimensions (int flags, int /*long*/ x, int /*long*/ y, int /*long*/ cx, int /*long*/ cy) {
+    if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_POSITION) !is 0) {
+        Point location = browser.getShell ().getLocation ();
+        if (x !is 0) C.memmove (x, new int[] {location.x}, 4); /* PRInt32 */
+        if (y !is 0) C.memmove (y, new int[] {location.y}, 4); /* PRInt32 */
+    }
+    if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_INNER) !is 0) {
+        Point size = browser.getSize ();
+        if (cx !is 0) C.memmove (cx, new int[] {size.x}, 4); /* PRInt32 */
+        if (cy !is 0) C.memmove (cy, new int[] {size.y}, 4); /* PRInt32 */
+    }
+    if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_OUTER) !is 0) {
+        Point size = browser.getShell().getSize ();
+        if (cx !is 0) C.memmove (cx, new int[] {size.x}, 4); /* PRInt32 */
+        if (cy !is 0) C.memmove (cy, new int[] {size.y}, 4); /* PRInt32 */
+    }
+    return XPCOM.NS_OK;
+}
+
+int SetFocus () {
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+    
+    nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
+    rc = baseWindow.SetFocus ();
+    if (rc !is XPCOM.NS_OK) error (rc);
+    baseWindow.Release ();
+
+    /*
+    * Note. Mozilla notifies here that one of the children took
+    * focus. This could or should be used to fire an DWT.FOCUS_IN
+    * event on Browser focus listeners.
+    */
+    return XPCOM.NS_OK;         
+}   
+
+int GetVisibility (int /*long*/ aVisibility) {
+    bool visible = browser.isVisible () && !browser.getShell ().getMinimized ();
+    XPCOM.memmove (aVisibility, new int[] {visible ? 1 : 0}, 4); /* PRBool */
+    return XPCOM.NS_OK;
+}
+
+int SetVisibility (int aVisibility) {
+    if (isChild) {
+        WindowEvent event = new WindowEvent (browser);
+        event.display = browser.getDisplay ();
+        event.widget = browser;
+        if (aVisibility !is 0) {
+            /*
+            * Bug in Mozilla.  When the JavaScript window.open is executed, Mozilla
+            * fires multiple SetVisibility 1 notifications.  The workaround is
+            * to ignore subsequent notifications. 
+            */
+            if (!visible) {
+                visible = true;
+                event.location = location;
+                event.size = size;
+                event.addressBar = (chromeFlags & nsIWebBrowserChrome.CHROME_LOCATIONBAR) !is 0;
+                event.menuBar = (chromeFlags & nsIWebBrowserChrome.CHROME_MENUBAR) !is 0;
+                event.statusBar = (chromeFlags & nsIWebBrowserChrome.CHROME_STATUSBAR) !is 0;
+                event.toolBar = (chromeFlags & nsIWebBrowserChrome.CHROME_TOOLBAR) !is 0;
+                for (int i = 0; i < visibilityWindowListeners.length; i++) {
+                    visibilityWindowListeners[i].show (event);
+                }
+                location = null;
+                size = null;
+            }
+        } else {
+            visible = false;
+            for (int i = 0; i < visibilityWindowListeners.length; i++) {
+                visibilityWindowListeners[i].hide (event);
+            }
+        }
+    } else {
+        visible = aVisibility !is 0;
+    }
+    return XPCOM.NS_OK;         
+}
+
+int GetTitle (int /*long*/ aTitle) {
+    return XPCOM.NS_OK;         
+}
+ 
+int SetTitle (int /*long*/ aTitle) {
+    if (awaitingNavigate || titleListeners.length is 0) return XPCOM.NS_OK;
+    TitleEvent event = new TitleEvent (browser);
+    event.display = browser.getDisplay ();
+    event.widget = browser;
+    /*
+    * To be consistent with other platforms the title event should
+    * contain the page's url if the page does not contain a <title>
+    * tag. 
+    */
+    int length = XPCOM.strlen_PRUnichar (aTitle);
+    if (length > 0) {
+        char[] dest = new char[length];
+        XPCOM.memmove (dest, aTitle, length * 2);
+        event.title = new String (dest);
+    } else {
+        event.title = getUrl ();
+    }
+    for (int i = 0; i < titleListeners.length; i++) {
+        titleListeners[i].changed (event);
+    }
+    return XPCOM.NS_OK;         
+}
+
+int GetSiteWindow (int /*long*/ aSiteWindow) {
+    /*
+    * Note.  The handle is expected to be an HWND on Windows and
+    * a GtkWidget* on GTK.  This callback is invoked on Windows
+    * when the javascript window.print is invoked and the print
+    * dialog comes up. If no handle is returned, the print dialog
+    * does not come up on this platform.  
+    */
+    XPCOM.memmove (aSiteWindow, new int /*long*/[] {embedHandle}, C.PTR_SIZEOF);
+    return XPCOM.NS_OK;         
+}  
+ 
+/* nsIWebBrowserChromeFocus */
+
+int FocusNextElement () {
+    /*
+    * Bug in Mozilla embedding API.  Mozilla takes back the focus after sending
+    * this event.  This prevents tabbing out of Mozilla. This behaviour can be reproduced
+    * with the Mozilla application TestGtkEmbed.  The workaround is to
+    * send the traversal notification after this callback returns.
+    */
+    browser.getDisplay ().asyncExec (new Runnable () {
+        public void run () {
+            if (browser.isDisposed ()) return;
+            browser.traverse (DWT.TRAVERSE_TAB_NEXT);
+        }
+    });
+    return XPCOM.NS_OK;  
+}
+
+int FocusPrevElement () {
+    /*
+    * Bug in Mozilla embedding API.  Mozilla takes back the focus after sending
+    * this event.  This prevents tabbing out of Mozilla. This behaviour can be reproduced
+    * with the Mozilla application TestGtkEmbed.  The workaround is to
+    * send the traversal notification after this callback returns.
+    */
+    browser.getDisplay ().asyncExec (new Runnable () {
+        public void run () {
+            if (browser.isDisposed ()) return;
+            browser.traverse (DWT.TRAVERSE_TAB_PREVIOUS);
+        }
+    });
+    return XPCOM.NS_OK;         
+}
+
+/* nsIContextMenuListener */
+
+int OnShowContextMenu (int aContextFlags, int /*long*/ aEvent, int /*long*/ aNode) {
+    if (awaitingNavigate) return XPCOM.NS_OK;
+
+    nsIDOMEvent domEvent = new nsIDOMEvent (aEvent);
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = domEvent.QueryInterface (nsIDOMMouseEvent.NS_IDOMMOUSEEVENT_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+    nsIDOMMouseEvent domMouseEvent = new nsIDOMMouseEvent (result[0]);
+    int[] aScreenX = new int[1], aScreenY = new int[1];
+    rc = domMouseEvent.GetScreenX (aScreenX);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    rc = domMouseEvent.GetScreenY (aScreenY);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    domMouseEvent.Release ();
+    
+    Event event = new Event ();
+    event.x = aScreenX[0];
+    event.y = aScreenY[0];
+    browser.notifyListeners (DWT.MenuDetect, event);
+    if (!event.doit) return XPCOM.NS_OK;
+    Menu menu = browser.getMenu ();
+    if (menu !is null && !menu.isDisposed ()) {
+        if (aScreenX[0] !is event.x || aScreenY[0] !is event.y) {
+            menu.setLocation (event.x, event.y);
+        }
+        menu.setVisible (true);
+    }
+    return XPCOM.NS_OK;         
+}
+
+/* nsIURIContentListener */
+
+int OnStartURIOpen (int /*long*/ aURI, int /*long*/ retval) {
+    if (awaitingNavigate || locationListeners.length is 0) {
+        XPCOM.memmove (retval, new int[] {0}, 4); /* PRBool */
+        return XPCOM.NS_OK;
+    }
+    nsIURI location = new nsIURI (aURI);
+    int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
+    location.GetSpec (aSpec);
+    int length = XPCOM.nsEmbedCString_Length (aSpec);
+    int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
+    buffer = XPCOM.nsEmbedCString_get (aSpec);
+    byte[] dest = new byte[length];
+    XPCOM.memmove (dest, buffer, length);
+    XPCOM.nsEmbedCString_delete (aSpec);
+    String value = new String (dest);
+    bool doit = true;
+    if (request is 0) {
+        /* 
+         * listeners should not be notified of internal transitions like "javascipt:..."
+         * because this is an implementation side-effect, not a true navigate
+         */
+        if (!value.startsWith (PREFIX_JAVASCRIPT)) {
+            LocationEvent event = new LocationEvent (browser);
+            event.display = browser.getDisplay();
+            event.widget = browser;
+            event.location = value;
+            /*
+             * If the URI indicates that the page is being rendered from memory
+             * (via setText()) then set it to about:blank to be consistent with IE.
+             */
+            if (event.location.equals (URI_FROMMEMORY)) event.location = ABOUT_BLANK;
+            event.doit = doit;
+            for (int i = 0; i < locationListeners.length; i++) {
+                locationListeners[i].changing (event);
+            }
+            doit = event.doit && !browser.isDisposed();
+        }
+    }
+    XPCOM.memmove (retval, new int[] {doit ? 0 : 1}, 4); /* PRBool */
+    return XPCOM.NS_OK;
+}
+
+int DoContent (int /*long*/ aContentType, int aIsContentPreferred, int /*long*/ aRequest, int /*long*/ aContentHandler, int /*long*/ retval) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int IsPreferred (int /*long*/ aContentType, int /*long*/ aDesiredContentType, int /*long*/ retval) {
+    bool preferred = false;
+    int size = XPCOM.strlen (aContentType);
+    if (size > 0) {
+        byte[] typeBytes = new byte[size + 1];
+        XPCOM.memmove (typeBytes, aContentType, size);
+        String contentType = new String (typeBytes, 0, size);
+
+        /* do not attempt to handle known problematic content types */
+        if (!contentType.equals (XPCOM.CONTENT_MAYBETEXT) && !contentType.equals (XPCOM.CONTENT_MULTIPART)) {
+            /* determine whether browser can handle the content type */
+            int /*long*/[] result = new int /*long*/[1];
+            int rc = XPCOM.NS_GetServiceManager (result);
+            if (rc !is XPCOM.NS_OK) error (rc);
+            if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+            nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+            result[0] = 0;
+
+            /* First try to use the nsIWebNavigationInfo if it's available (>= mozilla 1.8) */
+            byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_WEBNAVIGATIONINFO_CONTRACTID, true);
+            rc = serviceManager.GetServiceByContractID (aContractID, nsIWebNavigationInfo.NS_IWEBNAVIGATIONINFO_IID, result);
+            if (rc is 0) {
+                byte[] bytes = MozillaDelegate.wcsToMbcs (null, contentType, true);
+                int /*long*/ typePtr = XPCOM.nsEmbedCString_new (bytes, bytes.length);
+                nsIWebNavigationInfo info = new nsIWebNavigationInfo (result[0]);
+                result[0] = 0;
+                int[] isSupportedResult = new int[1]; /* PRUint32 */
+                rc = info.IsTypeSupported (typePtr, 0, isSupportedResult);
+                if (rc !is XPCOM.NS_OK) error (rc);
+                info.Release ();
+                XPCOM.nsEmbedCString_delete (typePtr);
+                preferred = isSupportedResult[0] !is 0;
+            } else {
+                /* nsIWebNavigationInfo is not available, so do the type lookup */
+                result[0] = 0;
+                rc = serviceManager.GetService (XPCOM.NS_CATEGORYMANAGER_CID, nsICategoryManager.NS_ICATEGORYMANAGER_IID, result);
+                if (rc !is XPCOM.NS_OK) error (rc);
+                if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+                nsICategoryManager categoryManager = new nsICategoryManager (result[0]);
+                result[0] = 0;
+                byte[] categoryBytes = MozillaDelegate.wcsToMbcs (null, "Gecko-Content-Viewers", true); //$NON-NLS-1$
+                rc = categoryManager.GetCategoryEntry (categoryBytes, typeBytes, result);
+                categoryManager.Release ();
+                /* if no viewer for the content type is registered then rc is XPCOM.NS_ERROR_NOT_AVAILABLE */
+                preferred = rc is XPCOM.NS_OK;
+            }
+            serviceManager.Release ();
+        }
+    }
+
+    XPCOM.memmove(retval, new int[] {preferred ? 1 : 0}, 4); /* PRBool */
+    if (preferred) {
+        XPCOM.memmove (aDesiredContentType, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    }
+    return XPCOM.NS_OK;
+}
+
+int CanHandleContent (int /*long*/ aContentType, int aIsContentPreferred, int /*long*/ aDesiredContentType, int /*long*/ retval) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetLoadCookie (int /*long*/ aLoadCookie) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetLoadCookie (int /*long*/ aLoadCookie) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetParentContentListener (int /*long*/ aParentContentListener) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+    
+int SetParentContentListener (int /*long*/ aParentContentListener) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsITooltipListener */
+
+int OnShowTooltip (int aXCoords, int aYCoords, int /*long*/ aTipText) {
+    if (awaitingNavigate) return XPCOM.NS_OK;
+
+    int length = XPCOM.strlen_PRUnichar (aTipText);
+    char[] dest = new char[length];
+    XPCOM.memmove (dest, aTipText, length * 2);
+    String text = new String (dest);
+    if (tip !is null && !tip.isDisposed ()) tip.dispose ();
+    Display display = browser.getDisplay ();
+    Shell parent = browser.getShell ();
+    tip = new Shell (parent, DWT.ON_TOP);
+    tip.setLayout (new FillLayout());
+    Label label = new Label (tip, DWT.CENTER);
+    label.setForeground (display.getSystemColor (DWT.COLOR_INFO_FOREGROUND));
+    label.setBackground (display.getSystemColor (DWT.COLOR_INFO_BACKGROUND));
+    label.setText (text);
+    /*
+    * Bug in Mozilla embedded API.  Tooltip coordinates are wrong for 
+    * elements inside an inline frame (IFrame tag).  The workaround is 
+    * to position the tooltip based on the mouse cursor location.
+    */
+    Point point = display.getCursorLocation ();
+    /* Assuming cursor is 21x21 because this is the size of
+     * the arrow cursor on Windows
+     */ 
+    point.y += 21;
+    tip.setLocation (point);
+    tip.pack ();
+    tip.setVisible (true);
+    return XPCOM.NS_OK;
+}
+
+int OnHideTooltip () {
+    if (tip !is null && !tip.isDisposed ()) tip.dispose ();
+    tip = null;
+    return XPCOM.NS_OK;
+}
+
+/* nsIDOMEventListener */
+
+int HandleEvent (int /*long*/ event) {
+    nsIDOMEvent domEvent = new nsIDOMEvent (event);
+
+    int /*long*/ type = XPCOM.nsEmbedString_new ();
+    int rc = domEvent.GetType (type);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    int length = XPCOM.nsEmbedString_Length (type);
+    int /*long*/ buffer = XPCOM.nsEmbedString_get (type);
+    char[] chars = new char[length];
+    XPCOM.memmove (chars, buffer, length * 2);
+    String typeString = new String (chars);
+    XPCOM.nsEmbedString_delete (type);
+
+    if (XPCOM.DOMEVENT_UNLOAD.equals (typeString)) {
+        int /*long*/[] result = new int /*long*/[1];
+        rc = domEvent.GetCurrentTarget (result);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+        nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]);
+        unhookDOMListeners (target);
+        target.Release ();
+        return XPCOM.NS_OK;
+    }
+
+    if (XPCOM.DOMEVENT_FOCUS.equals (typeString)) {
+        mozDelegate.handleFocus ();
+        return XPCOM.NS_OK;
+    }
+
+    if (XPCOM.DOMEVENT_KEYDOWN.equals (typeString)) {
+        int /*long*/[] result = new int /*long*/[1];
+        rc = domEvent.QueryInterface (nsIDOMKeyEvent.NS_IDOMKEYEVENT_IID, result);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+        nsIDOMKeyEvent domKeyEvent = new nsIDOMKeyEvent (result[0]);
+        result[0] = 0;
+
+        int[] aKeyCode = new int[1]; /* PRUint32 */
+        rc = domKeyEvent.GetKeyCode (aKeyCode);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        int keyCode = translateKey (aKeyCode[0]);
+
+        /*
+        * if keyCode is lastKeyCode then either a repeating key like Shift
+        * is being held or a key for which key events are not sent has been
+        * pressed.  In both of these cases a KeyDown should not be sent.
+        */
+        if (keyCode !is lastKeyCode) {
+            lastKeyCode = keyCode;
+            switch (keyCode) {
+                case DWT.SHIFT:
+                case DWT.CONTROL:
+                case DWT.ALT:
+                case DWT.CAPS_LOCK:
+                case DWT.NUM_LOCK:
+                case DWT.SCROLL_LOCK:
+                case DWT.COMMAND: {
+                    /* keypress events will not be received for these keys, so send KeyDowns for them now */
+                    int[] aAltKey = new int[1], aCtrlKey = new int[1], aShiftKey = new int[1], aMetaKey = new int[1]; /* PRBool */
+                    rc = domKeyEvent.GetAltKey (aAltKey);
+                    if (rc !is XPCOM.NS_OK) error (rc);
+                    rc = domKeyEvent.GetCtrlKey (aCtrlKey);
+                    if (rc !is XPCOM.NS_OK) error (rc);
+                    rc = domKeyEvent.GetShiftKey (aShiftKey);
+                    if (rc !is XPCOM.NS_OK) error (rc);
+                    rc = domKeyEvent.GetMetaKey (aMetaKey);
+                    if (rc !is XPCOM.NS_OK) error (rc);
+
+                    Event keyEvent = new Event ();
+                    keyEvent.widget = browser;
+                    keyEvent.type = DWT.KeyDown;
+                    keyEvent.keyCode = keyCode;
+                    keyEvent.stateMask = (aAltKey[0] !is 0 ? DWT.ALT : 0) | (aCtrlKey[0] !is 0 ? DWT.CTRL : 0) | (aShiftKey[0] !is 0 ? DWT.SHIFT : 0) | (aMetaKey[0] !is 0 ? DWT.COMMAND : 0);
+                    keyEvent.stateMask &= ~keyCode;     /* remove current keydown if it's a state key */
+                    browser.notifyListeners (keyEvent.type, keyEvent);
+                    if (!keyEvent.doit) {
+                        domEvent.PreventDefault ();
+                    }
+                    break;
+                }
+                default: {
+                    /* 
+                    * If the keydown has Meta (but not Meta+Ctrl) as a modifier then send a KeyDown event for it here
+                    * because a corresponding keypress event will not be received for it from the DOM.  If the keydown
+                    * does not have Meta as a modifier, or has Meta+Ctrl as a modifier, then then do nothing here
+                    * because its KeyDown event will be sent from the keypress listener.
+                    */
+                    int[] aMetaKey = new int[1]; /* PRBool */
+                    rc = domKeyEvent.GetMetaKey (aMetaKey);
+                    if (rc !is XPCOM.NS_OK) error (rc);
+                    if (aMetaKey[0] !is 0) {
+                        int[] aCtrlKey = new int[1]; /* PRBool */
+                        rc = domKeyEvent.GetCtrlKey (aCtrlKey);
+                        if (rc !is XPCOM.NS_OK) error (rc);
+                        if (aCtrlKey[0] is 0) {
+                            int[] aAltKey = new int[1], aShiftKey = new int[1]; /* PRBool */
+                            rc = domKeyEvent.GetAltKey (aAltKey);
+                            if (rc !is XPCOM.NS_OK) error (rc);
+                            rc = domKeyEvent.GetShiftKey (aShiftKey);
+                            if (rc !is XPCOM.NS_OK) error (rc);
+
+                            Event keyEvent = new Event ();
+                            keyEvent.widget = browser;
+                            keyEvent.type = DWT.KeyDown;
+                            keyEvent.keyCode = lastKeyCode;
+                            keyEvent.stateMask = (aAltKey[0] !is 0 ? DWT.ALT : 0) | (aCtrlKey[0] !is 0? DWT.CTRL : 0) | (aShiftKey[0] !is 0? DWT.SHIFT : 0) | (aMetaKey[0] !is 0? DWT.COMMAND : 0);
+                            browser.notifyListeners (keyEvent.type, keyEvent);
+                            if (!keyEvent.doit) {
+                                domEvent.PreventDefault ();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        domKeyEvent.Release ();
+        return XPCOM.NS_OK;
+    }
+
+    if (XPCOM.DOMEVENT_KEYPRESS.equals (typeString)) {
+        /*
+        * if keydown could not determine a keycode for this key then it's a
+        * key for which key events are not sent (eg.- the Windows key)
+        */
+        if (lastKeyCode is 0) return XPCOM.NS_OK;
+
+        /*
+        * On linux only, unexpected keypress events are received for some
+        * modifier keys.  The workaround is to ignore these events since
+        * KeyDown events are sent for these keys in the keydown listener.  
+        */
+        switch (lastKeyCode) {
+            case DWT.CAPS_LOCK:
+            case DWT.NUM_LOCK:
+            case DWT.SCROLL_LOCK: return XPCOM.NS_OK;
+        }
+
+        int /*long*/[] result = new int /*long*/[1];
+        rc = domEvent.QueryInterface (nsIDOMKeyEvent.NS_IDOMKEYEVENT_IID, result);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+        nsIDOMKeyEvent domKeyEvent = new nsIDOMKeyEvent (result[0]);
+        result[0] = 0;
+
+        int[] aAltKey = new int[1], aCtrlKey = new int[1], aShiftKey = new int[1], aMetaKey = new int[1]; /* PRBool */
+        rc = domKeyEvent.GetAltKey (aAltKey);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        rc = domKeyEvent.GetCtrlKey (aCtrlKey);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        rc = domKeyEvent.GetShiftKey (aShiftKey);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        rc = domKeyEvent.GetMetaKey (aMetaKey);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        domKeyEvent.Release ();
+
+        int[] aCharCode = new int[1]; /* PRUint32 */
+        rc = domKeyEvent.GetCharCode (aCharCode);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        lastCharCode = aCharCode[0];
+        if (lastCharCode is 0) {
+            switch (lastKeyCode) {
+                case DWT.TAB: lastCharCode = DWT.TAB; break;
+                case DWT.CR: lastCharCode = DWT.CR; break;
+                case DWT.BS: lastCharCode = DWT.BS; break;
+                case DWT.ESC: lastCharCode = DWT.ESC; break;
+                case DWT.DEL: lastCharCode = DWT.DEL; break;
+            }
+        }
+        if (aCtrlKey[0] !is 0 && (0 <= lastCharCode && lastCharCode <= 0x7F)) {
+            if ('a'  <= lastCharCode && lastCharCode <= 'z') lastCharCode -= 'a' - 'A';
+            if (64 <= lastCharCode && lastCharCode <= 95) lastCharCode -= 64;
+        }
+
+        Event keyEvent = new Event ();
+        keyEvent.widget = browser;
+        keyEvent.type = DWT.KeyDown;
+        keyEvent.keyCode = lastKeyCode;
+        keyEvent.character = (char)lastCharCode;
+        keyEvent.stateMask = (aAltKey[0] !is 0 ? DWT.ALT : 0) | (aCtrlKey[0] !is 0 ? DWT.CTRL : 0) | (aShiftKey[0] !is 0 ? DWT.SHIFT : 0) | (aMetaKey[0] !is 0 ? DWT.COMMAND : 0);
+        browser.notifyListeners (keyEvent.type, keyEvent);
+        if (!keyEvent.doit) {
+            domEvent.PreventDefault ();
+        }
+        return XPCOM.NS_OK;
+    }
+
+    if (XPCOM.DOMEVENT_KEYUP.equals (typeString)) {
+        int /*long*/[] result = new int /*long*/[1];
+        rc = domEvent.QueryInterface (nsIDOMKeyEvent.NS_IDOMKEYEVENT_IID, result);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+        nsIDOMKeyEvent domKeyEvent = new nsIDOMKeyEvent (result[0]);
+        result[0] = 0;
+
+        int[] aKeyCode = new int[1]; /* PRUint32 */
+        rc = domKeyEvent.GetKeyCode (aKeyCode);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        int keyCode = translateKey (aKeyCode[0]);
+        if (keyCode is 0) {
+            /* indicates a key for which key events are not sent */
+            domKeyEvent.Release ();
+            return XPCOM.NS_OK;
+        }
+        if (keyCode !is lastKeyCode) {
+            /* keyup does not correspond to the last keydown */
+            lastKeyCode = keyCode;
+            lastCharCode = 0;
+        }
+
+        int[] aAltKey = new int[1], aCtrlKey = new int[1], aShiftKey = new int[1], aMetaKey = new int[1]; /* PRBool */
+        rc = domKeyEvent.GetAltKey (aAltKey);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        rc = domKeyEvent.GetCtrlKey (aCtrlKey);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        rc = domKeyEvent.GetShiftKey (aShiftKey);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        rc = domKeyEvent.GetMetaKey (aMetaKey);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        domKeyEvent.Release ();
+
+        Event keyEvent = new Event ();
+        keyEvent.widget = browser;
+        keyEvent.type = DWT.KeyUp;
+        keyEvent.keyCode = lastKeyCode;
+        keyEvent.character = (char)lastCharCode;
+        keyEvent.stateMask = (aAltKey[0] !is 0 ? DWT.ALT : 0) | (aCtrlKey[0] !is 0 ? DWT.CTRL : 0) | (aShiftKey[0] !is 0 ? DWT.SHIFT : 0) | (aMetaKey[0] !is 0 ? DWT.COMMAND : 0);
+        switch (lastKeyCode) {
+            case DWT.SHIFT:
+            case DWT.CONTROL:
+            case DWT.ALT:
+            case DWT.COMMAND: {
+                keyEvent.stateMask |= lastKeyCode;
+            }
+        }
+        browser.notifyListeners (keyEvent.type, keyEvent);
+        if (!keyEvent.doit) {
+            domEvent.PreventDefault ();
+        }
+        lastKeyCode = lastCharCode = 0;
+        return XPCOM.NS_OK;
+    }
+
+    /* mouse event */
+
+    int /*long*/[] result = new int /*long*/[1];
+    rc = domEvent.QueryInterface (nsIDOMMouseEvent.NS_IDOMMOUSEEVENT_IID, result);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+    nsIDOMMouseEvent domMouseEvent = new nsIDOMMouseEvent (result[0]);
+    result[0] = 0;
+
+    /*
+     * MouseOver and MouseOut events are fired any time the mouse enters or exits
+     * any element within the Browser.  To ensure that DWT events are only
+     * fired for mouse movements into or out of the Browser, do not fire an
+     * event if the element being exited (on MouseOver) or entered (on MouseExit)
+     * is within the Browser.
+     */
+    if (XPCOM.DOMEVENT_MOUSEOVER.equals (typeString) || XPCOM.DOMEVENT_MOUSEOUT.equals (typeString)) {
+        rc = domMouseEvent.GetRelatedTarget (result);
+        if (rc !is XPCOM.NS_OK) error (rc);
+        if (result[0] !is 0) {
+            domMouseEvent.Release ();
+            return XPCOM.NS_OK;
+        }
+    }
+
+    int[] aClientX = new int[1], aClientY = new int[1], aDetail = new int[1]; /* PRInt32 */
+    rc = domMouseEvent.GetClientX (aClientX);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    rc = domMouseEvent.GetClientY (aClientY);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    rc = domMouseEvent.GetDetail (aDetail);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    short[] aButton = new short[1]; /* PRUint16 */
+    rc = domMouseEvent.GetButton (aButton);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    int[] aAltKey = new int[1], aCtrlKey = new int[1], aShiftKey = new int[1], aMetaKey = new int[1]; /* PRBool */
+    rc = domMouseEvent.GetAltKey (aAltKey);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    rc = domMouseEvent.GetCtrlKey (aCtrlKey);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    rc = domMouseEvent.GetShiftKey (aShiftKey);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    rc = domMouseEvent.GetMetaKey (aMetaKey);
+    if (rc !is XPCOM.NS_OK) error (rc);
+    domMouseEvent.Release ();
+
+    Event mouseEvent = new Event ();
+    mouseEvent.widget = browser;
+    mouseEvent.x = aClientX[0]; mouseEvent.y = aClientY[0];
+    mouseEvent.stateMask = (aAltKey[0] !is 0 ? DWT.ALT : 0) | (aCtrlKey[0] !is 0 ? DWT.CTRL : 0) | (aShiftKey[0] !is 0 ? DWT.SHIFT : 0) | (aMetaKey[0] !is 0 ? DWT.COMMAND : 0);
+
+    if (XPCOM.DOMEVENT_MOUSEDOWN.equals (typeString)) {
+        mozDelegate.handleMouseDown ();
+        mouseEvent.type = DWT.MouseDown;
+        mouseEvent.button = aButton[0] + 1;
+        mouseEvent.count = aDetail[0];
+    } else if (XPCOM.DOMEVENT_MOUSEUP.equals (typeString)) {
+        /*
+         * Bug on OSX.  For some reason multiple mouseup events come from the DOM
+         * when button 3 is released on OSX.  The first of these events has a count
+         * detail and the others do not.  The workaround is to not fire received
+         * button 3 mouseup events that do not have a count since mouse events
+         * without a click count are not valid.
+         */
+        int button = aButton[0] + 1;
+        int count = aDetail[0];
+        if (count is 0 && button is 3) return XPCOM.NS_OK;
+        mouseEvent.type = DWT.MouseUp;
+        mouseEvent.button = button;
+        mouseEvent.count = count;
+    } else if (XPCOM.DOMEVENT_MOUSEMOVE.equals (typeString)) {
+        mouseEvent.type = DWT.MouseMove;
+    } else if (XPCOM.DOMEVENT_MOUSEWHEEL.equals (typeString)) {
+        mouseEvent.type = DWT.MouseWheel;
+        mouseEvent.count = -aDetail[0];
+    } else if (XPCOM.DOMEVENT_MOUSEOVER.equals (typeString)) {
+        mouseEvent.type = DWT.MouseEnter;
+    } else if (XPCOM.DOMEVENT_MOUSEOUT.equals (typeString)) {
+        mouseEvent.type = DWT.MouseExit;
+    } else if (XPCOM.DOMEVENT_MOUSEDRAG.equals (typeString)) {
+        mouseEvent.type = DWT.DragDetect;
+        mouseEvent.button = aButton[0] + 1;
+        switch (mouseEvent.button) {
+            case 1: mouseEvent.stateMask |= DWT.BUTTON1; break;
+            case 2: mouseEvent.stateMask |= DWT.BUTTON2; break;
+            case 3: mouseEvent.stateMask |= DWT.BUTTON3; break;
+            case 4: mouseEvent.stateMask |= DWT.BUTTON4; break;
+            case 5: mouseEvent.stateMask |= DWT.BUTTON5; break;
+        }
+    }
+
+    browser.notifyListeners (mouseEvent.type, mouseEvent);
+    if (aDetail[0] is 2 && XPCOM.DOMEVENT_MOUSEDOWN.equals (typeString)) {
+        mouseEvent = new Event ();
+        mouseEvent.widget = browser;
+        mouseEvent.x = aClientX[0]; mouseEvent.y = aClientY[0];
+        mouseEvent.stateMask = (aAltKey[0] !is 0 ? DWT.ALT : 0) | (aCtrlKey[0] !is 0 ? DWT.CTRL : 0) | (aShiftKey[0] !is 0 ? DWT.SHIFT : 0) | (aMetaKey[0] !is 0 ? DWT.COMMAND : 0);
+        mouseEvent.type = DWT.MouseDoubleClick;
+        mouseEvent.button = aButton[0] + 1;
+        mouseEvent.count = aDetail[0];
+        browser.notifyListeners (mouseEvent.type, mouseEvent);  
+    }
+    return XPCOM.NS_OK;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/MozillaDelegate.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.MozillaDelegate;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.internal.Callback;
+import dwt.internal.Converter;
+import dwt.internal.gtk.GdkEvent;
+import dwt.internal.gtk.OS;
+import dwt.widgets.Display;
+import dwt.widgets.Event;
+import dwt.widgets.Listener;
+import dwt.widgets.Widget;
+
+class MozillaDelegate {
+    Browser browser;
+    int /*long*/ mozillaHandle, embedHandle;
+    bool hasFocus;
+    Listener listener;
+    static Callback eventCallback;
+    static int /*long*/ eventProc;
+    static final int STOP_PROPOGATE = 1;
+
+    static bool IsLinux;
+    static {
+        String osName = System.getProperty ("os.name").toLowerCase (); //$NON-NLS-1$
+        IsLinux = osName.startsWith ("linux"); //$NON-NLS-1$
+    }
+
+MozillaDelegate (Browser browser) {
+    super ();
+    if (!IsLinux) {
+        browser.dispose ();
+        DWT.error (DWT.ERROR_NO_HANDLES, null, " [Unsupported platform]"); //$NON-NLS-1$
+    }
+    this.browser = browser;
+}
+
+static int /*long*/ eventProc (int /*long*/ handle, int /*long*/ gdkEvent, int /*long*/ pointer) {
+    int /*long*/ parent = OS.gtk_widget_get_parent (handle);
+    parent = OS.gtk_widget_get_parent (parent);
+    if (parent is 0) return 0;
+    Widget widget = Display.getCurrent ().findWidget (parent);
+    if (widget !is null && widget instanceof Browser) {
+        return ((Mozilla)((Browser)widget).webBrowser).delegate.gtk_event (handle, gdkEvent, pointer);
+    }
+    return 0;
+}
+
+static Browser findBrowser (int /*long*/ handle) {
+    /*
+    * Note.  On GTK, Mozilla is embedded into a GtkHBox handle
+    * and not directly into the parent Composite handle.
+    */
+    int /*long*/ parent = OS.gtk_widget_get_parent (handle);
+    Display display = Display.getCurrent ();
+    return (Browser)display.findWidget (parent); 
+}
+
+static char[] mbcsToWcs (String codePage, byte [] buffer) {
+    return Converter.mbcsToWcs (codePage, buffer);
+}
+
+static byte[] wcsToMbcs (String codePage, String string, bool terminate) {
+    return Converter.wcsToMbcs (codePage, string, terminate);
+}
+
+int /*long*/ getHandle () {
+    /*
+    * Bug in Mozilla Linux GTK.  Embedding Mozilla into a GtkFixed
+    * handle causes problems with some Mozilla plug-ins.  For some
+    * reason, the Flash plug-in causes the child of the GtkFixed
+    * handle to be resized to 1 when the Flash document is loaded.
+    * That could be due to gtk_container_resize_children being called
+    * by Mozilla - or one of its plug-ins - on the GtkFixed handle,
+    * causing the child of the GtkFixed handle to be resized to 1.
+    * The workaround is to embed Mozilla into a GtkHBox handle.
+    */
+    embedHandle = OS.gtk_hbox_new (false, 0);
+    OS.gtk_container_add (browser.handle, embedHandle);
+    OS.gtk_widget_show (embedHandle);
+    return embedHandle;
+}
+
+String getLibraryName () {
+    return "libxpcom.so"; //$NON-NLS-1$
+}
+
+String getSWTInitLibraryName () {
+    return "swt-xpcominit"; //$NON-NLS-1$
+}
+
+int /*long*/ gtk_event (int /*long*/ handle, int /*long*/ gdkEvent, int /*long*/ pointer) {
+    GdkEvent event = new GdkEvent ();
+    OS.memmove (event, gdkEvent, GdkEvent.sizeof);
+    if (event.type is OS.GDK_BUTTON_PRESS) {
+        if (!hasFocus) browser.setFocus ();
+    }
+
+    /* 
+    * Stop the propagation of events that are not consumed by Mozilla, before
+    * they reach the parent embedder.  These event have already been received.
+    */
+    if (pointer is STOP_PROPOGATE) return 1;
+    return 0;
+}
+
+void handleFocus () {
+    if (hasFocus) return;
+    hasFocus = true;
+    listener = new Listener () {
+        public void handleEvent (Event event) {
+            if (event.widget is browser) return;
+            ((Mozilla)browser.webBrowser).Deactivate ();
+            hasFocus = false;
+            browser.getDisplay ().removeFilter (DWT.FocusIn, this);
+            browser.getShell ().removeListener (DWT.Deactivate, this);
+            listener = null;
+        }
+    };
+    browser.getDisplay ().addFilter (DWT.FocusIn, listener);
+    browser.getShell ().addListener (DWT.Deactivate, listener);
+}
+
+void handleMouseDown () {
+    int shellStyle = browser.getShell ().getStyle (); 
+    if ((shellStyle & DWT.ON_TOP) !is 0 && (((shellStyle & DWT.NO_FOCUS) is 0) || ((browser.getStyle () & DWT.NO_FOCUS) is 0))) {
+        browser.getDisplay ().asyncExec (new Runnable () {
+            public void run () {
+                if (browser is null || browser.isDisposed ()) return;
+                ((Mozilla)browser.webBrowser).Activate ();
+            }
+        });
+    }
+}
+
+bool hookEnterExit () {
+    return false;
+}
+
+void init () {
+    if (eventCallback is null) {
+        eventCallback = new Callback (getClass (), "eventProc", 3); //$NON-NLS-1$
+        eventProc = eventCallback.getAddress ();
+        if (eventProc is 0) {
+            browser.dispose ();
+            Mozilla.error (DWT.ERROR_NO_MORE_CALLBACKS);
+        }
+    }
+
+    /*
+    * Feature in Mozilla.  GtkEvents such as key down, key pressed may be consumed
+    * by Mozilla and never be received by the parent embedder.  The workaround
+    * is to find the top Mozilla gtk widget that receives all the Mozilla GtkEvents,
+    * i.e. the first child of the parent embedder. Then hook event callbacks and
+    * forward the event to the parent embedder before Mozilla received and consumed
+    * them.
+    */
+    int /*long*/ list = OS.gtk_container_get_children (embedHandle);
+    if (list !is 0) {
+        mozillaHandle = OS.g_list_data (list);
+        OS.g_list_free (list);
+        
+        if (mozillaHandle !is 0) {          
+            /* Note. Callback to get events before Mozilla receives and consumes them. */
+            OS.g_signal_connect (mozillaHandle, OS.event, eventProc, 0);
+            
+            /* 
+            * Note.  Callback to get the events not consumed by Mozilla - and to block 
+            * them so that they don't get propagated to the parent handle twice.  
+            * This hook is set after Mozilla and is therefore called after Mozilla's 
+            * handler because GTK dispatches events in their order of registration.
+            */
+            OS.g_signal_connect (mozillaHandle, OS.key_press_event, eventProc, STOP_PROPOGATE);
+            OS.g_signal_connect (mozillaHandle, OS.key_release_event, eventProc, STOP_PROPOGATE);
+            OS.g_signal_connect (mozillaHandle, OS.button_press_event, eventProc, STOP_PROPOGATE);
+        }
+    }
+}
+
+bool needsSpinup () {
+    return true;
+}
+
+void onDispose (int /*long*/ embedHandle) {
+    if (listener !is null) {
+        browser.getDisplay ().removeFilter (DWT.FocusIn, listener);
+        browser.getShell ().removeListener (DWT.Deactivate, listener);
+        listener = null;
+    }
+    browser = null;
+}
+
+void setSize (int /*long*/ embedHandle, int width, int height) {
+    OS.gtk_widget_set_size_request (embedHandle, width, height);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/OpenWindowListener.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.OpenWindowListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/** 
+ * This listener interface may be implemented in order to receive
+ * a {@link WindowEvent} notification when a new {@link Browser}
+ * needs to be provided by the application.
+ * 
+ * @see Browser#addOpenWindowListener(OpenWindowListener)
+ * @see Browser#removeOpenWindowListener(OpenWindowListener)
+ * @see CloseWindowListener
+ * @see VisibilityWindowListener
+ * 
+ * @since 3.0
+ */
+public interface OpenWindowListener extends DWTEventListener {
+
+/**
+ * This method is called when a new window needs to be created.
+ * <p>
+ * A particular <code>Browser</code> can be passed to the event.browser
+ * field to host the content of a new window.
+ * <p>
+ * A standalone system browser is used to host the new window
+ * if the event.required field value is false and if the event.browser 
+ * field is left <code>null</code>. The event.required field
+ * is true on platforms that don't support a standalone system browser for
+ * new window requests. 
+ * <p>
+ * The navigation is cancelled if the event.required field is set to
+ * true and the event.browser field is left <code>null</code>.
+ * <p>
+ * <p>The following fields in the <code>WindowEvent</code> apply:
+ * <ul>
+ * <li>(in/out) required true if the platform requires the user to provide a
+ * <code>Browser</code> to handle the new window or false otherwise.
+ * <li>(out) browser the new <code>Browser</code> that will host the 
+ * content of the new window.
+ * <li>(in) widget the <code>Browser</code> that is requesting to open a 
+ * new window
+ * </ul>
+ * 
+ * @param event the <code>WindowEvent</code> that needs to be passed a new
+ * <code>Browser</code> to handle the new window request
+ * 
+ * @since 3.0
+ */ 
+public void open(WindowEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/ProgressAdapter.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.ProgressAdapter;
+
+import dwt.dwthelper.utils;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the {@link ProgressListener} interface.
+ * <p>
+ * Classes that wish to deal with {@link ProgressEvent}'s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ * 
+ * @since 3.0
+ */
+public abstract class ProgressAdapter implements ProgressListener {
+ 
+public void changed(ProgressEvent event) {
+}
+
+public void completed(ProgressEvent event) {
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/ProgressEvent.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+module dwt.browser.ProgressEvent;
+
+import dwt.dwthelper.utils;
+
+import dwt.events.TypedEvent;
+import dwt.widgets.Widget;
+
+/**
+ * A <code>ProgressEvent</code> is sent by a {@link Browser} to
+ * {@link ProgressListener}'s when a progress is made during the
+ * loading of the current URL or when the loading of the current
+ * URL has been completed.
+ * 
+ * @since 3.0
+ */
+public class ProgressEvent : TypedEvent {
+    /** current value */
+    public int current;
+    /** total value */
+    public int total;
+    
+    static final long serialVersionUID = 3977018427045393972L;
+
+    this(Widget w) {
+        super(w);
+    }
+
+    /**
+    * Returns a string containing a concise, human-readable
+    * description of the receiver.
+    *
+    * @return a string representation of the event
+    */
+
+    public override String toString () {
+        return Format( "ProgressEvent { current={} total={} }",
+            current, total );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/ProgressListener.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.ProgressListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * a {@link ProgressEvent} notification when a {@link Browser}
+ * makes a progress in loading the current URL or when the
+ * current URL has been loaded.
+ * 
+ * @see Browser#addProgressListener(ProgressListener)
+ * @see Browser#removeProgressListener(ProgressListener)
+ * @see Browser#getUrl()
+ * 
+ * @since 3.0
+ */
+public interface ProgressListener extends DWTEventListener {
+    
+/**
+ * This method is called when a progress is made during the loading of the 
+ * current location.
+ * <p>
+ *
+ * <p>The following fields in the <code>ProgressEvent</code> apply:
+ * <ul>
+ * <li>(in) current the progress for the location currently being loaded
+ * <li>(in) total the maximum progress for the location currently being loaded
+ * <li>(in) widget the <code>Browser</code> whose current URL is being loaded
+ * </ul>
+ * 
+ * @param event the <code>ProgressEvent</code> related to the loading of the
+ * current location of a <code>Browser</code>
+ * 
+ * @since 3.0
+ */   
+public void changed(ProgressEvent event);
+    
+/**
+ * This method is called when the current location has been completely loaded.
+ * <p>
+ *
+ * <p>The following fields in the <code>ProgressEvent</code> apply:
+ * <ul>
+ * <li>(in) widget the <code>Browser</code> whose current URL has been loaded
+ * </ul>
+ * 
+ * @param event the <code>ProgressEvent</code> related to the <code>Browser</code>
+ * that has loaded its current URL.
+ * 
+ * @since 3.0
+ */
+public void completed(ProgressEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/PromptDialog.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.PromptDialog;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.layout.GridData;
+import dwt.layout.GridLayout;
+import dwt.widgets.Button;
+import dwt.widgets.Composite;
+import dwt.widgets.Dialog;
+import dwt.widgets.Display;
+import dwt.widgets.Event;
+import dwt.widgets.Label;
+import dwt.widgets.Listener;
+import dwt.widgets.Monitor;
+import dwt.widgets.Shell;
+import dwt.widgets.Text;
+import dwt.widgets.Widget;
+
+class PromptDialog extends Dialog {
+    
+    PromptDialog(Shell parent, int style) {
+        super(parent, style);
+    }
+    
+    PromptDialog(Shell parent) {
+        this(parent, 0);
+    }
+    
+    void alertCheck(String title, String text, String check, final int[] checkValue) {
+        Shell parent = getParent();
+        final Shell shell = new Shell(parent, DWT.DIALOG_TRIM | DWT.APPLICATION_MODAL);
+        if (title !is null) shell.setText(title);
+        GridLayout gridLayout = new GridLayout();
+        shell.setLayout(gridLayout);
+        Label label = new Label(shell, DWT.WRAP);
+        label.setText(text);
+        GridData data = new GridData();
+        Monitor monitor = parent.getMonitor();
+        int maxWidth = monitor.getBounds().width * 2 / 3;
+        int width = label.computeSize(DWT.DEFAULT, DWT.DEFAULT).x;
+        data.widthHint = Math.min(width, maxWidth);
+        data.horizontalAlignment = GridData.FILL;
+        data.grabExcessHorizontalSpace = true;
+        label.setLayoutData (data);
+
+        final Button checkButton = check !is null ? new Button(shell, DWT.CHECK) : null;
+        if (checkButton !is null) {
+            checkButton.setText(check);
+            checkButton.setSelection(checkValue[0] !is 0);
+            data = new GridData ();
+            data.horizontalAlignment = GridData.BEGINNING;
+            checkButton.setLayoutData (data);
+        }
+        Button okButton = new Button(shell, DWT.PUSH);
+        okButton.setText(DWT.getMessage("SWT_OK")); //$NON-NLS-1$
+        data = new GridData ();
+        data.horizontalAlignment = GridData.CENTER;
+        okButton.setLayoutData (data);
+        okButton.addListener(DWT.Selection, new Listener() {
+            public void handleEvent(Event event) {
+                if (checkButton !is null) checkValue[0] = checkButton.getSelection() ? 1 : 0;
+                shell.close();
+            }
+        });
+
+        shell.pack();
+        shell.open();
+        Display display = parent.getDisplay();
+        while (!shell.isDisposed()) {
+            if (!display.readAndDispatch()) display.sleep();
+        }
+    }
+
+    void confirmEx(String title, String text, String check, String button0, String button1, String button2, int defaultIndex, final int[] checkValue, final int[] result) {
+        Shell parent = getParent();
+        final Shell shell = new Shell(parent, DWT.DIALOG_TRIM | DWT.APPLICATION_MODAL);
+        shell.setText(title);
+        GridLayout gridLayout = new GridLayout();
+        shell.setLayout(gridLayout);
+        Label label = new Label(shell, DWT.WRAP);
+        label.setText(text);
+        GridData data = new GridData();
+        Monitor monitor = parent.getMonitor();
+        int maxWidth = monitor.getBounds().width * 2 / 3;
+        int width = label.computeSize(DWT.DEFAULT, DWT.DEFAULT).x;
+        data.widthHint = Math.min(width, maxWidth);
+        data.horizontalAlignment = GridData.FILL;
+        data.grabExcessHorizontalSpace = true;
+        label.setLayoutData (data);
+
+        final Button[] buttons = new Button[4];
+        Listener listener = new Listener() {
+            public void handleEvent(Event event) {
+                if (buttons[0] !is null) checkValue[0] = buttons[0].getSelection() ? 1 : 0;
+                Widget widget = event.widget;
+                for (int i = 1; i < buttons.length; i++) {
+                    if (widget is buttons[i]) {
+                        result[0] = i - 1;
+                        break;
+                    }
+                }
+                shell.close();
+            }   
+        };
+        if (check !is null) {
+            buttons[0] = new Button(shell, DWT.CHECK);
+            buttons[0].setText(check);
+            buttons[0].setSelection(checkValue[0] !is 0);
+            data = new GridData ();
+            data.horizontalAlignment = GridData.BEGINNING;
+            buttons[0].setLayoutData (data);
+        }
+        Composite composite = new Composite(shell, DWT.NONE);
+        data = new GridData();
+        data.horizontalAlignment = GridData.CENTER;
+        composite.setLayoutData (data);
+        GridLayout layout = new GridLayout();
+        layout.makeColumnsEqualWidth = true;
+        composite.setLayout(layout);
+        int buttonCount = 0;
+        if (button0 !is null) {
+            buttons[1] = new Button(composite, DWT.PUSH);
+            buttons[1].setText(button0);
+            buttons[1].addListener(DWT.Selection, listener);
+            buttons[1].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+            buttonCount++;
+        }
+        if (button1 !is null) {
+            buttons[2] = new Button(composite, DWT.PUSH);
+            buttons[2].setText(button1);
+            buttons[2].addListener(DWT.Selection, listener);
+            buttons[2].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+            buttonCount++;
+        }
+        if (button2 !is null) {
+            buttons[3] = new Button(composite, DWT.PUSH);
+            buttons[3].setText(button2);
+            buttons[3].addListener(DWT.Selection, listener);
+            buttons[3].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+            buttonCount++;
+        }
+        layout.numColumns = buttonCount;
+        Button defaultButton = buttons [defaultIndex + 1];
+        if (defaultButton !is null) shell.setDefaultButton (defaultButton);
+
+        shell.pack();
+        shell.open();
+        Display display = parent.getDisplay();
+        while (!shell.isDisposed()) {
+            if (!display.readAndDispatch()) display.sleep();
+        }
+    }
+    
+    void prompt(String title, String text, String check, final String[] value, final int[] checkValue, final int[] result) {
+        Shell parent = getParent();
+        final Shell shell = new Shell(parent, DWT.DIALOG_TRIM | DWT.APPLICATION_MODAL);
+        if (title !is null) shell.setText(title);
+        GridLayout gridLayout = new GridLayout();
+        shell.setLayout(gridLayout);
+        Label label = new Label(shell, DWT.WRAP);
+        label.setText(text);
+        GridData data = new GridData();
+        Monitor monitor = parent.getMonitor();
+        int maxWidth = monitor.getBounds().width * 2 / 3;
+        int width = label.computeSize(DWT.DEFAULT, DWT.DEFAULT).x;
+        data.widthHint = Math.min(width, maxWidth);
+        data.horizontalAlignment = GridData.FILL;
+        data.grabExcessHorizontalSpace = true;
+        label.setLayoutData (data);
+                
+        final Text valueText = new Text(shell, DWT.BORDER);
+        if (value[0] !is null) valueText.setText(value[0]);
+        data = new GridData();
+        width = valueText.computeSize(DWT.DEFAULT, DWT.DEFAULT).x;
+        if (width > maxWidth) data.widthHint = maxWidth;
+        data.horizontalAlignment = GridData.FILL;
+        data.grabExcessHorizontalSpace = true;
+        valueText.setLayoutData(data);
+
+        final Button[] buttons = new Button[3];
+        Listener listener = new Listener() {
+            public void handleEvent(Event event) {
+                if (buttons[0] !is null) checkValue[0] = buttons[0].getSelection() ? 1 : 0;
+                value[0] = valueText.getText();
+                result[0] = event.widget is buttons[1] ? 1 : 0;
+                shell.close();
+            }   
+        };
+        if (check !is null) {
+            buttons[0] = new Button(shell, DWT.CHECK);
+            buttons[0].setText(check);
+            buttons[0].setSelection(checkValue[0] !is 0);
+            data = new GridData ();
+            data.horizontalAlignment = GridData.BEGINNING;
+            buttons[0].setLayoutData (data);
+        }
+        Composite composite = new Composite(shell, DWT.NONE);
+        data = new GridData();
+        data.horizontalAlignment = GridData.CENTER;
+        composite.setLayoutData (data);
+        composite.setLayout(new GridLayout(2, true));
+        buttons[1] = new Button(composite, DWT.PUSH);
+        buttons[1].setText(DWT.getMessage("SWT_OK")); //$NON-NLS-1$
+        buttons[1].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        buttons[1].addListener(DWT.Selection, listener);
+        buttons[2] = new Button(composite, DWT.PUSH);
+        buttons[2].setText(DWT.getMessage("SWT_Cancel")); //$NON-NLS-1$
+        buttons[2].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        buttons[2].addListener(DWT.Selection, listener);
+
+        shell.pack();
+        shell.open();
+        Display display = parent.getDisplay();
+        while (!shell.isDisposed()) {
+            if (!display.readAndDispatch()) display.sleep();
+        }   
+    }
+
+    void promptUsernameAndPassword(String title, String text, String check, final String[] user, final String[] pass, final int[] checkValue, final int[] result) {
+        Shell parent = getParent();
+        final Shell shell = new Shell(parent, DWT.DIALOG_TRIM | DWT.APPLICATION_MODAL);
+        shell.setText(title);
+        GridLayout gridLayout = new GridLayout();
+        shell.setLayout(gridLayout);
+        Label label = new Label(shell, DWT.WRAP);
+        label.setText(text);
+        GridData data = new GridData();
+        Monitor monitor = parent.getMonitor();
+        int maxWidth = monitor.getBounds().width * 2 / 3;
+        int width = label.computeSize(DWT.DEFAULT, DWT.DEFAULT).x;
+        data.widthHint = Math.min(width, maxWidth);
+        data.horizontalAlignment = GridData.FILL;
+        data.grabExcessHorizontalSpace = true;
+        label.setLayoutData (data);
+        
+        Label userLabel = new Label(shell, DWT.NONE);
+        userLabel.setText(DWT.getMessage("SWT_Username")); //$NON-NLS-1$
+        
+        final Text userText = new Text(shell, DWT.BORDER);
+        if (user[0] !is null) userText.setText(user[0]);
+        data = new GridData();
+        data.horizontalAlignment = GridData.FILL;
+        data.grabExcessHorizontalSpace = true;
+        userText.setLayoutData(data);
+        
+        Label passwordLabel = new Label(shell, DWT.NONE);
+        passwordLabel.setText(DWT.getMessage("SWT_Password")); //$NON-NLS-1$
+        
+        final Text passwordText = new Text(shell, DWT.PASSWORD | DWT.BORDER);
+        if (pass[0] !is null) passwordText.setText(pass[0]);
+        data = new GridData();
+        data.horizontalAlignment = GridData.FILL;
+        data.grabExcessHorizontalSpace = true;
+        passwordText.setLayoutData(data);
+
+        final Button[] buttons = new Button[3];
+        Listener listener = new Listener() {
+            public void handleEvent(Event event) {
+                if (buttons[0] !is null) checkValue[0] = buttons[0].getSelection() ? 1 : 0;
+                user[0] = userText.getText();
+                pass[0] = passwordText.getText();
+                result[0] = event.widget is buttons[1] ? 1 : 0;
+                shell.close();
+            }   
+        };
+        if (check !is null) {
+            buttons[0] = new Button(shell, DWT.CHECK);
+            buttons[0].setText(check);
+            buttons[0].setSelection(checkValue[0] !is 0);
+            data = new GridData ();
+            data.horizontalAlignment = GridData.BEGINNING;
+            buttons[0].setLayoutData (data);
+        }
+        Composite composite = new Composite(shell, DWT.NONE);
+        data = new GridData();
+        data.horizontalAlignment = GridData.CENTER;
+        composite.setLayoutData (data);
+        composite.setLayout(new GridLayout(2, true));
+        buttons[1] = new Button(composite, DWT.PUSH);
+        buttons[1].setText(DWT.getMessage("SWT_OK")); //$NON-NLS-1$
+        buttons[1].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        buttons[1].addListener(DWT.Selection, listener);
+        buttons[2] = new Button(composite, DWT.PUSH);
+        buttons[2].setText(DWT.getMessage("SWT_Cancel")); //$NON-NLS-1$
+        buttons[2].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        buttons[2].addListener(DWT.Selection, listener);
+
+        shell.setDefaultButton(buttons[1]);
+        shell.pack();
+        shell.open();
+        Display display = parent.getDisplay();
+        while (!shell.isDisposed()) {
+            if (!display.readAndDispatch()) display.sleep();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/PromptService2.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,649 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.PromptService2;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.internal.C;
+import dwt.internal.Compatibility;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsEmbedString;
+import dwt.internal.mozilla.nsIAuthInformation;
+import dwt.internal.mozilla.nsIChannel;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIDOMWindow;
+import dwt.internal.mozilla.nsIEmbeddingSiteWindow;
+import dwt.internal.mozilla.nsIMemory;
+import dwt.internal.mozilla.nsIPromptService;
+import dwt.internal.mozilla.nsIPromptService2;
+import dwt.internal.mozilla.nsIServiceManager;
+import dwt.internal.mozilla.nsISupports;
+import dwt.internal.mozilla.nsIURI;
+import dwt.internal.mozilla.nsIWebBrowserChrome;
+import dwt.internal.mozilla.nsIWindowWatcher;
+import dwt.widgets.MessageBox;
+import dwt.widgets.Shell;
+
+class PromptService2 {
+    XPCOMObject supports;
+    XPCOMObject promptService;
+    XPCOMObject promptService2;
+    int refCount = 0;
+
+PromptService2 () {
+    createCOMInterfaces ();
+}
+
+int AddRef () {
+    refCount++;
+    return refCount;
+}
+
+void createCOMInterfaces () {
+    /* Create each of the interfaces that this object implements */
+    supports = new XPCOMObject (new int[] {2, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+    };
+    
+    promptService = new XPCOMObject (new int[] {2, 0, 0, 3, 5, 4, 6, 10, 7, 8, 7, 7}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return Alert (args[0], args[1], args[2]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return AlertCheck (args[0], args[1], args[2], args[3], args[4]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return Confirm (args[0], args[1], args[2], args[3]);}
+        public int /*long*/ method6 (int /*long*/[] args) {return ConfirmCheck (args[0], args[1], args[2], args[3], args[4], args[5]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return ConfirmEx (args[0], args[1], args[2], (int)/*64*/args[3], args[4], args[5], args[6], args[7], args[8], args[9]);}
+        public int /*long*/ method8 (int /*long*/[] args) {return Prompt (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);}
+        public int /*long*/ method9 (int /*long*/[] args) {return PromptUsernameAndPassword (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);}
+        public int /*long*/ method10 (int /*long*/[] args) {return PromptPassword (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);}
+        public int /*long*/ method11 (int /*long*/[] args) {return Select (args[0], args[1], args[2], (int)/*64*/args[3], args[4], args[5], args[6]);}
+    };
+    
+    promptService2 = new XPCOMObject (new int[] {2, 0, 0, 3, 5, 4, 6, 10, 7, 8, 7, 7, 7, 9}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return Alert (args[0], args[1], args[2]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return AlertCheck (args[0], args[1], args[2], args[3], args[4]);}
+        public int /*long*/ method5 (int /*long*/[] args) {return Confirm (args[0], args[1], args[2], args[3]);}
+        public int /*long*/ method6 (int /*long*/[] args) {return ConfirmCheck (args[0], args[1], args[2], args[3], args[4], args[5]);}
+        public int /*long*/ method7 (int /*long*/[] args) {return ConfirmEx (args[0], args[1], args[2], (int)/*64*/args[3], args[4], args[5], args[6], args[7], args[8], args[9]);}
+        public int /*long*/ method8 (int /*long*/[] args) {return Prompt (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);}
+        public int /*long*/ method9 (int /*long*/[] args) {return PromptUsernameAndPassword (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);}
+        public int /*long*/ method10 (int /*long*/[] args) {return PromptPassword (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);}
+        public int /*long*/ method11 (int /*long*/[] args) {return Select (args[0], args[1], args[2], (int)/*64*/args[3], args[4], args[5], args[6]);}
+        public int /*long*/ method12 (int /*long*/[] args) {return PromptAuth (args[0], args[1], (int)/*64*/args[2], args[3], args[4], args[5], args[6]);}
+        public int /*long*/ method13 (int /*long*/[] args) {return AsyncPromptAuth (args[0], args[1], args[2], args[3], (int)/*64*/args[4], args[5], args[6], args[7], args[8]);}
+    };
+}
+
+void disposeCOMInterfaces () {
+    if (supports !is null) {
+        supports.dispose ();
+        supports = null;
+    }   
+    if (promptService !is null) {
+        promptService.dispose ();
+        promptService = null;   
+    }
+    if (promptService2 !is null) {
+        promptService2.dispose ();
+        promptService2 = null;  
+    }
+}
+
+int /*long*/ getAddress () {
+    return promptService2.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+    if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+    nsID guid = new nsID ();
+    XPCOM.memmove (guid, riid, nsID.sizeof);
+    
+    if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIPromptService.NS_IPROMPTSERVICE_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {promptService.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIPromptService2.NS_IPROMPTSERVICE2_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {promptService2.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+
+    XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+            
+int Release () {
+    refCount--;
+    if (refCount is 0) disposeCOMInterfaces ();
+    return refCount;
+}
+
+Browser getBrowser (int /*long*/ aDOMWindow) {
+    if (aDOMWindow is 0) return null;
+
+    int /*long*/[] result = new int /*long*/[1];
+    int rc = XPCOM.NS_GetServiceManager (result);
+    if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+    if (result[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);
+    
+    nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+    result[0] = 0;
+    byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_WINDOWWATCHER_CONTRACTID, true);
+    rc = serviceManager.GetServiceByContractID (aContractID, nsIWindowWatcher.NS_IWINDOWWATCHER_IID, result);
+    if (rc !is XPCOM.NS_OK) Mozilla.error(rc);
+    if (result[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);       
+    serviceManager.Release ();
+    
+    nsIWindowWatcher windowWatcher = new nsIWindowWatcher (result[0]);
+    result[0] = 0;
+    /* the chrome will only be answered for the top-level nsIDOMWindow */
+    nsIDOMWindow window = new nsIDOMWindow (aDOMWindow);
+    rc = window.GetTop (result);
+    if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+    if (result[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);
+    aDOMWindow = result[0];
+    result[0] = 0;
+    rc = windowWatcher.GetChromeForWindow (aDOMWindow, result);
+    if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+    if (result[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);       
+    windowWatcher.Release ();   
+    
+    nsIWebBrowserChrome webBrowserChrome = new nsIWebBrowserChrome (result[0]);
+    result[0] = 0;
+    rc = webBrowserChrome.QueryInterface (nsIEmbeddingSiteWindow.NS_IEMBEDDINGSITEWINDOW_IID, result);
+    if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+    if (result[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);       
+    webBrowserChrome.Release ();
+    
+    nsIEmbeddingSiteWindow embeddingSiteWindow = new nsIEmbeddingSiteWindow (result[0]);
+    result[0] = 0;
+    rc = embeddingSiteWindow.GetSiteWindow (result);
+    if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+    if (result[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);       
+    embeddingSiteWindow.Release ();
+    
+    return Mozilla.findBrowser (result[0]); 
+}
+
+String getLabel (int buttonFlag, int index, int /*long*/ buttonTitle) {
+    String label = null;
+    int flag = (buttonFlag & (0xff * index)) / index;
+    switch (flag) {
+        case nsIPromptService.BUTTON_TITLE_CANCEL : label = DWT.getMessage ("SWT_Cancel"); break; //$NON-NLS-1$
+        case nsIPromptService.BUTTON_TITLE_NO : label = DWT.getMessage ("SWT_No"); break; //$NON-NLS-1$
+        case nsIPromptService.BUTTON_TITLE_OK : label = DWT.getMessage ("SWT_OK"); break; //$NON-NLS-1$
+        case nsIPromptService.BUTTON_TITLE_SAVE : label = DWT.getMessage ("SWT_Save"); break; //$NON-NLS-1$
+        case nsIPromptService.BUTTON_TITLE_YES : label = DWT.getMessage ("SWT_Yes"); break; //$NON-NLS-1$
+        case nsIPromptService.BUTTON_TITLE_IS_STRING : {
+            int length = XPCOM.strlen_PRUnichar (buttonTitle);
+            char[] dest = new char[length];
+            XPCOM.memmove (dest, buttonTitle, length * 2);
+            label = new String (dest);
+        }
+    }
+    return label;
+}
+
+/* nsIPromptService */
+
+int Alert (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText) {
+    Browser browser = getBrowser (aParent);
+    
+    int length = XPCOM.strlen_PRUnichar (aDialogTitle);
+    char[] dest = new char[length];
+    XPCOM.memmove (dest, aDialogTitle, length * 2);
+    String titleLabel = new String (dest);
+
+    length = XPCOM.strlen_PRUnichar (aText);
+    dest = new char[length];
+    XPCOM.memmove (dest, aText, length * 2);
+    String textLabel = new String (dest);
+
+    Shell shell = browser is null ? new Shell () : browser.getShell (); 
+    MessageBox messageBox = new MessageBox (shell, DWT.OK | DWT.ICON_WARNING);
+    messageBox.setText (titleLabel);
+    messageBox.setMessage (textLabel);
+    messageBox.open ();
+    return XPCOM.NS_OK;
+}
+
+int AlertCheck (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int /*long*/ aCheckMsg, int /*long*/ aCheckState) {
+    Browser browser = getBrowser (aParent);
+    
+    int length = XPCOM.strlen_PRUnichar (aDialogTitle);
+    char[] dest = new char[length];
+    XPCOM.memmove (dest, aDialogTitle, length * 2);
+    String titleLabel = new String (dest);
+
+    length = XPCOM.strlen_PRUnichar (aText);
+    dest = new char[length];
+    XPCOM.memmove (dest, aText, length * 2);
+    String textLabel = new String (dest);
+
+    length = XPCOM.strlen_PRUnichar (aCheckMsg);
+    dest = new char[length];
+    XPCOM.memmove (dest, aCheckMsg, length * 2);
+    String checkLabel = new String (dest);
+
+    Shell shell = browser is null ? new Shell () : browser.getShell ();
+    PromptDialog dialog = new PromptDialog (shell);
+    int[] check = new int[1];
+    if (aCheckState !is 0) XPCOM.memmove (check, aCheckState, 4); /* PRBool */
+    dialog.alertCheck (titleLabel, textLabel, checkLabel, check);
+    if (aCheckState !is 0) XPCOM.memmove (aCheckState, check, 4); /* PRBool */
+    return XPCOM.NS_OK;
+}
+
+int AsyncPromptAuth(int /*long*/ aParent, int /*long*/ aChannel, int /*long*/ aCallback, int /*long*/ aContext, int level, int /*long*/ authInfo, int /*long*/ checkboxLabel, int /*long*/ checkValue, int /*long*/ _retval) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int Confirm (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int /*long*/ _retval) {
+    Browser browser = getBrowser (aParent);
+    
+    int length = XPCOM.strlen_PRUnichar (aDialogTitle);
+    char[] dest = new char[length];
+    XPCOM.memmove (dest, aDialogTitle, length * 2);
+    String titleLabel = new String (dest);
+
+    length = XPCOM.strlen_PRUnichar (aText);
+    dest = new char[length];
+    XPCOM.memmove (dest, aText, length * 2);
+    String textLabel = new String (dest);
+
+    Shell shell = browser is null ? new Shell () : browser.getShell ();
+    MessageBox messageBox = new MessageBox (shell, DWT.OK | DWT.CANCEL | DWT.ICON_QUESTION);
+    messageBox.setText (titleLabel);
+    messageBox.setMessage (textLabel);
+    int id = messageBox.open ();
+    int[] result = {id is DWT.OK ? 1 : 0};
+    XPCOM.memmove (_retval, result, 4);
+    return XPCOM.NS_OK;
+}
+
+int ConfirmCheck (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int /*long*/ aCheckMsg, int /*long*/ aCheckState, int /*long*/ _retval) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int ConfirmEx (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int aButtonFlags, int /*long*/ aButton0Title, int /*long*/ aButton1Title, int /*long*/ aButton2Title, int /*long*/ aCheckMsg, int /*long*/ aCheckState, int /*long*/ _retval) {
+    Browser browser = getBrowser (aParent);
+    
+    int length = XPCOM.strlen_PRUnichar (aDialogTitle);
+    char[] dest = new char[length];
+    XPCOM.memmove (dest, aDialogTitle, length * 2);
+    String titleLabel = new String (dest);
+
+    length = XPCOM.strlen_PRUnichar (aText);
+    dest = new char[length];
+    XPCOM.memmove (dest, aText, length * 2);
+    String textLabel = new String (dest);
+    
+    String checkLabel = null;
+    if (aCheckMsg !is 0) {
+        length = XPCOM.strlen_PRUnichar (aCheckMsg);
+        dest = new char[length];
+        XPCOM.memmove (dest, aCheckMsg, length * 2);
+        checkLabel = new String (dest);
+    }
+    
+    String button0Label = getLabel (aButtonFlags, nsIPromptService.BUTTON_POS_0, aButton0Title);
+    String button1Label = getLabel (aButtonFlags, nsIPromptService.BUTTON_POS_1, aButton1Title);
+    String button2Label = getLabel (aButtonFlags, nsIPromptService.BUTTON_POS_2, aButton2Title);
+    
+    int defaultIndex = 0;
+    if ((aButtonFlags & nsIPromptService.BUTTON_POS_1_DEFAULT) !is 0) {
+        defaultIndex = 1;
+    } else if ((aButtonFlags & nsIPromptService.BUTTON_POS_2_DEFAULT) !is 0) {
+        defaultIndex = 2;
+    }
+    
+    Shell shell = browser is null ? new Shell () : browser.getShell ();
+    PromptDialog dialog = new PromptDialog (shell);
+    int[] check = new int[1], result = new int[1];
+    if (aCheckState !is 0) XPCOM.memmove (check, aCheckState, 4);
+    dialog.confirmEx (titleLabel, textLabel, checkLabel, button0Label, button1Label, button2Label, defaultIndex, check, result);
+    if (aCheckState !is 0) XPCOM.memmove (aCheckState, check, 4);
+    XPCOM.memmove (_retval, result, 4);
+    return XPCOM.NS_OK;
+}
+
+int Prompt (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int /*long*/ aValue, int /*long*/ aCheckMsg, int /*long*/ aCheckState, int /*long*/ _retval) {
+    Browser browser = getBrowser (aParent);
+    String titleLabel = null, textLabel, checkLabel = null;
+    String[] valueLabel = new String[1];
+    char[] dest;
+    int length;
+    if (aDialogTitle !is 0) {
+        length = XPCOM.strlen_PRUnichar (aDialogTitle);
+        dest = new char[length];
+        XPCOM.memmove (dest, aDialogTitle, length * 2);
+        titleLabel = new String (dest);
+    }
+    
+    length = XPCOM.strlen_PRUnichar (aText);
+    dest = new char[length];
+    XPCOM.memmove (dest, aText, length * 2);
+    textLabel = new String (dest);
+    
+    int /*long*/[] valueAddr = new int /*long*/[1];
+    XPCOM.memmove (valueAddr, aValue, C.PTR_SIZEOF);
+    if (valueAddr[0] !is 0) {
+        length = XPCOM.strlen_PRUnichar (valueAddr[0]);
+        dest = new char[length];
+        XPCOM.memmove (dest, valueAddr[0], length * 2);
+        valueLabel[0] = new String (dest);      
+    }
+    
+    if (aCheckMsg !is 0) {
+        length = XPCOM.strlen_PRUnichar (aCheckMsg);
+        if (length > 0) {
+            dest = new char[length];
+            XPCOM.memmove (dest, aCheckMsg, length * 2);
+            checkLabel = new String (dest);
+        }
+    }
+
+    Shell shell = browser is null ? new Shell () : browser.getShell ();
+    PromptDialog dialog = new PromptDialog (shell);
+    int[] check = new int[1], result = new int[1];
+    if (aCheckState !is 0) XPCOM.memmove (check, aCheckState, 4);
+    dialog.prompt (titleLabel, textLabel, checkLabel, valueLabel, check, result);
+
+    XPCOM.memmove (_retval, result, 4);
+    if (result[0] is 1) {
+        /* 
+        * User selected OK. User name and password are returned as PRUnichar values. Any default
+        * value that we override must be freed using the nsIMemory service.
+        */
+        int cnt, size;
+        int /*long*/ ptr;
+        char[] buffer;
+        int /*long*/[] result2 = new int /*long*/[1];
+        if (valueLabel[0] !is null) {
+            cnt = valueLabel[0].length ();
+            buffer = new char[cnt + 1];
+            valueLabel[0].getChars (0, cnt, buffer, 0);
+            size = buffer.length * 2;
+            ptr = C.malloc (size);
+            XPCOM.memmove (ptr, buffer, size);
+            XPCOM.memmove (aValue, new int /*long*/[] {ptr}, C.PTR_SIZEOF);
+
+            if (valueAddr[0] !is 0) {
+                int rc = XPCOM.NS_GetServiceManager (result2);
+                if (rc !is XPCOM.NS_OK) DWT.error (rc);
+                if (result2[0] is 0) DWT.error (XPCOM.NS_NOINTERFACE);
+            
+                nsIServiceManager serviceManager = new nsIServiceManager (result2[0]);
+                result2[0] = 0;
+                byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_MEMORY_CONTRACTID, true);
+                rc = serviceManager.GetServiceByContractID (aContractID, nsIMemory.NS_IMEMORY_IID, result2);
+                if (rc !is XPCOM.NS_OK) DWT.error (rc);
+                if (result2[0] is 0) DWT.error (XPCOM.NS_NOINTERFACE);      
+                serviceManager.Release ();
+                
+                nsIMemory memory = new nsIMemory (result2[0]);
+                result2[0] = 0;
+                memory.Free (valueAddr[0]);
+                memory.Release ();
+            }
+        }
+    }
+    if (aCheckState !is 0) XPCOM.memmove (aCheckState, check, 4);
+    return XPCOM.NS_OK;
+}
+
+int PromptAuth(int /*long*/ aParent, int /*long*/ aChannel, int level, int /*long*/ authInfo, int /*long*/ checkboxLabel, int /*long*/ checkboxValue, int /*long*/ _retval) {
+    Browser browser = getBrowser (aParent);
+    String checkLabel = null;
+    int[] checkValue = new int[1];
+    String[] userLabel = new String[1], passLabel = new String[1];
+
+    String title = DWT.getMessage ("SWT_Authentication_Required"); //$NON-NLS-1$
+
+    if (checkboxLabel !is 0 && checkboxValue !is 0) {
+        int length = XPCOM.strlen_PRUnichar (checkboxLabel);
+        char[] dest = new char[length];
+        XPCOM.memmove (dest, checkboxLabel, length * 2);
+        checkLabel = new String (dest);
+        XPCOM.memmove (checkValue, checkboxValue, 4); /* PRBool */
+    }
+
+    /* get initial username and password values */
+
+    nsIAuthInformation auth = new nsIAuthInformation (authInfo);
+
+    int /*long*/ ptr = XPCOM.nsEmbedString_new ();
+    int rc = auth.GetUsername (ptr);
+    if (rc !is XPCOM.NS_OK) DWT.error (rc);
+    int length = XPCOM.nsEmbedString_Length (ptr);
+    int /*long*/ buffer = XPCOM.nsEmbedString_get (ptr);
+    char[] chars = new char[length];
+    XPCOM.memmove (chars, buffer, length * 2);
+    userLabel[0] = new String (chars);
+    XPCOM.nsEmbedString_delete (ptr);
+
+    ptr = XPCOM.nsEmbedString_new ();
+    rc = auth.GetPassword (ptr);
+    if (rc !is XPCOM.NS_OK) DWT.error (rc);
+    length = XPCOM.nsEmbedString_Length (ptr);
+    buffer = XPCOM.nsEmbedString_get (ptr);
+    chars = new char[length];
+    XPCOM.memmove (chars, buffer, length * 2);
+    passLabel[0] = new String (chars);
+    XPCOM.nsEmbedString_delete (ptr);
+
+    /* compute the message text */
+
+    ptr = XPCOM.nsEmbedString_new ();
+    rc = auth.GetRealm (ptr);
+    if (rc !is XPCOM.NS_OK) DWT.error (rc);
+    length = XPCOM.nsEmbedString_Length (ptr);
+    buffer = XPCOM.nsEmbedString_get (ptr);
+    chars = new char[length];
+    XPCOM.memmove (chars, buffer, length * 2);
+    String realm = new String (chars);
+    XPCOM.nsEmbedString_delete (ptr);
+
+    nsIChannel channel = new nsIChannel (aChannel);
+    int /*long*/[] uri = new int /*long*/[1];
+    rc = channel.GetURI (uri);
+    if (rc !is XPCOM.NS_OK) DWT.error (rc);
+    if (uri[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);
+
+    nsIURI nsURI = new nsIURI (uri[0]);
+    int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
+    rc = nsURI.GetHost (aSpec);
+    if (rc !is XPCOM.NS_OK) DWT.error (rc);
+    length = XPCOM.nsEmbedCString_Length (aSpec);
+    buffer = XPCOM.nsEmbedCString_get (aSpec);
+    byte[] bytes = new byte[length];
+    XPCOM.memmove (bytes, buffer, length);
+    XPCOM.nsEmbedCString_delete (aSpec);
+    String host = new String (bytes);
+    nsURI.Release ();
+
+    String message;
+    if (realm.length () > 0 && host.length () > 0) {
+        message = Compatibility.getMessage ("SWT_Enter_Username_and_Password", new String[] {realm, host}); //$NON-NLS-1$
+    } else {
+        message = ""; //$NON-NLS-1$
+    }
+
+    /* open the prompter */
+    Shell shell = browser is null ? new Shell () : browser.getShell ();
+    PromptDialog dialog = new PromptDialog (shell);
+    int[] result = new int[1];
+    dialog.promptUsernameAndPassword (title, message, checkLabel, userLabel, passLabel, checkValue, result);
+
+    XPCOM.memmove (_retval, result, 4); /* PRBool */
+    if (result[0] is 1) {   /* User selected OK */
+        nsEmbedString string = new nsEmbedString (userLabel[0]);
+        rc = auth.SetUsername(string.getAddress ());
+        if (rc !is XPCOM.NS_OK) DWT.error (rc);
+        string.dispose ();
+        
+        string = new nsEmbedString (passLabel[0]);
+        rc = auth.SetPassword(string.getAddress ());
+        if (rc !is XPCOM.NS_OK) DWT.error (rc);
+        string.dispose ();
+    }
+
+    if (checkboxValue !is 0) XPCOM.memmove (checkboxValue, checkValue, 4); /* PRBool */
+    return XPCOM.NS_OK;
+}
+
+int PromptUsernameAndPassword (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int /*long*/ aUsername, int /*long*/ aPassword, int /*long*/ aCheckMsg, int /*long*/ aCheckState, int /*long*/ _retval) {
+    Browser browser = getBrowser (aParent);
+    String titleLabel, textLabel, checkLabel = null;
+    String[] userLabel = new String[1], passLabel = new String[1];
+    char[] dest;
+    int length;
+    if (aDialogTitle !is 0) {
+        length = XPCOM.strlen_PRUnichar (aDialogTitle);
+        dest = new char[length];
+        XPCOM.memmove (dest, aDialogTitle, length * 2);
+        titleLabel = new String (dest);
+    } else {
+        titleLabel = DWT.getMessage ("SWT_Authentication_Required");    //$NON-NLS-1$
+    }
+    
+    length = XPCOM.strlen_PRUnichar (aText);
+    dest = new char[length];
+    XPCOM.memmove (dest, aText, length * 2);
+    textLabel = new String (dest);
+    
+    int /*long*/[] userAddr = new int /*long*/[1];
+    XPCOM.memmove (userAddr, aUsername, C.PTR_SIZEOF);
+    if (userAddr[0] !is 0) {
+        length = XPCOM.strlen_PRUnichar (userAddr[0]);
+        dest = new char[length];
+        XPCOM.memmove (dest, userAddr[0], length * 2);
+        userLabel[0] = new String (dest);       
+    }
+    
+    int /*long*/[] passAddr = new int /*long*/[1];
+    XPCOM.memmove (passAddr, aPassword, C.PTR_SIZEOF);
+    if (passAddr[0] !is 0) {
+        length = XPCOM.strlen_PRUnichar (passAddr[0]);
+        dest = new char[length];
+        XPCOM.memmove (dest, passAddr[0], length * 2);
+        passLabel[0] = new String (dest);       
+    }
+    
+    if (aCheckMsg !is 0) {
+        length = XPCOM.strlen_PRUnichar (aCheckMsg);
+        if (length > 0) {
+            dest = new char[length];
+            XPCOM.memmove (dest, aCheckMsg, length * 2);
+            checkLabel = new String (dest);
+        }
+    }
+
+    Shell shell = browser is null ? new Shell () : browser.getShell ();
+    PromptDialog dialog = new PromptDialog (shell);
+    int[] check = new int[1], result = new int[1];
+    if (aCheckState !is 0) XPCOM.memmove (check, aCheckState, 4);   /* PRBool */
+    dialog.promptUsernameAndPassword (titleLabel, textLabel, checkLabel, userLabel, passLabel, check, result);
+
+    XPCOM.memmove (_retval, result, 4); /* PRBool */
+    if (result[0] is 1) {
+        /* 
+        * User selected OK. User name and password are returned as PRUnichar values. Any default
+        * value that we override must be freed using the nsIMemory service.
+        */
+        int cnt, size;
+        int /*long*/ ptr;
+        char[] buffer;
+        int /*long*/[] result2 = new int /*long*/[1];
+        if (userLabel[0] !is null) {
+            cnt = userLabel[0].length ();
+            buffer = new char[cnt + 1];
+            userLabel[0].getChars (0, cnt, buffer, 0);
+            size = buffer.length * 2;
+            ptr = C.malloc (size);
+            XPCOM.memmove (ptr, buffer, size);
+            XPCOM.memmove (aUsername, new int /*long*/[] {ptr}, C.PTR_SIZEOF);
+
+            if (userAddr[0] !is 0) {
+                int rc = XPCOM.NS_GetServiceManager (result2);
+                if (rc !is XPCOM.NS_OK) DWT.error (rc);
+                if (result2[0] is 0) DWT.error (XPCOM.NS_NOINTERFACE);
+            
+                nsIServiceManager serviceManager = new nsIServiceManager (result2[0]);
+                result2[0] = 0;
+                byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_MEMORY_CONTRACTID, true);
+                rc = serviceManager.GetServiceByContractID (aContractID, nsIMemory.NS_IMEMORY_IID, result2);
+                if (rc !is XPCOM.NS_OK) DWT.error (rc);
+                if (result[0] is 0) DWT.error (XPCOM.NS_NOINTERFACE);       
+                serviceManager.Release ();
+                
+                nsIMemory memory = new nsIMemory (result2[0]);
+                result2[0] = 0;
+                memory.Free (userAddr[0]);
+                memory.Release ();
+            }
+        }
+        if (passLabel[0] !is null) {
+            cnt = passLabel[0].length ();
+            buffer = new char[cnt + 1];
+            passLabel[0].getChars (0, cnt, buffer, 0);
+            size = buffer.length * 2;
+            ptr = C.malloc (size);
+            XPCOM.memmove (ptr, buffer, size);
+            XPCOM.memmove (aPassword, new int /*long*/[] {ptr}, C.PTR_SIZEOF);
+            
+            if (passAddr[0] !is 0) {
+                int rc = XPCOM.NS_GetServiceManager (result2);
+                if (rc !is XPCOM.NS_OK) DWT.error (rc);
+                if (result2[0] is 0) DWT.error (XPCOM.NS_NOINTERFACE);
+
+                nsIServiceManager serviceManager = new nsIServiceManager (result2[0]);
+                result2[0] = 0;
+                byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_MEMORY_CONTRACTID, true);
+                rc = serviceManager.GetServiceByContractID (aContractID, nsIMemory.NS_IMEMORY_IID, result2);
+                if (rc !is XPCOM.NS_OK) DWT.error (rc);
+                if (result2[0] is 0) DWT.error (XPCOM.NS_NOINTERFACE);      
+                serviceManager.Release ();
+
+                nsIMemory memory = new nsIMemory (result2[0]);
+                result2[0] = 0;
+                memory.Free (passAddr[0]);
+                memory.Release ();
+            }
+        }
+    }
+    if (aCheckState !is 0) XPCOM.memmove (aCheckState, check, 4); /* PRBool */
+    return XPCOM.NS_OK;
+}
+
+int PromptPassword (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int /*long*/ aPassword, int /*long*/ aCheckMsg, int /*long*/ aCheckState, int /*long*/ _retval) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int Select (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int aCount, int /*long*/ aSelectList, int /*long*/ aOutSelection, int /*long*/ _retval) {
+    return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/PromptService2Factory.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.PromptService2Factory;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIFactory;
+import dwt.internal.mozilla.nsISupports;
+
+class PromptService2Factory {
+    XPCOMObject supports;
+    XPCOMObject factory;
+    int refCount = 0;
+
+PromptService2Factory () {
+    createCOMInterfaces ();
+}
+
+int AddRef () {
+    refCount++;
+    return refCount;
+}
+
+void createCOMInterfaces () {
+    /* Create each of the interfaces that this object implements */
+    supports = new XPCOMObject (new int[] {2, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+    };
+    
+    factory = new XPCOMObject (new int[] {2, 0, 0, 3, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return CreateInstance (args[0], args[1], args[2]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return LockFactory ((int)/*64*/args[0]);}
+    };
+}
+
+void disposeCOMInterfaces () {
+    if (supports !is null) {
+        supports.dispose ();
+        supports = null;
+    }   
+    if (factory !is null) {
+        factory.dispose ();
+        factory = null; 
+    }
+}
+
+int /*long*/ getAddress () {
+    return factory.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+    if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+    nsID guid = new nsID ();
+    XPCOM.memmove (guid, riid, nsID.sizeof);
+    
+    if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIFactory.NS_IFACTORY_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {factory.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    
+    XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+            
+int Release () {
+    refCount--;
+    if (refCount is 0) disposeCOMInterfaces ();
+    return refCount;
+}
+    
+/* nsIFactory */
+
+int CreateInstance (int /*long*/ aOuter, int /*long*/ iid, int /*long*/ result) {
+    PromptService2 promptService = new PromptService2 ();
+    promptService.AddRef ();
+    XPCOM.memmove (result, new int /*long*/[] {promptService.getAddress ()}, C.PTR_SIZEOF);
+    return XPCOM.NS_OK;
+}
+
+int LockFactory (int lock) {
+    return XPCOM.NS_OK;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/SimpleEnumerator.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.SimpleEnumerator;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsISimpleEnumerator;
+import dwt.internal.mozilla.nsISupports;
+
+class SimpleEnumerator {
+    XPCOMObject supports;
+    XPCOMObject simpleEnumerator;
+    int refCount = 0;
+    nsISupports[] values;
+    int index = 0;
+
+SimpleEnumerator (nsISupports[] values) {
+    this.values = values;
+    for (int i = 0; i < values.length; i++) {
+        values[i].AddRef ();
+    }
+    createCOMInterfaces ();
+}
+
+int AddRef () {
+    refCount++;
+    return refCount;
+}
+
+void createCOMInterfaces () {
+    /* Create each of the interfaces that this object implements */
+    supports = new XPCOMObject (new int[] {2, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+    };
+
+    simpleEnumerator = new XPCOMObject (new int[] {2, 0, 0, 1, 1}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return HasMoreElements (args[0]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return GetNext (args[0]);}
+    };
+}
+
+void disposeCOMInterfaces () {
+    if (supports !is null) {
+        supports.dispose ();
+        supports = null;
+    }   
+    if (simpleEnumerator !is null) {
+        simpleEnumerator.dispose ();
+        simpleEnumerator = null;    
+    }
+    if (values !is null) {
+        for (int i = 0; i < values.length; i++) {
+            values[i].Release ();
+        }
+        values = null;
+    }
+}
+
+int /*long*/ getAddress () {
+    return simpleEnumerator.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+    if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+    nsID guid = new nsID ();
+    XPCOM.memmove (guid, riid, nsID.sizeof);
+
+    if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsISimpleEnumerator.NS_ISIMPLEENUMERATOR_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {simpleEnumerator.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+
+    XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+    refCount--;
+    if (refCount is 0) disposeCOMInterfaces ();
+    return refCount;
+}
+
+int HasMoreElements (int /*long*/ _retval) {
+    bool more = values !is null && index < values.length;
+    XPCOM.memmove (_retval, new int[] {more ? 1 : 0}, 4); /*PRBool */
+    return XPCOM.NS_OK;
+}   
+    
+int GetNext (int /*long*/ _retval) {
+    if (values is null || index is values.length) return XPCOM.NS_ERROR_UNEXPECTED;
+    nsISupports value = values[index++];
+    value.AddRef ();
+    XPCOM.memmove (_retval, new int /*long*/[] {value.getAddress ()}, C.PTR_SIZEOF);
+    return XPCOM.NS_OK;
+}       
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/StatusTextEvent.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.StatusTextEvent;
+
+import dwt.dwthelper.utils;
+
+import dwt.events.TypedEvent;
+import dwt.widgets.Widget;
+
+/**
+ * A <code>StatusTextEvent</code> is sent by a {@link Browser} to
+ * {@link StatusTextListener}'s when the status text is changed.
+ * The status text is typically displayed in the status bar of
+ * a browser application.
+ * 
+ * @since 3.0
+ */
+public class StatusTextEvent extends TypedEvent {
+    /** status text */
+    public String text;
+    
+    static final long serialVersionUID = 3258407348371600439L;
+
+StatusTextEvent(Widget w) {
+    super(w);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public String toString() {
+    String string = super.toString ();
+    return string.substring (0, string.length() - 1) // remove trailing '}'
+        + " text=" + text
+        + "}";
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/StatusTextListener.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.StatusTextListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * a {@link StatusTextEvent} notification when the status text for
+ * a {@link Browser} is changed.
+ * 
+ * @see Browser#addStatusTextListener(StatusTextListener)
+ * @see Browser#removeStatusTextListener(StatusTextListener)
+ * 
+ * @since 3.0
+ */
+public interface StatusTextListener extends DWTEventListener {
+
+/**
+ * This method is called when the status text is changed. The
+ * status text is typically displayed in the status bar of a browser 
+ * application. 
+ * <p>
+ *
+ * <p>The following fields in the <code>StatusTextEvent</code> apply:
+ * <ul>
+ * <li>(in) text the modified status text
+ * <li>(in) widget the <code>Browser</code> whose status text is changed
+ * </ul>
+ * 
+ * @param event the <code>StatusTextEvent</code> that contains the updated
+ * status description of a <code>Browser</code>
+ * 
+ * @since 3.0
+ */
+public void changed(StatusTextEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/TitleEvent.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.TitleEvent;
+
+import dwt.dwthelper.utils;
+
+import dwt.events.TypedEvent;
+import dwt.widgets.Widget;
+
+/**
+ * A <code>TitleEvent</code> is sent by a {@link Browser} to
+ * {@link TitleListener}'s when the title of the current document
+ * is available or when it is modified.
+ * 
+ * @since 3.0
+ */
+public class TitleEvent extends TypedEvent {
+    /** the title of the current document */
+    public String title;
+    
+    static final long serialVersionUID = 4121132532906340919L;
+
+TitleEvent(Widget w) {
+    super(w);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public String toString() {
+    String string = super.toString ();
+    return string.substring (0, string.length() - 1) // remove trailing '}'
+        + " title=" + title
+        + "}";
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/TitleListener.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.TitleListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * a {@link TitleEvent} notification when the title of the document
+ * displayed in a {@link Browser} is known or has been changed.
+ * 
+ * @see Browser#addTitleListener(TitleListener)
+ * @see Browser#removeTitleListener(TitleListener)
+ * 
+ * @since 3.0
+ */
+public interface TitleListener extends DWTEventListener {
+
+/**
+ * This method is called when the title of the current document
+ * is available or has changed.
+ * <p>
+ *
+ * <p>The following fields in the <code>TitleEvent</code> apply:
+ * <ul>
+ * <li>(in) title the title of the current document
+ * <li>(in) widget the <code>Browser</code> whose current document's
+ * title is known or modified
+ * </ul>
+ * 
+ * @param event the <code>TitleEvent</code> that contains the title
+ * of the document currently displayed in a <code>Browser</code>
+ * 
+ * @since 3.0
+ */
+public void changed(TitleEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/VisibilityWindowAdapter.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.VisibilityWindowAdapter;
+
+import dwt.dwthelper.utils;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the {@link VisibilityWindowListener} interface.
+ * <p>
+ * Classes that wish to deal with {@link WindowEvent}'s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ * 
+ * @since 3.0
+ */
+public abstract class VisibilityWindowAdapter implements VisibilityWindowListener {
+
+public void hide(WindowEvent event) {
+}
+ 
+public void show(WindowEvent event) {
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/VisibilityWindowListener.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.VisibilityWindowListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/** 
+ * This listener interface may be implemented in order to receive
+ * a {@link WindowEvent} notification when a window hosting a
+ * {@link Browser} needs to be displayed or hidden.
+ * 
+ * @see Browser#addVisibilityWindowListener(VisibilityWindowListener)
+ * @see Browser#removeVisibilityWindowListener(VisibilityWindowListener)
+ * @see OpenWindowListener
+ * @see CloseWindowListener
+ * 
+ * @since 3.0
+ */
+public interface VisibilityWindowListener extends DWTEventListener {
+    
+/**
+ * This method is called when the window hosting a <code>Browser</code> 
+ * is requested to be hidden. Application would typically hide the
+ * {@link dwt.widgets.Shell} that hosts the <code>Browser</code>.
+ * <p>
+ *
+ * <p>The following fields in the <code>WindowEvent</code> apply:
+ * <ul>
+ * <li>(in) widget the <code>Browser</code> that needs to be hidden
+ * </ul>
+ *
+ * @param event the <code>WindowEvent</code> that specifies the
+ * <code>Browser</code> that needs to be hidden
+ * 
+ * @see dwt.widgets.Shell#setVisible(bool)
+ * 
+ * @since 3.0
+ */ 
+public void hide(WindowEvent event);
+
+/**
+ * This method is called when the window hosting a <code>Browser</code>
+ * is requested to be displayed. Application would typically set the 
+ * location and the size of the {@link dwt.widgets.Shell} 
+ * that hosts the <code>Browser</code>, if a particular location and size
+ * are specified. The application would then open that <code>Shell</code>.
+ * <p>
+ *
+ * <p>The following fields in the <code>WindowEvent</code> apply:
+ * <ul>
+ * <li>(in) widget the <code>Browser</code> to display
+ * <li>(in) location the requested location for the <code>Shell</code> 
+ * hosting the browser. It is <code>null</code> if no location is set. 
+ * <li>(in) size the requested size for the <code>Browser</code>.
+ * The client area of the <code>Shell</code> hosting the
+ * <code>Browser</code> should be large enough to accommodate that size.
+ * It is <code>null</code> if no size is set.
+ * <li>(in) addressBar <code>true</code> if the <code>Shell</code> 
+ * hosting the <code>Browser</code> should display an address bar or
+ * <code>false</code> otherwise
+ * <li>(in) menuBar <code>true</code> if the <code>Shell</code> 
+ * hosting the <code>Browser</code> should display a menu bar or
+ * <code>false</code> otherwise
+ * <li>(in) statusBar <code>true</code> if the <code>Shell</code> 
+ * hosting the <code>Browser</code> should display a status bar or
+ * <code>false</code> otherwise
+ * <li>(in) toolBar <code>true</code> if the <code>Shell</code> 
+ * hosting the <code>Browser</code> should display a tool bar or
+ * <code>false</code> otherwise
+ * </ul>
+ *
+ * @param event the <code>WindowEvent</code> that specifies the
+ * <code>Browser</code> that needs to be displayed
+ * 
+ * @see dwt.widgets.Control#setLocation(dwt.graphics.Point)
+ * @see dwt.widgets.Control#setSize(dwt.graphics.Point)
+ * @see dwt.widgets.Shell#open()
+ * 
+ * @since 3.0
+ */ 
+public void show(WindowEvent event);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/WebBrowser.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,403 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.browser.WebBrowser;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.widgets.Composite;
+
+abstract class WebBrowser {
+    Browser browser;
+    CloseWindowListener[] closeWindowListeners = new CloseWindowListener[0];
+    LocationListener[] locationListeners = new LocationListener[0];
+    OpenWindowListener[] openWindowListeners = new OpenWindowListener[0];
+    ProgressListener[] progressListeners = new ProgressListener[0];
+    StatusTextListener[] statusTextListeners = new StatusTextListener[0];
+    TitleListener[] titleListeners = new TitleListener[0];
+    VisibilityWindowListener[] visibilityWindowListeners = new VisibilityWindowListener[0];
+
+    static Runnable MozillaClearSessions;
+    static Runnable NativeClearSessions;
+
+    /* Key Mappings */
+    static final int [][] KeyTable = {
+        /* Keyboard and Mouse Masks */
+        {18,    DWT.ALT},
+        {16,    DWT.SHIFT},
+        {17,    DWT.CONTROL},
+        {224,   DWT.COMMAND},
+
+        /* Literal Keys */
+        {65,    'a'},
+        {66,    'b'},
+        {67,    'c'},
+        {68,    'd'},
+        {69,    'e'},
+        {70,    'f'},
+        {71,    'g'},
+        {72,    'h'},
+        {73,    'i'},
+        {74,    'j'},
+        {75,    'k'},
+        {76,    'l'},
+        {77,    'm'},
+        {78,    'n'},
+        {79,    'o'},
+        {80,    'p'},
+        {81,    'q'},
+        {82,    'r'},
+        {83,    's'},
+        {84,    't'},
+        {85,    'u'},
+        {86,    'v'},
+        {87,    'w'},
+        {88,    'x'},
+        {89,    'y'},
+        {90,    'z'},
+        {48,    '0'},
+        {49,    '1'},
+        {50,    '2'},
+        {51,    '3'},
+        {52,    '4'},
+        {53,    '5'},
+        {54,    '6'},
+        {55,    '7'},
+        {56,    '8'},
+        {57,    '9'},
+        {32,    ' '},
+        {59,    ';'},
+        {61,    '='},
+        {188,   ','},
+        {190,   '.'},
+        {191,   '/'},
+        {219,   '['},
+        {221,   ']'},
+        {222,   '\''},
+        {192,   '`'},
+        {220,   '\\'},
+        {108,   '|'},
+
+        /* Non-Numeric Keypad Keys */
+        {37,    DWT.ARROW_LEFT},
+        {39,    DWT.ARROW_RIGHT},
+        {38,    DWT.ARROW_UP},
+        {40,    DWT.ARROW_DOWN},
+        {45,    DWT.INSERT},
+        {36,    DWT.HOME},
+        {35,    DWT.END},
+        {46,    DWT.DEL},
+        {33,    DWT.PAGE_UP},
+        {34,    DWT.PAGE_DOWN},
+
+        /* Virtual and Ascii Keys */
+        {8,     DWT.BS},
+        {13,    DWT.CR},
+        {9,     DWT.TAB},
+        {27,    DWT.ESC},
+        {12,    DWT.DEL},
+
+        /* Functions Keys */
+        {112,   DWT.F1},
+        {113,   DWT.F2},
+        {114,   DWT.F3},
+        {115,   DWT.F4},
+        {116,   DWT.F5},
+        {117,   DWT.F6},
+        {118,   DWT.F7},
+        {119,   DWT.F8},
+        {120,   DWT.F9},
+        {121,   DWT.F10},
+        {122,   DWT.F11},
+        {123,   DWT.F12},
+        {124,   DWT.F13},
+        {125,   DWT.F14},
+        {126,   DWT.F15},
+        {127,   0},
+        {128,   0},
+        {129,   0},
+        {130,   0},
+        {131,   0},
+        {132,   0},
+        {133,   0},
+        {134,   0},
+        {135,   0},
+
+        /* Numeric Keypad Keys */
+        {96,    DWT.KEYPAD_0},
+        {97,    DWT.KEYPAD_1},
+        {98,    DWT.KEYPAD_2},
+        {99,    DWT.KEYPAD_3},
+        {100,   DWT.KEYPAD_4},
+        {101,   DWT.KEYPAD_5},
+        {102,   DWT.KEYPAD_6},
+        {103,   DWT.KEYPAD_7},
+        {104,   DWT.KEYPAD_8},
+        {105,   DWT.KEYPAD_9},
+        {14,    DWT.KEYPAD_CR},
+        {107,   DWT.KEYPAD_ADD},
+        {109,   DWT.KEYPAD_SUBTRACT},
+        {106,   DWT.KEYPAD_MULTIPLY},
+        {111,   DWT.KEYPAD_DIVIDE},
+        {110,   DWT.KEYPAD_DECIMAL},
+
+        /* Other keys */
+        {20,    DWT.CAPS_LOCK},
+        {144,   DWT.NUM_LOCK},
+        {145,   DWT.SCROLL_LOCK},
+        {44,    DWT.PRINT_SCREEN},
+        {6,     DWT.HELP},
+        {19,    DWT.PAUSE},
+        {3,     DWT.BREAK},
+
+        /* Safari-specific */
+        {186,   ';'},
+        {187,   '='},
+        {189,   '-'},
+    };
+
+public void addCloseWindowListener (CloseWindowListener listener) {
+    CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length + 1];
+    System.arraycopy(closeWindowListeners, 0, newCloseWindowListeners, 0, closeWindowListeners.length);
+    closeWindowListeners = newCloseWindowListeners;
+    closeWindowListeners[closeWindowListeners.length - 1] = listener;
+}
+
+public void addLocationListener (LocationListener listener) {
+    LocationListener[] newLocationListeners = new LocationListener[locationListeners.length + 1];
+    System.arraycopy(locationListeners, 0, newLocationListeners, 0, locationListeners.length);
+    locationListeners = newLocationListeners;
+    locationListeners[locationListeners.length - 1] = listener;
+}
+
+public void addOpenWindowListener (OpenWindowListener listener) {
+    OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length + 1];
+    System.arraycopy(openWindowListeners, 0, newOpenWindowListeners, 0, openWindowListeners.length);
+    openWindowListeners = newOpenWindowListeners;
+    openWindowListeners[openWindowListeners.length - 1] = listener;
+}
+
+public void addProgressListener (ProgressListener listener) {
+    ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length + 1];
+    System.arraycopy(progressListeners, 0, newProgressListeners, 0, progressListeners.length);
+    progressListeners = newProgressListeners;
+    progressListeners[progressListeners.length - 1] = listener;
+}
+
+public void addStatusTextListener (StatusTextListener listener) {
+    StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length + 1];
+    System.arraycopy(statusTextListeners, 0, newStatusTextListeners, 0, statusTextListeners.length);
+    statusTextListeners = newStatusTextListeners;
+    statusTextListeners[statusTextListeners.length - 1] = listener;
+}
+
+public void addTitleListener (TitleListener listener) {
+    TitleListener[] newTitleListeners = new TitleListener[titleListeners.length + 1];
+    System.arraycopy(titleListeners, 0, newTitleListeners, 0, titleListeners.length);
+    titleListeners = newTitleListeners;
+    titleListeners[titleListeners.length - 1] = listener;
+}
+
+public void addVisibilityWindowListener (VisibilityWindowListener listener) {
+    VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length + 1];
+    System.arraycopy(visibilityWindowListeners, 0, newVisibilityWindowListeners, 0, visibilityWindowListeners.length);
+    visibilityWindowListeners = newVisibilityWindowListeners;
+    visibilityWindowListeners[visibilityWindowListeners.length - 1] = listener;
+}
+
+public abstract bool back ();
+
+public static void clearSessions () {
+    if (NativeClearSessions !is null) NativeClearSessions.run ();
+    if (MozillaClearSessions !is null) MozillaClearSessions.run ();
+}
+
+public abstract void create (Composite parent, int style);
+
+public abstract bool execute (String script);
+
+public abstract bool forward ();
+
+public abstract String getText ();
+
+public abstract String getUrl ();
+
+public Object getWebBrowser () {
+    return null;
+}
+
+public abstract bool isBackEnabled ();
+
+public bool isFocusControl () {
+    return false;
+}
+
+public abstract bool isForwardEnabled ();
+
+public abstract void refresh ();
+
+public void removeCloseWindowListener (CloseWindowListener listener) {
+    if (closeWindowListeners.length is 0) return;
+    int index = -1;
+    for (int i = 0; i < closeWindowListeners.length; i++) {
+        if (listener is closeWindowListeners[i]){
+            index = i;
+            break;
+        }
+    }
+    if (index is -1) return;
+    if (closeWindowListeners.length is 1) {
+        closeWindowListeners = new CloseWindowListener[0];
+        return;
+    }
+    CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length - 1];
+    System.arraycopy (closeWindowListeners, 0, newCloseWindowListeners, 0, index);
+    System.arraycopy (closeWindowListeners, index + 1, newCloseWindowListeners, index, closeWindowListeners.length - index - 1);
+    closeWindowListeners = newCloseWindowListeners;
+}
+
+public void removeLocationListener (LocationListener listener) {
+    if (locationListeners.length is 0) return;
+    int index = -1;
+    for (int i = 0; i < locationListeners.length; i++) {
+        if (listener is locationListeners[i]){
+            index = i;
+            break;
+        }
+    }
+    if (index is -1) return;
+    if (locationListeners.length is 1) {
+        locationListeners = new LocationListener[0];
+        return;
+    }
+    LocationListener[] newLocationListeners = new LocationListener[locationListeners.length - 1];
+    System.arraycopy (locationListeners, 0, newLocationListeners, 0, index);
+    System.arraycopy (locationListeners, index + 1, newLocationListeners, index, locationListeners.length - index - 1);
+    locationListeners = newLocationListeners;
+}
+
+public void removeOpenWindowListener (OpenWindowListener listener) {
+    if (openWindowListeners.length is 0) return;
+    int index = -1;
+    for (int i = 0; i < openWindowListeners.length; i++) {
+        if (listener is openWindowListeners[i]){
+            index = i;
+            break;
+        }
+    }
+    if (index is -1) return;
+    if (openWindowListeners.length is 1) {
+        openWindowListeners = new OpenWindowListener[0];
+        return;
+    }
+    OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length - 1];
+    System.arraycopy (openWindowListeners, 0, newOpenWindowListeners, 0, index);
+    System.arraycopy (openWindowListeners, index + 1, newOpenWindowListeners, index, openWindowListeners.length - index - 1);
+    openWindowListeners = newOpenWindowListeners;
+}
+
+public void removeProgressListener (ProgressListener listener) {
+    if (progressListeners.length is 0) return;
+    int index = -1;
+    for (int i = 0; i < progressListeners.length; i++) {
+        if (listener is progressListeners[i]){
+            index = i;
+            break;
+        }
+    }
+    if (index is -1) return;
+    if (progressListeners.length is 1) {
+        progressListeners = new ProgressListener[0];
+        return;
+    }
+    ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length - 1];
+    System.arraycopy (progressListeners, 0, newProgressListeners, 0, index);
+    System.arraycopy (progressListeners, index + 1, newProgressListeners, index, progressListeners.length - index - 1);
+    progressListeners = newProgressListeners;
+}
+
+public void removeStatusTextListener (StatusTextListener listener) {
+    if (statusTextListeners.length is 0) return;
+    int index = -1;
+    for (int i = 0; i < statusTextListeners.length; i++) {
+        if (listener is statusTextListeners[i]){
+            index = i;
+            break;
+        }
+    }
+    if (index is -1) return;
+    if (statusTextListeners.length is 1) {
+        statusTextListeners = new StatusTextListener[0];
+        return;
+    }
+    StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length - 1];
+    System.arraycopy (statusTextListeners, 0, newStatusTextListeners, 0, index);
+    System.arraycopy (statusTextListeners, index + 1, newStatusTextListeners, index, statusTextListeners.length - index - 1);
+    statusTextListeners = newStatusTextListeners;
+}
+
+public void removeTitleListener (TitleListener listener) {
+    if (titleListeners.length is 0) return;
+    int index = -1;
+    for (int i = 0; i < titleListeners.length; i++) {
+        if (listener is titleListeners[i]){
+            index = i;
+            break;
+        }
+    }
+    if (index is -1) return;
+    if (titleListeners.length is 1) {
+        titleListeners = new TitleListener[0];
+        return;
+    }
+    TitleListener[] newTitleListeners = new TitleListener[titleListeners.length - 1];
+    System.arraycopy (titleListeners, 0, newTitleListeners, 0, index);
+    System.arraycopy (titleListeners, index + 1, newTitleListeners, index, titleListeners.length - index - 1);
+    titleListeners = newTitleListeners;
+}
+
+public void removeVisibilityWindowListener (VisibilityWindowListener listener) {
+    if (visibilityWindowListeners.length is 0) return;
+    int index = -1;
+    for (int i = 0; i < visibilityWindowListeners.length; i++) {
+        if (listener is visibilityWindowListeners[i]){
+            index = i;
+            break;
+        }
+    }
+    if (index is -1) return;
+    if (visibilityWindowListeners.length is 1) {
+        visibilityWindowListeners = new VisibilityWindowListener[0];
+        return;
+    }
+    VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length - 1];
+    System.arraycopy (visibilityWindowListeners, 0, newVisibilityWindowListeners, 0, index);
+    System.arraycopy (visibilityWindowListeners, index + 1, newVisibilityWindowListeners, index, visibilityWindowListeners.length - index - 1);
+    visibilityWindowListeners = newVisibilityWindowListeners;
+}
+
+public void setBrowser (Browser browser) {
+    this.browser = browser;
+}
+
+public abstract bool setText (String html);
+
+public abstract bool setUrl (String url);
+
+public abstract void stop ();
+
+int translateKey (int key) {
+    for (int i = 0; i < KeyTable.length; i++) {
+        if (KeyTable[i][0] is key) return KeyTable[i][1];
+    }
+    return 0;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/WindowCreator2.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+module dwt.browser.WindowCreator2;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.Platform;
+
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.nsIBaseWindow;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsISupports;
+import dwt.internal.mozilla.nsIURI;
+import dwt.internal.mozilla.nsIWebBrowser;
+import dwt.internal.mozilla.nsIWebBrowserChrome;
+import dwt.internal.mozilla.nsIWindowCreator;
+
+import dwt.DWT;
+import dwt.graphics.Point;
+import dwt.layout.FillLayout;
+import dwt.widgets.Shell;
+
+class WindowCreator2 {
+    XPCOMObject supports;
+    XPCOMObject windowCreator;
+    XPCOMObject windowCreator2;
+    int refCount = 0;
+
+WindowCreator2 () {
+    createCOMInterfaces ();
+}
+
+int AddRef () {
+    refCount++;
+    return refCount;
+}
+
+void createCOMInterfaces () {
+    /* Create each of the interfaces that this object implements */
+    supports = new XPCOMObject (new int[] {2, 0, 0}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+    };
+
+    windowCreator = new XPCOMObject (new int[] {2, 0, 0, 3}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return CreateChromeWindow (args[0], (int)/*64*/args[1], args[2]);}
+    };
+
+    windowCreator2 = new XPCOMObject (new int[] {2, 0, 0, 3, 6}) {
+        public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+        public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+        public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+        public int /*long*/ method3 (int /*long*/[] args) {return CreateChromeWindow (args[0], (int)/*64*/args[1], args[2]);}
+        public int /*long*/ method4 (int /*long*/[] args) {return CreateChromeWindow2 (args[0], (int)/*64*/args[1], (int)/*64*/args[2], args[3], args[4], args[5]);}
+    };
+}
+
+void disposeCOMInterfaces () {
+    if (supports !is null) {
+        supports.dispose ();
+        supports = null;
+    }   
+    if (windowCreator !is null) {
+        windowCreator.dispose ();
+        windowCreator = null;   
+    }
+
+    if (windowCreator2 !is null) {
+        windowCreator2.dispose ();
+        windowCreator2 = null;  
+    }
+}
+
+int /*long*/ getAddress () {
+    return windowCreator.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+    if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+    nsID guid = new nsID ();
+    XPCOM.memmove (guid, riid, nsID.sizeof);
+    
+    if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIWindowCreator.NS_IWINDOWCREATOR_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {windowCreator.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+    if (guid.Equals (nsIWindowCreator2.NS_IWINDOWCREATOR2_IID)) {
+        XPCOM.memmove (ppvObject, new int /*long*/[] {windowCreator2.getAddress ()}, C.PTR_SIZEOF);
+        AddRef ();
+        return XPCOM.NS_OK;
+    }
+
+    XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+    return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+            
+int Release () {
+    refCount--;
+    if (refCount is 0) disposeCOMInterfaces ();
+    return refCount;
+}
+    
+/* nsIWindowCreator */
+
+int CreateChromeWindow (int /*long*/ parent, int chromeFlags, int /*long*/ _retval) {
+    return CreateChromeWindow2 (parent, chromeFlags, 0, 0, 0, _retval);
+}
+
+/* nsIWindowCreator2 */
+
+int CreateChromeWindow2 (int /*long*/ parent, int chromeFlags, int contextFlags, int /*long*/ uri, int /*long*/ cancel, int /*long*/ _retval) {
+    if (parent is 0 && (chromeFlags & nsIWebBrowserChrome.CHROME_OPENAS_CHROME) is 0) {
+        return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+    }
+    Browser src = null; 
+    if (parent !is 0) {
+        nsIWebBrowserChrome browserChromeParent = new nsIWebBrowserChrome (parent);
+        int /*long*/[] aWebBrowser = new int /*long*/[1];
+        int rc = browserChromeParent.GetWebBrowser (aWebBrowser);
+        if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+        if (aWebBrowser[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+        nsIWebBrowser webBrowser = new nsIWebBrowser (aWebBrowser[0]);
+        int /*long*/[] result = new int /*long*/[1];
+        rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
+        if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+        if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE);
+        webBrowser.Release ();
+
+        nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
+        result[0] = 0;
+        int /*long*/[] aParentNativeWindow = new int /*long*/[1];
+        rc = baseWindow.GetParentNativeWindow (aParentNativeWindow);
+        if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+        if (aParentNativeWindow[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE);
+        baseWindow.Release ();
+
+        src = Mozilla.findBrowser (aParentNativeWindow[0]);
+    }
+    final Browser browser;
+    bool doit = true;
+    if ((chromeFlags & nsIWebBrowserChrome.CHROME_OPENAS_CHROME) !is 0) {
+        /*
+        * Mozilla will request a new Browser in a modal window in order to emulate a native
+        * dialog that is not available to it (eg.- a print dialog on Linux).  For this
+        * reason modal requests are handled here so that the user is not exposed to them.
+        */
+        int style = DWT.DIALOG_TRIM;
+        if ((chromeFlags & nsIWebBrowserChrome.CHROME_MODAL) !is 0) style |= DWT.APPLICATION_MODAL; 
+        final Shell shell = src is null ?
+            new Shell (style) :
+            new Shell (src.getShell(), style);
+        shell.setLayout (new FillLayout ());
+        browser = new Browser (shell, src is null ? DWT.MOZILLA : src.getStyle () & DWT.MOZILLA);
+        browser.addVisibilityWindowListener (new VisibilityWindowListener () {
+            public void hide (WindowEvent event) {
+            }
+            public void show (WindowEvent event) {
+                if (event.location !is null) shell.setLocation (event.location);
+                if (event.size !is null) {
+                    Point size = event.size;
+                    shell.setSize (shell.computeSize (size.x, size.y));
+                }
+                shell.open ();
+            }
+        });
+        browser.addCloseWindowListener (new CloseWindowListener () {
+            public void close (WindowEvent event) {
+                shell.close ();
+            }
+        });
+        if (uri !is 0) {
+            nsIURI location = new nsIURI (uri);
+            int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
+            if (location.GetSpec (aSpec) is XPCOM.NS_OK) {
+                int length = XPCOM.nsEmbedCString_Length (aSpec);
+                if (length > 0) {
+                    int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
+                    byte[] dest = new byte[length];
+                    XPCOM.memmove (dest, buffer, length);
+                    browser.setUrl (new String (dest));
+                }
+            }
+            XPCOM.nsEmbedCString_delete (aSpec);
+        }
+    } else {
+        WindowEvent event = new WindowEvent (src);
+        event.display = src.getDisplay ();
+        event.widget = src;
+        event.required = true;
+        for (int i = 0; i < src.webBrowser.openWindowListeners.length; i++) {
+            src.webBrowser.openWindowListeners[i].open (event);
+        }
+        browser = event.browser;
+
+        /* Ensure that the Browser provided by the client is valid for use */ 
+        doit = browser !is null && !browser.isDisposed ();
+        if (doit) {
+            String platform = Platform.PLATFORM;
+            bool isMozillaNativePlatform = platform.equals ("gtk") || platform.equals ("motif"); //$NON-NLS-1$ //$NON-NLS-2$
+            doit = isMozillaNativePlatform || (browser.getStyle () & DWT.MOZILLA) !is 0;
+        }
+    }
+    if (doit) {
+        Mozilla mozilla = (Mozilla)browser.webBrowser;
+        mozilla.isChild = true;
+        int /*long*/ chromePtr = mozilla.webBrowserChrome.getAddress ();
+        nsIWebBrowserChrome webBrowserChrome = new nsIWebBrowserChrome (chromePtr);
+        webBrowserChrome.SetChromeFlags (chromeFlags);
+        webBrowserChrome.AddRef ();
+        XPCOM.memmove (_retval, new int /*long*/[] {chromePtr}, C.PTR_SIZEOF);
+    } else {
+        if (cancel !is 0) {
+            C.memmove (cancel, new int[] {1}, 4);   /* PRBool */
+        }
+    }
+    return doit ? XPCOM.NS_OK : XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/WindowEvent.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+module dwt.browser.WindowEvent;
+
+import dwt.dwthelper.utils;
+
+import dwt.events.TypedEvent;
+import dwt.graphics.Point;
+import dwt.widgets.Widget;
+
+/**
+ * A <code>WindowEvent</code> is sent by a {@link Browser} when
+ * a new window needs to be created or when an existing window needs to be
+ * closed. This notification occurs when a javascript command such as
+ * <code>window.open</code> or <code>window.close</code> gets executed by
+ * a <code>Browser</code>.
+ *
+ * <p>
+ * The following example shows how <code>WindowEvent</code>'s are typically
+ * handled.
+ * 
+ * <code><pre>
+ *  public static void main(String[] args) {
+ *      Display display = new Display();
+ *      Shell shell = new Shell(display);
+ *      shell.setText("Main Window");
+ *      shell.setLayout(new FillLayout());
+ *      Browser browser = new Browser(shell, DWT.NONE);
+ *      initialize(display, browser);
+ *      shell.open();
+ *      browser.setUrl("http://www.eclipse.org");
+ *      while (!shell.isDisposed()) {
+ *          if (!display.readAndDispatch())
+ *              display.sleep();
+ *      }
+ *      display.dispose();
+ *  }
+ *
+ *  static void initialize(final Display display, Browser browser) {
+ *      browser.addOpenWindowListener(new OpenWindowListener() {
+ *          public void open(WindowEvent event) {
+ *              // Certain platforms can provide a default full browser.
+ *              // simply return in that case if the application prefers
+ *              // the default full browser to the embedded one set below.
+ *              if (!event.required) return;
+ *
+ *              // Embed the new window
+ *              Shell shell = new Shell(display);
+ *              shell.setText("New Window");
+ *              shell.setLayout(new FillLayout());
+ *              Browser browser = new Browser(shell, DWT.NONE);
+ *              initialize(display, browser);
+ *              event.browser = browser;
+ *          }
+ *      });
+ *      browser.addVisibilityWindowListener(new VisibilityWindowListener() {
+ *          public void hide(WindowEvent event) {
+ *              Browser browser = (Browser)event.widget;
+ *              Shell shell = browser.getShell();
+ *              shell.setVisible(false);
+ *          }
+ *          public void show(WindowEvent event) {
+ *              Browser browser = (Browser)event.widget;
+ *              Shell shell = browser.getShell();
+ *              if (event.location !is null) shell.setLocation(event.location);
+ *              if (event.size !is null) {
+ *                  Point size = event.size;
+ *                  shell.setSize(shell.computeSize(size.x, size.y));
+ *              }
+ *              if (event.addressBar || event.menuBar || event.statusBar || event.toolBar) {
+ *                  // Create widgets for the address bar, menu bar, status bar and/or tool bar
+ *                  // leave enough space in the Shell to accommodate a Browser of the size
+ *                  // given by event.size
+ *              }
+ *              shell.open();
+ *          }
+ *      });
+ *      browser.addCloseWindowListener(new CloseWindowListener() {
+ *          public void close(WindowEvent event) {
+ *              Browser browser = (Browser)event.widget;
+ *              Shell shell = browser.getShell();
+ *              shell.close();
+ *          }
+ *      });
+ *  }
+ * </pre></code>
+ * 
+ * The following notifications are emitted when the user selects a hyperlink that targets a new window
+ * or as the result of a javascript that executes window.open. 
+ * 
+ * <p>Main Browser
+ * <ul>
+ *    <li>User selects a link that opens in a new window or javascript requests a new window</li>
+ *    <li>OpenWindowListener.open() notified</li>
+ *    <ul>
+ *          <li>Application creates a new Shell and a second Browser inside that Shell</li>
+ *          <li>Application registers WindowListener's on that second Browser, such as VisibilityWindowListener</li>
+ *          <li>Application returns the second Browser as the host for the new window content</li>
+ *    </ul>
+ * </ul>
+ * 
+ * <p>Second Browser
+ * <ul>
+ *    <li>VisibilityWindowListener.show() notified</li>
+ *    <ul>
+ *          <li>Application sets navigation tool bar, status bar, menu bar and Shell size
+ *          <li>Application makes the Shell hosting the second Browser visible
+ *          <li>User now sees the new window
+ *    </ul> 
+ * </ul>
+ * 
+ * @see CloseWindowListener
+ * @see OpenWindowListener
+ * @see VisibilityWindowListener
+ * 
+ * @since 3.0
+ */
+
+public class WindowEvent : TypedEvent {
+
+    /** 
+     * Specifies whether the platform requires the user to provide a
+     * <code>Browser</code> to handle the new window.
+     * 
+     * @since 3.1
+     */
+    public bool required;
+    
+    
+    /** 
+     * <code>Browser</code> provided by the application.
+     */
+    public Browser browser;
+
+    /** 
+     * Requested location for the <code>Shell</code> hosting the <code>Browser</code>.
+     * It is <code>null</code> if no location has been requested.
+     */
+    public Point location;
+
+    /** 
+     * Requested <code>Browser</code> size. The client area of the <code>Shell</code> 
+     * hosting the <code>Browser</code> should be large enough to accommodate that size. 
+     * It is <code>null</code> if no size has been requested.
+     */
+    public Point size;
+    
+    /**
+     * Specifies whether the <code>Shell</code> hosting the <code>Browser</code> should
+     * display an address bar.
+     * 
+     * @since 3.1
+     */
+    public bool addressBar;
+
+    /**
+     * Specifies whether the <code>Shell</code> hosting the <code>Browser</code> should
+     * display a menu bar.
+     * 
+     * @since 3.1
+     */
+    public bool menuBar;
+    
+    /**
+     * Specifies whether the <code>Shell</code> hosting the <code>Browser</code> should
+     * display a status bar.
+     * 
+     * @since 3.1
+     */
+    public bool statusBar;
+    
+    /**
+     * Specifies whether the <code>Shell</code> hosting the <code>Browser</code> should
+     * display a tool bar.
+     * 
+     * @since 3.1
+     */
+    public bool toolBar;
+    
+    static final long serialVersionUID = 3617851997387174969L;
+    
+    this(Widget w) {
+        super(w);
+    }
+
+    /**
+     * Returns a string containing a concise, human-readable
+     * description of the receiver.
+     *
+     * @return a string representation of the event
+     */
+
+    public override String toString () {
+        return Format( "WindowEvent {required={} browser={} location={} size={} addressBar={} menuBar={} statusBar={} toolBar={} }",
+        required, browser, location, size, addressBar, menuBar, statusBar, tooBar );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/internal/mozilla/nsEmbedString.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,99 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by Netscape are Copyright (C) 1998-1999
+ * Netscape Communications Corporation.  All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * IBM
+ * -  Binding to permit interfacing between Mozilla and DWT
+ * -  Copyright (C) 2004 IBM Corp.  All Rights Reserved.
+ *
+ * Port to the D programming language:
+ *     John Reimer <terminal.node@gmail.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+module dwt.internal.mozilla.nsEmbedString;
+
+import dwt.dwthelper.utils;
+import dwt.internal.mozilla.nsStringAPI;
+
+public class nsEmbedString 
+{
+    int /*long*/ handle;
+        
+    /**************************************************************************
+
+    **************************************************************************/
+
+    public this() 
+    {
+        handle = XPCOM.nsEmbedString_new();
+    }
+    
+    /**************************************************************************
+
+    **************************************************************************/
+
+    public nsEmbedString(String string)
+    {
+        if (string !is null) 
+        {
+            char[] aString = new char[string.length() + 1];
+            string.getChars(0, string.length(), aString, 0);
+            handle = XPCOM.nsEmbedString_new(aString);
+        }   
+    }
+    
+    /**************************************************************************
+
+    **************************************************************************/
+
+    public int /*long*/ getAddress() 
+    {
+        return handle;
+    }   
+        
+    /**************************************************************************
+
+    **************************************************************************/
+
+    public String toString() 
+    {
+        if (handle is 0) 
+            return null;
+        int length = XPCOM.nsEmbedString_Length(handle);
+        int /*long*/ buffer = XPCOM.nsEmbedString_get(handle);
+        char[] dest = new char[length];
+        XPCOM.memmove(dest, buffer, length * 2);
+        return new String(dest);
+    }   
+        
+    /**************************************************************************
+
+    **************************************************************************/
+
+    public void dispose() 
+    {
+        if (handle is 0) 
+            return;            
+        XPCOM.nsEmbedString_delete(handle);
+        handle = 0;     
+    }   
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/internal/mozilla/nsEmbedString2.d	Thu Jul 31 19:17:51 2008 -0700
@@ -0,0 +1,86 @@
+module dwt.internal.mozilla.nsEmbedString;
+
+import dwt.internal.mozilla.Common;
+import dwt.internal.mozilla.nsStringAPI;
+
+class nsEmbedString
+{
+	this(wchar[] s)
+	{
+		nsresult result;
+		result = NS_StringContainerInit2(&str, s.ptr, s.length, 0);
+		if (result != 0) // TODO: convert to XPCOM fail macro
+			throw new Exception("Init string container fail");
+	}
+
+	this()
+	{
+		nsresult result;
+		result = NS_StringContainerInit(&str);
+		if (result != 0) // TODO: convert to XPCOM fail macro
+			throw new Exception("Init string container fail");
+	}
+
+	nsAString* opCast()
+	{
+		return cast(nsAString*)&str;
+	}
+
+	wchar[] toString16()
+	{
+		wchar* buffer = null;
+		PRBool terminated;
+		uint len = NS_StringGetData(cast(nsAString*)&str, &buffer, &terminated);
+		wchar[] result = buffer[0 .. len].dup;
+		return result;
+	}
+
+	~this()
+	{
+		NS_StringContainerFinish(&str);
+	}
+private:
+	nsStringContainer str;
+}
+
+
+class nsEmbedCString
+{
+	this(char[] s)
+	{
+		nsresult result;
+		result = NS_CStringContainerInit2(&str, s.ptr, s.length, 0);
+		if (result != 0) // TODO: convert to XPCOM fail macro
+			throw new Exception("Init string container fail");
+	}
+
+	this()
+	{
+		nsresult result;
+		result = NS_CStringContainerInit(&str);
+		if (result != 0) // TODO: convert to XPCOM fail macro
+			throw new Exception("Init string container fail");
+	}
+
+	nsACString* opCast()
+	{
+		return cast(nsACString*)&str;
+	}
+
+	char[] toString()
+	{
+		char* buffer = null;
+		PRBool terminated;
+		uint len = NS_CStringGetData(cast(nsACString*)&str, &buffer, &terminated);
+		char[] result = buffer[0 .. len].dup;
+		return result;
+	}
+
+	~this()
+	{
+		NS_CStringContainerFinish(&str);
+	}
+private:
+	nsCStringContainer str;
+}
+
--- a/dwt/internal/mozilla/nsIInputStream.d	Sat Jul 26 14:37:23 2008 +0200
+++ b/dwt/internal/mozilla/nsIInputStream.d	Thu Jul 31 19:17:51 2008 -0700
@@ -6,7 +6,7 @@
 
 typedef nsresult function(nsIInputStream aInStream,
 	void *aClosure,
-	char *aFromSegment,
+	byte *aFromSegment,
 	PRUint32 aToOffset,
 	PRUint32 aCount,
 	PRUint32 *aWriteCount) nsWriteSegmentFun;
@@ -26,7 +26,7 @@
 
   nsresult Close();
   nsresult Available(PRUint32 *_retval);
-  nsresult Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval);
+  nsresult Read(byte * aBuf, PRUint32 aCount, PRUint32 *_retval);
   nsresult ReadSegments(nsWriteSegmentFun aWriter, void * aClosure, PRUint32 aCount, PRUint32 *_retval);
   nsresult IsNonBlocking(PRBool *_retval);
 
--- a/dwt/internal/mozilla/nsILocalFile.d	Sat Jul 26 14:37:23 2008 +0200
+++ b/dwt/internal/mozilla/nsILocalFile.d	Thu Jul 31 19:17:51 2008 -0700
@@ -20,25 +20,25 @@
 
 interface nsILocalFile : nsIFile {
 
-  static const char[] IID_STR = NS_ILOCALFILE_IID_STR;
-  static const nsIID IID = NS_ILOCALFILE_IID;
+    static const char[] IID_STR = NS_ILOCALFILE_IID_STR;
+    static const nsIID IID = NS_ILOCALFILE_IID;
 
-  nsresult InitWithPath(nsAString * filePath);
-  nsresult InitWithNativePath(nsACString * filePath);
-  nsresult InitWithFile(nsILocalFile aFile);
-  nsresult GetFollowLinks(PRBool *aFollowLinks);
-  nsresult SetFollowLinks(PRBool aFollowLinks);
-  nsresult OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc * *_retval);
-  nsresult OpenANSIFileDesc(char *mode, FILE * *_retval);
-  nsresult Load(PRLibrary * *_retval);
-  nsresult GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable);
-  nsresult AppendRelativePath(nsAString * relativeFilePath);
-  nsresult AppendRelativeNativePath(nsACString * relativeFilePath);
-  nsresult GetPersistentDescriptor(nsACString * aPersistentDescriptor);
-  nsresult SetPersistentDescriptor(nsACString * aPersistentDescriptor);
-  nsresult Reveal();
-  nsresult Launch();
-  nsresult GetRelativeDescriptor(nsILocalFile fromFile, nsACString * _retval);
-  nsresult SetRelativeDescriptor(nsILocalFile fromFile, nsACString * relativeDesc);
+    nsresult InitWithPath(nsAString * filePath);
+    nsresult InitWithNativePath(nsACString * filePath);
+    nsresult InitWithFile(nsILocalFile aFile);
+    nsresult GetFollowLinks(PRBool *aFollowLinks);
+    nsresult SetFollowLinks(PRBool aFollowLinks);
+    nsresult OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc * *_retval);
+    nsresult OpenANSIFileDesc(char *mode, FILE * *_retval);
+    nsresult Load(PRLibrary * *_retval);
+    nsresult GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable);
+    nsresult AppendRelativePath(nsAString * relativeFilePath);
+    nsresult AppendRelativeNativePath(nsACString * relativeFilePath);
+    nsresult GetPersistentDescriptor(nsACString * aPersistentDescriptor);
+    nsresult SetPersistentDescriptor(nsACString * aPersistentDescriptor);
+    nsresult Reveal();
+    nsresult Launch();
+    nsresult GetRelativeDescriptor(nsILocalFile fromFile, nsACString * _retval);
+    nsresult SetRelativeDescriptor(nsILocalFile fromFile, nsACString * relativeDesc);
 }
 
--- a/dwt/internal/mozilla/nsISupports.d	Sat Jul 26 14:37:23 2008 +0200
+++ b/dwt/internal/mozilla/nsISupports.d	Thu Jul 31 19:17:51 2008 -0700
@@ -11,16 +11,21 @@
 
 extern(System) 
 
-interface nsISupports {
-
-  static const char[] IID_STR = NS_ISUPPORTS_IID_STR;
-  static const nsIID IID = NS_ISUPPORTS_IID;
+interface IUnknown 
+{
+    static const char[] IID_STR = NS_ISUPPORTS_IID_STR;
+    static const nsIID IID = NS_ISUPPORTS_IID;
 
-  nsresult QueryInterface(nsIID * uuid, void * *result);
+    nsresult QueryInterface(nsIID * uuid, void **result);
 
-  nsrefcnt AddRef();
-  nsrefcnt Release();
-
+    nsrefcnt AddRef();
+    nsrefcnt Release();
 }
 
-// alias IUnknown nsISupports;
\ No newline at end of file
+// WHY WE USE COM's IUnknown for XPCOM:
+//
+// The IUnknown interface is special-cased in D and is specifically designed to be
+// compatible with MS COM.  XPCOM's nsISupports interface is the exact equivalent
+// of IUnknown so we alias it here to take advantage of D's COM support. -JJR
+
+alias IUnknown nsISupports;
\ No newline at end of file
--- a/dwt/internal/mozilla/nsStringAPI.d	Sat Jul 26 14:37:23 2008 +0200
+++ b/dwt/internal/mozilla/nsStringAPI.d	Thu Jul 31 19:17:51 2008 -0700
@@ -68,6 +68,9 @@
 alias nsAString nsAString_external;
 alias nsACString nsACString_external;
 
+alias nsAString nsEmbedString;
+alias nsACString nsEmbedCString;
+
 struct nsAString
 {
   static nsAString opCall(wchar[] s)
--- a/dwt/internal/mozilla/nsXPCOM.d	Sat Jul 26 14:37:23 2008 +0200
+++ b/dwt/internal/mozilla/nsXPCOM.d	Thu Jul 31 19:17:51 2008 -0700
@@ -1,3 +1,5 @@
+/******************************************************************************
+
 module dwt.internal.mozilla.nsXPCOM;
 
 import dwt.internal.mozilla.Common;
@@ -43,8 +45,8 @@
 nsresult  NS_GetComponentManager(nsIComponentManager *result);
 nsresult  NS_GetComponentRegistrar(nsIComponentRegistrar *result);
 nsresult  NS_GetMemoryManager(nsIMemory *result);
-nsresult  NS_NewLocalFile(nsAString path, PRBool followLinks, nsILocalFile *result);
-nsresult  NS_NewNativeLocalFile(nsACString path, PRBool followLinks, nsILocalFile *result);
+nsresult  NS_NewLocalFile(inout nsAString path, PRBool followLinks, nsILocalFile** result);
+nsresult  NS_NewNativeLocalFile(inout nsACString path, PRBool followLinks, nsILocalFile** result);
 void *    NS_Alloc(PRSize size);
 void *    NS_Realloc(void *ptr, PRSize size);
 void      NS_Free(void *ptr);