Mercurial > projects > dwt-linux
view dwt/browser/Mozilla.d @ 329:92aa2d7391f3
Added 'all.d' package import, a dwt.all for everything and a dwt.std for the essential stuff
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 18 Oct 2008 22:01:20 +0200 |
parents | c7c696cdfec2 |
children | 8235a17d9255 |
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 java.io.UnsupportedEncodingException; //import java.lang.reflect.Constructor; //import java.lang.reflect.InvocationTargetException; //import java.lang.reflect.Method; //import java.util.Enumeration; //import java.util.Locale; //import java.util.Vector; import dwt.DWT; import dwt.DWTError; import dwt.graphics.Device; import dwt.graphics.Point; import dwt.graphics.Rectangle; import dwt.internal.Compatibility; import dwt.internal.LONG; import dwt.internal.Library; import dwt.internal.mozilla.XPCOM; import dwt.internal.mozilla.XPCOMInit; 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.nsIDOMEvent; import dwt.internal.mozilla.nsIDOMEventTarget; import dwt.internal.mozilla.nsIDOMKeyEvent; import dwt.internal.mozilla.nsIDOMMouseEvent; import dwt.internal.mozilla.nsIDOMSerializer; import dwt.internal.mozilla.nsIDOMSerializer_1_7; import dwt.internal.mozilla.nsIDOMWindow; import dwt.internal.mozilla.nsIDOMWindowCollection; import dwt.internal.mozilla.nsIDirectoryService; import dwt.internal.mozilla.nsIDocShell; import dwt.internal.mozilla.nsIDocShell_1_8; import dwt.internal.mozilla.nsIDocShell_1_9; import dwt.internal.mozilla.nsIEmbeddingSiteWindow; import dwt.internal.mozilla.nsIFile; import dwt.internal.mozilla.nsIIOService; import dwt.internal.mozilla.nsIInterfaceRequestor; import dwt.internal.mozilla.nsIJSContextStack; import dwt.internal.mozilla.nsILocalFile; import dwt.internal.mozilla.nsIObserverService; import dwt.internal.mozilla.nsIPrefBranch; import dwt.internal.mozilla.nsIPrefLocalizedString; import dwt.internal.mozilla.nsIPrefService; import dwt.internal.mozilla.nsIProperties; import dwt.internal.mozilla.nsIRequest; import dwt.internal.mozilla.nsIServiceManager; import dwt.internal.mozilla.nsISimpleEnumerator; import dwt.internal.mozilla.nsISupports; import dwt.internal.mozilla.nsISupportsWeakReference; import dwt.internal.mozilla.nsITooltipListener; import dwt.internal.mozilla.nsIURI; import dwt.internal.mozilla.nsIURIContentListener; import dwt.internal.mozilla.nsIWeakReference; import dwt.internal.mozilla.nsIWebBrowser; import dwt.internal.mozilla.nsIWebBrowserChrome; import dwt.internal.mozilla.nsIWebBrowserChromeFocus; import dwt.internal.mozilla.nsIWebBrowserFocus; import dwt.internal.mozilla.nsIWebNavigation; import dwt.internal.mozilla.nsIWebNavigationInfo; import dwt.internal.mozilla.nsIWebProgress; import dwt.internal.mozilla.nsIWebProgressListener; import dwt.internal.mozilla.nsIWindowWatcher; import dwt.layout.FillLayout; import dwt.widgets.Composite; import dwt.widgets.Display; import dwt.widgets.Event; import dwt.widgets.Label; import dwt.widgets.Listener; import dwt.widgets.Menu; import dwt.widgets.Shell; class Mozilla : WebBrowser, nsIWeakReference, nsIWebProgressListener, nsIWebBrowserChrome, nsIWebBrowserFocus, nsIEmbeddingSiteWindow, nsIInterfaceRequestor, nsISupportsWeakReference, nsIContextMenuListener, nsIUriContextListener, nsITooltipListener, nsIDomEventListener { GtkWidget* embedHandle; nsIWebBrowser webBrowser; Object webBrowserObject; MozillaDelegate mozDelegate; /* Interfaces for this Mozilla embedding notification */ // XPCOMObject supports; // XPCOMObject weakReference; // XPCOMObject webProgressListener; // XPCOMObject webBrowserChrome; // XPCOMObject webBrowserChromeFocus; // XPCOMObject embeddingSiteWindow; // XPCOMObject interfaceRequestor; // XPCOMObject supportsWeakReference; // XPCOMObject contextMenuListener; // XPCOMObject uriContentListener; // XPCOMObject tooltipListener; // XPCOMObject domEventListener; 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 final String GRERANGE_LOWER = "1.8.1.2"; //$NON-NLS-1$ static final String GRERANGE_LOWER_FALLBACK = "1.8"; //$NON-NLS-1$ static final bool LowerRangeInclusive = true; static final String GRERANGE_UPPER = "1.9.*"; //$NON-NLS-1$ static final bool UpperRangeInclusive = true; static final int MAX_PORT = 65535; static final String SEPARATOR_OS = System.getProperty ("file.separator"); //$NON-NLS-1$ static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$ static final String DISPOSE_LISTENER_HOOKED = "dwt.browser.Mozilla.disposeListenerHooked"; //$NON-NLS-1$ static final String PREFIX_JAVASCRIPT = "javascript:"; //$NON-NLS-1$ static final String PREFERENCE_CHARSET = "intl.charset.default"; //$NON-NLS-1$ static final String PREFERENCE_DISABLEOPENDURINGLOAD = "dom.disable_open_during_load"; //$NON-NLS-1$ static final String PREFERENCE_DISABLEWINDOWSTATUSCHANGE = "dom.disable_window_status_change"; //$NON-NLS-1$ static final String PREFERENCE_LANGUAGES = "intl.accept_languages"; //$NON-NLS-1$ static final String PREFERENCE_PROXYHOST_FTP = "network.proxy.ftp"; //$NON-NLS-1$ static final String PREFERENCE_PROXYPORT_FTP = "network.proxy.ftp_port"; //$NON-NLS-1$ static final String PREFERENCE_PROXYHOST_HTTP = "network.proxy.http"; //$NON-NLS-1$ static final String PREFERENCE_PROXYPORT_HTTP = "network.proxy.http_port"; //$NON-NLS-1$ static final String PREFERENCE_PROXYHOST_SSL = "network.proxy.ssl"; //$NON-NLS-1$ static final String PREFERENCE_PROXYPORT_SSL = "network.proxy.ssl_port"; //$NON-NLS-1$ static final String PREFERENCE_PROXYTYPE = "network.proxy.type"; //$NON-NLS-1$ static final String PROFILE_AFTER_CHANGE = "profile-after-change"; //$NON-NLS-1$ static final String PROFILE_BEFORE_CHANGE = "profile-before-change"; //$NON-NLS-1$ static final String PROFILE_DIR = SEPARATOR_OS ~ "eclipse" ~ SEPARATOR_OS; //$NON-NLS-1$ static final String PROFILE_DO_CHANGE = "profile-do-change"; //$NON-NLS-1$ static final String PROPERTY_PROXYPORT = "network.proxy_port"; //$NON-NLS-1$ static final String PROPERTY_PROXYHOST = "network.proxy_host"; //$NON-NLS-1$ static final String SEPARATOR_LOCALE = "-"; //$NON-NLS-1$ static final String SHUTDOWN_PERSIST = "shutdown-persist"; //$NON-NLS-1$ static final String STARTUP = "startup"; //$NON-NLS-1$ static final String TOKENIZER_LOCALE = ","; //$NON-NLS-1$ static final String URI_FROMMEMORY = "file:///"; //$NON-NLS-1$ static final String XULRUNNER_PATH = "dwt.browser.XULRunnerPath"; //$NON-NLS-1$ // TEMPORARY CODE static final String GRE_INITIALIZED = "dwt.browser.XULRunnerInitialized"; //$NON-NLS-1$ static this () { MozillaClearSessions = new Runnable () { public void run () { if (!Initialized) return; nsIServiceManager serviceManager; int rc = XPCOM.NS_GetServiceManager (&serviceManager); if (rc !is XPCOM.NS_OK) error (rc); if (serviceManager is null) error (XPCOM.NS_NOINTERFACE); //nsIServiceManager serviceManager = new nsIServiceManager (result[0]); //result[0] = 0; //byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_COOKIEMANAGER_CONTRACTID, true); nsICookieManager manager; rc = serviceManager.GetServiceByContractID (XPCOM.NS_COOKIEMANAGER_CONTRACTID, nsICookieManager.IID, cast(void**)&manager); if (rc !is XPCOM.NS_OK) error (rc); if (manager is null) error (XPCOM.NS_NOINTERFACE); serviceManager.Release (); //nsICookieManager manager = new nsICookieManager (result[0]); //result[0] = 0; nsISimpleEnumerator enumerator; rc = manager.GetEnumerator (&enumerator); if (rc !is XPCOM.NS_OK) error (rc); manager.Release (); //nsISimpleEnumerator enumerator = new nsISimpleEnumerator (result[0]); PRBool moreElements; /* PRBool */ rc = enumerator.HasMoreElements (&moreElements); if (rc !is XPCOM.NS_OK) error (rc); while (moreElements !is 0) { //result[0] = 0; nsICookie cookie; rc = enumerator.GetNext (cast(nsISupports*)&cookie); if (rc !is XPCOM.NS_OK) error (rc); //nsICookie cookie = new nsICookie (result[0]); 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); //XPCOM.nsEmbedCString_delete (domain); //XPCOM.nsEmbedCString_delete (name); //XPCOM.nsEmbedCString_delete (path); if (rc !is XPCOM.NS_OK) error (rc); } cookie.Release (); rc = enumerator.HasMoreElements (&moreElements); if (rc !is XPCOM.NS_OK) error (rc); } enumerator.Release (); } }; } public void create (Composite parent, int style) { mozDelegate = new MozillaDelegate (super.browser); Display display = parent.getDisplay (); //int /*long*/[] result = new int /*long*/[1]; if (!Initialized) { bool initLoaded = false; bool IsXULRunner = false; String greInitialized = System.getProperty (GRE_INITIALIZED); if ("true" == 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 have to load an initial library in DWT, so set to "true" initLoaded = true; /+ if (mozillaPath is null) { try { String libName = mozDelegate.getSWTInitLibraryName (); Library.loadLibrary (libName); initLoaded = true; } catch (UnsatisfiedLinkError e) { /* * If this library failed to load then do not attempt to detect a * xulrunner to use. The Browser may still be usable if MOZILLA_FIVE_HOME * points at a GRE. */ } +/ } else { mozillaPath ~= SEPARATOR_OS ~ mozDelegate.getLibraryName (); IsXULRunner = true; } if (initLoaded) { /* attempt to discover a XULRunner to use as the GRE */ GREVersionRange range; //byte[] bytes = MozillaDelegate.wcsToMbcs (null, GRERANGE_LOWER, true); //int /*long*/ lower = C.malloc (bytes.length); //C.memmove (lower, bytes, bytes.length); range.lower = GRERANGE_LOWER; range.lowerInclusive = LowerRangeInclusive; //bytes = MozillaDelegate.wcsToMbcs (null, GRERANGE_UPPER, true); //int /*long*/ upper = C.malloc (bytes.length); //C.memmove (upper, bytes, bytes.length); range.upper = GRERANGE_UPPER; range.upperInclusive = UpperRangeInclusive; //int length = XPCOMInit.PATH_MAX; //int /*long*/ greBuffer = C.malloc (length); char[] greBuffer = new char[XPCOMInit.PATH_MAX]; //int /*long*/ propertiesPtr = C.malloc (2 * C.PTR_SIZEOF); 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) { //C.free (lower); //bytes = MozillaDelegate.wcsToMbcs (null, GRERANGE_LOWER_FALLBACK, true); //lower = C.malloc (bytes.length); //C.memmove (lower, bytes, bytes.length); range.lower = GRERANGE_LOWER_FALLBACK; rc = XPCOMInit.GRE_GetGREPathWithProperties (&range, 1, null, 0, greBuffer.ptr, greBuffer.length); } //C.free (lower); //C.free (upper); //C.free (propertiesPtr); if (rc is XPCOM.NS_OK) { /* indicates that a XULRunner was found */ //length = C.strlen (greBuffer); //bytes = new byte[length]; //C.memmove (bytes, greBuffer, length); //mozillaPath = new String (MozillaDelegate.mbcsToWcs (null, bytes)); 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) { // byte[] path = MozillaDelegate.wcsToMbcs (null, mozillaPath, true); rc = XPCOMInit.XPCOMGlueStartup (mozillaPath.ptr); if (rc !is XPCOM.NS_OK) { IsXULRunner = false; /* failed */ mozillaPath = mozillaPath[0 .. locatePrior( mozillaPath, SEPARATOR_OS )]; //mozillaPath = mozillaPath.substring (0, mozillaPath.lastIndexOf (SEPARATOR_OS)); if (Device.DEBUG) Stdout ("cannot use detected XULRunner: ") (mozillaPath).newline; //$NON-NLS-1$ } else { XPCOMInitWasGlued = true; } } } //C.free (greBuffer); } if (IsXULRunner) { if (Device.DEBUG) Stdout ("XULRunner path: ") (mozillaPath).newline; //$NON-NLS-1$ /+ try { Library.loadLibrary ("swt-xulrunner"); //$NON-NLS-1$ } catch (UnsatisfiedLinkError e) { DWT.error (DWT.ERROR_NO_HANDLES, e); } byte[] path = MozillaDelegate.wcsToMbcs (null, mozillaPath, true); int rc = XPCOM.XPCOMGlueStartup (path); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } +/ // No need for double layer initialization in DWT; glue is initialized -JJR 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[0 .. locatePrior( mozillaPath, SEPARATOR_OS )]; //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 = tango.sys.Environment.get(XPCOM.MOZILLA_FIVE_HOME); if (mozFiveHome !is null) { //int length = C.strlen (ptr); //byte[] buffer = new byte[length]; //C.memmove (buffer, ptr, length); 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) Stdout ("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$ } /+ try { Library.loadLibrary ("swt-mozilla"); //$NON-NLS-1$ } catch (UnsatisfiedLinkError e) { try { /* * The initial loadLibrary attempt may have failed as a result of the user's * system not having libstdc++.so.6 installed, so try to load the alternate * swt mozilla library that depends on libswtc++.so.5 instead. */ Library.loadLibrary ("swt-mozilla-gcc3"); //$NON-NLS-1$ } catch (UnsatisfiedLinkError ex) { browser.dispose (); /* * Print the error from the first failed attempt since at this point it's * known that the failure was not due to the libstdc++.so.6 dependency. */ DWT.error (DWT.ERROR_NO_HANDLES, e, " [MOZILLA_FIVE_HOME='" + mozillaPath + "']"); //$NON-NLS-1$ //$NON-NLS-2$ } } +/ } if (!Initialized) { nsILocalFile file; scope auto pathString = new nsEmbedString (mozillaPath); nsresult rc = XPCOM.NS_NewLocalFile (cast(nsAString*)pathString, 1, &localFile); //pathString.dispose (); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (localFile is null) { browser.dispose (); error (XPCOM.NS_ERROR_NULL_POINTER); } LocationProvider = new AppFileLocProvider (mozillaPath); LocationProvider.AddRef (); //nsIFile localFile = new nsILocalFile (retVal[0]); nsIDirectoryServiceProvider directoryServiceProvider; nsIServiceManager serviceManager; rc = LocationProvider.QueryInterface( &nsIDirectoryServiceProvider.IID, cast(void**)&directoryServiceProvider); if (rc !is XPCOM.NS_OK) { browser.dispose(); error(rc); } rc = XPCOM.NS_GetServiceManager(&serviceManager); if (rc !is XPCOM.NS_OK) { browser.dispose(); error(rc); } if (serviceManager is null || directoryServiceProvider is null) { browser.dispose; error (XPCOM.NS_ERROR_NULL_POINTER); } rc = XPCOM.NS_InitXPCOM2 (&serviceManager, 0, cast(IFile*)&localFile, &directoryServiceProvider); localFile.Release (); serviceManager.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); } } /+ /* If JavaXPCOM is detected then attempt to initialize it with the XULRunner being used */ if (IsXULRunner) { try { Class clazz = Class.forName ("org.mozilla.xpcom.Mozilla"); //$NON-NLS-1$ Method method = clazz.getMethod ("getInstance", new Class[0]); //$NON-NLS-1$ Object mozilla = method.invoke (null, new Object[0]); method = clazz.getMethod ("getComponentManager", new Class[0]); //$NON-NLS-1$ try { method.invoke (mozilla, new Object[0]); } catch (InvocationTargetException e) { /* indicates that JavaXPCOM has not been initialized yet */ Class fileClass = Class.forName ("java.io.File"); //$NON-NLS-1$ method = clazz.getMethod ("initialize", new Class[] {fileClass}); //$NON-NLS-1$ Constructor constructor = fileClass.getDeclaredConstructor (new Class[] {String.class}); Object argument = constructor.newInstance (new Object[] {mozillaPath}); method.invoke (mozilla, new Object[] {argument}); } } catch (ClassNotFoundException e) { /* JavaXPCOM is not on the classpath */ } catch (NoSuchMethodException e) { /* the JavaXPCOM on the classpath does not implement initialize() */ } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } catch (InstantiationException e) { } } +/ nsIComponentManager componentManager; int rc = XPCOM.NS_GetComponentManager (&componentManager); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (componentManager is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } //nsIComponentManager componentManager = new nsIComponentManager (result[0]); //result[0] = 0; if (mozDelegate.needsSpinup ()) { /* nsIAppShell is discontinued as of xulrunner 1.9, so do not fail if it is not found */ rc = componentManager.CreateInstance (XPCOM.NS_APPSHELL_CID, 0, nsIAppShell.IID, cast(void**)&AppShell); if (rc !is XPCOM.NS_ERROR_NO_INTERFACE) { if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (AppShell is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } //AppShell = new nsIAppShell (result[0]); rc = AppShell.Create (0, null); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } rc = AppShell.Spinup (); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } } //result[0] = 0; } WindowCreator = new WindowCreator2; WindowCreator.AddRef (); nsIServiceManager serviceManager; rc = XPCOM.NS_GetServiceManager (&serviceManager); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (serviceManager is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } //nsIServiceManager serviceManager = new nsIServiceManager (result[0]); //result[0] = 0; //byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_WINDOWWATCHER_CONTRACTID, true); nsIWindowWatcher windowWatcher; rc = serviceManager.GetServiceByContractID (XPCOM.NS_WINDOWWATCHER_CONTRACTID, nsIWindowWatcher.IID, cast(void**)&windowWatcher); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (windowWatcher is null) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } //nsIWindowWatcher windowWatcher = new nsIWindowWatcher (result[0]); //result[0] = 0; rc = windowWatcher.SetWindowCreator (&WindowCreator); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } windowWatcher.Release (); /* compute the profile directory and set it on the AppFileLocProvider */ if (LocationProvider !is null) { byte[] buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DIRECTORYSERVICE_CONTRACTID, true); rc = serviceManager.GetServiceByContractID (buffer, nsIDirectoryService.NS_IDIRECTORYSERVICE_IID, result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } nsIDirectoryService directoryService = new nsIDirectoryService (result[0]); result[0] = 0; rc = directoryService.QueryInterface (nsIProperties.NS_IPROPERTIES_IID, result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } directoryService.Release (); nsIProperties properties = new nsIProperties (result[0]); result[0] = 0; buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_APP_APPLICATION_REGISTRY_DIR, true); rc = properties.Get (buffer, nsIFile.NS_IFILE_IID, result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } properties.Release (); nsIFile profileDir = new nsIFile (result[0]); result[0] = 0; int /*long*/ path = XPCOM.nsEmbedCString_new (); rc = profileDir.GetNativePath (path); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } int length = XPCOM.nsEmbedCString_Length (path); int /*long*/ ptr = XPCOM.nsEmbedCString_get (path); buffer = new byte [length]; XPCOM.memmove (buffer, ptr, length); String profilePath = new String (MozillaDelegate.mbcsToWcs (null, buffer)) + PROFILE_DIR; LocationProvider.setProfilePath (profilePath); LocationProvider.isXULRunner = IsXULRunner; XPCOM.nsEmbedCString_delete (path); profileDir.Release (); /* notify observers of a new profile directory being used */ buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_OBSERVER_CONTRACTID, true); rc = serviceManager.GetServiceByContractID (buffer, nsIObserverService.NS_IOBSERVERSERVICE_IID, result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } nsIObserverService observerService = new nsIObserverService (result[0]); result[0] = 0; buffer = MozillaDelegate.wcsToMbcs (null, PROFILE_DO_CHANGE, true); length = STARTUP.length (); char[] chars = new char [length + 1]; STARTUP.getChars (0, length, chars, 0); rc = observerService.NotifyObservers (0, buffer, chars); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } buffer = MozillaDelegate.wcsToMbcs (null, PROFILE_AFTER_CHANGE, true); rc = observerService.NotifyObservers (0, buffer, chars); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } observerService.Release (); } /* * As a result of using a common profile the user cannot change their locale * and charset. The fix for this is to set mozilla's locale and charset * preference values according to the user's current locale and charset. */ aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFSERVICE_CONTRACTID, true); rc = serviceManager.GetServiceByContractID (aContractID, nsIPrefService.NS_IPREFSERVICE_IID, result); serviceManager.Release (); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } nsIPrefService prefService = new nsIPrefService (result[0]); result[0] = 0; byte[] buffer = new byte[1]; rc = prefService.GetBranch (buffer, result); /* empty buffer denotes root preference level */ prefService.Release (); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } nsIPrefBranch prefBranch = new nsIPrefBranch (result[0]); result[0] = 0; /* get Mozilla's current locale preference value */ String prefLocales = null; nsIPrefLocalizedString localizedString = null; buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_LANGUAGES, true); rc = prefBranch.GetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result); /* * Feature of Debian. For some reason attempting to query for the current locale * preference fails on Debian. The workaround for this is to assume a value of * "en-us,en" since this is typically the default value when mozilla is used without * a profile. */ if (rc !is XPCOM.NS_OK) { prefLocales = "en-us,en" + TOKENIZER_LOCALE; //$NON-NLS-1$ } else { if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } localizedString = new nsIPrefLocalizedString (result[0]); result[0] = 0; rc = localizedString.ToString (result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } int length = XPCOM.strlen_PRUnichar (result[0]); char[] dest = new char[length]; XPCOM.memmove (dest, result[0], length * 2); prefLocales = new String (dest) + TOKENIZER_LOCALE; } result[0] = 0; /* * construct the new locale preference value by prepending the * user's current locale and language to the original value */ Locale locale = Locale.getDefault (); String language = locale.getLanguage (); String country = locale.getCountry (); StringBuffer stringBuffer = new StringBuffer (language); stringBuffer.append (SEPARATOR_LOCALE); stringBuffer.append (country.toLowerCase ()); stringBuffer.append (TOKENIZER_LOCALE); stringBuffer.append (language); stringBuffer.append (TOKENIZER_LOCALE); String newLocales = stringBuffer.toString (); int start, end = -1; do { start = end + 1; end = prefLocales.indexOf (TOKENIZER_LOCALE, start); String token; if (end is -1) { token = prefLocales.substring (start); } else { token = prefLocales.substring (start, end); } if (token.length () > 0) { token = (token + TOKENIZER_LOCALE).trim (); /* ensure that duplicate locale values are not added */ if (newLocales.indexOf (token) is -1) { stringBuffer.append (token); } } } while (end !is -1); newLocales = stringBuffer.toString (); if (!newLocales.equals (prefLocales)) { /* write the new locale value */ newLocales = newLocales.substring (0, newLocales.length () - TOKENIZER_LOCALE.length ()); /* remove trailing tokenizer */ int length = newLocales.length (); char[] charBuffer = new char[length + 1]; newLocales.getChars (0, length, charBuffer, 0); if (localizedString is null) { byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID, true); rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } localizedString = new nsIPrefLocalizedString (result[0]); result[0] = 0; } localizedString.SetDataWithLength (length, charBuffer); rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress()); } if (localizedString !is null) { localizedString.Release (); localizedString = null; } /* get Mozilla's current charset preference value */ String prefCharset = null; buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_CHARSET, true); rc = prefBranch.GetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result); /* * Feature of Debian. For some reason attempting to query for the current charset * preference fails on Debian. The workaround for this is to assume a value of * "ISO-8859-1" since this is typically the default value when mozilla is used * without a profile. */ if (rc !is XPCOM.NS_OK) { prefCharset = "ISO-8859-1"; //$NON_NLS-1$ } else { if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } localizedString = new nsIPrefLocalizedString (result[0]); result[0] = 0; rc = localizedString.ToString (result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } int length = XPCOM.strlen_PRUnichar (result[0]); char[] dest = new char[length]; XPCOM.memmove (dest, result[0], length * 2); prefCharset = new String (dest); } result[0] = 0; String newCharset = System.getProperty ("file.encoding"); // $NON-NLS-1$ if (!newCharset.equals (prefCharset)) { /* write the new charset value */ int length = newCharset.length (); char[] charBuffer = new char[length + 1]; newCharset.getChars (0, length, charBuffer, 0); if (localizedString is null) { byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID, true); rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } localizedString = new nsIPrefLocalizedString (result[0]); result[0] = 0; } localizedString.SetDataWithLength (length, charBuffer); rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ()); } if (localizedString !is null) localizedString.Release (); /* * Check for proxy values set as documented java properties and update mozilla's * preferences with these values if needed. */ String proxyHost = System.getProperty (PROPERTY_PROXYHOST); String proxyPortString = System.getProperty (PROPERTY_PROXYPORT); int port = -1; if (proxyPortString !is null) { try { int value = Integer.valueOf (proxyPortString).intValue (); if (0 <= value && value <= MAX_PORT) port = value; } catch (NumberFormatException e) { /* do nothing, java property has non-integer value */ } } if (proxyHost !is null) { byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID, true); rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); localizedString = new nsIPrefLocalizedString (result[0]); result[0] = 0; int length = proxyHost.length (); char[] charBuffer = new char[length + 1]; proxyHost.getChars (0, length, charBuffer, 0); rc = localizedString.SetDataWithLength (length, charBuffer); if (rc !is XPCOM.NS_OK) error (rc); buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYHOST_FTP, true); rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ()); if (rc !is XPCOM.NS_OK) error (rc); buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYHOST_HTTP, true); rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ()); if (rc !is XPCOM.NS_OK) error (rc); buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYHOST_SSL, true); rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ()); if (rc !is XPCOM.NS_OK) error (rc); localizedString.Release (); } if (port !is -1) { buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYPORT_FTP, true); rc = prefBranch.SetIntPref (buffer, port); if (rc !is XPCOM.NS_OK) error (rc); buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYPORT_HTTP, true); rc = prefBranch.SetIntPref (buffer, port); if (rc !is XPCOM.NS_OK) error (rc); buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYPORT_SSL, true); rc = prefBranch.SetIntPref (buffer, port); if (rc !is XPCOM.NS_OK) error (rc); } if (proxyHost !is null || port !is -1) { buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYTYPE, true); rc = prefBranch.SetIntPref (buffer, 1); if (rc !is XPCOM.NS_OK) error (rc); } /* * Ensure that windows that are shown during page loads are not blocked. Firefox may * try to block these by default since such windows are often unwelcome, but this * assumption should not be made in the Browser's context. Since the Browser client * is responsible for creating the new Browser and Shell in an OpenWindowListener, * they should decide whether the new window is unwelcome or not and act accordingly. */ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_DISABLEOPENDURINGLOAD, true); rc = prefBranch.SetBoolPref (buffer, 0); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } /* Ensure that the status text can be set through means like javascript */ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_DISABLEWINDOWSTATUSCHANGE, true); rc = prefBranch.SetBoolPref (buffer, 0); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } prefBranch.Release (); PromptService2Factory factory = new PromptService2Factory (); factory.AddRef (); rc = componentManager.QueryInterface (nsIComponentRegistrar.NS_ICOMPONENTREGISTRAR_IID, result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } nsIComponentRegistrar componentRegistrar = new nsIComponentRegistrar (result[0]); result[0] = 0; aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PROMPTSERVICE_CONTRACTID, true); byte[] aClassName = MozillaDelegate.wcsToMbcs (null, "Prompt Service", true); //$NON-NLS-1$ rc = componentRegistrar.RegisterFactory (XPCOM.NS_PROMPTSERVICE_CID, aClassName, aContractID, factory.getAddress ()); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } factory.Release (); HelperAppLauncherDialogFactory dialogFactory = new HelperAppLauncherDialogFactory (); dialogFactory.AddRef (); aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_HELPERAPPLAUNCHERDIALOG_CONTRACTID, true); aClassName = MozillaDelegate.wcsToMbcs (null, "Helper App Launcher Dialog", true); //$NON-NLS-1$ rc = componentRegistrar.RegisterFactory (XPCOM.NS_HELPERAPPLAUNCHERDIALOG_CID, aClassName, aContractID, dialogFactory.getAddress ()); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } dialogFactory.Release (); /* * This Download factory will be used if the GRE version is < 1.8. * If the GRE version is 1.8.x then the Download factory that is registered later for * contract "Transfer" will be used. * If the GRE version is >= 1.9 then no Download factory is registered because this * functionality is provided by the GRE. */ DownloadFactory downloadFactory = new DownloadFactory (); downloadFactory.AddRef (); aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DOWNLOAD_CONTRACTID, true); aClassName = MozillaDelegate.wcsToMbcs (null, "Download", true); //$NON-NLS-1$ rc = componentRegistrar.RegisterFactory (XPCOM.NS_DOWNLOAD_CID, aClassName, aContractID, downloadFactory.getAddress ()); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } downloadFactory.Release (); FilePickerFactory pickerFactory = IsXULRunner ? new FilePickerFactory_1_8 () : new FilePickerFactory (); pickerFactory.AddRef (); aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_FILEPICKER_CONTRACTID, true); aClassName = MozillaDelegate.wcsToMbcs (null, "FilePicker", true); //$NON-NLS-1$ rc = componentRegistrar.RegisterFactory (XPCOM.NS_FILEPICKER_CID, aClassName, aContractID, pickerFactory.getAddress ()); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } pickerFactory.Release (); componentRegistrar.Release (); componentManager.Release (); Initialized = true; } if (display.getData (DISPOSE_LISTENER_HOOKED) is null) { display.setData (DISPOSE_LISTENER_HOOKED, DISPOSE_LISTENER_HOOKED); display.addListener (DWT.Dispose, new Listener () { public void handleEvent (Event event) { if (BrowserCount > 0) return; /* another display is still active */ int /*long*/[] result = new int /*long*/[1]; int rc = XPCOM.NS_GetServiceManager (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIServiceManager serviceManager = new nsIServiceManager (result[0]); result[0] = 0; byte[] buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_OBSERVER_CONTRACTID, true); rc = serviceManager.GetServiceByContractID (buffer, nsIObserverService.NS_IOBSERVERSERVICE_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIObserverService observerService = new nsIObserverService (result[0]); result[0] = 0; buffer = MozillaDelegate.wcsToMbcs (null, PROFILE_BEFORE_CHANGE, true); int length = SHUTDOWN_PERSIST.length (); char[] chars = new char [length + 1]; SHUTDOWN_PERSIST.getChars (0, length, chars, 0); rc = observerService.NotifyObservers (0, buffer, chars); if (rc !is XPCOM.NS_OK) error (rc); observerService.Release (); if (LocationProvider !is null) { String prefsLocation = LocationProvider.profilePath + AppFileLocProvider.PREFERENCES_FILE; nsEmbedString pathString = new nsEmbedString (prefsLocation); rc = XPCOM.NS_NewLocalFile (pathString.getAddress (), 1, result); if (rc !is XPCOM.NS_OK) Mozilla.error (rc); if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER); pathString.dispose (); nsILocalFile localFile = new nsILocalFile (result [0]); result[0] = 0; rc = localFile.QueryInterface (nsIFile.NS_IFILE_IID, result); if (rc !is XPCOM.NS_OK) Mozilla.error (rc); if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE); localFile.Release (); nsIFile prefFile = new nsIFile (result[0]); result[0] = 0; buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFSERVICE_CONTRACTID, true); rc = serviceManager.GetServiceByContractID (buffer, nsIPrefService.NS_IPREFSERVICE_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIPrefService prefService = new nsIPrefService (result[0]); result[0] = 0; rc = prefService.SavePrefFile(prefFile.getAddress ()); prefService.Release (); prefFile.Release (); } serviceManager.Release (); if (XPCOMWasGlued) { XPCOM.XPCOMGlueShutdown (); XPCOMWasGlued = false; } if (XPCOMInitWasGlued) { XPCOMInit.XPCOMGlueShutdown (); XPCOMInitWasGlued = false; } Initialized = false; } }); } BrowserCount++; int rc = XPCOM.NS_GetComponentManager (result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } nsIComponentManager componentManager = new nsIComponentManager (result[0]); result[0] = 0; nsID NS_IWEBBROWSER_CID = new nsID ("F1EAC761-87E9-11d3-AF80-00A024FFC08C"); //$NON-NLS-1$ rc = componentManager.CreateInstance (NS_IWEBBROWSER_CID, 0, nsIWebBrowser.NS_IWEBBROWSER_IID, result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } webBrowser = new nsIWebBrowser (result[0]); result[0] = 0; createCOMInterfaces (); AddRef (); rc = webBrowser.SetContainerWindow (webBrowserChrome.getAddress()); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_ERROR_NO_INTERFACE); } nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]); result[0] = 0; Rectangle rect = browser.getClientArea (); if (rect.isEmpty ()) { rect.width = 1; rect.height = 1; } embedHandle = mozDelegate.getHandle (); rc = baseWindow.InitWindow (embedHandle, 0, 0, 0, rect.width, rect.height); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (XPCOM.NS_ERROR_FAILURE); } rc = baseWindow.Create (); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (XPCOM.NS_ERROR_FAILURE); } rc = baseWindow.SetVisibility (1); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (XPCOM.NS_ERROR_FAILURE); } baseWindow.Release (); if (!PerformedVersionCheck) { PerformedVersionCheck = true; /* * Check for the availability of the pre-1.8 implementation of nsIDocShell * to determine if the GRE's version is < 1.8. */ rc = webBrowser.QueryInterface (nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID, result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (XPCOM.NS_ERROR_FAILURE); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_ERROR_NO_INTERFACE); } nsIInterfaceRequestor interfaceRequestor = new nsIInterfaceRequestor (result[0]); result[0] = 0; rc = interfaceRequestor.GetInterface (nsIDocShell.NS_IDOCSHELL_IID, result); if (rc is XPCOM.NS_OK && result[0] !is 0) { IsPre_1_8 = true; new nsISupports (result[0]).Release (); } result[0] = 0; /* * A Download factory for contract "Transfer" must be registered iff the GRE's version is 1.8.x. * Check for the availability of the 1.8 implementation of nsIDocShell to determine if the * GRE's version is 1.8.x. * If the GRE version is < 1.8 then the previously-registered Download factory for contract * "Download" will be used. * If the GRE version is >= 1.9 then no Download factory is registered because this * functionality is provided by the GRE. */ if (!IsPre_1_8) { rc = interfaceRequestor.GetInterface (nsIDocShell_1_8.NS_IDOCSHELL_IID, result); if (rc is XPCOM.NS_OK && result[0] !is 0) { /* 1.8 */ new nsISupports (result[0]).Release (); result[0] = 0; rc = componentManager.QueryInterface (nsIComponentRegistrar.NS_ICOMPONENTREGISTRAR_IID, result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_NOINTERFACE); } nsIComponentRegistrar componentRegistrar = new nsIComponentRegistrar (result[0]); DownloadFactory_1_8 downloadFactory_1_8 = new DownloadFactory_1_8 (); downloadFactory_1_8.AddRef (); byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_TRANSFER_CONTRACTID, true); byte[] aClassName = MozillaDelegate.wcsToMbcs (null, "Transfer", true); //$NON-NLS-1$ rc = componentRegistrar.RegisterFactory (XPCOM.NS_DOWNLOAD_CID, aClassName, aContractID, downloadFactory_1_8.getAddress ()); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } downloadFactory_1_8.Release (); componentRegistrar.Release (); } else { /* >= 1.9 */ /* * Bug in XULRunner 1.9. Mozilla no longer clears its background before initial content has * been set. As a result embedders appear broken if they do not immediately navigate to a url. * The workaround for this is to navigate to about:blank immediately so that the background is * cleared, but do not fire any corresponding events or allow Browser API calls to reveal this. * Once the client does a proper navigate with either setUrl() or setText() then resume as * normal. The Mozilla bug for this is https://bugzilla.mozilla.org/show_bug.cgi?id=415789. */ awaitingNavigate = true; rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } if (result[0] is 0) { browser.dispose (); error (XPCOM.NS_ERROR_NO_INTERFACE); } nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); char[] uri = new char[ABOUT_BLANK.length () + 1]; ABOUT_BLANK.getChars (0, ABOUT_BLANK.length (), uri, 0); rc = webNavigation.LoadURI (uri, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0); webNavigation.Release (); } } result[0] = 0; interfaceRequestor.Release (); } componentManager.Release (); rc = webBrowser.AddWebBrowserListener (weakReference.getAddress (), nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } rc = webBrowser.SetParentURIContentListener (uriContentListener.getAddress ()); if (rc !is XPCOM.NS_OK) { browser.dispose (); error (rc); } mozDelegate.init (); listener = new Listener () { public void handleEvent (Event event) { switch (event.type) { case DWT.Dispose: { /* make this handler run after other dispose listeners */ if (ignoreDispose) { ignoreDispose = false; break; } ignoreDispose = true; browser.notifyListeners (event.type, event); event.type = DWT.NONE; onDispose (event.display); break; } case DWT.Resize: onResize (); break; case DWT.FocusIn: Activate (); break; case DWT.Activate: Activate (); break; case DWT.Deactivate: { Display display = event.display; if (Mozilla.this.browser is display.getFocusControl ()) Deactivate (); break; } case DWT.Show: { /* * Feature in GTK Mozilla. Mozilla does not show up when * its container (a GTK fixed handle) is made visible * after having been hidden. The workaround is to reset * its size after the container has been made visible. */ Display display = event.display; display.asyncExec(new Runnable () { public void run() { if (browser.isDisposed ()) return; onResize (); } }); break; } } } }; int[] folderEvents = new int[] { DWT.Dispose, DWT.Resize, DWT.FocusIn, DWT.Activate, DWT.Deactivate, DWT.Show, DWT.KeyDown // needed to make browser traversable }; for (int i = 0; i < folderEvents.length; i++) { browser.addListener (folderEvents[i], listener); } } public bool back () { if (awaitingNavigate) return false; int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); rc = webNavigation.GoBack (); webNavigation.Release (); return rc is XPCOM.NS_OK; } public bool execute (String script) { if (awaitingNavigate) return false; String url = PREFIX_JAVASCRIPT + script + ";void(0);"; //$NON-NLS-1$ int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); char[] arg = url.toCharArray (); char[] c = new char[arg.length+1]; System.arraycopy (arg, 0, c, 0, arg.length); rc = webNavigation.LoadURI (c, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0); webNavigation.Release (); return rc is XPCOM.NS_OK; } static Browser findBrowser (void* handle) { return MozillaDelegate.findBrowser (cast(GtkWidget*)handle); } public bool forward () { if (awaitingNavigate) return false; int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); rc = webNavigation.GoForward (); webNavigation.Release (); return rc is XPCOM.NS_OK; } public String getText () { if (awaitingNavigate) return ""; //$NON-NLS-1$ int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.GetContentDOMWindow (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIDOMWindow window = new nsIDOMWindow (result[0]); result[0] = 0; rc = window.GetDocument (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); window.Release (); int /*long*/ document = result[0]; result[0] = 0; rc = XPCOM.NS_GetComponentManager (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIComponentManager componentManager = new nsIComponentManager (result[0]); result[0] = 0; byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DOMSERIALIZER_CONTRACTID, true); char[] chars = null; rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIDOMSerializer_1_7.NS_IDOMSERIALIZER_IID, result); if (rc is XPCOM.NS_OK) { /* mozilla >= 1.7 */ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIDOMSerializer_1_7 serializer = new nsIDOMSerializer_1_7 (result[0]); result[0] = 0; int /*long*/ string = XPCOM.nsEmbedString_new (); rc = serializer.SerializeToString (document, string); serializer.Release (); int length = XPCOM.nsEmbedString_Length (string); int /*long*/ buffer = XPCOM.nsEmbedString_get (string); chars = new char[length]; XPCOM.memmove (chars, buffer, length * 2); XPCOM.nsEmbedString_delete (string); } else { /* mozilla < 1.7 */ rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIDOMSerializer.NS_IDOMSERIALIZER_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIDOMSerializer serializer = new nsIDOMSerializer (result[0]); result[0] = 0; rc = serializer.SerializeToString (document, result); serializer.Release (); int length = XPCOM.strlen_PRUnichar (result[0]); chars = new char[length]; XPCOM.memmove (chars, result[0], length * 2); } componentManager.Release (); new nsISupports (document).Release (); return new String (chars); } public String getUrl () { if (awaitingNavigate) return ""; //$NON-NLS-1$ int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); int /*long*/[] aCurrentURI = new int /*long*/[1]; rc = webNavigation.GetCurrentURI (aCurrentURI); if (rc !is XPCOM.NS_OK) error (rc); webNavigation.Release (); byte[] dest = null; if (aCurrentURI[0] !is 0) { nsIURI uri = new nsIURI (aCurrentURI[0]); int /*long*/ aSpec = XPCOM.nsEmbedCString_new (); rc = uri.GetSpec (aSpec); if (rc !is XPCOM.NS_OK) error (rc); int length = XPCOM.nsEmbedCString_Length (aSpec); int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec); dest = new byte[length]; XPCOM.memmove (dest, buffer, length); XPCOM.nsEmbedCString_delete (aSpec); uri.Release (); } if (dest is null) return ""; //$NON-NLS-1$ String location = new String (dest); /* * If the URI indicates that the page is being rendered from memory * (via setText()) then set it to about:blank to be consistent with IE. */ if (location.equals (URI_FROMMEMORY)) location = ABOUT_BLANK; return location; } public Object getWebBrowser () { if ((browser.getStyle () & DWT.MOZILLA) is 0) return null; if (webBrowserObject !is null) return webBrowserObject; try { Class clazz = Class.forName ("org.mozilla.xpcom.Mozilla"); //$NON-NLS-1$ Method method = clazz.getMethod ("getInstance", new Class[0]); //$NON-NLS-1$ Object mozilla = method.invoke (null, new Object[0]); method = clazz.getMethod ("wrapXPCOMObject", new Class[] {Long.TYPE, String.class}); //$NON-NLS-1$ webBrowserObject = method.invoke (mozilla, new Object[] {new Long (webBrowser.getAddress ()), nsIWebBrowser.NS_IWEBBROWSER_IID_STR}); /* * The following AddRef() is needed to offset the automatic Release() that * will be performed by JavaXPCOM when webBrowserObject is finalized. */ webBrowser.AddRef (); return webBrowserObject; } catch (ClassNotFoundException e) { } catch (NoSuchMethodException e) { } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } return null; } public bool isBackEnabled () { if (awaitingNavigate) return false; int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); int[] aCanGoBack = new int[1]; /* PRBool */ rc = webNavigation.GetCanGoBack (aCanGoBack); webNavigation.Release (); return aCanGoBack[0] !is 0; } public bool isForwardEnabled () { if (awaitingNavigate) return false; int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); int[] aCanGoForward = new int[1]; /* PRBool */ rc = webNavigation.GetCanGoForward (aCanGoForward); webNavigation.Release (); return aCanGoForward[0] !is 0; } static String error (int code) { throw new DWTError ("XPCOM error " + code); //$NON-NLS-1$ } void onDispose (Display display) { int rc = webBrowser.RemoveWebBrowserListener (weakReference.getAddress (), nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID); if (rc !is XPCOM.NS_OK) error (rc); rc = webBrowser.SetParentURIContentListener (0); if (rc !is XPCOM.NS_OK) error (rc); unhookDOMListeners (); if (listener !is null) { int[] folderEvents = new int[] { DWT.Dispose, DWT.Resize, DWT.FocusIn, DWT.Activate, DWT.Deactivate, DWT.Show, DWT.KeyDown, }; for (int i = 0; i < folderEvents.length; i++) { browser.removeListener (folderEvents[i], listener); } listener = null; } int /*long*/[] result = new int /*long*/[1]; rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]); rc = baseWindow.Destroy (); if (rc !is XPCOM.NS_OK) error (rc); baseWindow.Release (); Release (); webBrowser.Release (); webBrowser = null; webBrowserObject = null; if (tip !is null && !tip.isDisposed ()) tip.dispose (); tip = null; location = size = null; Enumeration elements = unhookedDOMWindows.elements (); while (elements.hasMoreElements ()) { LONG ptrObject = (LONG)elements.nextElement (); new nsISupports (ptrObject.value).Release (); } unhookedDOMWindows = null; mozDelegate.onDispose (embedHandle); mozDelegate = null; embedHandle = 0; BrowserCount--; } void Activate () { int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIWebBrowserFocus.NS_IWEBBROWSERFOCUS_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIWebBrowserFocus webBrowserFocus = new nsIWebBrowserFocus (result[0]); rc = webBrowserFocus.Activate (); if (rc !is XPCOM.NS_OK) error (rc); webBrowserFocus.Release (); } void Deactivate () { int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIWebBrowserFocus.NS_IWEBBROWSERFOCUS_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIWebBrowserFocus webBrowserFocus = new nsIWebBrowserFocus (result[0]); rc = webBrowserFocus.Deactivate (); if (rc !is XPCOM.NS_OK) error (rc); webBrowserFocus.Release (); } void onResize () { Rectangle rect = browser.getClientArea (); int width = Math.max (1, rect.width); int height = Math.max (1, rect.height); int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); mozDelegate.setSize (embedHandle, width, height); nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]); rc = baseWindow.SetPositionAndSize (0, 0, width, height, 1); if (rc !is XPCOM.NS_OK) error (rc); baseWindow.Release (); } public void refresh () { if (awaitingNavigate) return; int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); if (rc !is XPCOM.NS_OK) error(rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); rc = webNavigation.Reload (nsIWebNavigation.LOAD_FLAGS_NONE); webNavigation.Release (); if (rc is XPCOM.NS_OK) return; /* * Feature in Mozilla. Reload returns an error code NS_ERROR_INVALID_POINTER * when it is called immediately after a request to load a new document using * LoadURI. The workaround is to ignore this error code. * * Feature in Mozilla. Attempting to reload a file that no longer exists * returns an error code of NS_ERROR_FILE_NOT_FOUND. This is equivalent to * attempting to load a non-existent local url, which is not a Browser error, * so this error code should be ignored. */ if (rc !is XPCOM.NS_ERROR_INVALID_POINTER && rc !is XPCOM.NS_ERROR_FILE_NOT_FOUND) error (rc); } public bool setText (String html) { /* * Feature in Mozilla. The focus memory of Mozilla must be * properly managed through the nsIWebBrowserFocus interface. * In particular, nsIWebBrowserFocus.deactivate must be called * when the focus moves from the browser (or one of its children * managed by Mozilla to another widget. We currently do not * get notified when a widget takes focus away from the Browser. * As a result, deactivate is not properly called. This causes * Mozilla to retake focus the next time a document is loaded. * This breaks the case where the HTML loaded in the Browser * varies while the user enters characters in a text widget. The text * widget loses focus every time new content is loaded. * The current workaround is to call deactivate everytime if * the browser currently does not have focus. A better workaround * would be to have a way to call deactivate when the Browser * or one of its children loses focus. */ if (browser !is browser.getDisplay ().getFocusControl ()) Deactivate (); /* convert the String containing HTML to an array of bytes with UTF-8 data */ byte[] data = null; try { data = html.getBytes ("UTF-8"); //$NON-NLS-1$ } catch (UnsupportedEncodingException e) { return false; } awaitingNavigate = false; byte[] contentTypeBuffer = MozillaDelegate.wcsToMbcs (null, "text/html", true); // $NON-NLS-1$ int /*long*/ aContentType = XPCOM.nsEmbedCString_new (contentTypeBuffer, contentTypeBuffer.length); byte[] contentCharsetBuffer = MozillaDelegate.wcsToMbcs (null, "UTF-8", true); //$NON-NLS-1$ int /*long*/ aContentCharset = XPCOM.nsEmbedCString_new (contentCharsetBuffer, contentCharsetBuffer.length); int /*long*/[] result = new int /*long*/[1]; int rc = XPCOM.NS_GetServiceManager (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIServiceManager serviceManager = new nsIServiceManager (result[0]); result[0] = 0; rc = serviceManager.GetService (XPCOM.NS_IOSERVICE_CID, nsIIOService.NS_IIOSERVICE_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); serviceManager.Release (); nsIIOService ioService = new nsIIOService (result[0]); result[0] = 0; /* * Note. Mozilla ignores LINK tags used to load CSS stylesheets * when the URI protocol for the nsInputStreamChannel * is about:blank. The fix is to specify the file protocol. */ byte[] aString = MozillaDelegate.wcsToMbcs (null, URI_FROMMEMORY, false); int /*long*/ aSpec = XPCOM.nsEmbedCString_new (aString, aString.length); rc = ioService.NewURI (aSpec, null, 0, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); XPCOM.nsEmbedCString_delete (aSpec); ioService.Release (); nsIURI uri = new nsIURI (result[0]); result[0] = 0; rc = webBrowser.QueryInterface (nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIInterfaceRequestor interfaceRequestor = new nsIInterfaceRequestor (result[0]); result[0] = 0; /* * Feature in Mozilla. LoadStream invokes the nsIInputStream argument * through a different thread. The callback mechanism must attach * a non java thread to the JVM otherwise the nsIInputStream Read and * Close methods never get called. */ InputStream inputStream = new InputStream (data); inputStream.AddRef (); rc = interfaceRequestor.GetInterface (nsIDocShell_1_9.NS_IDOCSHELL_IID, result); if (rc is XPCOM.NS_OK) { if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIDocShell_1_9 docShell = new nsIDocShell_1_9 (result[0]); rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType, aContentCharset, 0); docShell.Release (); } else { result[0] = 0; rc = interfaceRequestor.GetInterface (nsIDocShell_1_8.NS_IDOCSHELL_IID, result); if (rc is XPCOM.NS_OK) { if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIDocShell_1_8 docShell = new nsIDocShell_1_8 (result[0]); rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType, aContentCharset, 0); docShell.Release (); } else { result[0] = 0; rc = interfaceRequestor.GetInterface (nsIDocShell.NS_IDOCSHELL_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIDocShell docShell = new nsIDocShell (result[0]); rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType, aContentCharset, 0); docShell.Release (); } } if (rc !is XPCOM.NS_OK) error (rc); result[0] = 0; inputStream.Release (); interfaceRequestor.Release (); uri.Release (); XPCOM.nsEmbedCString_delete (aContentCharset); XPCOM.nsEmbedCString_delete (aContentType); return true; } public bool setUrl (String url) { awaitingNavigate = false; int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); char[] uri = new char[url.length () + 1]; url.getChars (0, url.length (), uri, 0); rc = webNavigation.LoadURI (uri, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0); webNavigation.Release (); return rc is XPCOM.NS_OK; } public void stop () { if (awaitingNavigate) return; int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); rc = webNavigation.Stop (nsIWebNavigation.STOP_ALL); if (rc !is XPCOM.NS_OK) error (rc); webNavigation.Release (); } void hookDOMListeners (nsIDOMEventTarget target, bool isTop) { nsEmbedString string = new nsEmbedString (XPCOM.DOMEVENT_FOCUS); target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_UNLOAD); target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDOWN); target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEUP); target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEMOVE); target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEWHEEL); target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDRAG); target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); /* * Only hook mouseover and mouseout if the target is a top-level frame, so that mouse moves * between frames will not generate events. */ if (isTop && mozDelegate.hookEnterExit ()) { string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOVER); target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOUT); target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); } string = new nsEmbedString (XPCOM.DOMEVENT_KEYDOWN); target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_KEYPRESS); target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_KEYUP); target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); } void unhookDOMListeners () { int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.GetContentDOMWindow (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIDOMWindow window = new nsIDOMWindow (result[0]); result[0] = 0; rc = window.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]); result[0] = 0; unhookDOMListeners (target); target.Release (); /* Listeners must be unhooked in pages contained in frames */ rc = window.GetFrames (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIDOMWindowCollection frames = new nsIDOMWindowCollection (result[0]); result[0] = 0; int[] frameCount = new int[1]; rc = frames.GetLength (frameCount); /* PRUint32 */ if (rc !is XPCOM.NS_OK) error (rc); int count = frameCount[0]; if (count > 0) { for (int i = 0; i < count; i++) { rc = frames.Item (i, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIDOMWindow frame = new nsIDOMWindow (result[0]); result[0] = 0; rc = frame.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); target = new nsIDOMEventTarget (result[0]); result[0] = 0; unhookDOMListeners (target); target.Release (); frame.Release (); } } frames.Release (); window.Release (); } void unhookDOMListeners (nsIDOMEventTarget target) { nsEmbedString string = new nsEmbedString (XPCOM.DOMEVENT_FOCUS); target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_UNLOAD); target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDOWN); target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEUP); target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEMOVE); target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEWHEEL); target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDRAG); target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOVER); target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOUT); target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_KEYDOWN); target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_KEYPRESS); target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); string = new nsEmbedString (XPCOM.DOMEVENT_KEYUP); target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0); string.dispose (); } /* nsISupports */ int QueryInterface (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; } int AddRef () { refCount++; return refCount; } int Release () { refCount--; if (refCount is 0) return 0; return refCount; } /* nsIWeakReference */ int QueryReferent (nsID* riid, void** ppvObject) { return QueryInterface (riid, ppvObject); } /* nsIInterfaceRequestor */ int GetInterface ( nsID* riid, void** ppvObject) { if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE; nsID guid = new nsID (); XPCOM.memmove (guid, riid, nsID.sizeof); if (guid.Equals (nsIDOMWindow.NS_IDOMWINDOW_IID)) { int /*long*/[] aContentDOMWindow = new int /*long*/[1]; int rc = webBrowser.GetContentDOMWindow (aContentDOMWindow); if (rc !is XPCOM.NS_OK) error (rc); if (aContentDOMWindow[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); XPCOM.memmove (ppvObject, aContentDOMWindow, C.PTR_SIZEOF); return rc; } return QueryInterface (riid, ppvObject); } int GetWeakReference (int /*long*/ ppvObject) { XPCOM.memmove (ppvObject, new int /*long*/[] {weakReference.getAddress ()}, C.PTR_SIZEOF); AddRef (); return XPCOM.NS_OK; } /* nsIWebProgressListener */ int OnStateChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStateFlags, int aStatus) { if ((aStateFlags & nsIWebProgressListener.STATE_IS_DOCUMENT) is 0) return XPCOM.NS_OK; if ((aStateFlags & nsIWebProgressListener.STATE_START) !is 0) { if (request is 0) request = aRequest; if (!awaitingNavigate) { /* * Add the page's nsIDOMWindow to the collection of windows that will * have DOM listeners added to them later on in the page loading * process. These listeners cannot be added yet because the * nsIDOMWindow is not ready to take them at this stage. */ int /*long*/[] result = new int /*long*/[1]; nsIWebProgress progress = new nsIWebProgress (aWebProgress); int rc = progress.GetDOMWindow (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); unhookedDOMWindows.addElement (new LONG (result[0])); } } else if ((aStateFlags & nsIWebProgressListener.STATE_REDIRECTING) !is 0) { if (request is aRequest) request = 0; } else if ((aStateFlags & nsIWebProgressListener.STATE_STOP) !is 0) { /* * If this page's nsIDOMWindow handle is still in unhookedDOMWindows then * add its DOM listeners now. It's possible for this to happen since * there is no guarantee that a STATE_TRANSFERRING state change will be * received for every window in a page, which is when these listeners * are typically added. */ int /*long*/[] result = new int /*long*/[1]; nsIWebProgress progress = new nsIWebProgress (aWebProgress); int rc = progress.GetDOMWindow (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIDOMWindow domWindow = new nsIDOMWindow (result[0]); LONG ptrObject = new LONG (result[0]); result[0] = 0; int index = unhookedDOMWindows.indexOf (ptrObject); if (index !is -1) { rc = webBrowser.GetContentDOMWindow (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); bool isTop = result[0] is domWindow.getAddress (); new nsISupports (result[0]).Release (); result[0] = 0; rc = domWindow.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]); result[0] = 0; hookDOMListeners (target, isTop); target.Release (); /* * Remove and unreference the nsIDOMWindow from the collection of windows * that are waiting to have DOM listeners hooked on them. */ unhookedDOMWindows.remove (ptrObject); new nsISupports (ptrObject.value).Release (); } domWindow.Release (); /* * Feature in Mozilla. When a request is redirected (STATE_REDIRECTING), * it never reaches the state STATE_STOP and it is replaced with a new request. * The new request is received when it is in the state STATE_STOP. * To handle this case, the variable request is set to 0 when the corresponding * request is redirected. The following request received with the state STATE_STOP * - the new request resulting from the redirection - is used to send * the ProgressListener.completed event. */ if (request is aRequest || request is 0) { request = 0; if (!awaitingNavigate) { StatusTextEvent event = new StatusTextEvent (browser); event.display = browser.getDisplay (); event.widget = browser; event.text = ""; //$NON-NLS-1$ for (int i = 0; i < statusTextListeners.length; i++) { statusTextListeners[i].changed (event); } ProgressEvent event2 = new ProgressEvent (browser); event2.display = browser.getDisplay (); event2.widget = browser; for (int i = 0; i < progressListeners.length; i++) { progressListeners[i].completed (event2); } } } } else if ((aStateFlags & nsIWebProgressListener.STATE_TRANSFERRING) !is 0) { /* * Hook DOM listeners to the page's nsIDOMWindow here because this is * the earliest opportunity to do so. */ int /*long*/[] result = new int /*long*/[1]; nsIWebProgress progress = new nsIWebProgress (aWebProgress); int rc = progress.GetDOMWindow (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIDOMWindow domWindow = new nsIDOMWindow (result[0]); LONG ptrObject = new LONG (result[0]); result[0] = 0; int index = unhookedDOMWindows.indexOf (ptrObject); if (index !is -1) { rc = webBrowser.GetContentDOMWindow (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); bool isTop = result[0] is domWindow.getAddress (); new nsISupports (result[0]).Release (); result[0] = 0; rc = domWindow.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]); result[0] = 0; hookDOMListeners (target, isTop); target.Release (); /* * Remove and unreference the nsIDOMWindow from the collection of windows * that are waiting to have DOM listeners hooked on them. */ unhookedDOMWindows.remove (ptrObject); new nsISupports (ptrObject.value).Release (); } domWindow.Release (); } return XPCOM.NS_OK; } int OnProgressChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aCurSelfProgress, int aMaxSelfProgress, int aCurTotalProgress, int aMaxTotalProgress) { if (awaitingNavigate || progressListeners.length is 0) return XPCOM.NS_OK; ProgressEvent event = new ProgressEvent (browser); event.display = browser.getDisplay (); event.widget = browser; event.current = aCurTotalProgress; event.total = aMaxTotalProgress; for (int i = 0; i < progressListeners.length; i++) { progressListeners[i].changed (event); } return XPCOM.NS_OK; } int OnLocationChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int /*long*/ aLocation) { /* * Feature in Mozilla. When a page is loaded via setText before a previous * setText page load has completed, the expected OnStateChange STATE_STOP for the * original setText never arrives because it gets replaced by the OnStateChange * STATE_STOP for the new request. This results in the request field never being * cleared because the original request's OnStateChange STATE_STOP is still expected * (but never arrives). To handle this case, the request field is updated to the new * overriding request since its OnStateChange STATE_STOP will be received next. */ if (request !is 0 && request !is aRequest) request = aRequest; if (awaitingNavigate || locationListeners.length is 0) return XPCOM.NS_OK; nsIWebProgress webProgress = new nsIWebProgress (aWebProgress); int /*long*/[] aDOMWindow = new int /*long*/[1]; int rc = webProgress.GetDOMWindow (aDOMWindow); if (rc !is XPCOM.NS_OK) error (rc); if (aDOMWindow[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIDOMWindow domWindow = new nsIDOMWindow (aDOMWindow[0]); int /*long*/[] aTop = new int /*long*/[1]; rc = domWindow.GetTop (aTop); if (rc !is XPCOM.NS_OK) error (rc); if (aTop[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); domWindow.Release (); nsIDOMWindow topWindow = new nsIDOMWindow (aTop[0]); topWindow.Release (); nsIURI location = new nsIURI (aLocation); int /*long*/ aSpec = XPCOM.nsEmbedCString_new (); location.GetSpec (aSpec); int length = XPCOM.nsEmbedCString_Length (aSpec); int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec); byte[] dest = new byte[length]; XPCOM.memmove (dest, buffer, length); XPCOM.nsEmbedCString_delete (aSpec); String url = new String (dest); /* * As of Mozilla 1.8, the first time that a page is displayed, regardless of * whether it's via Browser.setURL() or Browser.setText(), the GRE navigates * to about:blank and fires the corresponding navigation events. Do not send * this event on to the user since it is not expected. */ if (!IsPre_1_8 && aRequest is 0 && url.startsWith (ABOUT_BLANK)) return XPCOM.NS_OK; LocationEvent event = new LocationEvent (browser); event.display = browser.getDisplay (); event.widget = browser; event.location = url; /* * If the URI indicates that the page is being rendered from memory * (via setText()) then set it to about:blank to be consistent with IE. */ if (event.location.equals (URI_FROMMEMORY)) event.location = ABOUT_BLANK; event.top = aTop[0] is aDOMWindow[0]; for (int i = 0; i < locationListeners.length; i++) { locationListeners[i].changed (event); } return XPCOM.NS_OK; } int OnStatusChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStatus, int /*long*/ aMessage) { if (awaitingNavigate || statusTextListeners.length is 0) return XPCOM.NS_OK; StatusTextEvent event = new StatusTextEvent (browser); event.display = browser.getDisplay (); event.widget = browser; int length = XPCOM.strlen_PRUnichar (aMessage); char[] dest = new char[length]; XPCOM.memmove (dest, aMessage, length * 2); event.text = new String (dest); for (int i = 0; i < statusTextListeners.length; i++) { statusTextListeners[i].changed (event); } return XPCOM.NS_OK; } int OnSecurityChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int state) { return XPCOM.NS_OK; } /* nsIWebBrowserChrome */ int SetStatus (int statusType, int /*long*/ status) { if (awaitingNavigate || statusTextListeners.length is 0) return XPCOM.NS_OK; StatusTextEvent event = new StatusTextEvent (browser); event.display = browser.getDisplay (); event.widget = browser; int length = XPCOM.strlen_PRUnichar (status); char[] dest = new char[length]; XPCOM.memmove (dest, status, length * 2); String string = new String (dest); event.text = string; for (int i = 0; i < statusTextListeners.length; i++) { statusTextListeners[i].changed (event); } return XPCOM.NS_OK; } int GetWebBrowser (int /*long*/ aWebBrowser) { int /*long*/[] ret = new int /*long*/[1]; if (webBrowser !is null) { webBrowser.AddRef (); ret[0] = webBrowser.getAddress (); } XPCOM.memmove (aWebBrowser, ret, C.PTR_SIZEOF); return XPCOM.NS_OK; } int SetWebBrowser (int /*long*/ aWebBrowser) { if (webBrowser !is null) webBrowser.Release (); webBrowser = aWebBrowser !is 0 ? new nsIWebBrowser (aWebBrowser) : null; return XPCOM.NS_OK; } int GetChromeFlags (int /*long*/ aChromeFlags) { int[] ret = new int[1]; ret[0] = chromeFlags; XPCOM.memmove (aChromeFlags, ret, 4); /* PRUint32 */ return XPCOM.NS_OK; } int SetChromeFlags (int aChromeFlags) { chromeFlags = aChromeFlags; return XPCOM.NS_OK; } int DestroyBrowserWindow () { WindowEvent newEvent = new WindowEvent (browser); newEvent.display = browser.getDisplay (); newEvent.widget = browser; for (int i = 0; i < closeWindowListeners.length; i++) { closeWindowListeners[i].close (newEvent); } /* * Note on Mozilla. The DestroyBrowserWindow notification cannot be cancelled. * The browser widget cannot be used after this notification has been received. * The application is advised to close the window hosting the browser widget. * The browser widget must be disposed in all cases. */ browser.dispose (); return XPCOM.NS_OK; } int SizeBrowserTo (int aCX, int aCY) { size = new Point (aCX, aCY); bool isChrome = (chromeFlags & nsIWebBrowserChrome.CHROME_OPENAS_CHROME) !is 0; if (isChrome) { Shell shell = browser.getShell (); shell.setSize (shell.computeSize (size.x, size.y)); } return XPCOM.NS_OK; } int ShowAsModal () { int /*long*/[] result = new int /*long*/[1]; int rc = XPCOM.NS_GetServiceManager (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIServiceManager serviceManager = new nsIServiceManager (result[0]); result[0] = 0; byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_CONTEXTSTACK_CONTRACTID, true); rc = serviceManager.GetServiceByContractID (aContractID, nsIJSContextStack.NS_IJSCONTEXTSTACK_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); serviceManager.Release (); nsIJSContextStack stack = new nsIJSContextStack (result[0]); result[0] = 0; rc = stack.Push (0); if (rc !is XPCOM.NS_OK) error (rc); Shell shell = browser.getShell (); Display display = browser.getDisplay (); while (!shell.isDisposed ()) { if (!display.readAndDispatch ()) display.sleep (); } rc = stack.Pop (result); if (rc !is XPCOM.NS_OK) error (rc); stack.Release (); return XPCOM.NS_OK; } int IsWindowModal (int /*long*/ retval) { int result = (chromeFlags & nsIWebBrowserChrome.CHROME_MODAL) !is 0 ? 1 : 0; XPCOM.memmove (retval, new int[] {result}, 4); /* PRBool */ return XPCOM.NS_OK; } int ExitModalEventLoop (int aStatus) { return XPCOM.NS_OK; } /* nsIEmbeddingSiteWindow */ int SetDimensions (int flags, int x, int y, int cx, int cy) { if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_POSITION) !is 0) { location = new Point (x, y); browser.getShell ().setLocation (x, y); } if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_INNER) !is 0) { browser.setSize (cx, cy); } if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_OUTER) !is 0) { browser.getShell ().setSize (cx, cy); } return XPCOM.NS_OK; } int GetDimensions (int flags, int /*long*/ x, int /*long*/ y, int /*long*/ cx, int /*long*/ cy) { if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_POSITION) !is 0) { Point location = browser.getShell ().getLocation (); if (x !is 0) C.memmove (x, new int[] {location.x}, 4); /* PRInt32 */ if (y !is 0) C.memmove (y, new int[] {location.y}, 4); /* PRInt32 */ } if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_INNER) !is 0) { Point size = browser.getSize (); if (cx !is 0) C.memmove (cx, new int[] {size.x}, 4); /* PRInt32 */ if (cy !is 0) C.memmove (cy, new int[] {size.y}, 4); /* PRInt32 */ } if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_OUTER) !is 0) { Point size = browser.getShell().getSize (); if (cx !is 0) C.memmove (cx, new int[] {size.x}, 4); /* PRInt32 */ if (cy !is 0) C.memmove (cy, new int[] {size.y}, 4); /* PRInt32 */ } return XPCOM.NS_OK; } int SetFocus () { int /*long*/[] result = new int /*long*/[1]; int rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE); nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]); rc = baseWindow.SetFocus (); if (rc !is XPCOM.NS_OK) error (rc); baseWindow.Release (); /* * Note. Mozilla notifies here that one of the children took * focus. This could or should be used to fire an DWT.FOCUS_IN * event on Browser focus listeners. */ return XPCOM.NS_OK; } int GetVisibility (int /*long*/ aVisibility) { bool visible = browser.isVisible () && !browser.getShell ().getMinimized (); XPCOM.memmove (aVisibility, new int[] {visible ? 1 : 0}, 4); /* PRBool */ return XPCOM.NS_OK; } int SetVisibility (int aVisibility) { if (isChild) { WindowEvent event = new WindowEvent (browser); event.display = browser.getDisplay (); event.widget = browser; if (aVisibility !is 0) { /* * Bug in Mozilla. When the JavaScript window.open is executed, Mozilla * fires multiple SetVisibility 1 notifications. The workaround is * to ignore subsequent notifications. */ if (!visible) { visible = true; event.location = location; event.size = size; event.addressBar = (chromeFlags & nsIWebBrowserChrome.CHROME_LOCATIONBAR) !is 0; event.menuBar = (chromeFlags & nsIWebBrowserChrome.CHROME_MENUBAR) !is 0; event.statusBar = (chromeFlags & nsIWebBrowserChrome.CHROME_STATUSBAR) !is 0; event.toolBar = (chromeFlags & nsIWebBrowserChrome.CHROME_TOOLBAR) !is 0; for (int i = 0; i < visibilityWindowListeners.length; i++) { visibilityWindowListeners[i].show (event); } location = null; size = null; } } else { visible = false; for (int i = 0; i < visibilityWindowListeners.length; i++) { visibilityWindowListeners[i].hide (event); } } } else { visible = aVisibility !is 0; } return XPCOM.NS_OK; } int GetTitle (int /*long*/ aTitle) { return XPCOM.NS_OK; } int SetTitle (int /*long*/ aTitle) { if (awaitingNavigate || titleListeners.length is 0) return XPCOM.NS_OK; TitleEvent event = new TitleEvent (browser); event.display = browser.getDisplay (); event.widget = browser; /* * To be consistent with other platforms the title event should * contain the page's url if the page does not contain a <title> * tag. */ int length = XPCOM.strlen_PRUnichar (aTitle); if (length > 0) { char[] dest = new char[length]; XPCOM.memmove (dest, aTitle, length * 2); event.title = new String (dest); } else { event.title = getUrl (); } for (int i = 0; i < titleListeners.length; i++) { titleListeners[i].changed (event); } return XPCOM.NS_OK; } int GetSiteWindow (int /*long*/ aSiteWindow) { /* * Note. The handle is expected to be an HWND on Windows and * a GtkWidget* on GTK. This callback is invoked on Windows * when the javascript window.print is invoked and the print * dialog comes up. If no handle is returned, the print dialog * does not come up on this platform. */ XPCOM.memmove (aSiteWindow, new int /*long*/[] {embedHandle}, C.PTR_SIZEOF); return XPCOM.NS_OK; } /* nsIWebBrowserChromeFocus */ int FocusNextElement () { /* * Bug in Mozilla embedding API. Mozilla takes back the focus after sending * this event. This prevents tabbing out of Mozilla. This behaviour can be reproduced * with the Mozilla application TestGtkEmbed. The workaround is to * send the traversal notification after this callback returns. */ browser.getDisplay ().asyncExec (new Runnable () { public void run () { if (browser.isDisposed ()) return; browser.traverse (DWT.TRAVERSE_TAB_NEXT); } }); return XPCOM.NS_OK; } int FocusPrevElement () { /* * Bug in Mozilla embedding API. Mozilla takes back the focus after sending * this event. This prevents tabbing out of Mozilla. This behaviour can be reproduced * with the Mozilla application TestGtkEmbed. The workaround is to * send the traversal notification after this callback returns. */ browser.getDisplay ().asyncExec (new Runnable () { public void run () { if (browser.isDisposed ()) return; browser.traverse (DWT.TRAVERSE_TAB_PREVIOUS); } }); return XPCOM.NS_OK; } /* nsIContextMenuListener */ int OnShowContextMenu (int aContextFlags, int /*long*/ aEvent, int /*long*/ aNode) { if (awaitingNavigate) return XPCOM.NS_OK; nsIDOMEvent domEvent = new nsIDOMEvent (aEvent); int /*long*/[] result = new int /*long*/[1]; int rc = domEvent.QueryInterface (nsIDOMMouseEvent.NS_IDOMMOUSEEVENT_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIDOMMouseEvent domMouseEvent = new nsIDOMMouseEvent (result[0]); int[] aScreenX = new int[1], aScreenY = new int[1]; rc = domMouseEvent.GetScreenX (aScreenX); if (rc !is XPCOM.NS_OK) error (rc); rc = domMouseEvent.GetScreenY (aScreenY); if (rc !is XPCOM.NS_OK) error (rc); domMouseEvent.Release (); Event event = new Event (); event.x = aScreenX[0]; event.y = aScreenY[0]; browser.notifyListeners (DWT.MenuDetect, event); if (!event.doit) return XPCOM.NS_OK; Menu menu = browser.getMenu (); if (menu !is null && !menu.isDisposed ()) { if (aScreenX[0] !is event.x || aScreenY[0] !is event.y) { menu.setLocation (event.x, event.y); } menu.setVisible (true); } return XPCOM.NS_OK; } /* nsIURIContentListener */ int OnStartURIOpen (int /*long*/ aURI, int /*long*/ retval) { if (awaitingNavigate || locationListeners.length is 0) { XPCOM.memmove (retval, new int[] {0}, 4); /* PRBool */ return XPCOM.NS_OK; } nsIURI location = new nsIURI (aURI); int /*long*/ aSpec = XPCOM.nsEmbedCString_new (); location.GetSpec (aSpec); int length = XPCOM.nsEmbedCString_Length (aSpec); int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec); buffer = XPCOM.nsEmbedCString_get (aSpec); byte[] dest = new byte[length]; XPCOM.memmove (dest, buffer, length); XPCOM.nsEmbedCString_delete (aSpec); String value = new String (dest); bool doit = true; if (request is 0) { /* * listeners should not be notified of internal transitions like "javascipt:..." * because this is an implementation side-effect, not a true navigate */ if (!value.startsWith (PREFIX_JAVASCRIPT)) { LocationEvent event = new LocationEvent (browser); event.display = browser.getDisplay(); event.widget = browser; event.location = value; /* * If the URI indicates that the page is being rendered from memory * (via setText()) then set it to about:blank to be consistent with IE. */ if (event.location.equals (URI_FROMMEMORY)) event.location = ABOUT_BLANK; event.doit = doit; for (int i = 0; i < locationListeners.length; i++) { locationListeners[i].changing (event); } doit = event.doit && !browser.isDisposed(); } } XPCOM.memmove (retval, new int[] {doit ? 0 : 1}, 4); /* PRBool */ return XPCOM.NS_OK; } int DoContent (int /*long*/ aContentType, int aIsContentPreferred, int /*long*/ aRequest, int /*long*/ aContentHandler, int /*long*/ retval) { return XPCOM.NS_ERROR_NOT_IMPLEMENTED; } int IsPreferred (int /*long*/ aContentType, int /*long*/ aDesiredContentType, int /*long*/ retval) { bool preferred = false; int size = XPCOM.strlen (aContentType); if (size > 0) { byte[] typeBytes = new byte[size + 1]; XPCOM.memmove (typeBytes, aContentType, size); String contentType = new String (typeBytes, 0, size); /* do not attempt to handle known problematic content types */ if (!contentType.equals (XPCOM.CONTENT_MAYBETEXT) && !contentType.equals (XPCOM.CONTENT_MULTIPART)) { /* determine whether browser can handle the content type */ int /*long*/[] result = new int /*long*/[1]; int rc = XPCOM.NS_GetServiceManager (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIServiceManager serviceManager = new nsIServiceManager (result[0]); result[0] = 0; /* First try to use the nsIWebNavigationInfo if it's available (>= mozilla 1.8) */ byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_WEBNAVIGATIONINFO_CONTRACTID, true); rc = serviceManager.GetServiceByContractID (aContractID, nsIWebNavigationInfo.NS_IWEBNAVIGATIONINFO_IID, result); if (rc is 0) { byte[] bytes = MozillaDelegate.wcsToMbcs (null, contentType, true); int /*long*/ typePtr = XPCOM.nsEmbedCString_new (bytes, bytes.length); nsIWebNavigationInfo info = new nsIWebNavigationInfo (result[0]); result[0] = 0; int[] isSupportedResult = new int[1]; /* PRUint32 */ rc = info.IsTypeSupported (typePtr, 0, isSupportedResult); if (rc !is XPCOM.NS_OK) error (rc); info.Release (); XPCOM.nsEmbedCString_delete (typePtr); preferred = isSupportedResult[0] !is 0; } else { /* nsIWebNavigationInfo is not available, so do the type lookup */ result[0] = 0; rc = serviceManager.GetService (XPCOM.NS_CATEGORYMANAGER_CID, nsICategoryManager.NS_ICATEGORYMANAGER_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsICategoryManager categoryManager = new nsICategoryManager (result[0]); result[0] = 0; byte[] categoryBytes = MozillaDelegate.wcsToMbcs (null, "Gecko-Content-Viewers", true); //$NON-NLS-1$ rc = categoryManager.GetCategoryEntry (categoryBytes, typeBytes, result); categoryManager.Release (); /* if no viewer for the content type is registered then rc is XPCOM.NS_ERROR_NOT_AVAILABLE */ preferred = rc is XPCOM.NS_OK; } serviceManager.Release (); } } XPCOM.memmove(retval, new int[] {preferred ? 1 : 0}, 4); /* PRBool */ if (preferred) { XPCOM.memmove (aDesiredContentType, new int /*long*/[] {0}, C.PTR_SIZEOF); } return XPCOM.NS_OK; } int CanHandleContent (int /*long*/ aContentType, int aIsContentPreferred, int /*long*/ aDesiredContentType, int /*long*/ retval) { return XPCOM.NS_ERROR_NOT_IMPLEMENTED; } int GetLoadCookie (int /*long*/ aLoadCookie) { return XPCOM.NS_ERROR_NOT_IMPLEMENTED; } int SetLoadCookie (int /*long*/ aLoadCookie) { return XPCOM.NS_ERROR_NOT_IMPLEMENTED; } int GetParentContentListener (int /*long*/ aParentContentListener) { return XPCOM.NS_ERROR_NOT_IMPLEMENTED; } int SetParentContentListener (int /*long*/ aParentContentListener) { return XPCOM.NS_ERROR_NOT_IMPLEMENTED; } /* nsITooltipListener */ int OnShowTooltip (int aXCoords, int aYCoords, int /*long*/ aTipText) { if (awaitingNavigate) return XPCOM.NS_OK; int length = XPCOM.strlen_PRUnichar (aTipText); char[] dest = new char[length]; XPCOM.memmove (dest, aTipText, length * 2); String text = new String (dest); if (tip !is null && !tip.isDisposed ()) tip.dispose (); Display display = browser.getDisplay (); Shell parent = browser.getShell (); tip = new Shell (parent, DWT.ON_TOP); tip.setLayout (new FillLayout()); Label label = new Label (tip, DWT.CENTER); label.setForeground (display.getSystemColor (DWT.COLOR_INFO_FOREGROUND)); label.setBackground (display.getSystemColor (DWT.COLOR_INFO_BACKGROUND)); label.setText (text); /* * Bug in Mozilla embedded API. Tooltip coordinates are wrong for * elements inside an inline frame (IFrame tag). The workaround is * to position the tooltip based on the mouse cursor location. */ Point point = display.getCursorLocation (); /* Assuming cursor is 21x21 because this is the size of * the arrow cursor on Windows */ point.y += 21; tip.setLocation (point); tip.pack (); tip.setVisible (true); return XPCOM.NS_OK; } int OnHideTooltip () { if (tip !is null && !tip.isDisposed ()) tip.dispose (); tip = null; return XPCOM.NS_OK; } /* nsIDOMEventListener */ int HandleEvent (int /*long*/ event) { nsIDOMEvent domEvent = new nsIDOMEvent (event); int /*long*/ type = XPCOM.nsEmbedString_new (); int rc = domEvent.GetType (type); if (rc !is XPCOM.NS_OK) error (rc); int length = XPCOM.nsEmbedString_Length (type); int /*long*/ buffer = XPCOM.nsEmbedString_get (type); char[] chars = new char[length]; XPCOM.memmove (chars, buffer, length * 2); String typeString = new String (chars); XPCOM.nsEmbedString_delete (type); if (XPCOM.DOMEVENT_UNLOAD.equals (typeString)) { int /*long*/[] result = new int /*long*/[1]; rc = domEvent.GetCurrentTarget (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]); unhookDOMListeners (target); target.Release (); return XPCOM.NS_OK; } if (XPCOM.DOMEVENT_FOCUS.equals (typeString)) { mozDelegate.handleFocus (); return XPCOM.NS_OK; } if (XPCOM.DOMEVENT_KEYDOWN.equals (typeString)) { int /*long*/[] result = new int /*long*/[1]; rc = domEvent.QueryInterface (nsIDOMKeyEvent.NS_IDOMKEYEVENT_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIDOMKeyEvent domKeyEvent = new nsIDOMKeyEvent (result[0]); result[0] = 0; int[] aKeyCode = new int[1]; /* PRUint32 */ rc = domKeyEvent.GetKeyCode (aKeyCode); if (rc !is XPCOM.NS_OK) error (rc); int keyCode = translateKey (aKeyCode[0]); /* * if keyCode is lastKeyCode then either a repeating key like Shift * is being held or a key for which key events are not sent has been * pressed. In both of these cases a KeyDown should not be sent. */ if (keyCode !is lastKeyCode) { lastKeyCode = keyCode; switch (keyCode) { case DWT.SHIFT: case DWT.CONTROL: case DWT.ALT: case DWT.CAPS_LOCK: case DWT.NUM_LOCK: case DWT.SCROLL_LOCK: case DWT.COMMAND: { /* keypress events will not be received for these keys, so send KeyDowns for them now */ int[] aAltKey = new int[1], aCtrlKey = new int[1], aShiftKey = new int[1], aMetaKey = new int[1]; /* PRBool */ rc = domKeyEvent.GetAltKey (aAltKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domKeyEvent.GetCtrlKey (aCtrlKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domKeyEvent.GetShiftKey (aShiftKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domKeyEvent.GetMetaKey (aMetaKey); if (rc !is XPCOM.NS_OK) error (rc); Event keyEvent = new Event (); keyEvent.widget = browser; keyEvent.type = DWT.KeyDown; keyEvent.keyCode = keyCode; keyEvent.stateMask = (aAltKey[0] !is 0 ? DWT.ALT : 0) | (aCtrlKey[0] !is 0 ? DWT.CTRL : 0) | (aShiftKey[0] !is 0 ? DWT.SHIFT : 0) | (aMetaKey[0] !is 0 ? DWT.COMMAND : 0); keyEvent.stateMask &= ~keyCode; /* remove current keydown if it's a state key */ browser.notifyListeners (keyEvent.type, keyEvent); if (!keyEvent.doit) { domEvent.PreventDefault (); } break; } default: { /* * If the keydown has Meta (but not Meta+Ctrl) as a modifier then send a KeyDown event for it here * because a corresponding keypress event will not be received for it from the DOM. If the keydown * does not have Meta as a modifier, or has Meta+Ctrl as a modifier, then then do nothing here * because its KeyDown event will be sent from the keypress listener. */ int[] aMetaKey = new int[1]; /* PRBool */ rc = domKeyEvent.GetMetaKey (aMetaKey); if (rc !is XPCOM.NS_OK) error (rc); if (aMetaKey[0] !is 0) { int[] aCtrlKey = new int[1]; /* PRBool */ rc = domKeyEvent.GetCtrlKey (aCtrlKey); if (rc !is XPCOM.NS_OK) error (rc); if (aCtrlKey[0] is 0) { int[] aAltKey = new int[1], aShiftKey = new int[1]; /* PRBool */ rc = domKeyEvent.GetAltKey (aAltKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domKeyEvent.GetShiftKey (aShiftKey); if (rc !is XPCOM.NS_OK) error (rc); Event keyEvent = new Event (); keyEvent.widget = browser; keyEvent.type = DWT.KeyDown; keyEvent.keyCode = lastKeyCode; keyEvent.stateMask = (aAltKey[0] !is 0 ? DWT.ALT : 0) | (aCtrlKey[0] !is 0? DWT.CTRL : 0) | (aShiftKey[0] !is 0? DWT.SHIFT : 0) | (aMetaKey[0] !is 0? DWT.COMMAND : 0); browser.notifyListeners (keyEvent.type, keyEvent); if (!keyEvent.doit) { domEvent.PreventDefault (); } } } } } } domKeyEvent.Release (); return XPCOM.NS_OK; } if (XPCOM.DOMEVENT_KEYPRESS.equals (typeString)) { /* * if keydown could not determine a keycode for this key then it's a * key for which key events are not sent (eg.- the Windows key) */ if (lastKeyCode is 0) return XPCOM.NS_OK; /* * On linux only, unexpected keypress events are received for some * modifier keys. The workaround is to ignore these events since * KeyDown events are sent for these keys in the keydown listener. */ switch (lastKeyCode) { case DWT.CAPS_LOCK: case DWT.NUM_LOCK: case DWT.SCROLL_LOCK: return XPCOM.NS_OK; } int /*long*/[] result = new int /*long*/[1]; rc = domEvent.QueryInterface (nsIDOMKeyEvent.NS_IDOMKEYEVENT_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIDOMKeyEvent domKeyEvent = new nsIDOMKeyEvent (result[0]); result[0] = 0; int[] aAltKey = new int[1], aCtrlKey = new int[1], aShiftKey = new int[1], aMetaKey = new int[1]; /* PRBool */ rc = domKeyEvent.GetAltKey (aAltKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domKeyEvent.GetCtrlKey (aCtrlKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domKeyEvent.GetShiftKey (aShiftKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domKeyEvent.GetMetaKey (aMetaKey); if (rc !is XPCOM.NS_OK) error (rc); domKeyEvent.Release (); int[] aCharCode = new int[1]; /* PRUint32 */ rc = domKeyEvent.GetCharCode (aCharCode); if (rc !is XPCOM.NS_OK) error (rc); lastCharCode = aCharCode[0]; if (lastCharCode is 0) { switch (lastKeyCode) { case DWT.TAB: lastCharCode = DWT.TAB; break; case DWT.CR: lastCharCode = DWT.CR; break; case DWT.BS: lastCharCode = DWT.BS; break; case DWT.ESC: lastCharCode = DWT.ESC; break; case DWT.DEL: lastCharCode = DWT.DEL; break; } } if (aCtrlKey[0] !is 0 && (0 <= lastCharCode && lastCharCode <= 0x7F)) { if ('a' <= lastCharCode && lastCharCode <= 'z') lastCharCode -= 'a' - 'A'; if (64 <= lastCharCode && lastCharCode <= 95) lastCharCode -= 64; } Event keyEvent = new Event (); keyEvent.widget = browser; keyEvent.type = DWT.KeyDown; keyEvent.keyCode = lastKeyCode; keyEvent.character = (char)lastCharCode; keyEvent.stateMask = (aAltKey[0] !is 0 ? DWT.ALT : 0) | (aCtrlKey[0] !is 0 ? DWT.CTRL : 0) | (aShiftKey[0] !is 0 ? DWT.SHIFT : 0) | (aMetaKey[0] !is 0 ? DWT.COMMAND : 0); browser.notifyListeners (keyEvent.type, keyEvent); if (!keyEvent.doit) { domEvent.PreventDefault (); } return XPCOM.NS_OK; } if (XPCOM.DOMEVENT_KEYUP.equals (typeString)) { int /*long*/[] result = new int /*long*/[1]; rc = domEvent.QueryInterface (nsIDOMKeyEvent.NS_IDOMKEYEVENT_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIDOMKeyEvent domKeyEvent = new nsIDOMKeyEvent (result[0]); result[0] = 0; int[] aKeyCode = new int[1]; /* PRUint32 */ rc = domKeyEvent.GetKeyCode (aKeyCode); if (rc !is XPCOM.NS_OK) error (rc); int keyCode = translateKey (aKeyCode[0]); if (keyCode is 0) { /* indicates a key for which key events are not sent */ domKeyEvent.Release (); return XPCOM.NS_OK; } if (keyCode !is lastKeyCode) { /* keyup does not correspond to the last keydown */ lastKeyCode = keyCode; lastCharCode = 0; } int[] aAltKey = new int[1], aCtrlKey = new int[1], aShiftKey = new int[1], aMetaKey = new int[1]; /* PRBool */ rc = domKeyEvent.GetAltKey (aAltKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domKeyEvent.GetCtrlKey (aCtrlKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domKeyEvent.GetShiftKey (aShiftKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domKeyEvent.GetMetaKey (aMetaKey); if (rc !is XPCOM.NS_OK) error (rc); domKeyEvent.Release (); Event keyEvent = new Event (); keyEvent.widget = browser; keyEvent.type = DWT.KeyUp; keyEvent.keyCode = lastKeyCode; keyEvent.character = (char)lastCharCode; keyEvent.stateMask = (aAltKey[0] !is 0 ? DWT.ALT : 0) | (aCtrlKey[0] !is 0 ? DWT.CTRL : 0) | (aShiftKey[0] !is 0 ? DWT.SHIFT : 0) | (aMetaKey[0] !is 0 ? DWT.COMMAND : 0); switch (lastKeyCode) { case DWT.SHIFT: case DWT.CONTROL: case DWT.ALT: case DWT.COMMAND: { keyEvent.stateMask |= lastKeyCode; } } browser.notifyListeners (keyEvent.type, keyEvent); if (!keyEvent.doit) { domEvent.PreventDefault (); } lastKeyCode = lastCharCode = 0; return XPCOM.NS_OK; } /* mouse event */ int /*long*/[] result = new int /*long*/[1]; rc = domEvent.QueryInterface (nsIDOMMouseEvent.NS_IDOMMOUSEEVENT_IID, result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] is 0) error (XPCOM.NS_NOINTERFACE); nsIDOMMouseEvent domMouseEvent = new nsIDOMMouseEvent (result[0]); result[0] = 0; /* * MouseOver and MouseOut events are fired any time the mouse enters or exits * any element within the Browser. To ensure that DWT events are only * fired for mouse movements into or out of the Browser, do not fire an * event if the element being exited (on MouseOver) or entered (on MouseExit) * is within the Browser. */ if (XPCOM.DOMEVENT_MOUSEOVER.equals (typeString) || XPCOM.DOMEVENT_MOUSEOUT.equals (typeString)) { rc = domMouseEvent.GetRelatedTarget (result); if (rc !is XPCOM.NS_OK) error (rc); if (result[0] !is 0) { domMouseEvent.Release (); return XPCOM.NS_OK; } } int[] aClientX = new int[1], aClientY = new int[1], aDetail = new int[1]; /* PRInt32 */ rc = domMouseEvent.GetClientX (aClientX); if (rc !is XPCOM.NS_OK) error (rc); rc = domMouseEvent.GetClientY (aClientY); if (rc !is XPCOM.NS_OK) error (rc); rc = domMouseEvent.GetDetail (aDetail); if (rc !is XPCOM.NS_OK) error (rc); short[] aButton = new short[1]; /* PRUint16 */ rc = domMouseEvent.GetButton (aButton); if (rc !is XPCOM.NS_OK) error (rc); int[] aAltKey = new int[1], aCtrlKey = new int[1], aShiftKey = new int[1], aMetaKey = new int[1]; /* PRBool */ rc = domMouseEvent.GetAltKey (aAltKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domMouseEvent.GetCtrlKey (aCtrlKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domMouseEvent.GetShiftKey (aShiftKey); if (rc !is XPCOM.NS_OK) error (rc); rc = domMouseEvent.GetMetaKey (aMetaKey); if (rc !is XPCOM.NS_OK) error (rc); domMouseEvent.Release (); Event mouseEvent = new Event (); mouseEvent.widget = browser; mouseEvent.x = aClientX[0]; mouseEvent.y = aClientY[0]; mouseEvent.stateMask = (aAltKey[0] !is 0 ? DWT.ALT : 0) | (aCtrlKey[0] !is 0 ? DWT.CTRL : 0) | (aShiftKey[0] !is 0 ? DWT.SHIFT : 0) | (aMetaKey[0] !is 0 ? DWT.COMMAND : 0); if (XPCOM.DOMEVENT_MOUSEDOWN.equals (typeString)) { mozDelegate.handleMouseDown (); mouseEvent.type = DWT.MouseDown; mouseEvent.button = aButton[0] + 1; mouseEvent.count = aDetail[0]; } else if (XPCOM.DOMEVENT_MOUSEUP.equals (typeString)) { /* * Bug on OSX. For some reason multiple mouseup events come from the DOM * when button 3 is released on OSX. The first of these events has a count * detail and the others do not. The workaround is to not fire received * button 3 mouseup events that do not have a count since mouse events * without a click count are not valid. */ int button = aButton[0] + 1; int count = aDetail[0]; if (count is 0 && button is 3) return XPCOM.NS_OK; mouseEvent.type = DWT.MouseUp; mouseEvent.button = button; mouseEvent.count = count; } else if (XPCOM.DOMEVENT_MOUSEMOVE.equals (typeString)) { mouseEvent.type = DWT.MouseMove; } else if (XPCOM.DOMEVENT_MOUSEWHEEL.equals (typeString)) { mouseEvent.type = DWT.MouseWheel; mouseEvent.count = -aDetail[0]; } else if (XPCOM.DOMEVENT_MOUSEOVER.equals (typeString)) { mouseEvent.type = DWT.MouseEnter; } else if (XPCOM.DOMEVENT_MOUSEOUT.equals (typeString)) { mouseEvent.type = DWT.MouseExit; } else if (XPCOM.DOMEVENT_MOUSEDRAG.equals (typeString)) { mouseEvent.type = DWT.DragDetect; mouseEvent.button = aButton[0] + 1; switch (mouseEvent.button) { case 1: mouseEvent.stateMask |= DWT.BUTTON1; break; case 2: mouseEvent.stateMask |= DWT.BUTTON2; break; case 3: mouseEvent.stateMask |= DWT.BUTTON3; break; case 4: mouseEvent.stateMask |= DWT.BUTTON4; break; case 5: mouseEvent.stateMask |= DWT.BUTTON5; break; } } browser.notifyListeners (mouseEvent.type, mouseEvent); if (aDetail[0] is 2 && XPCOM.DOMEVENT_MOUSEDOWN.equals (typeString)) { mouseEvent = new Event (); mouseEvent.widget = browser; mouseEvent.x = aClientX[0]; mouseEvent.y = aClientY[0]; mouseEvent.stateMask = (aAltKey[0] !is 0 ? DWT.ALT : 0) | (aCtrlKey[0] !is 0 ? DWT.CTRL : 0) | (aShiftKey[0] !is 0 ? DWT.SHIFT : 0) | (aMetaKey[0] !is 0 ? DWT.COMMAND : 0); mouseEvent.type = DWT.MouseDoubleClick; mouseEvent.button = aButton[0] + 1; mouseEvent.count = aDetail[0]; browser.notifyListeners (mouseEvent.type, mouseEvent); } return XPCOM.NS_OK; } }