Mercurial > projects > dwt-mac
view dwt/browser/Mozilla.d @ 156:969e7de37c3d default tip
Fixes to get dwt to work with dmd and ldc
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Wed, 08 Jul 2009 21:56:44 +0200 |
parents | 07399639c0c8 |
children |
line wrap: on
line source
/******************************************************************************* * 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 tango.text.locale.Core; import tango.io.Stdout; import tango.text.convert.Format; import tango.io.Console; import tango.sys.Environment; import tango.stdc.string; version (linux) import dwt.internal.c.gtk; else version (darwin) import objc = dwt.internal.objc.runtime; import dwt.DWT; import dwt.DWTError; import dwt.graphics.Device; import dwt.graphics.Point; import dwt.graphics.Rectangle; import dwt.browser.Browser; import dwt.browser.WebBrowser; import dwt.browser.MozillaDelegate; import dwt.browser.AppFileLocProvider; import dwt.browser.WindowCreator2; import dwt.browser.PromptService2Factory; import dwt.browser.HelperAppLauncherDialogFactory; import dwt.browser.DownloadFactory; import dwt.browser.DownloadFactory_1_8; import dwt.browser.FilePickerFactory; import dwt.browser.FilePickerFactory_1_8; import dwt.browser.InputStream; import dwt.browser.StatusTextEvent; import dwt.browser.ProgressEvent; import dwt.browser.LocationEvent; import dwt.browser.WindowEvent; import dwt.browser.TitleEvent; import dwt.internal.Compatibility; import dwt.internal.LONG; import dwt.internal.Library; import XPCOM = dwt.internal.mozilla.XPCOM; import XPCOMInit = dwt.internal.mozilla.XPCOMInit; import dwt.internal.mozilla.Common; import dwt.internal.mozilla.nsEmbedString; 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.nsIDOMNode; import dwt.internal.mozilla.nsIDOMEvent; import dwt.internal.mozilla.nsIDOMEventListener; 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.nsIDOMDocument; import dwt.internal.mozilla.nsIDirectoryService; import dwt.internal.mozilla.nsIDocShell; import dwt.internal.mozilla.nsIEmbeddingSiteWindow; import dwt.internal.mozilla.nsIFile; import dwt.internal.mozilla.nsIFactory; 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.nsIRequest; import dwt.internal.mozilla.nsIServiceManager; import dwt.internal.mozilla.nsISimpleEnumerator; import dwt.internal.mozilla.nsIStreamListener; import dwt.internal.mozilla.nsISupports; 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.internal.mozilla.nsIWindowCreator; import dwt.internal.mozilla.nsStringAPI; 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; import dwt.widgets.Control; class Mozilla : WebBrowser, nsIWeakReference, nsIWebProgressListener, nsIWebBrowserChrome, nsIWebBrowserChromeFocus, nsIEmbeddingSiteWindow, nsIInterfaceRequestor, nsISupportsWeakReference, nsIContextMenuListener, nsIURIContentListener, nsITooltipListener, nsIDOMEventListener { version (linux) GtkWidget* embedHandle; else version (darwin) objc.id embedHandle; nsIWebBrowser webBrowser; Object webBrowserObject; MozillaDelegate mozDelegate; int chromeFlags = nsIWebBrowserChrome.CHROME_DEFAULT; int refCount, lastKeyCode, lastCharCode; nsIRequest request; Point location, size; bool visible, isChild, ignoreDispose, awaitingNavigate; Shell tip = null; Listener listener; nsIDOMWindow[] unhookedDOMWindows; 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 const String GRERANGE_LOWER = "1.8.1.2"; //$NON-NLS-1$ static const String GRERANGE_LOWER_FALLBACK = "1.8"; //$NON-NLS-1$ static const bool LowerRangeInclusive = true; static const String GRERANGE_UPPER = "1.9.*"; //$NON-NLS-1$ static const bool UpperRangeInclusive = true; static const int MAX_PORT = 65535; static const String SEPARATOR_OS = System.getProperty ("file.separator"); //$NON-NLS-1$ static const String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$ static const String DISPOSE_LISTENER_HOOKED = "dwt.browser.Mozilla.disposeListenerHooked"; //$NON-NLS-1$ static const String PREFIX_JAVASCRIPT = "javascript:"; //$NON-NLS-1$ static const String PREFERENCE_CHARSET = "intl.charset.default"; //$NON-NLS-1$ static const String PREFERENCE_DISABLEOPENDURINGLOAD = "dom.disable_open_during_load"; //$NON-NLS-1$ static const String PREFERENCE_DISABLEWINDOWSTATUSCHANGE = "dom.disable_window_status_change"; //$NON-NLS-1$ static const String PREFERENCE_LANGUAGES = "intl.accept_languages"; //$NON-NLS-1$ static const String PREFERENCE_PROXYHOST_FTP = "network.proxy.ftp"; //$NON-NLS-1$ static const String PREFERENCE_PROXYPORT_FTP = "network.proxy.ftp_port"; //$NON-NLS-1$ static const String PREFERENCE_PROXYHOST_HTTP = "network.proxy.http"; //$NON-NLS-1$ static const String PREFERENCE_PROXYPORT_HTTP = "network.proxy.http_port"; //$NON-NLS-1$ static const String PREFERENCE_PROXYHOST_SSL = "network.proxy.ssl"; //$NON-NLS-1$ static const String PREFERENCE_PROXYPORT_SSL = "network.proxy.ssl_port"; //$NON-NLS-1$ static const String PREFERENCE_PROXYTYPE = "network.proxy.type"; //$NON-NLS-1$ static const String PROFILE_AFTER_CHANGE = "profile-after-change"; //$NON-NLS-1$ static const String PROFILE_BEFORE_CHANGE = "profile-before-change"; //$NON-NLS-1$ static String PROFILE_DIR; //= SEPARATOR_OS ~ "eclipse" ~ SEPARATOR_OS; //$NON-NLS-1$ static const String PROFILE_DO_CHANGE = "profile-do-change"; //$NON-NLS-1$ static const String PROPERTY_PROXYPORT = "network.proxy_port"; //$NON-NLS-1$ static const String PROPERTY_PROXYHOST = "network.proxy_host"; //$NON-NLS-1$ static const String SEPARATOR_LOCALE = "-"; //$NON-NLS-1$ static const String SHUTDOWN_PERSIST = "shutdown-persist"; //$NON-NLS-1$ static const String STARTUP = "startup"; //$NON-NLS-1$ static const String TOKENIZER_LOCALE = ","; //$NON-NLS-1$ static const String URI_FROMMEMORY = "file:///"; //$NON-NLS-1$ static const String XULRUNNER_PATH = "dwt.browser.XULRunnerPath"; //$NON-NLS-1$ // TEMPORARY CODE static const String GRE_INITIALIZED = "dwt.browser.XULRunnerInitialized"; //$NON-NLS-1$ this () { PROFILE_DIR = SEPARATOR_OS ~ "eclipse" ~ SEPARATOR_OS; MozillaClearSessions = new class() Runnable { public void run () { if (!Initialized) return; nsIServiceManager serviceManager; int rc = XPCOM.NS_GetServiceManager (&serviceManager); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (serviceManager is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); nsICookieManager manager; rc = serviceManager.GetServiceByContractID (XPCOM.NS_COOKIEMANAGER_CONTRACTID.ptr, &nsICookieManager.IID, cast(void**)&manager); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (manager is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); serviceManager.Release (); nsISimpleEnumerator enumerator; rc = manager.GetEnumerator (&enumerator); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); manager.Release (); PRBool moreElements; rc = enumerator.HasMoreElements (&moreElements); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); while (moreElements !is 0) { nsICookie cookie; rc = enumerator.GetNext (cast(nsISupports*)&cookie); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); PRUint64 expires; rc = cookie.GetExpires (&expires); if (expires is 0) { /* indicates a session cookie */ scope auto domain = new nsEmbedCString; scope auto name = new nsEmbedCString; scope auto path = new nsEmbedCString; cookie.GetHost (cast(nsACString*)domain); cookie.GetName (cast(nsACString*)name); cookie.GetPath (cast(nsACString*)path); rc = manager.Remove (cast(nsACString*)domain, cast(nsACString*)name, cast(nsACString*)path, 0); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); } cookie.Release (); rc = enumerator.HasMoreElements (&moreElements); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); } enumerator.Release (); } }; } extern(D) public void create (Composite parent, int style) { mozDelegate = new MozillaDelegate (super.browser); Display display = parent.getDisplay (); if (!Initialized) { bool initLoaded = false; bool IsXULRunner = false; String greInitialized = System.getProperty (GRE_INITIALIZED); if ("true" == 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) { // we don't need to load an initial library in D, so set to "true" initLoaded = true; } else { mozillaPath ~= SEPARATOR_OS ~ mozDelegate.getLibraryName (); IsXULRunner = true; } if (initLoaded) { /* attempt to discover a XULRunner to use as the GRE */ XPCOMInit.GREVersionRange range; range.lower = GRERANGE_LOWER.ptr; range.lowerInclusive = LowerRangeInclusive; range.upper = GRERANGE_UPPER.ptr; range.upperInclusive = UpperRangeInclusive; char[] greBuffer = new char[XPCOMInit.PATH_MAX]; int rc = XPCOMInit.GRE_GetGREPathWithProperties (&range, 1, null, 0, greBuffer.ptr, 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) { range.lower = GRERANGE_LOWER_FALLBACK.ptr; rc = XPCOMInit.GRE_GetGREPathWithProperties (&range, 1, null, 0, greBuffer.ptr, greBuffer.length); } if (rc is XPCOM.NS_OK) { /* indicates that a XULRunner was found */ mozillaPath = greBuffer; 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) { rc = XPCOMInit.XPCOMGlueStartup (mozillaPath.ptr); if (rc !is XPCOM.NS_OK) { mozillaPath = mozillaPath.substring (0, mozillaPath.lastIndexOf (SEPARATOR_OS)); if (Device.DEBUG) Cerr ("cannot use detected XULRunner: ") (mozillaPath).newline; //$NON-NLS-1$ /* attempt to XPCOMGlueStartup the GRE pointed at by MOZILLA_FIVE_HOME */ auto ptr = Environment.get(XPCOM.MOZILLA_FIVE_HOME); if (ptr is null) { IsXULRunner = false; } else { mozillaPath = ptr; /* * Attempting to XPCOMGlueStartup a mozilla-based GRE !is xulrunner can * crash, so don't attempt unless the GRE appears to be xulrunner. */ if (mozillaPath.indexOf("xulrunner") is -1) { //$NON-NLS-1$ IsXULRunner = false; } else { mozillaPath ~= SEPARATOR_OS ~ mozDelegate.getLibraryName (); rc = XPCOMInit.XPCOMGlueStartup (toStringz(mozillaPath)); if (rc !is XPCOM.NS_OK) { IsXULRunner = false; mozillaPath = mozillaPath.substring (0, mozillaPath.lastIndexOf (SEPARATOR_OS)); if (Device.DEBUG) Cerr ("failed to start as XULRunner: " )(mozillaPath).newline; //$NON-NLS-1$ } } } } if (IsXULRunner) { XPCOMInitWasGlued = true; } } } } if (IsXULRunner) { if (Device.DEBUG) Cerr ("XULRunner path: ") (mozillaPath).newline; //$NON-NLS-1$ 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 */ auto mozFiveHome = Environment.get(XPCOM.MOZILLA_FIVE_HOME); if (mozFiveHome !is null) { mozillaPath = mozFiveHome; } else { browser.dispose (); DWT.error (DWT.ERROR_NO_HANDLES, null, " [Unknown Mozilla path (MOZILLA_FIVE_HOME not set)]"); //$NON-NLS-1$ } if (Device.DEBUG) Cerr ("Mozilla path: ") (mozillaPath).newline; //$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$ } } if (!Initialized) { nsILocalFile localFile; scope auto pathString = new nsEmbedString (mozillaPath.toString16()); nsresult rc = XPCOM.NS_NewLocalFile (cast(nsAString*)pathString, 1, &localFile); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (localFile is null) { browser.dispose (); error (XPCOM.NS_ERROR_NULL_POINTER); } LocationProvider = new AppFileLocProvider (mozillaPath); LocationProvider.AddRef (); nsIDirectoryServiceProvider directoryServiceProvider; rc = LocationProvider.QueryInterface( &nsIDirectoryServiceProvider.IID, cast(void**)&directoryServiceProvider); if (rc !is XPCOM.NS_OK) { browser.dispose(); error(rc); } rc = XPCOM.NS_InitXPCOM2 (null, cast(nsIFile)localFile, directoryServiceProvider); localFile.Release (); LocationProvider.Release(); if (rc !is XPCOM.NS_OK) { browser.dispose (); DWT.error (DWT.ERROR_NO_HANDLES, null, Format(" [MOZILLA_FIVE_HOME may not point at an embeddable GRE] [NS_InitEmbedding {0} error {1} ] ", mozillaPath, 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); } } nsIComponentManager componentManager; int rc = XPCOM.NS_GetComponentManager (&componentManager); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (componentManager is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } 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, null, &nsIAppShell.IID, cast(void**)&AppShell); if (rc !is XPCOM.NS_ERROR_NO_INTERFACE) { if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (AppShell is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } rc = AppShell.Create (null, null); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } rc = AppShell.Spinup (); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } } } WindowCreator = new WindowCreator2; WindowCreator.AddRef (); nsIServiceManager serviceManager; rc = XPCOM.NS_GetServiceManager (&serviceManager); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (serviceManager is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } nsIWindowWatcher windowWatcher; rc = serviceManager.GetServiceByContractID (XPCOM.NS_WINDOWWATCHER_CONTRACTID.ptr, &nsIWindowWatcher.IID, cast(void**)&windowWatcher); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (windowWatcher is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } rc = windowWatcher.SetWindowCreator (cast(nsIWindowCreator)WindowCreator); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } windowWatcher.Release (); if (LocationProvider !is null) { nsIDirectoryService directoryService; rc = serviceManager.GetServiceByContractID (XPCOM.NS_DIRECTORYSERVICE_CONTRACTID.ptr, &nsIDirectoryService.IID, cast(void**)&directoryService); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (directoryService is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } nsIProperties properties; rc = directoryService.QueryInterface (&nsIProperties.IID, cast(void**)&properties); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (properties is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } directoryService.Release (); nsIFile profileDir; rc = properties.Get (XPCOM.NS_APP_APPLICATION_REGISTRY_DIR.ptr, &nsIFile.IID, cast(void**)&profileDir); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (profileDir is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } properties.Release (); scope auto path = new nsEmbedCString; rc = profileDir.GetNativePath (cast(nsACString*)path); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } String profilePath = path.toString() ~ PROFILE_DIR; LocationProvider.setProfilePath (profilePath); LocationProvider.isXULRunner = IsXULRunner; profileDir.Release (); /* notify observers of a new profile directory being used */ nsIObserverService observerService; rc = serviceManager.GetServiceByContractID (XPCOM.NS_OBSERVER_CONTRACTID.ptr, &nsIObserverService.IID, cast(void**)&observerService); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (observerService is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } wchar* chars = STARTUP.toString16().toString16z(); rc = observerService.NotifyObservers (null, PROFILE_DO_CHANGE.ptr, chars); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } rc = observerService.NotifyObservers (null, PROFILE_AFTER_CHANGE.ptr, chars); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } 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. */ nsIPrefService prefService; rc = serviceManager.GetServiceByContractID (XPCOM.NS_PREFSERVICE_CONTRACTID.ptr, &nsIPrefService.IID, cast(void**)&prefService); serviceManager.Release (); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (serviceManager is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } char[1] buffer = new char[1]; nsIPrefBranch prefBranch; rc = prefService.GetBranch (buffer.ptr, &prefBranch); /* empty buffer denotes root preference level */ prefService.Release (); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (prefBranch is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } /* get Mozilla's current locale preference value */ String prefLocales = null; nsIPrefLocalizedString localizedString = null; //buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_LANGUAGES, true); rc = prefBranch.GetComplexValue (PREFERENCE_LANGUAGES.ptr, &nsIPrefLocalizedString.IID, cast(void**)&localizedString); /* * 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 (localizedString is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } PRUnichar* tmpChars; rc = localizedString.ToString (&tmpChars); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (tmpChars is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } int span = XPCOM.strlen_PRUnichar (tmpChars); prefLocales = Utf.toString(tmpChars[0 .. span]) ~ TOKENIZER_LOCALE; } /* * construct the new locale preference value by prepending the * user's current locale and language to the original value */ String language = Culture.current.twoLetterLanguageName (); String country = Region.current.twoLetterRegionName (); String stringBuffer = language.dup; stringBuffer ~= SEPARATOR_LOCALE; stringBuffer ~= country.toLowerCase (); stringBuffer ~= TOKENIZER_LOCALE; stringBuffer ~= language; stringBuffer ~= TOKENIZER_LOCALE; String newLocales = stringBuffer.dup; 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 ~= token; } } } while (end !is -1); newLocales[] = stringBuffer[]; if (!newLocales.equals (prefLocales)) { /* write the new locale value */ newLocales = newLocales.substring (0, newLocales.length () - TOKENIZER_LOCALE.length ()); /* remove trailing tokenizer */ if (localizedString is null) { rc = componentManager.CreateInstanceByContractID (XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID.ptr, null, &nsIPrefLocalizedString.IID, cast(void**)&localizedString); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (localizedString is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } } localizedString.SetDataWithLength (newLocales.length, newLocales.toString16().toString16z()); rc = prefBranch.SetComplexValue (PREFERENCE_LANGUAGES.ptr, &nsIPrefLocalizedString.IID, cast(nsISupports)localizedString); } if (localizedString !is null) { localizedString.Release (); localizedString = null; } /* get Mozilla's current charset preference value */ String prefCharset = null; rc = prefBranch.GetComplexValue (PREFERENCE_CHARSET.ptr, &nsIPrefLocalizedString.IID, cast(void**)&localizedString); /* * 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 (localizedString is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } PRUnichar* tmpChar; rc = localizedString.ToString (&tmpChar); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (tmpChar is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } int span = XPCOM.strlen_PRUnichar (tmpChar); prefCharset = Utf.toString(tmpChar[0 .. span]); } String newCharset = System.getProperty ("file.encoding"); // $NON-NLS-1$ if (!newCharset.equals (prefCharset)) { /* write the new charset value */ if (localizedString is null) { rc = componentManager.CreateInstanceByContractID (XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID.ptr, null, &nsIPrefLocalizedString.IID, cast(void**)&localizedString); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (localizedString is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } } localizedString.SetDataWithLength (newCharset.length, newCharset.toString16().toString16z()); rc = prefBranch.SetComplexValue (PREFERENCE_CHARSET.ptr, &nsIPrefLocalizedString.IID, cast(nsISupports)localizedString); } 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. */ // NOTE: in dwt, these properties don't exist so both keys will return null // (which appears to be ok in this situaion) 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) { rc = componentManager.CreateInstanceByContractID (XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID.ptr, null, &nsIPrefLocalizedString.IID, cast(void**)&localizedString); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (localizedString is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); rc = localizedString.SetDataWithLength (proxyHost.length, proxyHost.toString16().toString16z()); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = prefBranch.SetComplexValue (PREFERENCE_PROXYHOST_FTP.ptr, &nsIPrefLocalizedString.IID, cast(nsISupports)localizedString); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = prefBranch.SetComplexValue (PREFERENCE_PROXYHOST_HTTP.ptr, &nsIPrefLocalizedString.IID, cast(nsISupports)localizedString); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = prefBranch.SetComplexValue (PREFERENCE_PROXYHOST_SSL.ptr, &nsIPrefLocalizedString.IID, cast(nsISupports)localizedString); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); localizedString.Release (); } if (port !is -1) { rc = prefBranch.SetIntPref (PREFERENCE_PROXYPORT_FTP.ptr, port); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = prefBranch.SetIntPref (PREFERENCE_PROXYPORT_HTTP.ptr, port); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = prefBranch.SetIntPref (PREFERENCE_PROXYPORT_SSL.ptr, port); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); } if (proxyHost !is null || port !is -1) { rc = prefBranch.SetIntPref (PREFERENCE_PROXYTYPE.ptr, 1); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); } /* * 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. */ rc = prefBranch.SetBoolPref (PREFERENCE_DISABLEOPENDURINGLOAD.ptr, 0); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } /* Ensure that the status text can be set through means like javascript */ rc = prefBranch.SetBoolPref (PREFERENCE_DISABLEWINDOWSTATUSCHANGE.ptr, 0); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } prefBranch.Release (); PromptService2Factory factory = new PromptService2Factory (); factory.AddRef (); nsIComponentRegistrar componentRegistrar; rc = componentManager.QueryInterface (&nsIComponentRegistrar.IID, cast(void**)&componentRegistrar); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (componentRegistrar is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } String aClassName = "Prompt Service"; rc = componentRegistrar.RegisterFactory (&XPCOM.NS_PROMPTSERVICE_CID, aClassName.ptr, XPCOM.NS_PROMPTSERVICE_CONTRACTID.ptr, cast(nsIFactory)factory); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } factory.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 (); aClassName = "Download"; rc = componentRegistrar.RegisterFactory (&XPCOM.NS_DOWNLOAD_CID, aClassName.ptr, XPCOM.NS_DOWNLOAD_CONTRACTID.ptr, cast(nsIFactory)downloadFactory); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } downloadFactory.Release (); FilePickerFactory pickerFactory = IsXULRunner ? new FilePickerFactory_1_8 () : new FilePickerFactory (); pickerFactory.AddRef (); aClassName = "FilePicker"; rc = componentRegistrar.RegisterFactory (&XPCOM.NS_FILEPICKER_CID, aClassName.ptr, XPCOM.NS_FILEPICKER_CONTRACTID.ptr, cast(nsIFactory)pickerFactory); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } pickerFactory.Release (); componentRegistrar.Release (); componentManager.Release (); Initialized = true; } if (display.getData (DISPOSE_LISTENER_HOOKED) is null) { display.setData (DISPOSE_LISTENER_HOOKED, stringcast(DISPOSE_LISTENER_HOOKED)); display.addListener (DWT.Dispose, dgListener( &handleDisposeEvent, display ) ); } BrowserCount++; nsIComponentManager componentManager; int rc = XPCOM.NS_GetComponentManager (&componentManager); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (componentManager is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } nsID NS_IWEBBROWSER_CID = { 0xF1EAC761, 0x87E9, 0x11d3, [0xAF, 0x80, 0x00, 0xA0, 0x24, 0xFF, 0xC0, 0x8C] }; //$NON-NLS-1$ rc = componentManager.CreateInstance (&NS_IWEBBROWSER_CID, null, &nsIWebBrowser.IID, cast(void**)&webBrowser); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (webBrowser is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); } this.AddRef (); rc = webBrowser.SetContainerWindow ( cast(nsIWebBrowserChrome)this ); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } nsIBaseWindow baseWindow; rc = webBrowser.QueryInterface (&nsIBaseWindow.IID, cast(void**)&baseWindow); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (baseWindow is null) { browser.dispose (); error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); } Rectangle rect = browser.getClientArea (); if (rect.isEmpty ()) { rect.width = 1; rect.height = 1; } embedHandle = mozDelegate.getHandle (); rc = baseWindow.InitWindow (cast(void*)embedHandle, null, 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; nsIComponentRegistrar componentRegistrar; rc = componentManager.QueryInterface (&nsIComponentRegistrar.IID, cast(void**)&componentRegistrar); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__,__LINE__); } if (componentRegistrar is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE,__FILE__,__LINE__); } HelperAppLauncherDialogFactory dialogFactory = new HelperAppLauncherDialogFactory (); dialogFactory.AddRef (); String aClassName = "Helper App Launcher Dialog"; //$NON-NLS-1$ rc = componentRegistrar.RegisterFactory (&XPCOM.NS_HELPERAPPLAUNCHERDIALOG_CID, aClassName.ptr, XPCOM.NS_HELPERAPPLAUNCHERDIALOG_CONTRACTID.ptr, cast(nsIFactory)dialogFactory); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc,__FILE__,__LINE__); } dialogFactory.Release (); /* * Check for the availability of the pre-1.8 implementation of nsIDocShell * to determine if the GRE's version is < 1.8. */ nsIInterfaceRequestor interfaceRequestor; rc = webBrowser.QueryInterface (&nsIInterfaceRequestor.IID, cast(void**)&interfaceRequestor); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (XPCOM.NS_ERROR_FAILURE); } if (interfaceRequestor is null) { browser.dispose (); error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); } nsIDocShell docShell; rc = interfaceRequestor.GetInterface (&nsIDocShell.IID, cast(void**)&docShell); if (rc is XPCOM.NS_OK && docShell !is null) { IsPre_1_8 = true; docShell.Release (); } /* * 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) { nsIDocShell_1_8 docShell_1_8; rc = interfaceRequestor.GetInterface (&nsIDocShell_1_8.IID, cast(void**)&docShell_1_8); if (rc is XPCOM.NS_OK && docShell_1_8 !is null) { /* 1.8 */ docShell_1_8.Release (); DownloadFactory_1_8 downloadFactory_1_8 = new DownloadFactory_1_8 (); downloadFactory_1_8.AddRef (); aClassName = "Transfer"; //$NON-NLS-1$ rc = componentRegistrar.RegisterFactory (&XPCOM.NS_DOWNLOAD_CID, aClassName.ptr, XPCOM.NS_TRANSFER_CONTRACTID.ptr, cast(nsIFactory)downloadFactory_1_8); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } downloadFactory_1_8.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; nsIWebNavigation webNavigation; rc = webBrowser.QueryInterface (&nsIWebNavigation.IID, cast(void**)&webNavigation); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } if (webNavigation is null) { browser.dispose (); error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); } rc = webNavigation.LoadURI (ABOUT_BLANK.toString16().toString16z(), nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null); webNavigation.Release (); dialogFactory.isPre_1_9 = false; } } interfaceRequestor.Release (); componentRegistrar.Release (); } componentManager.Release (); rc = webBrowser.AddWebBrowserListener (cast(nsIWeakReference)this, &nsIWebProgressListener.IID); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } // TODO: Find appropriate place to "Release" uriContentListener -JJR nsIURIContentListener uriContentListener; this.QueryInterface(&nsIURIContentListener.IID, cast(void**)&uriContentListener); if (rc !is XPCOM.NS_OK) { browser.dispose(); error(rc); } if (uriContentListener is null) { browser.dispose(); error(XPCOM.NS_ERROR_NO_INTERFACE); } rc = webBrowser.SetParentURIContentListener (uriContentListener); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc, __FILE__, __LINE__); } mozDelegate.init (); int[] folderEvents = [ 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], dgListener( &handleFolderEvent )); } } /******************************************************************************* Event Handlers for the Mozilla Class: These represent replacements for SWT's anonymous classes as used within the Mozilla class. Since D 1.0x anonymous classes do not work equivalently to Java's, we replace the anonymous classes with D delegates and templates (ie dgListener which wrap the delegate in a class). This circumvents some nasty, evasive bugs. extern(D) becomes a necessary override on these methods because this class implements a XPCOM/COM interface resulting in all class methods defaulting to extern(System). -JJR ******************************************************************************/ extern(D) private void handleDisposeEvent (Event event, Display display) { if (BrowserCount > 0) return; /* another display is still active */ nsIServiceManager serviceManager; int rc = XPCOM.NS_GetServiceManager (&serviceManager); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (serviceManager is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); nsIObserverService observerService; rc = serviceManager.GetServiceByContractID (XPCOM.NS_OBSERVER_CONTRACTID.ptr, &nsIObserverService.IID, cast(void**)&observerService); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (observerService is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); rc = observerService.NotifyObservers (null, PROFILE_BEFORE_CHANGE.ptr, SHUTDOWN_PERSIST.toString16().toString16z()); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); observerService.Release (); if (LocationProvider !is null) { String prefsLocation = LocationProvider.profilePath ~ AppFileLocProvider.PREFERENCES_FILE; scope auto pathString = new nsEmbedString (prefsLocation.toString16()); nsILocalFile localFile; rc = XPCOM.NS_NewLocalFile (cast(nsAString*)pathString, 1, &localFile); if (rc !is XPCOM.NS_OK) Mozilla.error (rc, __FILE__, __LINE__); if (localFile is null) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER); nsIFile prefFile; rc = localFile.QueryInterface (&nsIFile.IID, cast(void**)&prefFile); if (rc !is XPCOM.NS_OK) Mozilla.error (rc, __FILE__, __LINE__); if (prefFile is null) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); localFile.Release (); nsIPrefService prefService; rc = serviceManager.GetServiceByContractID (XPCOM.NS_PREFSERVICE_CONTRACTID.ptr, &nsIPrefService.IID, cast(void**)&prefService); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (prefService is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); rc = prefService.SavePrefFile(prefFile); prefService.Release (); prefFile.Release (); } serviceManager.Release (); if (XPCOMWasGlued) { /* * XULRunner 1.9 can crash on Windows if XPCOMGlueShutdown is invoked here, * presumably because one or more of its unloaded symbols are referenced when * this callback returns. The workaround is to delay invoking XPCOMGlueShutdown * so that its symbols are still available once this callback returns. */ display.asyncExec (new class() Runnable { public void run () { XPCOMInit.XPCOMGlueShutdown (); } }); XPCOMWasGlued = XPCOMInitWasGlued = false; } Initialized = false; } extern(D) private void handleFolderEvent (Event event) { Control control = cast(Control)browser; 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 (control 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 class () Runnable { public void run() { if (browser.isDisposed ()) return; onResize (); } }); break; } default: break; } } /******************************************************************************* *******************************************************************************/ extern(D) public bool back () { if (awaitingNavigate) return false; //int /*long*/[] result = new int /*long*/[1]; nsIWebNavigation webNavigation; int rc = webBrowser.QueryInterface (&nsIWebNavigation.IID, cast(void**)&webNavigation); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (webNavigation is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); rc = webNavigation.GoBack (); webNavigation.Release (); return rc is XPCOM.NS_OK; } extern(D) 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]; nsIWebNavigation webNavigation; int rc = webBrowser.QueryInterface (&nsIWebNavigation.IID, cast(void**)&webNavigation); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (webNavigation is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //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 (url.toString16().toString16z(), nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null); webNavigation.Release (); return rc is XPCOM.NS_OK; } extern(D) static Browser findBrowser (void* handle) { version (linux) return MozillaDelegate.findBrowser (cast(GtkWidget*)handle); version (darwin) return MozillaDelegate.findBrowser (cast(objc.id)handle); } extern(D) public bool forward () { if (awaitingNavigate) return false; //int /*long*/[] result = new int /*long*/[1]; nsIWebNavigation webNavigation; int rc = webBrowser.QueryInterface (&nsIWebNavigation.IID, cast(void**)&webNavigation); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (webNavigation is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); rc = webNavigation.GoForward (); webNavigation.Release (); return rc is XPCOM.NS_OK; } extern(D) public String getText () { if (awaitingNavigate) return ""; //$NON-NLS-1$ //int /*long*/[] result = new int /*long*/[1]; nsIDOMWindow window; int rc = webBrowser.GetContentDOMWindow (&window); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (window is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //nsIDOMWindow window = new nsIDOMWindow (result[0]); //result[0] = 0; nsIDOMDocument document; rc = window.GetDocument (&document); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (document is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); window.Release (); //int /*long*/ document = result[0]; //result[0] = 0; nsIComponentManager componentManager; rc = XPCOM.NS_GetComponentManager (&componentManager); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (componentManager is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //nsIComponentManager componentManager = new nsIComponentManager (result[0]); //result[0] = 0; //byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DOMSERIALIZER_CONTRACTID, true); String chars = null; nsIDOMSerializer_1_7 serializer_1_7; rc = componentManager.CreateInstanceByContractID (XPCOM.NS_DOMSERIALIZER_CONTRACTID.ptr, null, &nsIDOMSerializer_1_7.IID, cast(void**)&serializer_1_7); if (rc is XPCOM.NS_OK) { /* mozilla >= 1.7 */ if (serializer_1_7 is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //nsIDOMSerializer_1_7 serializer = new nsIDOMSerializer_1_7 (result[0]); //result[0] = 0; scope auto string = new nsEmbedString; rc = serializer_1_7.SerializeToString (cast(nsIDOMNode)document, cast(nsAString*) string); serializer_1_7.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); chars = string.toString(); } else { /* mozilla < 1.7 */ nsIDOMSerializer serializer; rc = componentManager.CreateInstanceByContractID (XPCOM.NS_DOMSERIALIZER_CONTRACTID.ptr, null, &nsIDOMSerializer.IID, cast(void**)&serializer); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (serializer is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); // TODO: Lookup SerializeToString contract. Find out if the string must provide it's own memory to the method. -JJR PRUnichar* string; //nsIDOMSerializer serializer = new nsIDOMSerializer (result[0]); //result[0] = 0; rc = serializer.SerializeToString (cast(nsIDOMNode)document, &string ); serializer.Release (); //int length = XPCOM.strlen_PRUnichar (string); //chars = new char[length]; //XPCOM.memmove (chars, result[0], length * 2); chars = Utf.toString(fromString16z(string)); } componentManager.Release (); document.Release (); return chars.dup; } extern(D) public String getUrl () { if (awaitingNavigate) return ""; //$NON-NLS-1$ //int /*long*/[] result = new int /*long*/[1]; nsIWebNavigation webNavigation; int rc = webBrowser.QueryInterface (&nsIWebNavigation.IID, cast(void**)&webNavigation); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (webNavigation is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); nsIURI aCurrentURI; rc = webNavigation.GetCurrentURI (&aCurrentURI); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); webNavigation.Release (); String location = null; if (aCurrentURI !is null) { //nsIURI uri = new nsIURI (aCurrentURI[0]); scope auto aSpec = new nsEmbedCString; rc = aCurrentURI.GetSpec (cast(nsACString*)aSpec); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); //int length = XPCOM.nsEmbedCString_Length (aSpec); //int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec); location = aSpec.toString; //XPCOM.memmove (dest, buffer, length); //XPCOM.nsEmbedCString_delete (aSpec); aCurrentURI.Release (); } if (location is null) return ""; //$NON-NLS-1$ /* * 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; } extern(D) public Object getWebBrowser () { if ((browser.getStyle () & DWT.MOZILLA) is 0) return null; if (webBrowserObject !is null) return webBrowserObject; implMissing(__FILE__,__LINE__); /+ try { // TODO: this references the JavaXPCOM browser... not sure what needs to be done here, // but I don't think this method is necessary. 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 = 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; } extern(D) public bool isBackEnabled () { if (awaitingNavigate) return false; //int /*long*/[] result = new int /*long*/[1]; nsIWebNavigation webNavigation; int rc = webBrowser.QueryInterface (&nsIWebNavigation.IID, cast(void**)&webNavigation); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (webNavigation is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); PRBool aCanGoBack; /* PRBool */ rc = webNavigation.GetCanGoBack (&aCanGoBack); webNavigation.Release (); return aCanGoBack !is 0; } extern(D) public bool isForwardEnabled () { if (awaitingNavigate) return false; //int /*long*/[] result = new int /*long*/[1]; nsIWebNavigation webNavigation; int rc = webBrowser.QueryInterface (&nsIWebNavigation.IID, cast(void**)&webNavigation); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (webNavigation is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); PRBool aCanGoForward; /* PRBool */ rc = webNavigation.GetCanGoForward (&aCanGoForward); webNavigation.Release (); return aCanGoForward !is 0; } extern(D) static void error (int code ) { error ( code, "NOT GIVEN", 0 ); } extern(D) static String error (int code, char[] file, int line) { Stdout ("File: ")(file)(" Line: ")(line).newline; throw new DWTError ("XPCOM error " ~ Integer.toString(code)); //$NON-NLS-1$ } extern(D) void onDispose (Display display) { int rc = webBrowser.RemoveWebBrowserListener (cast(nsIWeakReference)this, &nsIWebProgressListener.IID); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = webBrowser.SetParentURIContentListener (null); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); unhookDOMListeners (); if (listener !is null) { int[] folderEvents = [ 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]; nsIBaseWindow baseWindow; rc = webBrowser.QueryInterface (&nsIBaseWindow.IID, cast(void**)&baseWindow); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (baseWindow is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]); rc = baseWindow.Destroy (); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); 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 (); foreach (win ; unhookedDOMWindows) { //LONG ptrObject = (LONG)elements.nextElement (); win.Release (); } unhookedDOMWindows = null; mozDelegate.onDispose (embedHandle); mozDelegate = null; embedHandle = null; BrowserCount--; } extern(D) void Activate () { //int /*long*/[] result = new int /*long*/[1]; nsIWebBrowserFocus webBrowserFocus; int rc = webBrowser.QueryInterface (&nsIWebBrowserFocus.IID, cast(void**)&webBrowserFocus); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (webBrowserFocus is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIWebBrowserFocus webBrowserFocus = new nsIWebBrowserFocus (result[0]); rc = webBrowserFocus.Activate (); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); webBrowserFocus.Release (); } extern(D) void Deactivate () { //int /*long*/[] result = new int /*long*/[1]; nsIWebBrowserFocus webBrowserFocus; int rc = webBrowser.QueryInterface (&nsIWebBrowserFocus.IID, cast(void**)&webBrowserFocus); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (webBrowserFocus is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIWebBrowserFocus webBrowserFocus = new nsIWebBrowserFocus (result[0]); rc = webBrowserFocus.Deactivate (); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); webBrowserFocus.Release (); } extern(D) 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]; nsIBaseWindow baseWindow; int rc = webBrowser.QueryInterface (&nsIBaseWindow.IID, cast(void**)&baseWindow); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (baseWindow is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); 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, __FILE__, __LINE__); baseWindow.Release (); } extern(D) public void refresh () { if (awaitingNavigate) return; //int /*long*/[] result = new int /*long*/[1]; nsIWebNavigation webNavigation; int rc = webBrowser.QueryInterface (&nsIWebNavigation.IID, cast(void**)&webNavigation); if (rc !is XPCOM.NS_OK) error(rc); if (webNavigation is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //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, __FILE__, __LINE__); } extern(D) 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$ scope auto aContentType = new nsEmbedCString ("text/html"); //byte[] contentCharsetBuffer = MozillaDelegate.wcsToMbcs (null, "UTF-8", true); //$NON-NLS-1$ scope auto aContentCharset = new nsEmbedCString ("UTF-8"); //int /*long*/[] result = new int /*long*/[1]; nsIServiceManager serviceManager; int rc = XPCOM.NS_GetServiceManager (&serviceManager); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (serviceManager is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //nsIServiceManager serviceManager = new nsIServiceManager (result[0]); //result[0] = 0; nsIIOService ioService; rc = serviceManager.GetService (&XPCOM.NS_IOSERVICE_CID, &nsIIOService.IID, cast(void**)&ioService); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (ioService is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); 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); scope auto aSpec = new nsEmbedCString(URI_FROMMEMORY); nsIURI uri; rc = ioService.NewURI (cast(nsACString*)aSpec, null, null, &uri); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (uri is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //XPCOM.nsEmbedCString_delete (aSpec); ioService.Release (); //nsIURI uri = new nsIURI (result[0]); //result[0] = 0; nsIInterfaceRequestor interfaceRequestor; rc = webBrowser.QueryInterface (&nsIInterfaceRequestor.IID, cast(void**)&interfaceRequestor); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (interfaceRequestor is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //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. */ // Using fully qualified name for disambiguation with dwthelper InputStream -JJR auto inputStream = new dwt.browser.InputStream.InputStream (cast(byte[])html); inputStream.AddRef (); nsIDocShell_1_9 docShell_1_9; rc = interfaceRequestor.GetInterface (&nsIDocShell_1_9.IID, cast(void**)&docShell_1_9); if (rc is XPCOM.NS_OK) { if (docShell_1_9 is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIDocShell_1_9 docShell = new nsIDocShell_1_9 (result[0]); rc = docShell_1_9.LoadStream (inputStream, uri, cast(nsACString*)aContentType, cast(nsACString*)aContentCharset, null); docShell_1_9.Release (); } else { //result[0] = 0; nsIDocShell_1_8 docShell_1_8; rc = interfaceRequestor.GetInterface (&nsIDocShell_1_8.IID, cast(void**)&docShell_1_8); if (rc is XPCOM.NS_OK) { if (docShell_1_8 is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIDocShell_1_8 docShell = new nsIDocShell_1_8 (result[0]); rc = docShell_1_8.LoadStream (inputStream, uri, cast(nsACString*)aContentType, cast(nsACString*)aContentCharset, null); docShell_1_8.Release (); } else { //result[0] = 0; nsIDocShell docShell; rc = interfaceRequestor.GetInterface (&nsIDocShell.IID, cast(void**)&docShell); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (docShell is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIDocShell docShell = new nsIDocShell (result[0]); rc = docShell.LoadStream (inputStream, uri, cast(nsACString*) aContentType, cast(nsACString*)aContentCharset, null); docShell.Release (); } } if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); //result[0] = 0; inputStream.Release (); interfaceRequestor.Release (); uri.Release (); //XPCOM.nsEmbedCString_delete (aContentCharset); //XPCOM.nsEmbedCString_delete (aContentType); return true; } extern(D) public bool setUrl (String url) { awaitingNavigate = false; nsIWebNavigation webNavigation; int rc = webBrowser.QueryInterface (&nsIWebNavigation.IID, cast(void**)&webNavigation); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (webNavigation is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); rc = webNavigation.LoadURI (url.toString16().toString16z(), nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null); webNavigation.Release (); return rc is XPCOM.NS_OK; } extern(D) public void stop () { if (awaitingNavigate) return; nsIWebNavigation webNavigation; //int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (&nsIWebNavigation.IID, cast(void**)&webNavigation); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (webNavigation is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); rc = webNavigation.Stop (nsIWebNavigation.STOP_ALL); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); webNavigation.Release (); } extern(D) void hookDOMListeners (nsIDOMEventTarget target, bool isTop) { scope auto string = new nsEmbedString (XPCOM.DOMEVENT_FOCUS.toString16()); target.AddEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_UNLOAD.toString16()); target.AddEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDOWN.toString16()); target.AddEventListener (cast(nsAString*)string,cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEUP.toString16()); target.AddEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEMOVE.toString16()); target.AddEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEWHEEL.toString16()); target.AddEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDRAG.toString16()); target.AddEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 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.toString16()); target.AddEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOUT.toString16()); target.AddEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); } string = new nsEmbedString (XPCOM.DOMEVENT_KEYDOWN.toString16()); target.AddEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_KEYPRESS.toString16()); target.AddEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_KEYUP.toString16()); target.AddEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); } extern(D) void unhookDOMListeners () { //int /*long*/[] result = new int /*long*/[1]; nsIDOMWindow window; int rc = webBrowser.GetContentDOMWindow (&window); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (window is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIDOMWindow window = new nsIDOMWindow (result[0]); //result[0] = 0; nsIDOMEventTarget target; rc = window.QueryInterface (&nsIDOMEventTarget.IID, cast(void**)&target); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (target is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]); //result[0] = 0; unhookDOMListeners (target); target.Release (); /* Listeners must be unhooked in pages contained in frames */ nsIDOMWindowCollection frames; rc = window.GetFrames (&frames); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (frames is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIDOMWindowCollection frames = new nsIDOMWindowCollection (result[0]); //result[0] = 0; PRUint32 count; rc = frames.GetLength (&count); /* PRUint32 */ if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); //int count = frameCount[0]; if (count > 0) { nsIDOMWindow frame; for (int i = 0; i < count; i++) { rc = frames.Item (i, &frame); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (frame is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIDOMWindow frame = new nsIDOMWindow (result[0]); //result[0] = 0; rc = frame.QueryInterface (&nsIDOMEventTarget.IID, cast(void**)&target); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (target is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //target = new nsIDOMEventTarget (result[0]); //result[0] = 0; unhookDOMListeners (target); target.Release (); frame.Release (); } } frames.Release (); window.Release (); } extern(D) void unhookDOMListeners (nsIDOMEventTarget target) { scope auto string = new nsEmbedString (XPCOM.DOMEVENT_FOCUS.toString16()); target.RemoveEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_UNLOAD.toString16()); target.RemoveEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDOWN.toString16()); target.RemoveEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEUP.toString16()); target.RemoveEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEMOVE.toString16()); target.RemoveEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEWHEEL.toString16()); target.RemoveEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDRAG.toString16()); target.RemoveEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOVER.toString16()); target.RemoveEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOUT.toString16()); target.RemoveEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_KEYDOWN.toString16()); target.RemoveEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_KEYPRESS.toString16()); target.RemoveEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_KEYUP.toString16()); target.RemoveEventListener (cast(nsAString*)string, cast(nsIDOMEventListener)this, 0); //string.dispose (); } /* nsISupports */ extern(System) nsresult QueryInterface (nsID* riid, void** ppvObject) { if (riid is null || ppvObject is null) return XPCOM.NS_ERROR_NO_INTERFACE; if (*riid == nsISupports.IID) { *ppvObject = cast(void*)cast(nsISupports)this; AddRef (); return XPCOM.NS_OK; } if (*riid == nsIWeakReference.IID) { *ppvObject = cast(void*)cast(nsIWeakReference)this; AddRef (); return XPCOM.NS_OK; } if (*riid == nsIWebProgressListener.IID) { *ppvObject = cast(void*)cast(nsIWebProgressListener)this; AddRef (); return XPCOM.NS_OK; } if (*riid == nsIWebBrowserChrome.IID) { *ppvObject = cast(void*)cast(nsIWebBrowserChrome)this; AddRef (); return XPCOM.NS_OK; } if (*riid == nsIWebBrowserChromeFocus.IID) { *ppvObject = cast(void*)cast(nsIWebBrowserChromeFocus)this; AddRef (); return XPCOM.NS_OK; } if (*riid == nsIEmbeddingSiteWindow.IID) { *ppvObject = cast(void*)cast(nsIEmbeddingSiteWindow)this; AddRef (); return XPCOM.NS_OK; } if (*riid == nsIInterfaceRequestor.IID) { *ppvObject = cast(void*)cast(nsIInterfaceRequestor)this; AddRef (); return XPCOM.NS_OK; } if (*riid == nsISupportsWeakReference.IID) { *ppvObject = cast(void*)cast(nsISupportsWeakReference)this; AddRef (); return XPCOM.NS_OK; } if (*riid == nsIContextMenuListener.IID) { *ppvObject = cast(void*)cast(nsIContextMenuListener)this; AddRef (); return XPCOM.NS_OK; } if (*riid == nsIURIContentListener.IID) { *ppvObject = cast(void*)cast(nsIURIContentListener)this; AddRef (); return XPCOM.NS_OK; } if (*riid == nsITooltipListener.IID) { *ppvObject = cast(void*)cast(nsITooltipListener)this; AddRef (); return XPCOM.NS_OK; } *ppvObject = null; return XPCOM.NS_ERROR_NO_INTERFACE; } extern(System) nsrefcnt AddRef () { refCount++; return refCount; } extern(System) nsrefcnt Release () { refCount--; if (refCount is 0) return 0; return refCount; } /* nsIWeakReference */ extern(System) nsresult QueryReferent (nsID* riid, void** ppvObject) { return QueryInterface (riid, ppvObject); } /* nsIInterfaceRequestor */ extern(System) nsresult GetInterface ( nsID* riid, void** ppvObject) { if (riid is null || ppvObject is null) return XPCOM.NS_ERROR_NO_INTERFACE; //nsID guid = new nsID (); //XPCOM.memmove (guid, riid, nsID.sizeof); if (*riid == nsIDOMWindow.IID) { nsIDOMWindow aContentDOMWindow; //int /*long*/[] aContentDOMWindow = new int /*long*/[1]; int rc = webBrowser.GetContentDOMWindow (&aContentDOMWindow); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (aContentDOMWindow is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); *ppvObject = cast(void*)aContentDOMWindow; //XPCOM.memmove (ppvObject, aContentDOMWindow, C.PTR_SIZEOF); return rc; } return QueryInterface (riid, ppvObject); } extern(System) nsresult GetWeakReference (nsIWeakReference* ppvObject) { *ppvObject = cast(nsIWeakReference)this; //XPCOM.memmove (ppvObject, new int /*long*/[] {weakReference.getAddress ()}, C.PTR_SIZEOF); AddRef (); return XPCOM.NS_OK; } /* nsIWebProgressListener */ extern(System) nsresult OnStateChange (nsIWebProgress aWebProgress, nsIRequest aRequest, PRUint32 aStateFlags, nsresult aStatus) { if ((aStateFlags & nsIWebProgressListener.STATE_IS_DOCUMENT) is 0) return XPCOM.NS_OK; if ((aStateFlags & nsIWebProgressListener.STATE_START) !is 0) { if (request is null) 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]; nsIDOMWindow window; //nsIWebProgress progress = new nsIWebProgress (aWebProgress); int rc = aWebProgress.GetDOMWindow (&window); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (window is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); unhookedDOMWindows ~= window; } } else if ((aStateFlags & nsIWebProgressListener.STATE_REDIRECTING) !is 0) { if (request is aRequest) request = null; } 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); nsIDOMWindow domWindow; int rc = aWebProgress.GetDOMWindow (&domWindow); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (domWindow is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //nsIDOMWindow domWindow = new nsIDOMWindow (result[0]); //LONG ptrObject = new LONG (result[0]); //result[0] = 0; int index = unhookedDOMWindows.arrayIndexOf (domWindow); if (index !is -1) { nsIDOMWindow contentWindow; rc = webBrowser.GetContentDOMWindow (&contentWindow); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (contentWindow is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); bool isTop = contentWindow is domWindow; contentWindow.Release (); //result[0] = 0; nsIDOMEventTarget target; rc = domWindow.QueryInterface (&nsIDOMEventTarget.IID, cast(void**)&target); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (target is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //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 = unhookedDOMWindows.arrayIndexRemove (index); domWindow.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 null) { request = null; 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); nsIDOMWindow domWindow; int rc = aWebProgress.GetDOMWindow (&domWindow); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (domWindow is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //nsIDOMWindow domWindow = new nsIDOMWindow (result[0]); //LONG ptrObject = new LONG (result[0]); //result[0] = 0; int index = unhookedDOMWindows.arrayIndexOf ( domWindow); if (index !is -1) { nsIDOMWindow contentWindow; rc = webBrowser.GetContentDOMWindow (&contentWindow); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (contentWindow is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); bool isTop = contentWindow is domWindow; contentWindow.Release (); //result[0] = 0; nsIDOMEventTarget target; rc = domWindow.QueryInterface (&nsIDOMEventTarget.IID, cast(void**)&target); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (target is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //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 = unhookedDOMWindows.arrayIndexRemove(index); domWindow.Release (); } domWindow.Release (); } return XPCOM.NS_OK; } extern(System) nsresult OnProgressChange (nsIWebProgress aWebProgress, nsIRequest aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) { if (awaitingNavigate || super.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 < super.progressListeners.length; i++) { super.progressListeners[i].changed (event); } return XPCOM.NS_OK; } extern(System) nsresult OnLocationChange (nsIWebProgress aWebProgress, nsIRequest aRequest, nsIURI 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 null && request !is aRequest) request = aRequest; if (awaitingNavigate || locationListeners.length is 0) return XPCOM.NS_OK; //nsIWebProgress webProgress = new nsIWebProgress (aWebProgress); nsIDOMWindow domWindow; //int /*long*/[] aDOMWindow = new int /*long*/[1]; int rc = aWebProgress.GetDOMWindow (&domWindow); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (domWindow is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIDOMWindow domWindow = new nsIDOMWindow (aDOMWindow[0]); //int /*long*/[] aTop = new int /*long*/[1]; nsIDOMWindow topWindow; rc = domWindow.GetTop (&topWindow); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (topWindow is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); domWindow.Release (); //nsIDOMWindow topWindow = new nsIDOMWindow (aTop[0]); topWindow.Release (); //nsIURI location = new nsIURI (aLocation); scope auto aSpec = new nsEmbedCString; aLocation.GetSpec (cast(nsACString*)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 = aSpec.toString; /* * 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 null && 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 = topWindow is domWindow; for (int i = 0; i < locationListeners.length; i++) { locationListeners[i].changed (event); } return XPCOM.NS_OK; } extern(System) nsresult OnStatusChange (nsIWebProgress aWebProgress, nsIRequest aRequest, nsresult aStatus, PRUnichar* 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 = Utf.toString(fromString16z(aMessage)); for (int i = 0; i < statusTextListeners.length; i++) { statusTextListeners[i].changed (event); } return XPCOM.NS_OK; } extern(System) nsresult OnSecurityChange (nsIWebProgress aWebProgress, nsIRequest aRequest, PRUint32 state) { return XPCOM.NS_OK; } /* nsIWebBrowserChrome */ extern(System) nsresult SetStatus (PRUint32 statusType, PRUnichar* 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 = Utf.toString(fromString16z(status)); for (int i = 0; i < statusTextListeners.length; i++) { statusTextListeners[i].changed (event); } return XPCOM.NS_OK; } extern(System) nsresult GetWebBrowser (nsIWebBrowser* aWebBrowser) { //int /*long*/[] ret = new int /*long*/[1]; if (webBrowser !is null) { webBrowser.AddRef (); *aWebBrowser = webBrowser; } //XPCOM.memmove (aWebBrowser, ret, C.PTR_SIZEOF); return XPCOM.NS_OK; } extern(System) nsresult SetWebBrowser (nsIWebBrowser aWebBrowser) { if (webBrowser !is null) webBrowser.Release (); webBrowser = aWebBrowser !is null ? cast(nsIWebBrowser)cast(void*)aWebBrowser : null; return XPCOM.NS_OK; } extern(System) nsresult GetChromeFlags (PRUint32* aChromeFlags) { //int[] ret = new int[1]; *aChromeFlags = chromeFlags; //XPCOM.memmove (aChromeFlags, ret, 4); /* PRUint32 */ return XPCOM.NS_OK; } extern(System) nsresult SetChromeFlags (PRUint32 aChromeFlags) { chromeFlags = aChromeFlags; return XPCOM.NS_OK; } extern(System) nsresult 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; } extern(System) nsresult SizeBrowserTo (PRInt32 aCX, PRInt32 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; } extern(System) nsresult ShowAsModal () { //int /*long*/[] result = new int /*long*/[1]; nsIServiceManager serviceManager; int rc = XPCOM.NS_GetServiceManager (&serviceManager); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (serviceManager is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //nsIServiceManager serviceManager = new nsIServiceManager (result[0]); //result[0] = 0; //byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_CONTEXTSTACK_CONTRACTID, true); nsIJSContextStack stack; rc = serviceManager.GetServiceByContractID (XPCOM.NS_CONTEXTSTACK_CONTRACTID.ptr, &nsIJSContextStack.IID, cast(void**)&stack); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (stack is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); serviceManager.Release (); //nsIJSContextStack stack = new nsIJSContextStack (result[0]); //result[0] = 0; rc = stack.Push (null); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); Shell shell = browser.getShell (); Display display = browser.getDisplay (); while (!shell.isDisposed ()) { if (!display.readAndDispatch ()) display.sleep (); } JSContext* result; rc = stack.Pop (&result); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); stack.Release (); return XPCOM.NS_OK; } extern(System) nsresult IsWindowModal (PRBool* retval) { *retval = (chromeFlags & nsIWebBrowserChrome.CHROME_MODAL) !is 0 ? 1 : 0; //XPCOM.memmove (retval, new int[] {result}, 4); /* PRBool */ return XPCOM.NS_OK; } extern(System) nsresult ExitModalEventLoop (nsresult aStatus) { return XPCOM.NS_OK; } /* nsIEmbeddingSiteWindow */ extern(System) nsresult SetDimensions (PRUint32 flags, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 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; } extern(System) nsresult GetDimensions (PRUint32 flags, PRInt32* x, PRInt32* y, PRInt32* cx, PRInt32* cy) { if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_POSITION) !is 0) { Point location = browser.getShell ().getLocation (); if (x !is null) *x = location.x; /* PRInt32 */ if (y !is null) *y = location.y; /* PRInt32 */ } if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_INNER) !is 0) { Point size = browser.getSize (); if (cx !is null) *cx = size.x; /* PRInt32 */ if (cy !is null) *cy = size.y; /* PRInt32 */ } if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_OUTER) !is 0) { Point size = browser.getShell().getSize (); if (cx !is null) *cx = size.x; /* PRInt32 */ if (cy !is null) *cy = size.y; /* PRInt32 */ } return XPCOM.NS_OK; } extern(System) nsresult SetFocus () { //int /*long*/[] result = new int /*long*/[1]; nsIBaseWindow baseWindow; int rc = webBrowser.QueryInterface (&nsIBaseWindow.IID, cast(void**)&baseWindow); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (baseWindow is null) error (XPCOM.NS_ERROR_NO_INTERFACE, __FILE__, __LINE__); //nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]); rc = baseWindow.SetFocus (); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); 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; } extern(System) nsresult GetVisibility (PRBool* aVisibility) { bool visible = browser.isVisible () && !browser.getShell ().getMinimized (); *aVisibility = visible ? 1 : 0; //XPCOM.memmove (aVisibility, new int[] {visible ? 1 : 0}, 4); /* PRBool */ return XPCOM.NS_OK; } extern(System) nsresult SetVisibility (PRBool 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; } extern(System) nsresult GetTitle (PRUnichar** aTitle) { return XPCOM.NS_OK; } extern(System) nsresult SetTitle (PRUnichar* 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 = Utf.toString(fromString16z(aTitle)); } else { event.title = getUrl (); } for (int i = 0; i < titleListeners.length; i++) { titleListeners[i].changed (event); } return XPCOM.NS_OK; } extern(System) nsresult GetSiteWindow (void** 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. */ *aSiteWindow = cast(void*) embedHandle; return XPCOM.NS_OK; } /* nsIWebBrowserChromeFocus */ extern(System) nsresult 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 class() Runnable { public void run () { if (browser.isDisposed ()) return; browser.traverse (DWT.TRAVERSE_TAB_NEXT); } }); return XPCOM.NS_OK; } extern(System) nsresult 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 class() Runnable { public void run () { if (browser.isDisposed ()) return; browser.traverse (DWT.TRAVERSE_TAB_PREVIOUS); } }); return XPCOM.NS_OK; } /* nsIContextMenuListener */ extern(System) nsresult OnShowContextMenu (PRUint32 aContextFlags, nsIDOMEvent aEvent, nsIDOMNode aNode) { if (awaitingNavigate) return XPCOM.NS_OK; //nsIDOMEvent domEvent = new nsIDOMEvent (aEvent); //int /*long*/[] result = new int /*long*/[1]; nsIDOMMouseEvent domMouseEvent; int rc = aEvent.QueryInterface (&nsIDOMMouseEvent.IID, cast(void**)&domMouseEvent); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (domMouseEvent is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //nsIDOMMouseEvent domMouseEvent = new nsIDOMMouseEvent (result[0]); PRInt32 aScreenX, aScreenY; rc = domMouseEvent.GetScreenX (&aScreenX); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domMouseEvent.GetScreenY (&aScreenY); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); domMouseEvent.Release (); auto event = new Event; event.x = aScreenX; event.y = aScreenY; browser.notifyListeners (DWT.MenuDetect, event); if (!event.doit) return XPCOM.NS_OK; Menu menu = browser.getMenu (); if (menu !is null && !menu.isDisposed ()) { if (aScreenX !is event.x || aScreenY !is event.y) { menu.setLocation (event.x, event.y); } menu.setVisible (true); } return XPCOM.NS_OK; } /* nsIURIContentListener */ extern(System) nsresult OnStartURIOpen (nsIURI aURI, PRBool* retval) { if (awaitingNavigate || locationListeners.length is 0) { *retval = 0; //XPCOM.memmove (retval, new int[] {0}, 4); /* PRBool */ return XPCOM.NS_OK; } //nsIURI location = new nsIURI (aURI); scope auto aSpec = new nsEmbedCString; aURI.GetSpec (cast(nsACString*)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 = aSpec.toString; bool doit = true; if (request is null) { /* * 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(); } } *retval = doit ? 0 : 1; //XPCOM.memmove (retval, new int[] {doit ? 0 : 1}, 4); /* PRBool */ return XPCOM.NS_OK; } extern(System) nsresult DoContent (char* aContentType, PRBool aIsContentPreferred, nsIRequest aRequest, nsIStreamListener* aContentHandler, PRBool* retval) { return XPCOM.NS_ERROR_NOT_IMPLEMENTED; } extern(System) nsresult IsPreferred (char* aContentType, char** aDesiredContentType, PRBool* retval) { bool preferred = false; auto size = strlen (aContentType); if (size > 0) { //byte[] typeBytes = new byte[size + 1]; //XPCOM.memmove (typeBytes, aContentType, size); String contentType = fromStringz(aContentType); /* 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]; nsIServiceManager serviceManager; int rc = XPCOM.NS_GetServiceManager (&serviceManager); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (serviceManager is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //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); nsIWebNavigationInfo info; rc = serviceManager.GetServiceByContractID (XPCOM.NS_WEBNAVIGATIONINFO_CONTRACTID.ptr, &nsIWebNavigationInfo.IID, cast(void**)&info); if (rc is XPCOM.NS_OK) { //byte[] bytes = MozillaDelegate.wcsToMbcs (null, contentType, true); scope auto typePtr = new nsEmbedCString(contentType); //nsIWebNavigationInfo info = new nsIWebNavigationInfo (result[0]); //result[0] = 0; PRUint32 isSupportedResult; /* PRUint32 */ rc = info.IsTypeSupported (cast(nsACString*)typePtr, null, &isSupportedResult); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); info.Release (); //XPCOM.nsEmbedCString_delete (typePtr); preferred = isSupportedResult !is 0; } else { /* nsIWebNavigationInfo is not available, so do the type lookup */ //result[0] = 0; nsICategoryManager categoryManager; rc = serviceManager.GetService (&XPCOM.NS_CATEGORYMANAGER_CID, &nsICategoryManager.IID, cast(void**)&categoryManager); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (categoryManager is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //nsICategoryManager categoryManager = new nsICategoryManager (result[0]); //result[0] = 0; char* categoryBytes = "Gecko-Content-Viewers"; //$NON-NLS-1$ char* result; rc = categoryManager.GetCategoryEntry (categoryBytes, aContentType, &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 (); } } *retval = preferred ? 1 : 0; /* PRBool */ if (preferred) { *aDesiredContentType = null; } return XPCOM.NS_OK; } extern(System) nsresult CanHandleContent (char* aContentType, PRBool aIsContentPreferred, char** aDesiredContentType, PRBool* retval) { return XPCOM.NS_ERROR_NOT_IMPLEMENTED; } extern(System) nsresult GetLoadCookie (nsISupports* aLoadCookie) { return XPCOM.NS_ERROR_NOT_IMPLEMENTED; } extern(System) nsresult SetLoadCookie (nsISupports aLoadCookie) { return XPCOM.NS_ERROR_NOT_IMPLEMENTED; } extern(System) nsresult GetParentContentListener (nsIURIContentListener* aParentContentListener) { return XPCOM.NS_ERROR_NOT_IMPLEMENTED; } extern(System) nsresult SetParentContentListener (nsIURIContentListener aParentContentListener) { return XPCOM.NS_ERROR_NOT_IMPLEMENTED; } /* nsITooltipListener */ extern(System) nsresult OnShowTooltip (PRInt32 aXCoords, PRInt32 aYCoords, PRUnichar* 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 = Utf.toString(fromString16z(aTipText)); 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; } extern(System) nsresult OnHideTooltip () { if (tip !is null && !tip.isDisposed ()) tip.dispose (); tip = null; return XPCOM.NS_OK; } /* nsIDOMEventListener */ extern(System) nsresult HandleEvent (nsIDOMEvent event) { //nsIDOMEvent domEvent = new nsIDOMEvent (event); scope auto type = new nsEmbedString; int rc = event.GetType (cast(nsAString*)type); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); //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 = type.toString; //XPCOM.nsEmbedString_delete (type); if (XPCOM.DOMEVENT_UNLOAD.equals (typeString)) { //int /*long*/[] result = new int /*long*/[1]; nsIDOMEventTarget target; rc = event.GetCurrentTarget (&target); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (target is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //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]; nsIDOMKeyEvent domKeyEvent; rc = event.QueryInterface (&nsIDOMKeyEvent.IID, cast(void**)&domKeyEvent); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (domKeyEvent is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //nsIDOMKeyEvent domKeyEvent = new nsIDOMKeyEvent (result[0]); //result[0] = 0; PRUint32 aKeyCode; /* PRUint32 */ rc = domKeyEvent.GetKeyCode (&aKeyCode); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); int keyCode = super.translateKey (aKeyCode); /* * 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 */ PRBool aAltKey, aCtrlKey, aShiftKey, aMetaKey; /* PRBool */ rc = domKeyEvent.GetAltKey (&aAltKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domKeyEvent.GetCtrlKey (&aCtrlKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domKeyEvent.GetShiftKey (&aShiftKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domKeyEvent.GetMetaKey (&aMetaKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); Event keyEvent = new Event (); keyEvent.widget = browser; keyEvent.type = DWT.KeyDown; keyEvent.keyCode = keyCode; keyEvent.stateMask = (aAltKey !is 0 ? DWT.ALT : 0) | (aCtrlKey !is 0 ? DWT.CTRL : 0) | (aShiftKey !is 0 ? DWT.SHIFT : 0) | (aMetaKey !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) { event.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. */ PRBool aMetaKey; /* PRBool */ rc = domKeyEvent.GetMetaKey (&aMetaKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (aMetaKey !is 0) { PRBool aCtrlKey; /* PRBool */ rc = domKeyEvent.GetCtrlKey (&aCtrlKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (aCtrlKey is 0) { PRBool aAltKey, aShiftKey; /* PRBool */ rc = domKeyEvent.GetAltKey (&aAltKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domKeyEvent.GetShiftKey (&aShiftKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); Event keyEvent = new Event (); keyEvent.widget = browser; keyEvent.type = DWT.KeyDown; keyEvent.keyCode = lastKeyCode; keyEvent.stateMask = (aAltKey !is 0 ? DWT.ALT : 0) | (aCtrlKey !is 0? DWT.CTRL : 0) | (aShiftKey !is 0? DWT.SHIFT : 0) | (aMetaKey !is 0? DWT.COMMAND : 0); browser.notifyListeners (keyEvent.type, keyEvent); if (!keyEvent.doit) { event.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; default: break; } //int /*long*/[] result = new int /*long*/[1]; nsIDOMKeyEvent domKeyEvent; rc = event.QueryInterface (&nsIDOMKeyEvent.IID, cast(void**)&domKeyEvent); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (domKeyEvent is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //nsIDOMKeyEvent domKeyEvent = new nsIDOMKeyEvent (result[0]); //result[0] = 0; PRBool aAltKey, aCtrlKey, aShiftKey, aMetaKey; /* PRBool */ rc = domKeyEvent.GetAltKey (&aAltKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domKeyEvent.GetCtrlKey (&aCtrlKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domKeyEvent.GetShiftKey (&aShiftKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domKeyEvent.GetMetaKey (&aMetaKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); domKeyEvent.Release (); PRUint32 aCharCode; /* PRUint32 */ rc = domKeyEvent.GetCharCode (&aCharCode); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); lastCharCode = aCharCode; 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; default: break; } } if (aCtrlKey !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 = cast(wchar)lastCharCode; keyEvent.stateMask = (aAltKey !is 0 ? DWT.ALT : 0) | (aCtrlKey !is 0 ? DWT.CTRL : 0) | (aShiftKey !is 0 ? DWT.SHIFT : 0) | (aMetaKey !is 0 ? DWT.COMMAND : 0); browser.notifyListeners (keyEvent.type, keyEvent); if (!keyEvent.doit) { event.PreventDefault (); } return XPCOM.NS_OK; } if (XPCOM.DOMEVENT_KEYUP.equals (typeString)) { //int /*long*/[] result = new int /*long*/[1]; nsIDOMKeyEvent domKeyEvent; rc = event.QueryInterface (&nsIDOMKeyEvent.IID, cast(void**)&domKeyEvent); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (domKeyEvent is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //nsIDOMKeyEvent domKeyEvent = new nsIDOMKeyEvent (result[0]); //result[0] = 0; PRUint32 aKeyCode; /* PRUint32 */ rc = domKeyEvent.GetKeyCode (&aKeyCode); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); int keyCode = super.translateKey (aKeyCode); 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; } PRBool aAltKey, aCtrlKey, aShiftKey, aMetaKey; /* PRBool */ rc = domKeyEvent.GetAltKey (&aAltKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domKeyEvent.GetCtrlKey (&aCtrlKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domKeyEvent.GetShiftKey (&aShiftKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domKeyEvent.GetMetaKey (&aMetaKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); domKeyEvent.Release (); Event keyEvent = new Event (); keyEvent.widget = browser; keyEvent.type = DWT.KeyUp; keyEvent.keyCode = lastKeyCode; keyEvent.character = cast(wchar)lastCharCode; keyEvent.stateMask = (aAltKey !is 0 ? DWT.ALT : 0) | (aCtrlKey !is 0 ? DWT.CTRL : 0) | (aShiftKey !is 0 ? DWT.SHIFT : 0) | (aMetaKey !is 0 ? DWT.COMMAND : 0); switch (lastKeyCode) { case DWT.SHIFT: case DWT.CONTROL: case DWT.ALT: case DWT.COMMAND: { keyEvent.stateMask |= lastKeyCode; } default: break; } browser.notifyListeners (keyEvent.type, keyEvent); if (!keyEvent.doit) { event.PreventDefault (); } lastKeyCode = lastCharCode = 0; return XPCOM.NS_OK; } /* mouse event */ //int /*long*/[] result = new int /*long*/[1]; nsIDOMMouseEvent domMouseEvent; rc = event.QueryInterface (&nsIDOMMouseEvent.IID, cast(void**)&domMouseEvent); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (domMouseEvent is null) error (XPCOM.NS_NOINTERFACE, __FILE__, __LINE__); //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)) { nsIDOMEventTarget eventTarget; rc = domMouseEvent.GetRelatedTarget (&eventTarget); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); if (eventTarget !is null) { domMouseEvent.Release (); return XPCOM.NS_OK; } } PRInt32 aClientX, aClientY, aDetail; /* PRInt32 */ rc = domMouseEvent.GetClientX (&aClientX); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domMouseEvent.GetClientY (&aClientY); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domMouseEvent.GetDetail (&aDetail); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); PRUint16 aButton; /* PRUint16 */ rc = domMouseEvent.GetButton (&aButton); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); PRBool aAltKey, aCtrlKey, aShiftKey, aMetaKey; /* PRBool */ rc = domMouseEvent.GetAltKey (&aAltKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domMouseEvent.GetCtrlKey (&aCtrlKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domMouseEvent.GetShiftKey (&aShiftKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); rc = domMouseEvent.GetMetaKey (&aMetaKey); if (rc !is XPCOM.NS_OK) error (rc, __FILE__, __LINE__); domMouseEvent.Release (); Event mouseEvent = new Event (); mouseEvent.widget = browser; mouseEvent.x = aClientX; mouseEvent.y = aClientY; mouseEvent.stateMask = (aAltKey !is 0 ? DWT.ALT : 0) | (aCtrlKey !is 0 ? DWT.CTRL : 0) | (aShiftKey !is 0 ? DWT.SHIFT : 0) | (aMetaKey !is 0 ? DWT.COMMAND : 0); if (XPCOM.DOMEVENT_MOUSEDOWN.equals (typeString)) { mozDelegate.handleMouseDown (); mouseEvent.type = DWT.MouseDown; mouseEvent.button = aButton + 1; mouseEvent.count = aDetail; } 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 + 1; int count = aDetail; 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; } 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 + 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; default: break; } } browser.notifyListeners (mouseEvent.type, mouseEvent); if (aDetail is 2 && XPCOM.DOMEVENT_MOUSEDOWN.equals (typeString)) { mouseEvent = new Event (); mouseEvent.widget = browser; mouseEvent.x = aClientX; mouseEvent.y = aClientY; mouseEvent.stateMask = (aAltKey !is 0 ? DWT.ALT : 0) | (aCtrlKey !is 0 ? DWT.CTRL : 0) | (aShiftKey !is 0 ? DWT.SHIFT : 0) | (aMetaKey !is 0 ? DWT.COMMAND : 0); mouseEvent.type = DWT.MouseDoubleClick; mouseEvent.button = aButton + 1; mouseEvent.count = aDetail; browser.notifyListeners (mouseEvent.type, mouseEvent); } return XPCOM.NS_OK; } }