comparison dwt/browser/Mozilla.d @ 0:380af2bdd8e5

Upload of whole dwt tree
author Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com>
date Sat, 09 Aug 2008 17:00:02 +0200
parents
children 649b8e223d5a
comparison
equal deleted inserted replaced
-1:000000000000 0:380af2bdd8e5
1 /*******************************************************************************
2 * Copyright (c) 2003, 2007 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 module dwt.browser.Mozilla;
12
13 import dwt.dwthelper.utils;
14
15 import java.io.UnsupportedEncodingException;
16 import java.lang.reflect.Constructor;
17 import java.lang.reflect.InvocationTargetException;
18 import java.lang.reflect.Method;
19 import java.util.Enumeration;
20 import java.util.Locale;
21 import java.util.Vector;
22
23 import dwt.DWT;
24 import dwt.DWTError;
25 import dwt.graphics.Device;
26 import dwt.graphics.Point;
27 import dwt.graphics.Rectangle;
28 import dwt.internal.C;
29 import dwt.internal.Compatibility;
30 import dwt.internal.LONG;
31 import dwt.internal.Library;
32 import dwt.internal.mozilla.GREVersionRange;
33 import dwt.internal.mozilla.XPCOM;
34 import dwt.internal.mozilla.XPCOMInit;
35 import dwt.internal.mozilla.XPCOMObject;
36 import dwt.internal.mozilla.nsEmbedString;
37 import dwt.internal.mozilla.nsIAppShell;
38 import dwt.internal.mozilla.nsIBaseWindow;
39 import dwt.internal.mozilla.nsICategoryManager;
40 import dwt.internal.mozilla.nsIComponentManager;
41 import dwt.internal.mozilla.nsIComponentRegistrar;
42 import dwt.internal.mozilla.nsIContextMenuListener;
43 import dwt.internal.mozilla.nsICookie;
44 import dwt.internal.mozilla.nsICookieManager;
45 import dwt.internal.mozilla.nsID;
46 import dwt.internal.mozilla.nsIDOMEvent;
47 import dwt.internal.mozilla.nsIDOMEventTarget;
48 import dwt.internal.mozilla.nsIDOMKeyEvent;
49 import dwt.internal.mozilla.nsIDOMMouseEvent;
50 import dwt.internal.mozilla.nsIDOMSerializer;
51 import dwt.internal.mozilla.nsIDOMSerializer_1_7;
52 import dwt.internal.mozilla.nsIDOMWindow;
53 import dwt.internal.mozilla.nsIDOMWindowCollection;
54 import dwt.internal.mozilla.nsIDirectoryService;
55 import dwt.internal.mozilla.nsIDocShell;
56 import dwt.internal.mozilla.nsIDocShell_1_8;
57 import dwt.internal.mozilla.nsIDocShell_1_9;
58 import dwt.internal.mozilla.nsIEmbeddingSiteWindow;
59 import dwt.internal.mozilla.nsIFile;
60 import dwt.internal.mozilla.nsIIOService;
61 import dwt.internal.mozilla.nsIInterfaceRequestor;
62 import dwt.internal.mozilla.nsIJSContextStack;
63 import dwt.internal.mozilla.nsILocalFile;
64 import dwt.internal.mozilla.nsIObserverService;
65 import dwt.internal.mozilla.nsIPrefBranch;
66 import dwt.internal.mozilla.nsIPrefLocalizedString;
67 import dwt.internal.mozilla.nsIPrefService;
68 import dwt.internal.mozilla.nsIProperties;
69 import dwt.internal.mozilla.nsIServiceManager;
70 import dwt.internal.mozilla.nsISimpleEnumerator;
71 import dwt.internal.mozilla.nsISupports;
72 import dwt.internal.mozilla.nsISupportsWeakReference;
73 import dwt.internal.mozilla.nsITooltipListener;
74 import dwt.internal.mozilla.nsIURI;
75 import dwt.internal.mozilla.nsIURIContentListener;
76 import dwt.internal.mozilla.nsIWeakReference;
77 import dwt.internal.mozilla.nsIWebBrowser;
78 import dwt.internal.mozilla.nsIWebBrowserChrome;
79 import dwt.internal.mozilla.nsIWebBrowserChromeFocus;
80 import dwt.internal.mozilla.nsIWebBrowserFocus;
81 import dwt.internal.mozilla.nsIWebNavigation;
82 import dwt.internal.mozilla.nsIWebNavigationInfo;
83 import dwt.internal.mozilla.nsIWebProgress;
84 import dwt.internal.mozilla.nsIWebProgressListener;
85 import dwt.internal.mozilla.nsIWindowWatcher;
86 import dwt.layout.FillLayout;
87 import dwt.widgets.Composite;
88 import dwt.widgets.Display;
89 import dwt.widgets.Event;
90 import dwt.widgets.Label;
91 import dwt.widgets.Listener;
92 import dwt.widgets.Menu;
93 import dwt.widgets.Shell;
94
95 class Mozilla extends WebBrowser {
96 int /*long*/ embedHandle;
97 nsIWebBrowser webBrowser;
98 Object webBrowserObject;
99 MozillaDelegate delegate;
100
101 /* Interfaces for this Mozilla embedding notification */
102 XPCOMObject supports;
103 XPCOMObject weakReference;
104 XPCOMObject webProgressListener;
105 XPCOMObject webBrowserChrome;
106 XPCOMObject webBrowserChromeFocus;
107 XPCOMObject embeddingSiteWindow;
108 XPCOMObject interfaceRequestor;
109 XPCOMObject supportsWeakReference;
110 XPCOMObject contextMenuListener;
111 XPCOMObject uriContentListener;
112 XPCOMObject tooltipListener;
113 XPCOMObject domEventListener;
114 int chromeFlags = nsIWebBrowserChrome.CHROME_DEFAULT;
115 int refCount, lastKeyCode, lastCharCode;
116 int /*long*/ request;
117 Point location, size;
118 bool visible, isChild, ignoreDispose, awaitingNavigate;
119 Shell tip = null;
120 Listener listener;
121 Vector unhookedDOMWindows = new Vector ();
122
123 static nsIAppShell AppShell;
124 static AppFileLocProvider LocationProvider;
125 static WindowCreator2 WindowCreator;
126 static int BrowserCount;
127 static bool Initialized, IsPre_1_8, PerformedVersionCheck, XPCOMWasGlued, XPCOMInitWasGlued;
128
129 /* XULRunner detect constants */
130 static final String GRERANGE_LOWER = "1.8.1.2"; //$NON-NLS-1$
131 static final String GRERANGE_LOWER_FALLBACK = "1.8"; //$NON-NLS-1$
132 static final bool LowerRangeInclusive = true;
133 static final String GRERANGE_UPPER = "1.9.*"; //$NON-NLS-1$
134 static final bool UpperRangeInclusive = true;
135
136 static final int MAX_PORT = 65535;
137 static final String SEPARATOR_OS = System.getProperty ("file.separator"); //$NON-NLS-1$
138 static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
139 static final String DISPOSE_LISTENER_HOOKED = "dwt.browser.Mozilla.disposeListenerHooked"; //$NON-NLS-1$
140 static final String PREFIX_JAVASCRIPT = "javascript:"; //$NON-NLS-1$
141 static final String PREFERENCE_CHARSET = "intl.charset.default"; //$NON-NLS-1$
142 static final String PREFERENCE_DISABLEOPENDURINGLOAD = "dom.disable_open_during_load"; //$NON-NLS-1$
143 static final String PREFERENCE_DISABLEWINDOWSTATUSCHANGE = "dom.disable_window_status_change"; //$NON-NLS-1$
144 static final String PREFERENCE_LANGUAGES = "intl.accept_languages"; //$NON-NLS-1$
145 static final String PREFERENCE_PROXYHOST_FTP = "network.proxy.ftp"; //$NON-NLS-1$
146 static final String PREFERENCE_PROXYPORT_FTP = "network.proxy.ftp_port"; //$NON-NLS-1$
147 static final String PREFERENCE_PROXYHOST_HTTP = "network.proxy.http"; //$NON-NLS-1$
148 static final String PREFERENCE_PROXYPORT_HTTP = "network.proxy.http_port"; //$NON-NLS-1$
149 static final String PREFERENCE_PROXYHOST_SSL = "network.proxy.ssl"; //$NON-NLS-1$
150 static final String PREFERENCE_PROXYPORT_SSL = "network.proxy.ssl_port"; //$NON-NLS-1$
151 static final String PREFERENCE_PROXYTYPE = "network.proxy.type"; //$NON-NLS-1$
152 static final String PROFILE_AFTER_CHANGE = "profile-after-change"; //$NON-NLS-1$
153 static final String PROFILE_BEFORE_CHANGE = "profile-before-change"; //$NON-NLS-1$
154 static final String PROFILE_DIR = SEPARATOR_OS + "eclipse" + SEPARATOR_OS; //$NON-NLS-1$
155 static final String PROFILE_DO_CHANGE = "profile-do-change"; //$NON-NLS-1$
156 static final String PROPERTY_PROXYPORT = "network.proxy_port"; //$NON-NLS-1$
157 static final String PROPERTY_PROXYHOST = "network.proxy_host"; //$NON-NLS-1$
158 static final String SEPARATOR_LOCALE = "-"; //$NON-NLS-1$
159 static final String SHUTDOWN_PERSIST = "shutdown-persist"; //$NON-NLS-1$
160 static final String STARTUP = "startup"; //$NON-NLS-1$
161 static final String TOKENIZER_LOCALE = ","; //$NON-NLS-1$
162 static final String URI_FROMMEMORY = "file:///"; //$NON-NLS-1$
163 static final String XULRUNNER_PATH = "dwt.browser.XULRunnerPath"; //$NON-NLS-1$
164
165 // TEMPORARY CODE
166 static final String GRE_INITIALIZED = "dwt.browser.XULRunnerInitialized"; //$NON-NLS-1$
167
168 static {
169 MozillaClearSessions = new Runnable () {
170 public void run () {
171 if (!Initialized) return;
172 int /*long*/[] result = new int /*long*/[1];
173 int rc = XPCOM.NS_GetServiceManager (result);
174 if (rc !is XPCOM.NS_OK) error (rc);
175 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
176 nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
177 result[0] = 0;
178 byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_COOKIEMANAGER_CONTRACTID, true);
179 rc = serviceManager.GetServiceByContractID (aContractID, nsICookieManager.NS_ICOOKIEMANAGER_IID, result);
180 if (rc !is XPCOM.NS_OK) error (rc);
181 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
182 serviceManager.Release ();
183
184 nsICookieManager manager = new nsICookieManager (result[0]);
185 result[0] = 0;
186 rc = manager.GetEnumerator (result);
187 if (rc !is XPCOM.NS_OK) error (rc);
188 manager.Release ();
189
190 nsISimpleEnumerator enumerator = new nsISimpleEnumerator (result[0]);
191 int[] moreElements = new int[1]; /* PRBool */
192 rc = enumerator.HasMoreElements (moreElements);
193 if (rc !is XPCOM.NS_OK) error (rc);
194 while (moreElements[0] !is 0) {
195 result[0] = 0;
196 rc = enumerator.GetNext (result);
197 if (rc !is XPCOM.NS_OK) error (rc);
198 nsICookie cookie = new nsICookie (result[0]);
199 long[] expires = new long[1];
200 rc = cookie.GetExpires (expires);
201 if (expires[0] is 0) {
202 /* indicates a session cookie */
203 int /*long*/ domain = XPCOM.nsEmbedCString_new ();
204 int /*long*/ name = XPCOM.nsEmbedCString_new ();
205 int /*long*/ path = XPCOM.nsEmbedCString_new ();
206 cookie.GetHost (domain);
207 cookie.GetName (name);
208 cookie.GetPath (path);
209 rc = manager.Remove (domain, name, path, 0);
210 XPCOM.nsEmbedCString_delete (domain);
211 XPCOM.nsEmbedCString_delete (name);
212 XPCOM.nsEmbedCString_delete (path);
213 if (rc !is XPCOM.NS_OK) error (rc);
214 }
215 cookie.Release ();
216 rc = enumerator.HasMoreElements (moreElements);
217 if (rc !is XPCOM.NS_OK) error (rc);
218 }
219 enumerator.Release ();
220 }
221 };
222 }
223
224 public void create (Composite parent, int style) {
225 delegate = new MozillaDelegate (browser);
226 Display display = parent.getDisplay ();
227
228 int /*long*/[] result = new int /*long*/[1];
229 if (!Initialized) {
230 bool initLoaded = false;
231 bool IsXULRunner = false;
232
233 String greInitialized = System.getProperty (GRE_INITIALIZED);
234 if ("true".equals (greInitialized)) { //$NON-NLS-1$
235 /*
236 * Another browser has already initialized xulrunner in this process,
237 * so just bind to it instead of trying to initialize a new one.
238 */
239 Initialized = true;
240 }
241
242 String mozillaPath = System.getProperty (XULRUNNER_PATH);
243 /*
244 * Browser clients that ship XULRunner in a plug-in must have an opportunity
245 * to set the dwt.browser.XULRunnerPath system property to point
246 * at their XULRunner before the first Mozilla-based Browser is created. To
247 * facilitate this, reflection is used to reference non-existent class
248 * dwt.browser.XULRunnerInitializer the first time a Mozilla-
249 * based Browser is created. A client wishing to use this hook can do so
250 * by creating a fragment of dwt that implements this class and
251 * sets the system property in its static initializer.
252 */
253 if (mozillaPath is null) {
254 try {
255 Class.forName ("dwt.browser.XULRunnerInitializer"); //$NON-NLS-1$
256 mozillaPath = System.getProperty (XULRUNNER_PATH);
257 } catch (ClassNotFoundException e) {
258 /* no fragment is providing this class, which is the typical case */
259 }
260 }
261
262 if (mozillaPath is null) {
263 try {
264 String libName = delegate.getSWTInitLibraryName ();
265 Library.loadLibrary (libName);
266 initLoaded = true;
267 } catch (UnsatisfiedLinkError e) {
268 /*
269 * If this library failed to load then do not attempt to detect a
270 * xulrunner to use. The Browser may still be usable if MOZILLA_FIVE_HOME
271 * points at a GRE.
272 */
273 }
274 } else {
275 mozillaPath += SEPARATOR_OS + delegate.getLibraryName ();
276 IsXULRunner = true;
277 }
278
279 if (initLoaded) {
280 /* attempt to discover a XULRunner to use as the GRE */
281 GREVersionRange range = new GREVersionRange ();
282 byte[] bytes = MozillaDelegate.wcsToMbcs (null, GRERANGE_LOWER, true);
283 int /*long*/ lower = C.malloc (bytes.length);
284 C.memmove (lower, bytes, bytes.length);
285 range.lower = lower;
286 range.lowerInclusive = LowerRangeInclusive;
287
288 bytes = MozillaDelegate.wcsToMbcs (null, GRERANGE_UPPER, true);
289 int /*long*/ upper = C.malloc (bytes.length);
290 C.memmove (upper, bytes, bytes.length);
291 range.upper = upper;
292 range.upperInclusive = UpperRangeInclusive;
293
294 int length = XPCOMInit.PATH_MAX;
295 int /*long*/ greBuffer = C.malloc (length);
296 int /*long*/ propertiesPtr = C.malloc (2 * C.PTR_SIZEOF);
297 int rc = XPCOMInit.GRE_GetGREPathWithProperties (range, 1, propertiesPtr, 0, greBuffer, length);
298
299 /*
300 * A XULRunner was not found that supports wrapping of XPCOM handles as JavaXPCOM objects.
301 * Drop the lower version bound and try to detect an earlier XULRunner installation.
302 */
303 if (rc !is XPCOM.NS_OK) {
304 C.free (lower);
305 bytes = MozillaDelegate.wcsToMbcs (null, GRERANGE_LOWER_FALLBACK, true);
306 lower = C.malloc (bytes.length);
307 C.memmove (lower, bytes, bytes.length);
308 range.lower = lower;
309 rc = XPCOMInit.GRE_GetGREPathWithProperties (range, 1, propertiesPtr, 0, greBuffer, length);
310 }
311
312 C.free (lower);
313 C.free (upper);
314 C.free (propertiesPtr);
315 if (rc is XPCOM.NS_OK) {
316 /* indicates that a XULRunner was found */
317 length = C.strlen (greBuffer);
318 bytes = new byte[length];
319 C.memmove (bytes, greBuffer, length);
320 mozillaPath = new String (MozillaDelegate.mbcsToWcs (null, bytes));
321 IsXULRunner = mozillaPath.length () > 0;
322
323 /*
324 * Test whether the detected XULRunner can be used as the GRE before loading swt's
325 * XULRunner library. If it cannot be used then fall back to attempting to use
326 * the GRE pointed to by MOZILLA_FIVE_HOME.
327 *
328 * One case where this will fail is attempting to use a 64-bit xulrunner while swt
329 * is running in 32-bit mode, or vice versa.
330 */
331 if (IsXULRunner) {
332 byte[] path = MozillaDelegate.wcsToMbcs (null, mozillaPath, true);
333 rc = XPCOMInit.XPCOMGlueStartup (path);
334 if (rc !is XPCOM.NS_OK) {
335 IsXULRunner = false; /* failed */
336 mozillaPath = mozillaPath.substring (0, mozillaPath.lastIndexOf (SEPARATOR_OS));
337 if (Device.DEBUG) System.out.println ("cannot use detected XULRunner: " + mozillaPath); //$NON-NLS-1$
338 } else {
339 XPCOMInitWasGlued = true;
340 }
341 }
342 }
343 C.free (greBuffer);
344 }
345
346 if (IsXULRunner) {
347 if (Device.DEBUG) System.out.println ("XULRunner path: " + mozillaPath); //$NON-NLS-1$
348 try {
349 Library.loadLibrary ("swt-xulrunner"); //$NON-NLS-1$
350 } catch (UnsatisfiedLinkError e) {
351 DWT.error (DWT.ERROR_NO_HANDLES, e);
352 }
353 byte[] path = MozillaDelegate.wcsToMbcs (null, mozillaPath, true);
354 int rc = XPCOM.XPCOMGlueStartup (path);
355 if (rc !is XPCOM.NS_OK) {
356 browser.dispose ();
357 error (rc);
358 }
359 XPCOMWasGlued = true;
360
361 /*
362 * Remove the trailing xpcom lib name from mozillaPath because the
363 * Mozilla.initialize and NS_InitXPCOM2 invocations require a directory name only.
364 */
365 mozillaPath = mozillaPath.substring (0, mozillaPath.lastIndexOf (SEPARATOR_OS));
366 } else {
367 if ((style & DWT.MOZILLA) !is 0) {
368 browser.dispose ();
369 String errorString = (mozillaPath !is null && mozillaPath.length () > 0) ?
370 " [Failed to use detected XULRunner: " + mozillaPath + "]" :
371 " [Could not detect registered XULRunner to use]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
372 DWT.error (DWT.ERROR_NO_HANDLES, null, errorString);
373 }
374
375 /* attempt to use the GRE pointed at by MOZILLA_FIVE_HOME */
376 int /*long*/ ptr = C.getenv (MozillaDelegate.wcsToMbcs (null, XPCOM.MOZILLA_FIVE_HOME, true));
377 if (ptr !is 0) {
378 int length = C.strlen (ptr);
379 byte[] buffer = new byte[length];
380 C.memmove (buffer, ptr, length);
381 mozillaPath = new String (MozillaDelegate.mbcsToWcs (null, buffer));
382 } else {
383 browser.dispose ();
384 DWT.error (DWT.ERROR_NO_HANDLES, null, " [Unknown Mozilla path (MOZILLA_FIVE_HOME not set)]"); //$NON-NLS-1$
385 }
386 if (Device.DEBUG) System.out.println ("Mozilla path: " + mozillaPath); //$NON-NLS-1$
387
388 /*
389 * Note. Embedding a Mozilla GTK1.2 causes a crash. The workaround
390 * is to check the version of GTK used by Mozilla by looking for
391 * the libwidget_gtk.so library used by Mozilla GTK1.2. Mozilla GTK2
392 * uses the libwidget_gtk2.so library.
393 */
394 if (Compatibility.fileExists (mozillaPath, "components/libwidget_gtk.so")) { //$NON-NLS-1$
395 browser.dispose ();
396 DWT.error (DWT.ERROR_NO_HANDLES, null, " [Mozilla GTK2 required (GTK1.2 detected)]"); //$NON-NLS-1$
397 }
398
399 try {
400 Library.loadLibrary ("swt-mozilla"); //$NON-NLS-1$
401 } catch (UnsatisfiedLinkError e) {
402 try {
403 /*
404 * The initial loadLibrary attempt may have failed as a result of the user's
405 * system not having libstdc++.so.6 installed, so try to load the alternate
406 * swt mozilla library that depends on libswtc++.so.5 instead.
407 */
408 Library.loadLibrary ("swt-mozilla-gcc3"); //$NON-NLS-1$
409 } catch (UnsatisfiedLinkError ex) {
410 browser.dispose ();
411 /*
412 * Print the error from the first failed attempt since at this point it's
413 * known that the failure was not due to the libstdc++.so.6 dependency.
414 */
415 DWT.error (DWT.ERROR_NO_HANDLES, e, " [MOZILLA_FIVE_HOME='" + mozillaPath + "']"); //$NON-NLS-1$ //$NON-NLS-2$
416 }
417 }
418 }
419
420 if (!Initialized) {
421 int /*long*/[] retVal = new int /*long*/[1];
422 nsEmbedString pathString = new nsEmbedString (mozillaPath);
423 int rc = XPCOM.NS_NewLocalFile (pathString.getAddress (), 1, retVal);
424 pathString.dispose ();
425 if (rc !is XPCOM.NS_OK) {
426 browser.dispose ();
427 error (rc);
428 }
429 if (retVal[0] is 0) {
430 browser.dispose ();
431 error (XPCOM.NS_ERROR_NULL_POINTER);
432 }
433
434 LocationProvider = new AppFileLocProvider (mozillaPath);
435 LocationProvider.AddRef ();
436
437 nsIFile localFile = new nsILocalFile (retVal[0]);
438 rc = XPCOM.NS_InitXPCOM2 (0, localFile.getAddress(), LocationProvider.getAddress ());
439 localFile.Release ();
440 if (rc !is XPCOM.NS_OK) {
441 browser.dispose ();
442 DWT.error (DWT.ERROR_NO_HANDLES, null, " [MOZILLA_FIVE_HOME may not point at an embeddable GRE] [NS_InitEmbedding " + mozillaPath + " error " + rc + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
443 }
444 System.setProperty (GRE_INITIALIZED, "true"); //$NON-NLS-1$
445 if (IsXULRunner) {
446 System.setProperty (XULRUNNER_PATH, mozillaPath);
447 }
448 }
449
450 /* If JavaXPCOM is detected then attempt to initialize it with the XULRunner being used */
451 if (IsXULRunner) {
452 try {
453 Class clazz = Class.forName ("org.mozilla.xpcom.Mozilla"); //$NON-NLS-1$
454 Method method = clazz.getMethod ("getInstance", new Class[0]); //$NON-NLS-1$
455 Object mozilla = method.invoke (null, new Object[0]);
456 method = clazz.getMethod ("getComponentManager", new Class[0]); //$NON-NLS-1$
457 try {
458 method.invoke (mozilla, new Object[0]);
459 } catch (InvocationTargetException e) {
460 /* indicates that JavaXPCOM has not been initialized yet */
461 Class fileClass = Class.forName ("java.io.File"); //$NON-NLS-1$
462 method = clazz.getMethod ("initialize", new Class[] {fileClass}); //$NON-NLS-1$
463 Constructor constructor = fileClass.getDeclaredConstructor (new Class[] {String.class});
464 Object argument = constructor.newInstance (new Object[] {mozillaPath});
465 method.invoke (mozilla, new Object[] {argument});
466 }
467 } catch (ClassNotFoundException e) {
468 /* JavaXPCOM is not on the classpath */
469 } catch (NoSuchMethodException e) {
470 /* the JavaXPCOM on the classpath does not implement initialize() */
471 } catch (IllegalArgumentException e) {
472 } catch (IllegalAccessException e) {
473 } catch (InvocationTargetException e) {
474 } catch (InstantiationException e) {
475 }
476 }
477
478 int rc = XPCOM.NS_GetComponentManager (result);
479 if (rc !is XPCOM.NS_OK) {
480 browser.dispose ();
481 error (rc);
482 }
483 if (result[0] is 0) {
484 browser.dispose ();
485 error (XPCOM.NS_NOINTERFACE);
486 }
487
488 nsIComponentManager componentManager = new nsIComponentManager (result[0]);
489 result[0] = 0;
490 if (delegate.needsSpinup ()) {
491 /* nsIAppShell is discontinued as of xulrunner 1.9, so do not fail if it is not found */
492 rc = componentManager.CreateInstance (XPCOM.NS_APPSHELL_CID, 0, nsIAppShell.NS_IAPPSHELL_IID, result);
493 if (rc !is XPCOM.NS_ERROR_NO_INTERFACE) {
494 if (rc !is XPCOM.NS_OK) {
495 browser.dispose ();
496 error (rc);
497 }
498 if (result[0] is 0) {
499 browser.dispose ();
500 error (XPCOM.NS_NOINTERFACE);
501 }
502
503 AppShell = new nsIAppShell (result[0]);
504 rc = AppShell.Create (0, null);
505 if (rc !is XPCOM.NS_OK) {
506 browser.dispose ();
507 error (rc);
508 }
509 rc = AppShell.Spinup ();
510 if (rc !is XPCOM.NS_OK) {
511 browser.dispose ();
512 error (rc);
513 }
514 }
515 result[0] = 0;
516 }
517
518 WindowCreator = new WindowCreator2 ();
519 WindowCreator.AddRef ();
520
521 rc = XPCOM.NS_GetServiceManager (result);
522 if (rc !is XPCOM.NS_OK) {
523 browser.dispose ();
524 error (rc);
525 }
526 if (result[0] is 0) {
527 browser.dispose ();
528 error (XPCOM.NS_NOINTERFACE);
529 }
530
531 nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
532 result[0] = 0;
533 byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_WINDOWWATCHER_CONTRACTID, true);
534 rc = serviceManager.GetServiceByContractID (aContractID, nsIWindowWatcher.NS_IWINDOWWATCHER_IID, result);
535 if (rc !is XPCOM.NS_OK) {
536 browser.dispose ();
537 error (rc);
538 }
539 if (result[0] is 0) {
540 browser.dispose ();
541 error (XPCOM.NS_NOINTERFACE);
542 }
543
544 nsIWindowWatcher windowWatcher = new nsIWindowWatcher (result[0]);
545 result[0] = 0;
546 rc = windowWatcher.SetWindowCreator (WindowCreator.getAddress());
547 if (rc !is XPCOM.NS_OK) {
548 browser.dispose ();
549 error (rc);
550 }
551 windowWatcher.Release ();
552
553 /* compute the profile directory and set it on the AppFileLocProvider */
554 if (LocationProvider !is null) {
555 byte[] buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DIRECTORYSERVICE_CONTRACTID, true);
556 rc = serviceManager.GetServiceByContractID (buffer, nsIDirectoryService.NS_IDIRECTORYSERVICE_IID, result);
557 if (rc !is XPCOM.NS_OK) {
558 browser.dispose ();
559 error (rc);
560 }
561 if (result[0] is 0) {
562 browser.dispose ();
563 error (XPCOM.NS_NOINTERFACE);
564 }
565
566 nsIDirectoryService directoryService = new nsIDirectoryService (result[0]);
567 result[0] = 0;
568 rc = directoryService.QueryInterface (nsIProperties.NS_IPROPERTIES_IID, result);
569 if (rc !is XPCOM.NS_OK) {
570 browser.dispose ();
571 error (rc);
572 }
573 if (result[0] is 0) {
574 browser.dispose ();
575 error (XPCOM.NS_NOINTERFACE);
576 }
577 directoryService.Release ();
578
579 nsIProperties properties = new nsIProperties (result[0]);
580 result[0] = 0;
581 buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_APP_APPLICATION_REGISTRY_DIR, true);
582 rc = properties.Get (buffer, nsIFile.NS_IFILE_IID, result);
583 if (rc !is XPCOM.NS_OK) {
584 browser.dispose ();
585 error (rc);
586 }
587 if (result[0] is 0) {
588 browser.dispose ();
589 error (XPCOM.NS_NOINTERFACE);
590 }
591 properties.Release ();
592
593 nsIFile profileDir = new nsIFile (result[0]);
594 result[0] = 0;
595 int /*long*/ path = XPCOM.nsEmbedCString_new ();
596 rc = profileDir.GetNativePath (path);
597 if (rc !is XPCOM.NS_OK) {
598 browser.dispose ();
599 error (rc);
600 }
601 int length = XPCOM.nsEmbedCString_Length (path);
602 int /*long*/ ptr = XPCOM.nsEmbedCString_get (path);
603 buffer = new byte [length];
604 XPCOM.memmove (buffer, ptr, length);
605 String profilePath = new String (MozillaDelegate.mbcsToWcs (null, buffer)) + PROFILE_DIR;
606 LocationProvider.setProfilePath (profilePath);
607 LocationProvider.isXULRunner = IsXULRunner;
608 XPCOM.nsEmbedCString_delete (path);
609 profileDir.Release ();
610
611 /* notify observers of a new profile directory being used */
612 buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_OBSERVER_CONTRACTID, true);
613 rc = serviceManager.GetServiceByContractID (buffer, nsIObserverService.NS_IOBSERVERSERVICE_IID, result);
614 if (rc !is XPCOM.NS_OK) {
615 browser.dispose ();
616 error (rc);
617 }
618 if (result[0] is 0) {
619 browser.dispose ();
620 error (XPCOM.NS_NOINTERFACE);
621 }
622
623 nsIObserverService observerService = new nsIObserverService (result[0]);
624 result[0] = 0;
625 buffer = MozillaDelegate.wcsToMbcs (null, PROFILE_DO_CHANGE, true);
626 length = STARTUP.length ();
627 char[] chars = new char [length + 1];
628 STARTUP.getChars (0, length, chars, 0);
629 rc = observerService.NotifyObservers (0, buffer, chars);
630 if (rc !is XPCOM.NS_OK) {
631 browser.dispose ();
632 error (rc);
633 }
634 buffer = MozillaDelegate.wcsToMbcs (null, PROFILE_AFTER_CHANGE, true);
635 rc = observerService.NotifyObservers (0, buffer, chars);
636 if (rc !is XPCOM.NS_OK) {
637 browser.dispose ();
638 error (rc);
639 }
640 observerService.Release ();
641 }
642
643 /*
644 * As a result of using a common profile the user cannot change their locale
645 * and charset. The fix for this is to set mozilla's locale and charset
646 * preference values according to the user's current locale and charset.
647 */
648 aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFSERVICE_CONTRACTID, true);
649 rc = serviceManager.GetServiceByContractID (aContractID, nsIPrefService.NS_IPREFSERVICE_IID, result);
650 serviceManager.Release ();
651 if (rc !is XPCOM.NS_OK) {
652 browser.dispose ();
653 error (rc);
654 }
655 if (result[0] is 0) {
656 browser.dispose ();
657 error (XPCOM.NS_NOINTERFACE);
658 }
659
660 nsIPrefService prefService = new nsIPrefService (result[0]);
661 result[0] = 0;
662 byte[] buffer = new byte[1];
663 rc = prefService.GetBranch (buffer, result); /* empty buffer denotes root preference level */
664 prefService.Release ();
665 if (rc !is XPCOM.NS_OK) {
666 browser.dispose ();
667 error (rc);
668 }
669 if (result[0] is 0) {
670 browser.dispose ();
671 error (XPCOM.NS_NOINTERFACE);
672 }
673
674 nsIPrefBranch prefBranch = new nsIPrefBranch (result[0]);
675 result[0] = 0;
676
677 /* get Mozilla's current locale preference value */
678 String prefLocales = null;
679 nsIPrefLocalizedString localizedString = null;
680 buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_LANGUAGES, true);
681 rc = prefBranch.GetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
682 /*
683 * Feature of Debian. For some reason attempting to query for the current locale
684 * preference fails on Debian. The workaround for this is to assume a value of
685 * "en-us,en" since this is typically the default value when mozilla is used without
686 * a profile.
687 */
688 if (rc !is XPCOM.NS_OK) {
689 prefLocales = "en-us,en" + TOKENIZER_LOCALE; //$NON-NLS-1$
690 } else {
691 if (result[0] is 0) {
692 browser.dispose ();
693 error (XPCOM.NS_NOINTERFACE);
694 }
695 localizedString = new nsIPrefLocalizedString (result[0]);
696 result[0] = 0;
697 rc = localizedString.ToString (result);
698 if (rc !is XPCOM.NS_OK) {
699 browser.dispose ();
700 error (rc);
701 }
702 if (result[0] is 0) {
703 browser.dispose ();
704 error (XPCOM.NS_NOINTERFACE);
705 }
706 int length = XPCOM.strlen_PRUnichar (result[0]);
707 char[] dest = new char[length];
708 XPCOM.memmove (dest, result[0], length * 2);
709 prefLocales = new String (dest) + TOKENIZER_LOCALE;
710 }
711 result[0] = 0;
712
713 /*
714 * construct the new locale preference value by prepending the
715 * user's current locale and language to the original value
716 */
717 Locale locale = Locale.getDefault ();
718 String language = locale.getLanguage ();
719 String country = locale.getCountry ();
720 StringBuffer stringBuffer = new StringBuffer (language);
721 stringBuffer.append (SEPARATOR_LOCALE);
722 stringBuffer.append (country.toLowerCase ());
723 stringBuffer.append (TOKENIZER_LOCALE);
724 stringBuffer.append (language);
725 stringBuffer.append (TOKENIZER_LOCALE);
726 String newLocales = stringBuffer.toString ();
727
728 int start, end = -1;
729 do {
730 start = end + 1;
731 end = prefLocales.indexOf (TOKENIZER_LOCALE, start);
732 String token;
733 if (end is -1) {
734 token = prefLocales.substring (start);
735 } else {
736 token = prefLocales.substring (start, end);
737 }
738 if (token.length () > 0) {
739 token = (token + TOKENIZER_LOCALE).trim ();
740 /* ensure that duplicate locale values are not added */
741 if (newLocales.indexOf (token) is -1) {
742 stringBuffer.append (token);
743 }
744 }
745 } while (end !is -1);
746 newLocales = stringBuffer.toString ();
747 if (!newLocales.equals (prefLocales)) {
748 /* write the new locale value */
749 newLocales = newLocales.substring (0, newLocales.length () - TOKENIZER_LOCALE.length ()); /* remove trailing tokenizer */
750 int length = newLocales.length ();
751 char[] charBuffer = new char[length + 1];
752 newLocales.getChars (0, length, charBuffer, 0);
753 if (localizedString is null) {
754 byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID, true);
755 rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
756 if (rc !is XPCOM.NS_OK) {
757 browser.dispose ();
758 error (rc);
759 }
760 if (result[0] is 0) {
761 browser.dispose ();
762 error (XPCOM.NS_NOINTERFACE);
763 }
764 localizedString = new nsIPrefLocalizedString (result[0]);
765 result[0] = 0;
766 }
767 localizedString.SetDataWithLength (length, charBuffer);
768 rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress());
769 }
770 if (localizedString !is null) {
771 localizedString.Release ();
772 localizedString = null;
773 }
774
775 /* get Mozilla's current charset preference value */
776 String prefCharset = null;
777 buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_CHARSET, true);
778 rc = prefBranch.GetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
779 /*
780 * Feature of Debian. For some reason attempting to query for the current charset
781 * preference fails on Debian. The workaround for this is to assume a value of
782 * "ISO-8859-1" since this is typically the default value when mozilla is used
783 * without a profile.
784 */
785 if (rc !is XPCOM.NS_OK) {
786 prefCharset = "ISO-8859-1"; //$NON_NLS-1$
787 } else {
788 if (result[0] is 0) {
789 browser.dispose ();
790 error (XPCOM.NS_NOINTERFACE);
791 }
792 localizedString = new nsIPrefLocalizedString (result[0]);
793 result[0] = 0;
794 rc = localizedString.ToString (result);
795 if (rc !is XPCOM.NS_OK) {
796 browser.dispose ();
797 error (rc);
798 }
799 if (result[0] is 0) {
800 browser.dispose ();
801 error (XPCOM.NS_NOINTERFACE);
802 }
803 int length = XPCOM.strlen_PRUnichar (result[0]);
804 char[] dest = new char[length];
805 XPCOM.memmove (dest, result[0], length * 2);
806 prefCharset = new String (dest);
807 }
808 result[0] = 0;
809
810 String newCharset = System.getProperty ("file.encoding"); // $NON-NLS-1$
811 if (!newCharset.equals (prefCharset)) {
812 /* write the new charset value */
813 int length = newCharset.length ();
814 char[] charBuffer = new char[length + 1];
815 newCharset.getChars (0, length, charBuffer, 0);
816 if (localizedString is null) {
817 byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID, true);
818 rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
819 if (rc !is XPCOM.NS_OK) {
820 browser.dispose ();
821 error (rc);
822 }
823 if (result[0] is 0) {
824 browser.dispose ();
825 error (XPCOM.NS_NOINTERFACE);
826 }
827 localizedString = new nsIPrefLocalizedString (result[0]);
828 result[0] = 0;
829 }
830 localizedString.SetDataWithLength (length, charBuffer);
831 rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ());
832 }
833 if (localizedString !is null) localizedString.Release ();
834
835 /*
836 * Check for proxy values set as documented java properties and update mozilla's
837 * preferences with these values if needed.
838 */
839 String proxyHost = System.getProperty (PROPERTY_PROXYHOST);
840 String proxyPortString = System.getProperty (PROPERTY_PROXYPORT);
841
842 int port = -1;
843 if (proxyPortString !is null) {
844 try {
845 int value = Integer.valueOf (proxyPortString).intValue ();
846 if (0 <= value && value <= MAX_PORT) port = value;
847 } catch (NumberFormatException e) {
848 /* do nothing, java property has non-integer value */
849 }
850 }
851
852 if (proxyHost !is null) {
853 byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID, true);
854 rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
855 if (rc !is XPCOM.NS_OK) error (rc);
856 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
857
858 localizedString = new nsIPrefLocalizedString (result[0]);
859 result[0] = 0;
860 int length = proxyHost.length ();
861 char[] charBuffer = new char[length + 1];
862 proxyHost.getChars (0, length, charBuffer, 0);
863 rc = localizedString.SetDataWithLength (length, charBuffer);
864 if (rc !is XPCOM.NS_OK) error (rc);
865 buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYHOST_FTP, true);
866 rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ());
867 if (rc !is XPCOM.NS_OK) error (rc);
868 buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYHOST_HTTP, true);
869 rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ());
870 if (rc !is XPCOM.NS_OK) error (rc);
871 buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYHOST_SSL, true);
872 rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ());
873 if (rc !is XPCOM.NS_OK) error (rc);
874 localizedString.Release ();
875 }
876
877 if (port !is -1) {
878 buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYPORT_FTP, true);
879 rc = prefBranch.SetIntPref (buffer, port);
880 if (rc !is XPCOM.NS_OK) error (rc);
881 buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYPORT_HTTP, true);
882 rc = prefBranch.SetIntPref (buffer, port);
883 if (rc !is XPCOM.NS_OK) error (rc);
884 buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYPORT_SSL, true);
885 rc = prefBranch.SetIntPref (buffer, port);
886 if (rc !is XPCOM.NS_OK) error (rc);
887 }
888
889 if (proxyHost !is null || port !is -1) {
890 buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYTYPE, true);
891 rc = prefBranch.SetIntPref (buffer, 1);
892 if (rc !is XPCOM.NS_OK) error (rc);
893 }
894
895 /*
896 * Ensure that windows that are shown during page loads are not blocked. Firefox may
897 * try to block these by default since such windows are often unwelcome, but this
898 * assumption should not be made in the Browser's context. Since the Browser client
899 * is responsible for creating the new Browser and Shell in an OpenWindowListener,
900 * they should decide whether the new window is unwelcome or not and act accordingly.
901 */
902 buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_DISABLEOPENDURINGLOAD, true);
903 rc = prefBranch.SetBoolPref (buffer, 0);
904 if (rc !is XPCOM.NS_OK) {
905 browser.dispose ();
906 error (rc);
907 }
908
909 /* Ensure that the status text can be set through means like javascript */
910 buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_DISABLEWINDOWSTATUSCHANGE, true);
911 rc = prefBranch.SetBoolPref (buffer, 0);
912 if (rc !is XPCOM.NS_OK) {
913 browser.dispose ();
914 error (rc);
915 }
916
917 prefBranch.Release ();
918
919 PromptService2Factory factory = new PromptService2Factory ();
920 factory.AddRef ();
921
922 rc = componentManager.QueryInterface (nsIComponentRegistrar.NS_ICOMPONENTREGISTRAR_IID, result);
923 if (rc !is XPCOM.NS_OK) {
924 browser.dispose ();
925 error (rc);
926 }
927 if (result[0] is 0) {
928 browser.dispose ();
929 error (XPCOM.NS_NOINTERFACE);
930 }
931
932 nsIComponentRegistrar componentRegistrar = new nsIComponentRegistrar (result[0]);
933 result[0] = 0;
934 aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PROMPTSERVICE_CONTRACTID, true);
935 byte[] aClassName = MozillaDelegate.wcsToMbcs (null, "Prompt Service", true); //$NON-NLS-1$
936 rc = componentRegistrar.RegisterFactory (XPCOM.NS_PROMPTSERVICE_CID, aClassName, aContractID, factory.getAddress ());
937 if (rc !is XPCOM.NS_OK) {
938 browser.dispose ();
939 error (rc);
940 }
941 factory.Release ();
942
943 HelperAppLauncherDialogFactory dialogFactory = new HelperAppLauncherDialogFactory ();
944 dialogFactory.AddRef ();
945 aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_HELPERAPPLAUNCHERDIALOG_CONTRACTID, true);
946 aClassName = MozillaDelegate.wcsToMbcs (null, "Helper App Launcher Dialog", true); //$NON-NLS-1$
947 rc = componentRegistrar.RegisterFactory (XPCOM.NS_HELPERAPPLAUNCHERDIALOG_CID, aClassName, aContractID, dialogFactory.getAddress ());
948 if (rc !is XPCOM.NS_OK) {
949 browser.dispose ();
950 error (rc);
951 }
952 dialogFactory.Release ();
953
954 /*
955 * This Download factory will be used if the GRE version is < 1.8.
956 * If the GRE version is 1.8.x then the Download factory that is registered later for
957 * contract "Transfer" will be used.
958 * If the GRE version is >= 1.9 then no Download factory is registered because this
959 * functionality is provided by the GRE.
960 */
961 DownloadFactory downloadFactory = new DownloadFactory ();
962 downloadFactory.AddRef ();
963 aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DOWNLOAD_CONTRACTID, true);
964 aClassName = MozillaDelegate.wcsToMbcs (null, "Download", true); //$NON-NLS-1$
965 rc = componentRegistrar.RegisterFactory (XPCOM.NS_DOWNLOAD_CID, aClassName, aContractID, downloadFactory.getAddress ());
966 if (rc !is XPCOM.NS_OK) {
967 browser.dispose ();
968 error (rc);
969 }
970 downloadFactory.Release ();
971
972 FilePickerFactory pickerFactory = IsXULRunner ? new FilePickerFactory_1_8 () : new FilePickerFactory ();
973 pickerFactory.AddRef ();
974 aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_FILEPICKER_CONTRACTID, true);
975 aClassName = MozillaDelegate.wcsToMbcs (null, "FilePicker", true); //$NON-NLS-1$
976 rc = componentRegistrar.RegisterFactory (XPCOM.NS_FILEPICKER_CID, aClassName, aContractID, pickerFactory.getAddress ());
977 if (rc !is XPCOM.NS_OK) {
978 browser.dispose ();
979 error (rc);
980 }
981 pickerFactory.Release ();
982
983 componentRegistrar.Release ();
984 componentManager.Release ();
985
986 Initialized = true;
987 }
988
989 if (display.getData (DISPOSE_LISTENER_HOOKED) is null) {
990 display.setData (DISPOSE_LISTENER_HOOKED, DISPOSE_LISTENER_HOOKED);
991 display.addListener (DWT.Dispose, new Listener () {
992 public void handleEvent (Event event) {
993 if (BrowserCount > 0) return; /* another display is still active */
994
995 int /*long*/[] result = new int /*long*/[1];
996 int rc = XPCOM.NS_GetServiceManager (result);
997 if (rc !is XPCOM.NS_OK) error (rc);
998 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
999
1000 nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
1001 result[0] = 0;
1002 byte[] buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_OBSERVER_CONTRACTID, true);
1003 rc = serviceManager.GetServiceByContractID (buffer, nsIObserverService.NS_IOBSERVERSERVICE_IID, result);
1004 if (rc !is XPCOM.NS_OK) error (rc);
1005 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
1006
1007 nsIObserverService observerService = new nsIObserverService (result[0]);
1008 result[0] = 0;
1009 buffer = MozillaDelegate.wcsToMbcs (null, PROFILE_BEFORE_CHANGE, true);
1010 int length = SHUTDOWN_PERSIST.length ();
1011 char[] chars = new char [length + 1];
1012 SHUTDOWN_PERSIST.getChars (0, length, chars, 0);
1013 rc = observerService.NotifyObservers (0, buffer, chars);
1014 if (rc !is XPCOM.NS_OK) error (rc);
1015 observerService.Release ();
1016
1017 if (LocationProvider !is null) {
1018 String prefsLocation = LocationProvider.profilePath + AppFileLocProvider.PREFERENCES_FILE;
1019 nsEmbedString pathString = new nsEmbedString (prefsLocation);
1020 rc = XPCOM.NS_NewLocalFile (pathString.getAddress (), 1, result);
1021 if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
1022 if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
1023 pathString.dispose ();
1024
1025 nsILocalFile localFile = new nsILocalFile (result [0]);
1026 result[0] = 0;
1027 rc = localFile.QueryInterface (nsIFile.NS_IFILE_IID, result);
1028 if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
1029 if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE);
1030 localFile.Release ();
1031
1032 nsIFile prefFile = new nsIFile (result[0]);
1033 result[0] = 0;
1034
1035 buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFSERVICE_CONTRACTID, true);
1036 rc = serviceManager.GetServiceByContractID (buffer, nsIPrefService.NS_IPREFSERVICE_IID, result);
1037 if (rc !is XPCOM.NS_OK) error (rc);
1038 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
1039
1040 nsIPrefService prefService = new nsIPrefService (result[0]);
1041 result[0] = 0;
1042 rc = prefService.SavePrefFile(prefFile.getAddress ());
1043 prefService.Release ();
1044 prefFile.Release ();
1045 }
1046 serviceManager.Release ();
1047
1048 if (XPCOMWasGlued) {
1049 XPCOM.XPCOMGlueShutdown ();
1050 XPCOMWasGlued = false;
1051 }
1052 if (XPCOMInitWasGlued) {
1053 XPCOMInit.XPCOMGlueShutdown ();
1054 XPCOMInitWasGlued = false;
1055 }
1056 Initialized = false;
1057 }
1058 });
1059 }
1060
1061 BrowserCount++;
1062 int rc = XPCOM.NS_GetComponentManager (result);
1063 if (rc !is XPCOM.NS_OK) {
1064 browser.dispose ();
1065 error (rc);
1066 }
1067 if (result[0] is 0) {
1068 browser.dispose ();
1069 error (XPCOM.NS_NOINTERFACE);
1070 }
1071
1072 nsIComponentManager componentManager = new nsIComponentManager (result[0]);
1073 result[0] = 0;
1074 nsID NS_IWEBBROWSER_CID = new nsID ("F1EAC761-87E9-11d3-AF80-00A024FFC08C"); //$NON-NLS-1$
1075 rc = componentManager.CreateInstance (NS_IWEBBROWSER_CID, 0, nsIWebBrowser.NS_IWEBBROWSER_IID, result);
1076 if (rc !is XPCOM.NS_OK) {
1077 browser.dispose ();
1078 error (rc);
1079 }
1080 if (result[0] is 0) {
1081 browser.dispose ();
1082 error (XPCOM.NS_NOINTERFACE);
1083 }
1084
1085 webBrowser = new nsIWebBrowser (result[0]);
1086 result[0] = 0;
1087
1088 createCOMInterfaces ();
1089 AddRef ();
1090
1091 rc = webBrowser.SetContainerWindow (webBrowserChrome.getAddress());
1092 if (rc !is XPCOM.NS_OK) {
1093 browser.dispose ();
1094 error (rc);
1095 }
1096
1097 rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
1098 if (rc !is XPCOM.NS_OK) {
1099 browser.dispose ();
1100 error (rc);
1101 }
1102 if (result[0] is 0) {
1103 browser.dispose ();
1104 error (XPCOM.NS_ERROR_NO_INTERFACE);
1105 }
1106
1107 nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
1108 result[0] = 0;
1109 Rectangle rect = browser.getClientArea ();
1110 if (rect.isEmpty ()) {
1111 rect.width = 1;
1112 rect.height = 1;
1113 }
1114
1115 embedHandle = delegate.getHandle ();
1116
1117 rc = baseWindow.InitWindow (embedHandle, 0, 0, 0, rect.width, rect.height);
1118 if (rc !is XPCOM.NS_OK) {
1119 browser.dispose ();
1120 error (XPCOM.NS_ERROR_FAILURE);
1121 }
1122 rc = baseWindow.Create ();
1123 if (rc !is XPCOM.NS_OK) {
1124 browser.dispose ();
1125 error (XPCOM.NS_ERROR_FAILURE);
1126 }
1127 rc = baseWindow.SetVisibility (1);
1128 if (rc !is XPCOM.NS_OK) {
1129 browser.dispose ();
1130 error (XPCOM.NS_ERROR_FAILURE);
1131 }
1132 baseWindow.Release ();
1133
1134 if (!PerformedVersionCheck) {
1135 PerformedVersionCheck = true;
1136
1137 /*
1138 * Check for the availability of the pre-1.8 implementation of nsIDocShell
1139 * to determine if the GRE's version is < 1.8.
1140 */
1141 rc = webBrowser.QueryInterface (nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID, result);
1142 if (rc !is XPCOM.NS_OK) {
1143 browser.dispose ();
1144 error (XPCOM.NS_ERROR_FAILURE);
1145 }
1146 if (result[0] is 0) {
1147 browser.dispose ();
1148 error (XPCOM.NS_ERROR_NO_INTERFACE);
1149 }
1150 nsIInterfaceRequestor interfaceRequestor = new nsIInterfaceRequestor (result[0]);
1151 result[0] = 0;
1152
1153 rc = interfaceRequestor.GetInterface (nsIDocShell.NS_IDOCSHELL_IID, result);
1154 if (rc is XPCOM.NS_OK && result[0] !is 0) {
1155 IsPre_1_8 = true;
1156 new nsISupports (result[0]).Release ();
1157 }
1158 result[0] = 0;
1159
1160 /*
1161 * A Download factory for contract "Transfer" must be registered iff the GRE's version is 1.8.x.
1162 * Check for the availability of the 1.8 implementation of nsIDocShell to determine if the
1163 * GRE's version is 1.8.x.
1164 * If the GRE version is < 1.8 then the previously-registered Download factory for contract
1165 * "Download" will be used.
1166 * If the GRE version is >= 1.9 then no Download factory is registered because this
1167 * functionality is provided by the GRE.
1168 */
1169 if (!IsPre_1_8) {
1170 rc = interfaceRequestor.GetInterface (nsIDocShell_1_8.NS_IDOCSHELL_IID, result);
1171 if (rc is XPCOM.NS_OK && result[0] !is 0) { /* 1.8 */
1172 new nsISupports (result[0]).Release ();
1173 result[0] = 0;
1174 rc = componentManager.QueryInterface (nsIComponentRegistrar.NS_ICOMPONENTREGISTRAR_IID, result);
1175 if (rc !is XPCOM.NS_OK) {
1176 browser.dispose ();
1177 error (rc);
1178 }
1179 if (result[0] is 0) {
1180 browser.dispose ();
1181 error (XPCOM.NS_NOINTERFACE);
1182 }
1183
1184 nsIComponentRegistrar componentRegistrar = new nsIComponentRegistrar (result[0]);
1185 DownloadFactory_1_8 downloadFactory_1_8 = new DownloadFactory_1_8 ();
1186 downloadFactory_1_8.AddRef ();
1187 byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_TRANSFER_CONTRACTID, true);
1188 byte[] aClassName = MozillaDelegate.wcsToMbcs (null, "Transfer", true); //$NON-NLS-1$
1189 rc = componentRegistrar.RegisterFactory (XPCOM.NS_DOWNLOAD_CID, aClassName, aContractID, downloadFactory_1_8.getAddress ());
1190 if (rc !is XPCOM.NS_OK) {
1191 browser.dispose ();
1192 error (rc);
1193 }
1194 downloadFactory_1_8.Release ();
1195 componentRegistrar.Release ();
1196 } else { /* >= 1.9 */
1197 /*
1198 * Bug in XULRunner 1.9. Mozilla no longer clears its background before initial content has
1199 * been set. As a result embedders appear broken if they do not immediately navigate to a url.
1200 * The workaround for this is to navigate to about:blank immediately so that the background is
1201 * cleared, but do not fire any corresponding events or allow Browser API calls to reveal this.
1202 * Once the client does a proper navigate with either setUrl() or setText() then resume as
1203 * normal. The Mozilla bug for this is https://bugzilla.mozilla.org/show_bug.cgi?id=415789.
1204 */
1205 awaitingNavigate = true;
1206 rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
1207 if (rc !is XPCOM.NS_OK) {
1208 browser.dispose ();
1209 error (rc);
1210 }
1211 if (result[0] is 0) {
1212 browser.dispose ();
1213 error (XPCOM.NS_ERROR_NO_INTERFACE);
1214 }
1215 nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
1216 char[] uri = new char[ABOUT_BLANK.length () + 1];
1217 ABOUT_BLANK.getChars (0, ABOUT_BLANK.length (), uri, 0);
1218 rc = webNavigation.LoadURI (uri, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0);
1219 webNavigation.Release ();
1220 }
1221 }
1222 result[0] = 0;
1223 interfaceRequestor.Release ();
1224 }
1225 componentManager.Release ();
1226
1227 rc = webBrowser.AddWebBrowserListener (weakReference.getAddress (), nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID);
1228 if (rc !is XPCOM.NS_OK) {
1229 browser.dispose ();
1230 error (rc);
1231 }
1232
1233 rc = webBrowser.SetParentURIContentListener (uriContentListener.getAddress ());
1234 if (rc !is XPCOM.NS_OK) {
1235 browser.dispose ();
1236 error (rc);
1237 }
1238
1239 delegate.init ();
1240
1241 listener = new Listener () {
1242 public void handleEvent (Event event) {
1243 switch (event.type) {
1244 case DWT.Dispose: {
1245 /* make this handler run after other dispose listeners */
1246 if (ignoreDispose) {
1247 ignoreDispose = false;
1248 break;
1249 }
1250 ignoreDispose = true;
1251 browser.notifyListeners (event.type, event);
1252 event.type = DWT.NONE;
1253 onDispose (event.display);
1254 break;
1255 }
1256 case DWT.Resize: onResize (); break;
1257 case DWT.FocusIn: Activate (); break;
1258 case DWT.Activate: Activate (); break;
1259 case DWT.Deactivate: {
1260 Display display = event.display;
1261 if (Mozilla.this.browser is display.getFocusControl ()) Deactivate ();
1262 break;
1263 }
1264 case DWT.Show: {
1265 /*
1266 * Feature in GTK Mozilla. Mozilla does not show up when
1267 * its container (a GTK fixed handle) is made visible
1268 * after having been hidden. The workaround is to reset
1269 * its size after the container has been made visible.
1270 */
1271 Display display = event.display;
1272 display.asyncExec(new Runnable () {
1273 public void run() {
1274 if (browser.isDisposed ()) return;
1275 onResize ();
1276 }
1277 });
1278 break;
1279 }
1280 }
1281 }
1282 };
1283 int[] folderEvents = new int[] {
1284 DWT.Dispose,
1285 DWT.Resize,
1286 DWT.FocusIn,
1287 DWT.Activate,
1288 DWT.Deactivate,
1289 DWT.Show,
1290 DWT.KeyDown // needed to make browser traversable
1291 };
1292 for (int i = 0; i < folderEvents.length; i++) {
1293 browser.addListener (folderEvents[i], listener);
1294 }
1295 }
1296
1297 public bool back () {
1298 if (awaitingNavigate) return false;
1299
1300 int /*long*/[] result = new int /*long*/[1];
1301 int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
1302 if (rc !is XPCOM.NS_OK) error (rc);
1303 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1304
1305 nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
1306 rc = webNavigation.GoBack ();
1307 webNavigation.Release ();
1308 return rc is XPCOM.NS_OK;
1309 }
1310
1311 void createCOMInterfaces () {
1312 // Create each of the interfaces that this object implements
1313 supports = new XPCOMObject (new int[] {2, 0, 0}) {
1314 public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
1315 public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
1316 public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
1317 };
1318
1319 weakReference = new XPCOMObject (new int[] {2, 0, 0, 2}) {
1320 public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
1321 public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
1322 public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
1323 public int /*long*/ method3 (int /*long*/[] args) {return QueryReferent (args[0], args[1]);}
1324 };
1325
1326 webProgressListener = new XPCOMObject (new int[] {2, 0, 0, 4, 6, 3, 4, 3}) {
1327 public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
1328 public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
1329 public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
1330 public int /*long*/ method3 (int /*long*/[] args) {return OnStateChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3]);}
1331 public int /*long*/ method4 (int /*long*/[] args) {return OnProgressChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4], (int)/*64*/args[5]);}
1332 public int /*long*/ method5 (int /*long*/[] args) {return OnLocationChange (args[0], args[1], args[2]);}
1333 public int /*long*/ method6 (int /*long*/[] args) {return OnStatusChange (args[0], args[1], (int)/*64*/args[2], args[3]);}
1334 public int /*long*/ method7 (int /*long*/[] args) {return OnSecurityChange (args[0], args[1], (int)/*64*/args[2]);}
1335 };
1336
1337 webBrowserChrome = new XPCOMObject (new int[] {2, 0, 0, 2, 1, 1, 1, 1, 0, 2, 0, 1, 1}) {
1338 public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
1339 public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
1340 public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
1341 public int /*long*/ method3 (int /*long*/[] args) {return SetStatus ((int)/*64*/args[0], args[1]);}
1342 public int /*long*/ method4 (int /*long*/[] args) {return GetWebBrowser (args[0]);}
1343 public int /*long*/ method5 (int /*long*/[] args) {return SetWebBrowser (args[0]);}
1344 public int /*long*/ method6 (int /*long*/[] args) {return GetChromeFlags (args[0]);}
1345 public int /*long*/ method7 (int /*long*/[] args) {return SetChromeFlags ((int)/*64*/args[0]);}
1346 public int /*long*/ method8 (int /*long*/[] args) {return DestroyBrowserWindow ();}
1347 public int /*long*/ method9 (int /*long*/[] args) {return SizeBrowserTo ((int)/*64*/args[0], (int)/*64*/args[1]);}
1348 public int /*long*/ method10 (int /*long*/[] args) {return ShowAsModal ();}
1349 public int /*long*/ method11 (int /*long*/[] args) {return IsWindowModal (args[0]);}
1350 public int /*long*/ method12 (int /*long*/[] args) {return ExitModalEventLoop ((int)/*64*/args[0]);}
1351 };
1352
1353 webBrowserChromeFocus = new XPCOMObject (new int[] {2, 0, 0, 0, 0}) {
1354 public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
1355 public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
1356 public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
1357 public int /*long*/ method3 (int /*long*/[] args) {return FocusNextElement ();}
1358 public int /*long*/ method4 (int /*long*/[] args) {return FocusPrevElement ();}
1359 };
1360
1361 embeddingSiteWindow = new XPCOMObject (new int[] {2, 0, 0, 5, 5, 0, 1, 1, 1, 1, 1}) {
1362 public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
1363 public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
1364 public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
1365 public int /*long*/ method3 (int /*long*/[] args) {return SetDimensions ((int)/*64*/args[0], (int)/*64*/args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4]);}
1366 public int /*long*/ method4 (int /*long*/[] args) {return GetDimensions ((int)/*64*/args[0], args[1], args[2], args[3], args[4]);}
1367 public int /*long*/ method5 (int /*long*/[] args) {return SetFocus ();}
1368 public int /*long*/ method6 (int /*long*/[] args) {return GetVisibility (args[0]);}
1369 public int /*long*/ method7 (int /*long*/[] args) {return SetVisibility ((int)/*64*/args[0]);}
1370 public int /*long*/ method8 (int /*long*/[] args) {return GetTitle (args[0]);}
1371 public int /*long*/ method9 (int /*long*/[] args) {return SetTitle (args[0]);}
1372 public int /*long*/ method10 (int /*long*/[] args) {return GetSiteWindow (args[0]);}
1373 };
1374
1375 interfaceRequestor = new XPCOMObject (new int[] {2, 0, 0, 2} ){
1376 public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
1377 public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
1378 public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
1379 public int /*long*/ method3 (int /*long*/[] args) {return GetInterface (args[0], args[1]);}
1380 };
1381
1382 supportsWeakReference = new XPCOMObject (new int[] {2, 0, 0, 1}) {
1383 public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
1384 public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
1385 public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
1386 public int /*long*/ method3 (int /*long*/[] args) {return GetWeakReference (args[0]);}
1387 };
1388
1389 contextMenuListener = new XPCOMObject (new int[] {2, 0, 0, 3}) {
1390 public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
1391 public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
1392 public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
1393 public int /*long*/ method3 (int /*long*/[] args) {return OnShowContextMenu ((int)/*64*/args[0], args[1], args[2]);}
1394 };
1395
1396 uriContentListener = new XPCOMObject (new int[] {2, 0, 0, 2, 5, 3, 4, 1, 1, 1, 1}) {
1397 public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
1398 public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
1399 public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
1400 public int /*long*/ method3 (int /*long*/[] args) {return OnStartURIOpen (args[0], args[1]);}
1401 public int /*long*/ method4 (int /*long*/[] args) {return DoContent (args[0], (int)/*64*/args[1], args[2], args[3], args[4]);}
1402 public int /*long*/ method5 (int /*long*/[] args) {return IsPreferred (args[0], args[1], args[2]);}
1403 public int /*long*/ method6 (int /*long*/[] args) {return CanHandleContent (args[0], (int)/*64*/args[1], args[2], args[3]);}
1404 public int /*long*/ method7 (int /*long*/[] args) {return GetLoadCookie (args[0]);}
1405 public int /*long*/ method8 (int /*long*/[] args) {return SetLoadCookie (args[0]);}
1406 public int /*long*/ method9 (int /*long*/[] args) {return GetParentContentListener (args[0]);}
1407 public int /*long*/ method10 (int /*long*/[] args) {return SetParentContentListener (args[0]);}
1408 };
1409
1410 tooltipListener = new XPCOMObject (new int[] {2, 0, 0, 3, 0}) {
1411 public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
1412 public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
1413 public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
1414 public int /*long*/ method3 (int /*long*/[] args) {return OnShowTooltip ((int)/*64*/args[0], (int)/*64*/args[1], args[2]);}
1415 public int /*long*/ method4 (int /*long*/[] args) {return OnHideTooltip ();}
1416 };
1417
1418 domEventListener = new XPCOMObject (new int[] {2, 0, 0, 1}) {
1419 public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
1420 public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
1421 public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
1422 public int /*long*/ method3 (int /*long*/[] args) {return HandleEvent (args[0]);}
1423 };
1424 }
1425
1426 void disposeCOMInterfaces () {
1427 if (supports !is null) {
1428 supports.dispose ();
1429 supports = null;
1430 }
1431 if (weakReference !is null) {
1432 weakReference.dispose ();
1433 weakReference = null;
1434 }
1435 if (webProgressListener !is null) {
1436 webProgressListener.dispose ();
1437 webProgressListener = null;
1438 }
1439 if (webBrowserChrome !is null) {
1440 webBrowserChrome.dispose ();
1441 webBrowserChrome = null;
1442 }
1443 if (webBrowserChromeFocus !is null) {
1444 webBrowserChromeFocus.dispose ();
1445 webBrowserChromeFocus = null;
1446 }
1447 if (embeddingSiteWindow !is null) {
1448 embeddingSiteWindow.dispose ();
1449 embeddingSiteWindow = null;
1450 }
1451 if (interfaceRequestor !is null) {
1452 interfaceRequestor.dispose ();
1453 interfaceRequestor = null;
1454 }
1455 if (supportsWeakReference !is null) {
1456 supportsWeakReference.dispose ();
1457 supportsWeakReference = null;
1458 }
1459 if (contextMenuListener !is null) {
1460 contextMenuListener.dispose ();
1461 contextMenuListener = null;
1462 }
1463 if (uriContentListener !is null) {
1464 uriContentListener.dispose ();
1465 uriContentListener = null;
1466 }
1467 if (tooltipListener !is null) {
1468 tooltipListener.dispose ();
1469 tooltipListener = null;
1470 }
1471 if (domEventListener !is null) {
1472 domEventListener.dispose ();
1473 domEventListener = null;
1474 }
1475 }
1476
1477 public bool execute (String script) {
1478 if (awaitingNavigate) return false;
1479
1480 String url = PREFIX_JAVASCRIPT + script + ";void(0);"; //$NON-NLS-1$
1481 int /*long*/[] result = new int /*long*/[1];
1482 int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
1483 if (rc !is XPCOM.NS_OK) error (rc);
1484 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1485
1486 nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
1487 char[] arg = url.toCharArray ();
1488 char[] c = new char[arg.length+1];
1489 System.arraycopy (arg, 0, c, 0, arg.length);
1490 rc = webNavigation.LoadURI (c, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0);
1491 webNavigation.Release ();
1492 return rc is XPCOM.NS_OK;
1493 }
1494
1495 static Browser findBrowser (int /*long*/ handle) {
1496 return MozillaDelegate.findBrowser (handle);
1497 }
1498
1499 public bool forward () {
1500 if (awaitingNavigate) return false;
1501
1502 int /*long*/[] result = new int /*long*/[1];
1503 int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
1504 if (rc !is XPCOM.NS_OK) error (rc);
1505 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1506
1507 nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
1508 rc = webNavigation.GoForward ();
1509 webNavigation.Release ();
1510
1511 return rc is XPCOM.NS_OK;
1512 }
1513
1514 public String getText () {
1515 if (awaitingNavigate) return ""; //$NON-NLS-1$
1516
1517 int /*long*/[] result = new int /*long*/[1];
1518 int rc = webBrowser.GetContentDOMWindow (result);
1519 if (rc !is XPCOM.NS_OK) error (rc);
1520 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
1521
1522 nsIDOMWindow window = new nsIDOMWindow (result[0]);
1523 result[0] = 0;
1524 rc = window.GetDocument (result);
1525 if (rc !is XPCOM.NS_OK) error (rc);
1526 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
1527 window.Release ();
1528
1529 int /*long*/ document = result[0];
1530 result[0] = 0;
1531 rc = XPCOM.NS_GetComponentManager (result);
1532 if (rc !is XPCOM.NS_OK) error (rc);
1533 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
1534
1535 nsIComponentManager componentManager = new nsIComponentManager (result[0]);
1536 result[0] = 0;
1537 byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DOMSERIALIZER_CONTRACTID, true);
1538 char[] chars = null;
1539
1540 rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIDOMSerializer_1_7.NS_IDOMSERIALIZER_IID, result);
1541 if (rc is XPCOM.NS_OK) { /* mozilla >= 1.7 */
1542 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
1543
1544 nsIDOMSerializer_1_7 serializer = new nsIDOMSerializer_1_7 (result[0]);
1545 result[0] = 0;
1546 int /*long*/ string = XPCOM.nsEmbedString_new ();
1547 rc = serializer.SerializeToString (document, string);
1548 serializer.Release ();
1549
1550 int length = XPCOM.nsEmbedString_Length (string);
1551 int /*long*/ buffer = XPCOM.nsEmbedString_get (string);
1552 chars = new char[length];
1553 XPCOM.memmove (chars, buffer, length * 2);
1554 XPCOM.nsEmbedString_delete (string);
1555 } else { /* mozilla < 1.7 */
1556 rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIDOMSerializer.NS_IDOMSERIALIZER_IID, result);
1557 if (rc !is XPCOM.NS_OK) error (rc);
1558 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
1559
1560 nsIDOMSerializer serializer = new nsIDOMSerializer (result[0]);
1561 result[0] = 0;
1562 rc = serializer.SerializeToString (document, result);
1563 serializer.Release ();
1564
1565 int length = XPCOM.strlen_PRUnichar (result[0]);
1566 chars = new char[length];
1567 XPCOM.memmove (chars, result[0], length * 2);
1568 }
1569
1570 componentManager.Release ();
1571 new nsISupports (document).Release ();
1572 return new String (chars);
1573 }
1574
1575 public String getUrl () {
1576 if (awaitingNavigate) return ""; //$NON-NLS-1$
1577
1578 int /*long*/[] result = new int /*long*/[1];
1579 int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
1580 if (rc !is XPCOM.NS_OK) error (rc);
1581 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1582
1583 nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
1584 int /*long*/[] aCurrentURI = new int /*long*/[1];
1585 rc = webNavigation.GetCurrentURI (aCurrentURI);
1586 if (rc !is XPCOM.NS_OK) error (rc);
1587 webNavigation.Release ();
1588
1589 byte[] dest = null;
1590 if (aCurrentURI[0] !is 0) {
1591 nsIURI uri = new nsIURI (aCurrentURI[0]);
1592 int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
1593 rc = uri.GetSpec (aSpec);
1594 if (rc !is XPCOM.NS_OK) error (rc);
1595 int length = XPCOM.nsEmbedCString_Length (aSpec);
1596 int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
1597 dest = new byte[length];
1598 XPCOM.memmove (dest, buffer, length);
1599 XPCOM.nsEmbedCString_delete (aSpec);
1600 uri.Release ();
1601 }
1602 if (dest is null) return ""; //$NON-NLS-1$
1603
1604 String location = new String (dest);
1605 /*
1606 * If the URI indicates that the page is being rendered from memory
1607 * (via setText()) then set it to about:blank to be consistent with IE.
1608 */
1609 if (location.equals (URI_FROMMEMORY)) location = ABOUT_BLANK;
1610 return location;
1611 }
1612
1613 public Object getWebBrowser () {
1614 if ((browser.getStyle () & DWT.MOZILLA) is 0) return null;
1615 if (webBrowserObject !is null) return webBrowserObject;
1616
1617 try {
1618 Class clazz = Class.forName ("org.mozilla.xpcom.Mozilla"); //$NON-NLS-1$
1619 Method method = clazz.getMethod ("getInstance", new Class[0]); //$NON-NLS-1$
1620 Object mozilla = method.invoke (null, new Object[0]);
1621 method = clazz.getMethod ("wrapXPCOMObject", new Class[] {Long.TYPE, String.class}); //$NON-NLS-1$
1622 webBrowserObject = method.invoke (mozilla, new Object[] {new Long (webBrowser.getAddress ()), nsIWebBrowser.NS_IWEBBROWSER_IID_STR});
1623 /*
1624 * The following AddRef() is needed to offset the automatic Release() that
1625 * will be performed by JavaXPCOM when webBrowserObject is finalized.
1626 */
1627 webBrowser.AddRef ();
1628 return webBrowserObject;
1629 } catch (ClassNotFoundException e) {
1630 } catch (NoSuchMethodException e) {
1631 } catch (IllegalArgumentException e) {
1632 } catch (IllegalAccessException e) {
1633 } catch (InvocationTargetException e) {
1634 }
1635 return null;
1636 }
1637
1638 public bool isBackEnabled () {
1639 if (awaitingNavigate) return false;
1640
1641 int /*long*/[] result = new int /*long*/[1];
1642 int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
1643 if (rc !is XPCOM.NS_OK) error (rc);
1644 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1645
1646 nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
1647 int[] aCanGoBack = new int[1]; /* PRBool */
1648 rc = webNavigation.GetCanGoBack (aCanGoBack);
1649 webNavigation.Release ();
1650 return aCanGoBack[0] !is 0;
1651 }
1652
1653 public bool isForwardEnabled () {
1654 if (awaitingNavigate) return false;
1655
1656 int /*long*/[] result = new int /*long*/[1];
1657 int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
1658 if (rc !is XPCOM.NS_OK) error (rc);
1659 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1660
1661 nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
1662 int[] aCanGoForward = new int[1]; /* PRBool */
1663 rc = webNavigation.GetCanGoForward (aCanGoForward);
1664 webNavigation.Release ();
1665 return aCanGoForward[0] !is 0;
1666 }
1667
1668 static String error (int code) {
1669 throw new DWTError ("XPCOM error " + code); //$NON-NLS-1$
1670 }
1671
1672 void onDispose (Display display) {
1673 int rc = webBrowser.RemoveWebBrowserListener (weakReference.getAddress (), nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID);
1674 if (rc !is XPCOM.NS_OK) error (rc);
1675
1676 rc = webBrowser.SetParentURIContentListener (0);
1677 if (rc !is XPCOM.NS_OK) error (rc);
1678
1679 unhookDOMListeners ();
1680 if (listener !is null) {
1681 int[] folderEvents = new int[] {
1682 DWT.Dispose,
1683 DWT.Resize,
1684 DWT.FocusIn,
1685 DWT.Activate,
1686 DWT.Deactivate,
1687 DWT.Show,
1688 DWT.KeyDown,
1689 };
1690 for (int i = 0; i < folderEvents.length; i++) {
1691 browser.removeListener (folderEvents[i], listener);
1692 }
1693 listener = null;
1694 }
1695
1696 int /*long*/[] result = new int /*long*/[1];
1697 rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
1698 if (rc !is XPCOM.NS_OK) error (rc);
1699 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1700
1701 nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
1702 rc = baseWindow.Destroy ();
1703 if (rc !is XPCOM.NS_OK) error (rc);
1704 baseWindow.Release ();
1705
1706 Release ();
1707 webBrowser.Release ();
1708 webBrowser = null;
1709 webBrowserObject = null;
1710
1711 if (tip !is null && !tip.isDisposed ()) tip.dispose ();
1712 tip = null;
1713 location = size = null;
1714
1715 Enumeration elements = unhookedDOMWindows.elements ();
1716 while (elements.hasMoreElements ()) {
1717 LONG ptrObject = (LONG)elements.nextElement ();
1718 new nsISupports (ptrObject.value).Release ();
1719 }
1720 unhookedDOMWindows = null;
1721
1722 delegate.onDispose (embedHandle);
1723 delegate = null;
1724
1725 embedHandle = 0;
1726 BrowserCount--;
1727 }
1728
1729 void Activate () {
1730 int /*long*/[] result = new int /*long*/[1];
1731 int rc = webBrowser.QueryInterface (nsIWebBrowserFocus.NS_IWEBBROWSERFOCUS_IID, result);
1732 if (rc !is XPCOM.NS_OK) error (rc);
1733 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1734
1735 nsIWebBrowserFocus webBrowserFocus = new nsIWebBrowserFocus (result[0]);
1736 rc = webBrowserFocus.Activate ();
1737 if (rc !is XPCOM.NS_OK) error (rc);
1738 webBrowserFocus.Release ();
1739 }
1740
1741 void Deactivate () {
1742 int /*long*/[] result = new int /*long*/[1];
1743 int rc = webBrowser.QueryInterface (nsIWebBrowserFocus.NS_IWEBBROWSERFOCUS_IID, result);
1744 if (rc !is XPCOM.NS_OK) error (rc);
1745 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1746
1747 nsIWebBrowserFocus webBrowserFocus = new nsIWebBrowserFocus (result[0]);
1748 rc = webBrowserFocus.Deactivate ();
1749 if (rc !is XPCOM.NS_OK) error (rc);
1750 webBrowserFocus.Release ();
1751 }
1752
1753 void onResize () {
1754 Rectangle rect = browser.getClientArea ();
1755 int width = Math.max (1, rect.width);
1756 int height = Math.max (1, rect.height);
1757
1758 int /*long*/[] result = new int /*long*/[1];
1759 int rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
1760 if (rc !is XPCOM.NS_OK) error (rc);
1761 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1762
1763 delegate.setSize (embedHandle, width, height);
1764 nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
1765 rc = baseWindow.SetPositionAndSize (0, 0, width, height, 1);
1766 if (rc !is XPCOM.NS_OK) error (rc);
1767 baseWindow.Release ();
1768 }
1769
1770 public void refresh () {
1771 if (awaitingNavigate) return;
1772
1773 int /*long*/[] result = new int /*long*/[1];
1774 int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
1775 if (rc !is XPCOM.NS_OK) error(rc);
1776 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1777
1778 nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
1779 rc = webNavigation.Reload (nsIWebNavigation.LOAD_FLAGS_NONE);
1780 webNavigation.Release ();
1781 if (rc is XPCOM.NS_OK) return;
1782 /*
1783 * Feature in Mozilla. Reload returns an error code NS_ERROR_INVALID_POINTER
1784 * when it is called immediately after a request to load a new document using
1785 * LoadURI. The workaround is to ignore this error code.
1786 *
1787 * Feature in Mozilla. Attempting to reload a file that no longer exists
1788 * returns an error code of NS_ERROR_FILE_NOT_FOUND. This is equivalent to
1789 * attempting to load a non-existent local url, which is not a Browser error,
1790 * so this error code should be ignored.
1791 */
1792 if (rc !is XPCOM.NS_ERROR_INVALID_POINTER && rc !is XPCOM.NS_ERROR_FILE_NOT_FOUND) error (rc);
1793 }
1794
1795 public bool setText (String html) {
1796 /*
1797 * Feature in Mozilla. The focus memory of Mozilla must be
1798 * properly managed through the nsIWebBrowserFocus interface.
1799 * In particular, nsIWebBrowserFocus.deactivate must be called
1800 * when the focus moves from the browser (or one of its children
1801 * managed by Mozilla to another widget. We currently do not
1802 * get notified when a widget takes focus away from the Browser.
1803 * As a result, deactivate is not properly called. This causes
1804 * Mozilla to retake focus the next time a document is loaded.
1805 * This breaks the case where the HTML loaded in the Browser
1806 * varies while the user enters characters in a text widget. The text
1807 * widget loses focus every time new content is loaded.
1808 * The current workaround is to call deactivate everytime if
1809 * the browser currently does not have focus. A better workaround
1810 * would be to have a way to call deactivate when the Browser
1811 * or one of its children loses focus.
1812 */
1813 if (browser !is browser.getDisplay ().getFocusControl ()) Deactivate ();
1814
1815 /* convert the String containing HTML to an array of bytes with UTF-8 data */
1816 byte[] data = null;
1817 try {
1818 data = html.getBytes ("UTF-8"); //$NON-NLS-1$
1819 } catch (UnsupportedEncodingException e) {
1820 return false;
1821 }
1822
1823 awaitingNavigate = false;
1824
1825 byte[] contentTypeBuffer = MozillaDelegate.wcsToMbcs (null, "text/html", true); // $NON-NLS-1$
1826 int /*long*/ aContentType = XPCOM.nsEmbedCString_new (contentTypeBuffer, contentTypeBuffer.length);
1827 byte[] contentCharsetBuffer = MozillaDelegate.wcsToMbcs (null, "UTF-8", true); //$NON-NLS-1$
1828 int /*long*/ aContentCharset = XPCOM.nsEmbedCString_new (contentCharsetBuffer, contentCharsetBuffer.length);
1829
1830 int /*long*/[] result = new int /*long*/[1];
1831 int rc = XPCOM.NS_GetServiceManager (result);
1832 if (rc !is XPCOM.NS_OK) error (rc);
1833 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
1834
1835 nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
1836 result[0] = 0;
1837 rc = serviceManager.GetService (XPCOM.NS_IOSERVICE_CID, nsIIOService.NS_IIOSERVICE_IID, result);
1838 if (rc !is XPCOM.NS_OK) error (rc);
1839 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
1840 serviceManager.Release ();
1841
1842 nsIIOService ioService = new nsIIOService (result[0]);
1843 result[0] = 0;
1844 /*
1845 * Note. Mozilla ignores LINK tags used to load CSS stylesheets
1846 * when the URI protocol for the nsInputStreamChannel
1847 * is about:blank. The fix is to specify the file protocol.
1848 */
1849 byte[] aString = MozillaDelegate.wcsToMbcs (null, URI_FROMMEMORY, false);
1850 int /*long*/ aSpec = XPCOM.nsEmbedCString_new (aString, aString.length);
1851 rc = ioService.NewURI (aSpec, null, 0, result);
1852 if (rc !is XPCOM.NS_OK) error (rc);
1853 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
1854 XPCOM.nsEmbedCString_delete (aSpec);
1855 ioService.Release ();
1856
1857 nsIURI uri = new nsIURI (result[0]);
1858 result[0] = 0;
1859
1860 rc = webBrowser.QueryInterface (nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID, result);
1861 if (rc !is XPCOM.NS_OK) error (rc);
1862 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1863 nsIInterfaceRequestor interfaceRequestor = new nsIInterfaceRequestor (result[0]);
1864 result[0] = 0;
1865
1866 /*
1867 * Feature in Mozilla. LoadStream invokes the nsIInputStream argument
1868 * through a different thread. The callback mechanism must attach
1869 * a non java thread to the JVM otherwise the nsIInputStream Read and
1870 * Close methods never get called.
1871 */
1872 InputStream inputStream = new InputStream (data);
1873 inputStream.AddRef ();
1874
1875 rc = interfaceRequestor.GetInterface (nsIDocShell_1_9.NS_IDOCSHELL_IID, result);
1876 if (rc is XPCOM.NS_OK) {
1877 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1878 nsIDocShell_1_9 docShell = new nsIDocShell_1_9 (result[0]);
1879 rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType, aContentCharset, 0);
1880 docShell.Release ();
1881 } else {
1882 result[0] = 0;
1883 rc = interfaceRequestor.GetInterface (nsIDocShell_1_8.NS_IDOCSHELL_IID, result);
1884 if (rc is XPCOM.NS_OK) {
1885 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1886 nsIDocShell_1_8 docShell = new nsIDocShell_1_8 (result[0]);
1887 rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType, aContentCharset, 0);
1888 docShell.Release ();
1889 } else {
1890 result[0] = 0;
1891 rc = interfaceRequestor.GetInterface (nsIDocShell.NS_IDOCSHELL_IID, result);
1892 if (rc !is XPCOM.NS_OK) error (rc);
1893 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1894 nsIDocShell docShell = new nsIDocShell (result[0]);
1895 rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType, aContentCharset, 0);
1896 docShell.Release ();
1897 }
1898 }
1899 if (rc !is XPCOM.NS_OK) error (rc);
1900 result[0] = 0;
1901
1902 inputStream.Release ();
1903 interfaceRequestor.Release ();
1904 uri.Release ();
1905 XPCOM.nsEmbedCString_delete (aContentCharset);
1906 XPCOM.nsEmbedCString_delete (aContentType);
1907 return true;
1908 }
1909
1910 public bool setUrl (String url) {
1911 awaitingNavigate = false;
1912
1913 int /*long*/[] result = new int /*long*/[1];
1914 int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
1915 if (rc !is XPCOM.NS_OK) error (rc);
1916 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1917
1918 nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
1919 char[] uri = new char[url.length () + 1];
1920 url.getChars (0, url.length (), uri, 0);
1921 rc = webNavigation.LoadURI (uri, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0);
1922 webNavigation.Release ();
1923 return rc is XPCOM.NS_OK;
1924 }
1925
1926 public void stop () {
1927 if (awaitingNavigate) return;
1928
1929 int /*long*/[] result = new int /*long*/[1];
1930 int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
1931 if (rc !is XPCOM.NS_OK) error (rc);
1932 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1933
1934 nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
1935 rc = webNavigation.Stop (nsIWebNavigation.STOP_ALL);
1936 if (rc !is XPCOM.NS_OK) error (rc);
1937 webNavigation.Release ();
1938 }
1939
1940 void hookDOMListeners (nsIDOMEventTarget target, bool isTop) {
1941 nsEmbedString string = new nsEmbedString (XPCOM.DOMEVENT_FOCUS);
1942 target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
1943 string.dispose ();
1944 string = new nsEmbedString (XPCOM.DOMEVENT_UNLOAD);
1945 target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
1946 string.dispose ();
1947 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDOWN);
1948 target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
1949 string.dispose ();
1950 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEUP);
1951 target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
1952 string.dispose ();
1953 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEMOVE);
1954 target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
1955 string.dispose ();
1956 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEWHEEL);
1957 target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
1958 string.dispose ();
1959 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDRAG);
1960 target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
1961 string.dispose ();
1962
1963 /*
1964 * Only hook mouseover and mouseout if the target is a top-level frame, so that mouse moves
1965 * between frames will not generate events.
1966 */
1967 if (isTop && delegate.hookEnterExit ()) {
1968 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOVER);
1969 target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
1970 string.dispose ();
1971 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOUT);
1972 target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
1973 string.dispose ();
1974 }
1975
1976 string = new nsEmbedString (XPCOM.DOMEVENT_KEYDOWN);
1977 target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
1978 string.dispose ();
1979 string = new nsEmbedString (XPCOM.DOMEVENT_KEYPRESS);
1980 target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
1981 string.dispose ();
1982 string = new nsEmbedString (XPCOM.DOMEVENT_KEYUP);
1983 target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
1984 string.dispose ();
1985 }
1986
1987 void unhookDOMListeners () {
1988 int /*long*/[] result = new int /*long*/[1];
1989 int rc = webBrowser.GetContentDOMWindow (result);
1990 if (rc !is XPCOM.NS_OK) error (rc);
1991 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1992
1993 nsIDOMWindow window = new nsIDOMWindow (result[0]);
1994 result[0] = 0;
1995 rc = window.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result);
1996 if (rc !is XPCOM.NS_OK) error (rc);
1997 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
1998
1999 nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]);
2000 result[0] = 0;
2001 unhookDOMListeners (target);
2002 target.Release ();
2003
2004 /* Listeners must be unhooked in pages contained in frames */
2005 rc = window.GetFrames (result);
2006 if (rc !is XPCOM.NS_OK) error (rc);
2007 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
2008 nsIDOMWindowCollection frames = new nsIDOMWindowCollection (result[0]);
2009 result[0] = 0;
2010 int[] frameCount = new int[1];
2011 rc = frames.GetLength (frameCount); /* PRUint32 */
2012 if (rc !is XPCOM.NS_OK) error (rc);
2013 int count = frameCount[0];
2014
2015 if (count > 0) {
2016 for (int i = 0; i < count; i++) {
2017 rc = frames.Item (i, result);
2018 if (rc !is XPCOM.NS_OK) error (rc);
2019 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
2020
2021 nsIDOMWindow frame = new nsIDOMWindow (result[0]);
2022 result[0] = 0;
2023 rc = frame.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result);
2024 if (rc !is XPCOM.NS_OK) error (rc);
2025 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
2026
2027 target = new nsIDOMEventTarget (result[0]);
2028 result[0] = 0;
2029 unhookDOMListeners (target);
2030 target.Release ();
2031 frame.Release ();
2032 }
2033 }
2034 frames.Release ();
2035 window.Release ();
2036 }
2037
2038 void unhookDOMListeners (nsIDOMEventTarget target) {
2039 nsEmbedString string = new nsEmbedString (XPCOM.DOMEVENT_FOCUS);
2040 target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
2041 string.dispose ();
2042 string = new nsEmbedString (XPCOM.DOMEVENT_UNLOAD);
2043 target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
2044 string.dispose ();
2045 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDOWN);
2046 target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
2047 string.dispose ();
2048 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEUP);
2049 target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
2050 string.dispose ();
2051 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEMOVE);
2052 target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
2053 string.dispose ();
2054 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEWHEEL);
2055 target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
2056 string.dispose ();
2057 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDRAG);
2058 target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
2059 string.dispose ();
2060 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOVER);
2061 target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
2062 string.dispose ();
2063 string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOUT);
2064 target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
2065 string.dispose ();
2066 string = new nsEmbedString (XPCOM.DOMEVENT_KEYDOWN);
2067 target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
2068 string.dispose ();
2069 string = new nsEmbedString (XPCOM.DOMEVENT_KEYPRESS);
2070 target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
2071 string.dispose ();
2072 string = new nsEmbedString (XPCOM.DOMEVENT_KEYUP);
2073 target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
2074 string.dispose ();
2075 }
2076
2077 /* nsISupports */
2078
2079 int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
2080 if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
2081
2082 nsID guid = new nsID ();
2083 XPCOM.memmove (guid, riid, nsID.sizeof);
2084
2085 if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
2086 XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
2087 AddRef ();
2088 return XPCOM.NS_OK;
2089 }
2090 if (guid.Equals (nsIWeakReference.NS_IWEAKREFERENCE_IID)) {
2091 XPCOM.memmove (ppvObject, new int /*long*/[] {weakReference.getAddress ()}, C.PTR_SIZEOF);
2092 AddRef ();
2093 return XPCOM.NS_OK;
2094 }
2095 if (guid.Equals (nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID)) {
2096 XPCOM.memmove (ppvObject, new int /*long*/[] {webProgressListener.getAddress ()}, C.PTR_SIZEOF);
2097 AddRef ();
2098 return XPCOM.NS_OK;
2099 }
2100 if (guid.Equals (nsIWebBrowserChrome.NS_IWEBBROWSERCHROME_IID)) {
2101 XPCOM.memmove (ppvObject, new int /*long*/[] {webBrowserChrome.getAddress ()}, C.PTR_SIZEOF);
2102 AddRef ();
2103 return XPCOM.NS_OK;
2104 }
2105 if (guid.Equals (nsIWebBrowserChromeFocus.NS_IWEBBROWSERCHROMEFOCUS_IID)) {
2106 XPCOM.memmove (ppvObject, new int /*long*/[] {webBrowserChromeFocus.getAddress ()}, C.PTR_SIZEOF);
2107 AddRef ();
2108 return XPCOM.NS_OK;
2109 }
2110 if (guid.Equals (nsIEmbeddingSiteWindow.NS_IEMBEDDINGSITEWINDOW_IID)) {
2111 XPCOM.memmove (ppvObject, new int /*long*/[] {embeddingSiteWindow.getAddress ()}, C.PTR_SIZEOF);
2112 AddRef ();
2113 return XPCOM.NS_OK;
2114 }
2115 if (guid.Equals (nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID)) {
2116 XPCOM.memmove (ppvObject, new int /*long*/[] {interfaceRequestor.getAddress ()}, C.PTR_SIZEOF);
2117 AddRef ();
2118 return XPCOM.NS_OK;
2119 }
2120 if (guid.Equals (nsISupportsWeakReference.NS_ISUPPORTSWEAKREFERENCE_IID)) {
2121 XPCOM.memmove (ppvObject, new int /*long*/[] {supportsWeakReference.getAddress ()}, C.PTR_SIZEOF);
2122 AddRef ();
2123 return XPCOM.NS_OK;
2124 }
2125 if (guid.Equals (nsIContextMenuListener.NS_ICONTEXTMENULISTENER_IID)) {
2126 XPCOM.memmove (ppvObject, new int /*long*/[] {contextMenuListener.getAddress ()}, C.PTR_SIZEOF);
2127 AddRef ();
2128 return XPCOM.NS_OK;
2129 }
2130 if (guid.Equals (nsIURIContentListener.NS_IURICONTENTLISTENER_IID)) {
2131 XPCOM.memmove (ppvObject, new int /*long*/[] {uriContentListener.getAddress ()}, C.PTR_SIZEOF);
2132 AddRef ();
2133 return XPCOM.NS_OK;
2134 }
2135 if (guid.Equals (nsITooltipListener.NS_ITOOLTIPLISTENER_IID)) {
2136 XPCOM.memmove (ppvObject, new int /*long*/[] {tooltipListener.getAddress ()}, C.PTR_SIZEOF);
2137 AddRef ();
2138 return XPCOM.NS_OK;
2139 }
2140 XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
2141 return XPCOM.NS_ERROR_NO_INTERFACE;
2142 }
2143
2144 int AddRef () {
2145 refCount++;
2146 return refCount;
2147 }
2148
2149 int Release () {
2150 refCount--;
2151 if (refCount is 0) disposeCOMInterfaces ();
2152 return refCount;
2153 }
2154
2155 /* nsIWeakReference */
2156
2157 int QueryReferent (int /*long*/ riid, int /*long*/ ppvObject) {
2158 return QueryInterface (riid, ppvObject);
2159 }
2160
2161 /* nsIInterfaceRequestor */
2162
2163 int GetInterface (int /*long*/ riid, int /*long*/ ppvObject) {
2164 if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
2165 nsID guid = new nsID ();
2166 XPCOM.memmove (guid, riid, nsID.sizeof);
2167 if (guid.Equals (nsIDOMWindow.NS_IDOMWINDOW_IID)) {
2168 int /*long*/[] aContentDOMWindow = new int /*long*/[1];
2169 int rc = webBrowser.GetContentDOMWindow (aContentDOMWindow);
2170 if (rc !is XPCOM.NS_OK) error (rc);
2171 if (aContentDOMWindow[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
2172 XPCOM.memmove (ppvObject, aContentDOMWindow, C.PTR_SIZEOF);
2173 return rc;
2174 }
2175 return QueryInterface (riid, ppvObject);
2176 }
2177
2178 int GetWeakReference (int /*long*/ ppvObject) {
2179 XPCOM.memmove (ppvObject, new int /*long*/[] {weakReference.getAddress ()}, C.PTR_SIZEOF);
2180 AddRef ();
2181 return XPCOM.NS_OK;
2182 }
2183
2184 /* nsIWebProgressListener */
2185
2186 int OnStateChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStateFlags, int aStatus) {
2187 if ((aStateFlags & nsIWebProgressListener.STATE_IS_DOCUMENT) is 0) return XPCOM.NS_OK;
2188 if ((aStateFlags & nsIWebProgressListener.STATE_START) !is 0) {
2189 if (request is 0) request = aRequest;
2190
2191 if (!awaitingNavigate) {
2192 /*
2193 * Add the page's nsIDOMWindow to the collection of windows that will
2194 * have DOM listeners added to them later on in the page loading
2195 * process. These listeners cannot be added yet because the
2196 * nsIDOMWindow is not ready to take them at this stage.
2197 */
2198 int /*long*/[] result = new int /*long*/[1];
2199 nsIWebProgress progress = new nsIWebProgress (aWebProgress);
2200 int rc = progress.GetDOMWindow (result);
2201 if (rc !is XPCOM.NS_OK) error (rc);
2202 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
2203 unhookedDOMWindows.addElement (new LONG (result[0]));
2204 }
2205 } else if ((aStateFlags & nsIWebProgressListener.STATE_REDIRECTING) !is 0) {
2206 if (request is aRequest) request = 0;
2207 } else if ((aStateFlags & nsIWebProgressListener.STATE_STOP) !is 0) {
2208 /*
2209 * If this page's nsIDOMWindow handle is still in unhookedDOMWindows then
2210 * add its DOM listeners now. It's possible for this to happen since
2211 * there is no guarantee that a STATE_TRANSFERRING state change will be
2212 * received for every window in a page, which is when these listeners
2213 * are typically added.
2214 */
2215 int /*long*/[] result = new int /*long*/[1];
2216 nsIWebProgress progress = new nsIWebProgress (aWebProgress);
2217 int rc = progress.GetDOMWindow (result);
2218 if (rc !is XPCOM.NS_OK) error (rc);
2219 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
2220 nsIDOMWindow domWindow = new nsIDOMWindow (result[0]);
2221
2222 LONG ptrObject = new LONG (result[0]);
2223 result[0] = 0;
2224 int index = unhookedDOMWindows.indexOf (ptrObject);
2225 if (index !is -1) {
2226 rc = webBrowser.GetContentDOMWindow (result);
2227 if (rc !is XPCOM.NS_OK) error (rc);
2228 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
2229 bool isTop = result[0] is domWindow.getAddress ();
2230 new nsISupports (result[0]).Release ();
2231 result[0] = 0;
2232
2233 rc = domWindow.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result);
2234 if (rc !is XPCOM.NS_OK) error (rc);
2235 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
2236
2237 nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]);
2238 result[0] = 0;
2239 hookDOMListeners (target, isTop);
2240 target.Release ();
2241
2242 /*
2243 * Remove and unreference the nsIDOMWindow from the collection of windows
2244 * that are waiting to have DOM listeners hooked on them.
2245 */
2246 unhookedDOMWindows.remove (ptrObject);
2247 new nsISupports (ptrObject.value).Release ();
2248 }
2249 domWindow.Release ();
2250
2251 /*
2252 * Feature in Mozilla. When a request is redirected (STATE_REDIRECTING),
2253 * it never reaches the state STATE_STOP and it is replaced with a new request.
2254 * The new request is received when it is in the state STATE_STOP.
2255 * To handle this case, the variable request is set to 0 when the corresponding
2256 * request is redirected. The following request received with the state STATE_STOP
2257 * - the new request resulting from the redirection - is used to send
2258 * the ProgressListener.completed event.
2259 */
2260 if (request is aRequest || request is 0) {
2261 request = 0;
2262 if (!awaitingNavigate) {
2263 StatusTextEvent event = new StatusTextEvent (browser);
2264 event.display = browser.getDisplay ();
2265 event.widget = browser;
2266 event.text = ""; //$NON-NLS-1$
2267 for (int i = 0; i < statusTextListeners.length; i++) {
2268 statusTextListeners[i].changed (event);
2269 }
2270 ProgressEvent event2 = new ProgressEvent (browser);
2271 event2.display = browser.getDisplay ();
2272 event2.widget = browser;
2273 for (int i = 0; i < progressListeners.length; i++) {
2274 progressListeners[i].completed (event2);
2275 }
2276 }
2277 }
2278 } else if ((aStateFlags & nsIWebProgressListener.STATE_TRANSFERRING) !is 0) {
2279 /*
2280 * Hook DOM listeners to the page's nsIDOMWindow here because this is
2281 * the earliest opportunity to do so.
2282 */
2283 int /*long*/[] result = new int /*long*/[1];
2284 nsIWebProgress progress = new nsIWebProgress (aWebProgress);
2285 int rc = progress.GetDOMWindow (result);
2286 if (rc !is XPCOM.NS_OK) error (rc);
2287 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
2288 nsIDOMWindow domWindow = new nsIDOMWindow (result[0]);
2289
2290 LONG ptrObject = new LONG (result[0]);
2291 result[0] = 0;
2292 int index = unhookedDOMWindows.indexOf (ptrObject);
2293 if (index !is -1) {
2294 rc = webBrowser.GetContentDOMWindow (result);
2295 if (rc !is XPCOM.NS_OK) error (rc);
2296 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
2297 bool isTop = result[0] is domWindow.getAddress ();
2298 new nsISupports (result[0]).Release ();
2299 result[0] = 0;
2300
2301 rc = domWindow.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result);
2302 if (rc !is XPCOM.NS_OK) error (rc);
2303 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
2304
2305 nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]);
2306 result[0] = 0;
2307 hookDOMListeners (target, isTop);
2308 target.Release ();
2309
2310 /*
2311 * Remove and unreference the nsIDOMWindow from the collection of windows
2312 * that are waiting to have DOM listeners hooked on them.
2313 */
2314 unhookedDOMWindows.remove (ptrObject);
2315 new nsISupports (ptrObject.value).Release ();
2316 }
2317 domWindow.Release ();
2318 }
2319 return XPCOM.NS_OK;
2320 }
2321
2322 int OnProgressChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aCurSelfProgress, int aMaxSelfProgress, int aCurTotalProgress, int aMaxTotalProgress) {
2323 if (awaitingNavigate || progressListeners.length is 0) return XPCOM.NS_OK;
2324 ProgressEvent event = new ProgressEvent (browser);
2325 event.display = browser.getDisplay ();
2326 event.widget = browser;
2327 event.current = aCurTotalProgress;
2328 event.total = aMaxTotalProgress;
2329 for (int i = 0; i < progressListeners.length; i++) {
2330 progressListeners[i].changed (event);
2331 }
2332 return XPCOM.NS_OK;
2333 }
2334
2335 int OnLocationChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int /*long*/ aLocation) {
2336 /*
2337 * Feature in Mozilla. When a page is loaded via setText before a previous
2338 * setText page load has completed, the expected OnStateChange STATE_STOP for the
2339 * original setText never arrives because it gets replaced by the OnStateChange
2340 * STATE_STOP for the new request. This results in the request field never being
2341 * cleared because the original request's OnStateChange STATE_STOP is still expected
2342 * (but never arrives). To handle this case, the request field is updated to the new
2343 * overriding request since its OnStateChange STATE_STOP will be received next.
2344 */
2345 if (request !is 0 && request !is aRequest) request = aRequest;
2346
2347 if (awaitingNavigate || locationListeners.length is 0) return XPCOM.NS_OK;
2348
2349 nsIWebProgress webProgress = new nsIWebProgress (aWebProgress);
2350 int /*long*/[] aDOMWindow = new int /*long*/[1];
2351 int rc = webProgress.GetDOMWindow (aDOMWindow);
2352 if (rc !is XPCOM.NS_OK) error (rc);
2353 if (aDOMWindow[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
2354
2355 nsIDOMWindow domWindow = new nsIDOMWindow (aDOMWindow[0]);
2356 int /*long*/[] aTop = new int /*long*/[1];
2357 rc = domWindow.GetTop (aTop);
2358 if (rc !is XPCOM.NS_OK) error (rc);
2359 if (aTop[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
2360 domWindow.Release ();
2361
2362 nsIDOMWindow topWindow = new nsIDOMWindow (aTop[0]);
2363 topWindow.Release ();
2364
2365 nsIURI location = new nsIURI (aLocation);
2366 int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
2367 location.GetSpec (aSpec);
2368 int length = XPCOM.nsEmbedCString_Length (aSpec);
2369 int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
2370 byte[] dest = new byte[length];
2371 XPCOM.memmove (dest, buffer, length);
2372 XPCOM.nsEmbedCString_delete (aSpec);
2373 String url = new String (dest);
2374
2375 /*
2376 * As of Mozilla 1.8, the first time that a page is displayed, regardless of
2377 * whether it's via Browser.setURL() or Browser.setText(), the GRE navigates
2378 * to about:blank and fires the corresponding navigation events. Do not send
2379 * this event on to the user since it is not expected.
2380 */
2381 if (!IsPre_1_8 && aRequest is 0 && url.startsWith (ABOUT_BLANK)) return XPCOM.NS_OK;
2382
2383 LocationEvent event = new LocationEvent (browser);
2384 event.display = browser.getDisplay ();
2385 event.widget = browser;
2386 event.location = url;
2387 /*
2388 * If the URI indicates that the page is being rendered from memory
2389 * (via setText()) then set it to about:blank to be consistent with IE.
2390 */
2391 if (event.location.equals (URI_FROMMEMORY)) event.location = ABOUT_BLANK;
2392 event.top = aTop[0] is aDOMWindow[0];
2393 for (int i = 0; i < locationListeners.length; i++) {
2394 locationListeners[i].changed (event);
2395 }
2396 return XPCOM.NS_OK;
2397 }
2398
2399 int OnStatusChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStatus, int /*long*/ aMessage) {
2400 if (awaitingNavigate || statusTextListeners.length is 0) return XPCOM.NS_OK;
2401 StatusTextEvent event = new StatusTextEvent (browser);
2402 event.display = browser.getDisplay ();
2403 event.widget = browser;
2404 int length = XPCOM.strlen_PRUnichar (aMessage);
2405 char[] dest = new char[length];
2406 XPCOM.memmove (dest, aMessage, length * 2);
2407 event.text = new String (dest);
2408 for (int i = 0; i < statusTextListeners.length; i++) {
2409 statusTextListeners[i].changed (event);
2410 }
2411 return XPCOM.NS_OK;
2412 }
2413
2414 int OnSecurityChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int state) {
2415 return XPCOM.NS_OK;
2416 }
2417
2418 /* nsIWebBrowserChrome */
2419
2420 int SetStatus (int statusType, int /*long*/ status) {
2421 if (awaitingNavigate || statusTextListeners.length is 0) return XPCOM.NS_OK;
2422 StatusTextEvent event = new StatusTextEvent (browser);
2423 event.display = browser.getDisplay ();
2424 event.widget = browser;
2425 int length = XPCOM.strlen_PRUnichar (status);
2426 char[] dest = new char[length];
2427 XPCOM.memmove (dest, status, length * 2);
2428 String string = new String (dest);
2429 event.text = string;
2430 for (int i = 0; i < statusTextListeners.length; i++) {
2431 statusTextListeners[i].changed (event);
2432 }
2433 return XPCOM.NS_OK;
2434 }
2435
2436 int GetWebBrowser (int /*long*/ aWebBrowser) {
2437 int /*long*/[] ret = new int /*long*/[1];
2438 if (webBrowser !is null) {
2439 webBrowser.AddRef ();
2440 ret[0] = webBrowser.getAddress ();
2441 }
2442 XPCOM.memmove (aWebBrowser, ret, C.PTR_SIZEOF);
2443 return XPCOM.NS_OK;
2444 }
2445
2446 int SetWebBrowser (int /*long*/ aWebBrowser) {
2447 if (webBrowser !is null) webBrowser.Release ();
2448 webBrowser = aWebBrowser !is 0 ? new nsIWebBrowser (aWebBrowser) : null;
2449 return XPCOM.NS_OK;
2450 }
2451
2452 int GetChromeFlags (int /*long*/ aChromeFlags) {
2453 int[] ret = new int[1];
2454 ret[0] = chromeFlags;
2455 XPCOM.memmove (aChromeFlags, ret, 4); /* PRUint32 */
2456 return XPCOM.NS_OK;
2457 }
2458
2459 int SetChromeFlags (int aChromeFlags) {
2460 chromeFlags = aChromeFlags;
2461 return XPCOM.NS_OK;
2462 }
2463
2464 int DestroyBrowserWindow () {
2465 WindowEvent newEvent = new WindowEvent (browser);
2466 newEvent.display = browser.getDisplay ();
2467 newEvent.widget = browser;
2468 for (int i = 0; i < closeWindowListeners.length; i++) {
2469 closeWindowListeners[i].close (newEvent);
2470 }
2471 /*
2472 * Note on Mozilla. The DestroyBrowserWindow notification cannot be cancelled.
2473 * The browser widget cannot be used after this notification has been received.
2474 * The application is advised to close the window hosting the browser widget.
2475 * The browser widget must be disposed in all cases.
2476 */
2477 browser.dispose ();
2478 return XPCOM.NS_OK;
2479 }
2480
2481 int SizeBrowserTo (int aCX, int aCY) {
2482 size = new Point (aCX, aCY);
2483 bool isChrome = (chromeFlags & nsIWebBrowserChrome.CHROME_OPENAS_CHROME) !is 0;
2484 if (isChrome) {
2485 Shell shell = browser.getShell ();
2486 shell.setSize (shell.computeSize (size.x, size.y));
2487 }
2488 return XPCOM.NS_OK;
2489 }
2490
2491 int ShowAsModal () {
2492 int /*long*/[] result = new int /*long*/[1];
2493 int rc = XPCOM.NS_GetServiceManager (result);
2494 if (rc !is XPCOM.NS_OK) error (rc);
2495 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
2496
2497 nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
2498 result[0] = 0;
2499 byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_CONTEXTSTACK_CONTRACTID, true);
2500 rc = serviceManager.GetServiceByContractID (aContractID, nsIJSContextStack.NS_IJSCONTEXTSTACK_IID, result);
2501 if (rc !is XPCOM.NS_OK) error (rc);
2502 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
2503 serviceManager.Release ();
2504
2505 nsIJSContextStack stack = new nsIJSContextStack (result[0]);
2506 result[0] = 0;
2507 rc = stack.Push (0);
2508 if (rc !is XPCOM.NS_OK) error (rc);
2509
2510 Shell shell = browser.getShell ();
2511 Display display = browser.getDisplay ();
2512 while (!shell.isDisposed ()) {
2513 if (!display.readAndDispatch ()) display.sleep ();
2514 }
2515
2516 rc = stack.Pop (result);
2517 if (rc !is XPCOM.NS_OK) error (rc);
2518 stack.Release ();
2519 return XPCOM.NS_OK;
2520 }
2521
2522 int IsWindowModal (int /*long*/ retval) {
2523 int result = (chromeFlags & nsIWebBrowserChrome.CHROME_MODAL) !is 0 ? 1 : 0;
2524 XPCOM.memmove (retval, new int[] {result}, 4); /* PRBool */
2525 return XPCOM.NS_OK;
2526 }
2527
2528 int ExitModalEventLoop (int aStatus) {
2529 return XPCOM.NS_OK;
2530 }
2531
2532 /* nsIEmbeddingSiteWindow */
2533
2534 int SetDimensions (int flags, int x, int y, int cx, int cy) {
2535 if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_POSITION) !is 0) {
2536 location = new Point (x, y);
2537 browser.getShell ().setLocation (x, y);
2538 }
2539 if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_INNER) !is 0) {
2540 browser.setSize (cx, cy);
2541 }
2542 if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_OUTER) !is 0) {
2543 browser.getShell ().setSize (cx, cy);
2544 }
2545 return XPCOM.NS_OK;
2546 }
2547
2548 int GetDimensions (int flags, int /*long*/ x, int /*long*/ y, int /*long*/ cx, int /*long*/ cy) {
2549 if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_POSITION) !is 0) {
2550 Point location = browser.getShell ().getLocation ();
2551 if (x !is 0) C.memmove (x, new int[] {location.x}, 4); /* PRInt32 */
2552 if (y !is 0) C.memmove (y, new int[] {location.y}, 4); /* PRInt32 */
2553 }
2554 if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_INNER) !is 0) {
2555 Point size = browser.getSize ();
2556 if (cx !is 0) C.memmove (cx, new int[] {size.x}, 4); /* PRInt32 */
2557 if (cy !is 0) C.memmove (cy, new int[] {size.y}, 4); /* PRInt32 */
2558 }
2559 if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_OUTER) !is 0) {
2560 Point size = browser.getShell().getSize ();
2561 if (cx !is 0) C.memmove (cx, new int[] {size.x}, 4); /* PRInt32 */
2562 if (cy !is 0) C.memmove (cy, new int[] {size.y}, 4); /* PRInt32 */
2563 }
2564 return XPCOM.NS_OK;
2565 }
2566
2567 int SetFocus () {
2568 int /*long*/[] result = new int /*long*/[1];
2569 int rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
2570 if (rc !is XPCOM.NS_OK) error (rc);
2571 if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
2572
2573 nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
2574 rc = baseWindow.SetFocus ();
2575 if (rc !is XPCOM.NS_OK) error (rc);
2576 baseWindow.Release ();
2577
2578 /*
2579 * Note. Mozilla notifies here that one of the children took
2580 * focus. This could or should be used to fire an DWT.FOCUS_IN
2581 * event on Browser focus listeners.
2582 */
2583 return XPCOM.NS_OK;
2584 }
2585
2586 int GetVisibility (int /*long*/ aVisibility) {
2587 bool visible = browser.isVisible () && !browser.getShell ().getMinimized ();
2588 XPCOM.memmove (aVisibility, new int[] {visible ? 1 : 0}, 4); /* PRBool */
2589 return XPCOM.NS_OK;
2590 }
2591
2592 int SetVisibility (int aVisibility) {
2593 if (isChild) {
2594 WindowEvent event = new WindowEvent (browser);
2595 event.display = browser.getDisplay ();
2596 event.widget = browser;
2597 if (aVisibility !is 0) {
2598 /*
2599 * Bug in Mozilla. When the JavaScript window.open is executed, Mozilla
2600 * fires multiple SetVisibility 1 notifications. The workaround is
2601 * to ignore subsequent notifications.
2602 */
2603 if (!visible) {
2604 visible = true;
2605 event.location = location;
2606 event.size = size;
2607 event.addressBar = (chromeFlags & nsIWebBrowserChrome.CHROME_LOCATIONBAR) !is 0;
2608 event.menuBar = (chromeFlags & nsIWebBrowserChrome.CHROME_MENUBAR) !is 0;
2609 event.statusBar = (chromeFlags & nsIWebBrowserChrome.CHROME_STATUSBAR) !is 0;
2610 event.toolBar = (chromeFlags & nsIWebBrowserChrome.CHROME_TOOLBAR) !is 0;
2611 for (int i = 0; i < visibilityWindowListeners.length; i++) {
2612 visibilityWindowListeners[i].show (event);
2613 }
2614 location = null;
2615 size = null;
2616 }
2617 } else {
2618 visible = false;
2619 for (int i = 0; i < visibilityWindowListeners.length; i++) {
2620 visibilityWindowListeners[i].hide (event);
2621 }
2622 }
2623 } else {
2624 visible = aVisibility !is 0;
2625 }
2626 return XPCOM.NS_OK;
2627 }
2628
2629 int GetTitle (int /*long*/ aTitle) {
2630 return XPCOM.NS_OK;
2631 }
2632
2633 int SetTitle (int /*long*/ aTitle) {
2634 if (awaitingNavigate || titleListeners.length is 0) return XPCOM.NS_OK;
2635 TitleEvent event = new TitleEvent (browser);
2636 event.display = browser.getDisplay ();
2637 event.widget = browser;
2638 /*
2639 * To be consistent with other platforms the title event should
2640 * contain the page's url if the page does not contain a <title>
2641 * tag.
2642 */
2643 int length = XPCOM.strlen_PRUnichar (aTitle);
2644 if (length > 0) {
2645 char[] dest = new char[length];
2646 XPCOM.memmove (dest, aTitle, length * 2);
2647 event.title = new String (dest);
2648 } else {
2649 event.title = getUrl ();
2650 }
2651 for (int i = 0; i < titleListeners.length; i++) {
2652 titleListeners[i].changed (event);
2653 }
2654 return XPCOM.NS_OK;
2655 }
2656
2657 int GetSiteWindow (int /*long*/ aSiteWindow) {
2658 /*
2659 * Note. The handle is expected to be an HWND on Windows and
2660 * a GtkWidget* on GTK. This callback is invoked on Windows
2661 * when the javascript window.print is invoked and the print
2662 * dialog comes up. If no handle is returned, the print dialog
2663 * does not come up on this platform.
2664 */
2665 XPCOM.memmove (aSiteWindow, new int /*long*/[] {embedHandle}, C.PTR_SIZEOF);
2666 return XPCOM.NS_OK;
2667 }
2668
2669 /* nsIWebBrowserChromeFocus */
2670
2671 int FocusNextElement () {
2672 /*
2673 * Bug in Mozilla embedding API. Mozilla takes back the focus after sending
2674 * this event. This prevents tabbing out of Mozilla. This behaviour can be reproduced
2675 * with the Mozilla application TestGtkEmbed. The workaround is to
2676 * send the traversal notification after this callback returns.
2677 */
2678 browser.getDisplay ().asyncExec (new Runnable () {
2679 public void run () {
2680 if (browser.isDisposed ()) return;
2681 browser.traverse (DWT.TRAVERSE_TAB_NEXT);
2682 }
2683 });
2684 return XPCOM.NS_OK;
2685 }
2686
2687 int FocusPrevElement () {
2688 /*
2689 * Bug in Mozilla embedding API. Mozilla takes back the focus after sending
2690 * this event. This prevents tabbing out of Mozilla. This behaviour can be reproduced
2691 * with the Mozilla application TestGtkEmbed. The workaround is to
2692 * send the traversal notification after this callback returns.
2693 */
2694 browser.getDisplay ().asyncExec (new Runnable () {
2695 public void run () {
2696 if (browser.isDisposed ()) return;
2697 browser.traverse (DWT.TRAVERSE_TAB_PREVIOUS);
2698 }
2699 });
2700 return XPCOM.NS_OK;
2701 }
2702
2703 /* nsIContextMenuListener */
2704
2705 int OnShowContextMenu (int aContextFlags, int /*long*/ aEvent, int /*long*/ aNode) {
2706 if (awaitingNavigate) return XPCOM.NS_OK;
2707
2708 nsIDOMEvent domEvent = new nsIDOMEvent (aEvent);
2709 int /*long*/[] result = new int /*long*/[1];
2710 int rc = domEvent.QueryInterface (nsIDOMMouseEvent.NS_IDOMMOUSEEVENT_IID, result);
2711 if (rc !is XPCOM.NS_OK) error (rc);
2712 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
2713
2714 nsIDOMMouseEvent domMouseEvent = new nsIDOMMouseEvent (result[0]);
2715 int[] aScreenX = new int[1], aScreenY = new int[1];
2716 rc = domMouseEvent.GetScreenX (aScreenX);
2717 if (rc !is XPCOM.NS_OK) error (rc);
2718 rc = domMouseEvent.GetScreenY (aScreenY);
2719 if (rc !is XPCOM.NS_OK) error (rc);
2720 domMouseEvent.Release ();
2721
2722 Event event = new Event ();
2723 event.x = aScreenX[0];
2724 event.y = aScreenY[0];
2725 browser.notifyListeners (DWT.MenuDetect, event);
2726 if (!event.doit || browser.isDisposed ()) return XPCOM.NS_OK;
2727 Menu menu = browser.getMenu ();
2728 if (menu !is null && !menu.isDisposed ()) {
2729 if (aScreenX[0] !is event.x || aScreenY[0] !is event.y) {
2730 menu.setLocation (event.x, event.y);
2731 }
2732 menu.setVisible (true);
2733 }
2734 return XPCOM.NS_OK;
2735 }
2736
2737 /* nsIURIContentListener */
2738
2739 int OnStartURIOpen (int /*long*/ aURI, int /*long*/ retval) {
2740 if (awaitingNavigate || locationListeners.length is 0) {
2741 XPCOM.memmove (retval, new int[] {0}, 4); /* PRBool */
2742 return XPCOM.NS_OK;
2743 }
2744 nsIURI location = new nsIURI (aURI);
2745 int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
2746 location.GetSpec (aSpec);
2747 int length = XPCOM.nsEmbedCString_Length (aSpec);
2748 int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
2749 buffer = XPCOM.nsEmbedCString_get (aSpec);
2750 byte[] dest = new byte[length];
2751 XPCOM.memmove (dest, buffer, length);
2752 XPCOM.nsEmbedCString_delete (aSpec);
2753 String value = new String (dest);
2754 bool doit = true;
2755 if (request is 0) {
2756 /*
2757 * listeners should not be notified of internal transitions like "javascipt:..."
2758 * because this is an implementation side-effect, not a true navigate
2759 */
2760 if (!value.startsWith (PREFIX_JAVASCRIPT)) {
2761 LocationEvent event = new LocationEvent (browser);
2762 event.display = browser.getDisplay();
2763 event.widget = browser;
2764 event.location = value;
2765 /*
2766 * If the URI indicates that the page is being rendered from memory
2767 * (via setText()) then set it to about:blank to be consistent with IE.
2768 */
2769 if (event.location.equals (URI_FROMMEMORY)) event.location = ABOUT_BLANK;
2770 event.doit = doit;
2771 for (int i = 0; i < locationListeners.length; i++) {
2772 locationListeners[i].changing (event);
2773 }
2774 doit = event.doit && !browser.isDisposed();
2775 }
2776 }
2777 XPCOM.memmove (retval, new int[] {doit ? 0 : 1}, 4); /* PRBool */
2778 return XPCOM.NS_OK;
2779 }
2780
2781 int DoContent (int /*long*/ aContentType, int aIsContentPreferred, int /*long*/ aRequest, int /*long*/ aContentHandler, int /*long*/ retval) {
2782 return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
2783 }
2784
2785 int IsPreferred (int /*long*/ aContentType, int /*long*/ aDesiredContentType, int /*long*/ retval) {
2786 bool preferred = false;
2787 int size = XPCOM.strlen (aContentType);
2788 if (size > 0) {
2789 byte[] typeBytes = new byte[size + 1];
2790 XPCOM.memmove (typeBytes, aContentType, size);
2791 String contentType = new String (typeBytes, 0, size);
2792
2793 /* do not attempt to handle known problematic content types */
2794 if (!contentType.equals (XPCOM.CONTENT_MAYBETEXT) && !contentType.equals (XPCOM.CONTENT_MULTIPART)) {
2795 /* determine whether browser can handle the content type */
2796 int /*long*/[] result = new int /*long*/[1];
2797 int rc = XPCOM.NS_GetServiceManager (result);
2798 if (rc !is XPCOM.NS_OK) error (rc);
2799 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
2800 nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
2801 result[0] = 0;
2802
2803 /* First try to use the nsIWebNavigationInfo if it's available (>= mozilla 1.8) */
2804 byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_WEBNAVIGATIONINFO_CONTRACTID, true);
2805 rc = serviceManager.GetServiceByContractID (aContractID, nsIWebNavigationInfo.NS_IWEBNAVIGATIONINFO_IID, result);
2806 if (rc is 0) {
2807 byte[] bytes = MozillaDelegate.wcsToMbcs (null, contentType, true);
2808 int /*long*/ typePtr = XPCOM.nsEmbedCString_new (bytes, bytes.length);
2809 nsIWebNavigationInfo info = new nsIWebNavigationInfo (result[0]);
2810 result[0] = 0;
2811 int[] isSupportedResult = new int[1]; /* PRUint32 */
2812 rc = info.IsTypeSupported (typePtr, 0, isSupportedResult);
2813 if (rc !is XPCOM.NS_OK) error (rc);
2814 info.Release ();
2815 XPCOM.nsEmbedCString_delete (typePtr);
2816 preferred = isSupportedResult[0] !is 0;
2817 } else {
2818 /* nsIWebNavigationInfo is not available, so do the type lookup */
2819 result[0] = 0;
2820 rc = serviceManager.GetService (XPCOM.NS_CATEGORYMANAGER_CID, nsICategoryManager.NS_ICATEGORYMANAGER_IID, result);
2821 if (rc !is XPCOM.NS_OK) error (rc);
2822 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
2823
2824 nsICategoryManager categoryManager = new nsICategoryManager (result[0]);
2825 result[0] = 0;
2826 byte[] categoryBytes = MozillaDelegate.wcsToMbcs (null, "Gecko-Content-Viewers", true); //$NON-NLS-1$
2827 rc = categoryManager.GetCategoryEntry (categoryBytes, typeBytes, result);
2828 categoryManager.Release ();
2829 /* if no viewer for the content type is registered then rc is XPCOM.NS_ERROR_NOT_AVAILABLE */
2830 preferred = rc is XPCOM.NS_OK;
2831 }
2832 serviceManager.Release ();
2833 }
2834 }
2835
2836 XPCOM.memmove(retval, new int[] {preferred ? 1 : 0}, 4); /* PRBool */
2837 if (preferred) {
2838 XPCOM.memmove (aDesiredContentType, new int /*long*/[] {0}, C.PTR_SIZEOF);
2839 }
2840 return XPCOM.NS_OK;
2841 }
2842
2843 int CanHandleContent (int /*long*/ aContentType, int aIsContentPreferred, int /*long*/ aDesiredContentType, int /*long*/ retval) {
2844 return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
2845 }
2846
2847 int GetLoadCookie (int /*long*/ aLoadCookie) {
2848 return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
2849 }
2850
2851 int SetLoadCookie (int /*long*/ aLoadCookie) {
2852 return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
2853 }
2854
2855 int GetParentContentListener (int /*long*/ aParentContentListener) {
2856 return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
2857 }
2858
2859 int SetParentContentListener (int /*long*/ aParentContentListener) {
2860 return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
2861 }
2862
2863 /* nsITooltipListener */
2864
2865 int OnShowTooltip (int aXCoords, int aYCoords, int /*long*/ aTipText) {
2866 if (awaitingNavigate) return XPCOM.NS_OK;
2867
2868 int length = XPCOM.strlen_PRUnichar (aTipText);
2869 char[] dest = new char[length];
2870 XPCOM.memmove (dest, aTipText, length * 2);
2871 String text = new String (dest);
2872 if (tip !is null && !tip.isDisposed ()) tip.dispose ();
2873 Display display = browser.getDisplay ();
2874 Shell parent = browser.getShell ();
2875 tip = new Shell (parent, DWT.ON_TOP);
2876 tip.setLayout (new FillLayout());
2877 Label label = new Label (tip, DWT.CENTER);
2878 label.setForeground (display.getSystemColor (DWT.COLOR_INFO_FOREGROUND));
2879 label.setBackground (display.getSystemColor (DWT.COLOR_INFO_BACKGROUND));
2880 label.setText (text);
2881 /*
2882 * Bug in Mozilla embedded API. Tooltip coordinates are wrong for
2883 * elements inside an inline frame (IFrame tag). The workaround is
2884 * to position the tooltip based on the mouse cursor location.
2885 */
2886 Point point = display.getCursorLocation ();
2887 /* Assuming cursor is 21x21 because this is the size of
2888 * the arrow cursor on Windows
2889 */
2890 point.y += 21;
2891 tip.setLocation (point);
2892 tip.pack ();
2893 tip.setVisible (true);
2894 return XPCOM.NS_OK;
2895 }
2896
2897 int OnHideTooltip () {
2898 if (tip !is null && !tip.isDisposed ()) tip.dispose ();
2899 tip = null;
2900 return XPCOM.NS_OK;
2901 }
2902
2903 /* nsIDOMEventListener */
2904
2905 int HandleEvent (int /*long*/ event) {
2906 nsIDOMEvent domEvent = new nsIDOMEvent (event);
2907
2908 int /*long*/ type = XPCOM.nsEmbedString_new ();
2909 int rc = domEvent.GetType (type);
2910 if (rc !is XPCOM.NS_OK) error (rc);
2911 int length = XPCOM.nsEmbedString_Length (type);
2912 int /*long*/ buffer = XPCOM.nsEmbedString_get (type);
2913 char[] chars = new char[length];
2914 XPCOM.memmove (chars, buffer, length * 2);
2915 String typeString = new String (chars);
2916 XPCOM.nsEmbedString_delete (type);
2917
2918 if (XPCOM.DOMEVENT_UNLOAD.equals (typeString)) {
2919 int /*long*/[] result = new int /*long*/[1];
2920 rc = domEvent.GetCurrentTarget (result);
2921 if (rc !is XPCOM.NS_OK) error (rc);
2922 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
2923
2924 nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]);
2925 unhookDOMListeners (target);
2926 target.Release ();
2927 return XPCOM.NS_OK;
2928 }
2929
2930 if (XPCOM.DOMEVENT_FOCUS.equals (typeString)) {
2931 delegate.handleFocus ();
2932 return XPCOM.NS_OK;
2933 }
2934
2935 if (XPCOM.DOMEVENT_KEYDOWN.equals (typeString)) {
2936 int /*long*/[] result = new int /*long*/[1];
2937 rc = domEvent.QueryInterface (nsIDOMKeyEvent.NS_IDOMKEYEVENT_IID, result);
2938 if (rc !is XPCOM.NS_OK) error (rc);
2939 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
2940 nsIDOMKeyEvent domKeyEvent = new nsIDOMKeyEvent (result[0]);
2941 result[0] = 0;
2942
2943 int[] aKeyCode = new int[1]; /* PRUint32 */
2944 rc = domKeyEvent.GetKeyCode (aKeyCode);
2945 if (rc !is XPCOM.NS_OK) error (rc);
2946 int keyCode = translateKey (aKeyCode[0]);
2947
2948 /*
2949 * if keyCode is lastKeyCode then either a repeating key like Shift
2950 * is being held or a key for which key events are not sent has been
2951 * pressed. In both of these cases a KeyDown should not be sent.
2952 */
2953 if (keyCode !is lastKeyCode) {
2954 lastKeyCode = keyCode;
2955 switch (keyCode) {
2956 case DWT.SHIFT:
2957 case DWT.CONTROL:
2958 case DWT.ALT:
2959 case DWT.CAPS_LOCK:
2960 case DWT.NUM_LOCK:
2961 case DWT.SCROLL_LOCK:
2962 case DWT.COMMAND: {
2963 /* keypress events will not be received for these keys, so send KeyDowns for them now */
2964 int[] aAltKey = new int[1], aCtrlKey = new int[1], aShiftKey = new int[1], aMetaKey = new int[1]; /* PRBool */
2965 rc = domKeyEvent.GetAltKey (aAltKey);
2966 if (rc !is XPCOM.NS_OK) error (rc);
2967 rc = domKeyEvent.GetCtrlKey (aCtrlKey);
2968 if (rc !is XPCOM.NS_OK) error (rc);
2969 rc = domKeyEvent.GetShiftKey (aShiftKey);
2970 if (rc !is XPCOM.NS_OK) error (rc);
2971 rc = domKeyEvent.GetMetaKey (aMetaKey);
2972 if (rc !is XPCOM.NS_OK) error (rc);
2973
2974 Event keyEvent = new Event ();
2975 keyEvent.widget = browser;
2976 keyEvent.type = DWT.KeyDown;
2977 keyEvent.keyCode = keyCode;
2978 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);
2979 keyEvent.stateMask &= ~keyCode; /* remove current keydown if it's a state key */
2980 browser.notifyListeners (keyEvent.type, keyEvent);
2981 if (!keyEvent.doit || browser.isDisposed ()) {
2982 domEvent.PreventDefault ();
2983 }
2984 break;
2985 }
2986 default: {
2987 /*
2988 * If the keydown has Meta (but not Meta+Ctrl) as a modifier then send a KeyDown event for it here
2989 * because a corresponding keypress event will not be received for it from the DOM. If the keydown
2990 * does not have Meta as a modifier, or has Meta+Ctrl as a modifier, then then do nothing here
2991 * because its KeyDown event will be sent from the keypress listener.
2992 */
2993 int[] aMetaKey = new int[1]; /* PRBool */
2994 rc = domKeyEvent.GetMetaKey (aMetaKey);
2995 if (rc !is XPCOM.NS_OK) error (rc);
2996 if (aMetaKey[0] !is 0) {
2997 int[] aCtrlKey = new int[1]; /* PRBool */
2998 rc = domKeyEvent.GetCtrlKey (aCtrlKey);
2999 if (rc !is XPCOM.NS_OK) error (rc);
3000 if (aCtrlKey[0] is 0) {
3001 int[] aAltKey = new int[1], aShiftKey = new int[1]; /* PRBool */
3002 rc = domKeyEvent.GetAltKey (aAltKey);
3003 if (rc !is XPCOM.NS_OK) error (rc);
3004 rc = domKeyEvent.GetShiftKey (aShiftKey);
3005 if (rc !is XPCOM.NS_OK) error (rc);
3006
3007 Event keyEvent = new Event ();
3008 keyEvent.widget = browser;
3009 keyEvent.type = DWT.KeyDown;
3010 keyEvent.keyCode = lastKeyCode;
3011 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);
3012 browser.notifyListeners (keyEvent.type, keyEvent);
3013 if (!keyEvent.doit || browser.isDisposed ()) {
3014 domEvent.PreventDefault ();
3015 }
3016 }
3017 }
3018 }
3019 }
3020 }
3021
3022 domKeyEvent.Release ();
3023 return XPCOM.NS_OK;
3024 }
3025
3026 if (XPCOM.DOMEVENT_KEYPRESS.equals (typeString)) {
3027 /*
3028 * if keydown could not determine a keycode for this key then it's a
3029 * key for which key events are not sent (eg.- the Windows key)
3030 */
3031 if (lastKeyCode is 0) return XPCOM.NS_OK;
3032
3033 /*
3034 * On linux only, unexpected keypress events are received for some
3035 * modifier keys. The workaround is to ignore these events since
3036 * KeyDown events are sent for these keys in the keydown listener.
3037 */
3038 switch (lastKeyCode) {
3039 case DWT.CAPS_LOCK:
3040 case DWT.NUM_LOCK:
3041 case DWT.SCROLL_LOCK: return XPCOM.NS_OK;
3042 }
3043
3044 int /*long*/[] result = new int /*long*/[1];
3045 rc = domEvent.QueryInterface (nsIDOMKeyEvent.NS_IDOMKEYEVENT_IID, result);
3046 if (rc !is XPCOM.NS_OK) error (rc);
3047 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
3048 nsIDOMKeyEvent domKeyEvent = new nsIDOMKeyEvent (result[0]);
3049 result[0] = 0;
3050
3051 int[] aAltKey = new int[1], aCtrlKey = new int[1], aShiftKey = new int[1], aMetaKey = new int[1]; /* PRBool */
3052 rc = domKeyEvent.GetAltKey (aAltKey);
3053 if (rc !is XPCOM.NS_OK) error (rc);
3054 rc = domKeyEvent.GetCtrlKey (aCtrlKey);
3055 if (rc !is XPCOM.NS_OK) error (rc);
3056 rc = domKeyEvent.GetShiftKey (aShiftKey);
3057 if (rc !is XPCOM.NS_OK) error (rc);
3058 rc = domKeyEvent.GetMetaKey (aMetaKey);
3059 if (rc !is XPCOM.NS_OK) error (rc);
3060 domKeyEvent.Release ();
3061
3062 int[] aCharCode = new int[1]; /* PRUint32 */
3063 rc = domKeyEvent.GetCharCode (aCharCode);
3064 if (rc !is XPCOM.NS_OK) error (rc);
3065 lastCharCode = aCharCode[0];
3066 if (lastCharCode is 0) {
3067 switch (lastKeyCode) {
3068 case DWT.TAB: lastCharCode = DWT.TAB; break;
3069 case DWT.CR: lastCharCode = DWT.CR; break;
3070 case DWT.BS: lastCharCode = DWT.BS; break;
3071 case DWT.ESC: lastCharCode = DWT.ESC; break;
3072 case DWT.DEL: lastCharCode = DWT.DEL; break;
3073 }
3074 }
3075 if (aCtrlKey[0] !is 0 && (0 <= lastCharCode && lastCharCode <= 0x7F)) {
3076 if ('a' <= lastCharCode && lastCharCode <= 'z') lastCharCode -= 'a' - 'A';
3077 if (64 <= lastCharCode && lastCharCode <= 95) lastCharCode -= 64;
3078 }
3079
3080 Event keyEvent = new Event ();
3081 keyEvent.widget = browser;
3082 keyEvent.type = DWT.KeyDown;
3083 keyEvent.keyCode = lastKeyCode;
3084 keyEvent.character = (char)lastCharCode;
3085 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);
3086 browser.notifyListeners (keyEvent.type, keyEvent);
3087 if (!keyEvent.doit || browser.isDisposed ()) {
3088 domEvent.PreventDefault ();
3089 }
3090 return XPCOM.NS_OK;
3091 }
3092
3093 if (XPCOM.DOMEVENT_KEYUP.equals (typeString)) {
3094 int /*long*/[] result = new int /*long*/[1];
3095 rc = domEvent.QueryInterface (nsIDOMKeyEvent.NS_IDOMKEYEVENT_IID, result);
3096 if (rc !is XPCOM.NS_OK) error (rc);
3097 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
3098 nsIDOMKeyEvent domKeyEvent = new nsIDOMKeyEvent (result[0]);
3099 result[0] = 0;
3100
3101 int[] aKeyCode = new int[1]; /* PRUint32 */
3102 rc = domKeyEvent.GetKeyCode (aKeyCode);
3103 if (rc !is XPCOM.NS_OK) error (rc);
3104 int keyCode = translateKey (aKeyCode[0]);
3105 if (keyCode is 0) {
3106 /* indicates a key for which key events are not sent */
3107 domKeyEvent.Release ();
3108 return XPCOM.NS_OK;
3109 }
3110 if (keyCode !is lastKeyCode) {
3111 /* keyup does not correspond to the last keydown */
3112 lastKeyCode = keyCode;
3113 lastCharCode = 0;
3114 }
3115
3116 int[] aAltKey = new int[1], aCtrlKey = new int[1], aShiftKey = new int[1], aMetaKey = new int[1]; /* PRBool */
3117 rc = domKeyEvent.GetAltKey (aAltKey);
3118 if (rc !is XPCOM.NS_OK) error (rc);
3119 rc = domKeyEvent.GetCtrlKey (aCtrlKey);
3120 if (rc !is XPCOM.NS_OK) error (rc);
3121 rc = domKeyEvent.GetShiftKey (aShiftKey);
3122 if (rc !is XPCOM.NS_OK) error (rc);
3123 rc = domKeyEvent.GetMetaKey (aMetaKey);
3124 if (rc !is XPCOM.NS_OK) error (rc);
3125 domKeyEvent.Release ();
3126
3127 Event keyEvent = new Event ();
3128 keyEvent.widget = browser;
3129 keyEvent.type = DWT.KeyUp;
3130 keyEvent.keyCode = lastKeyCode;
3131 keyEvent.character = (char)lastCharCode;
3132 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);
3133 switch (lastKeyCode) {
3134 case DWT.SHIFT:
3135 case DWT.CONTROL:
3136 case DWT.ALT:
3137 case DWT.COMMAND: {
3138 keyEvent.stateMask |= lastKeyCode;
3139 }
3140 }
3141 browser.notifyListeners (keyEvent.type, keyEvent);
3142 if (!keyEvent.doit || browser.isDisposed ()) {
3143 domEvent.PreventDefault ();
3144 }
3145 lastKeyCode = lastCharCode = 0;
3146 return XPCOM.NS_OK;
3147 }
3148
3149 /* mouse event */
3150
3151 int /*long*/[] result = new int /*long*/[1];
3152 rc = domEvent.QueryInterface (nsIDOMMouseEvent.NS_IDOMMOUSEEVENT_IID, result);
3153 if (rc !is XPCOM.NS_OK) error (rc);
3154 if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
3155 nsIDOMMouseEvent domMouseEvent = new nsIDOMMouseEvent (result[0]);
3156 result[0] = 0;
3157
3158 /*
3159 * MouseOver and MouseOut events are fired any time the mouse enters or exits
3160 * any element within the Browser. To ensure that DWT events are only
3161 * fired for mouse movements into or out of the Browser, do not fire an
3162 * event if the element being exited (on MouseOver) or entered (on MouseExit)
3163 * is within the Browser.
3164 */
3165 if (XPCOM.DOMEVENT_MOUSEOVER.equals (typeString) || XPCOM.DOMEVENT_MOUSEOUT.equals (typeString)) {
3166 rc = domMouseEvent.GetRelatedTarget (result);
3167 if (rc !is XPCOM.NS_OK) error (rc);
3168 if (result[0] !is 0) {
3169 domMouseEvent.Release ();
3170 return XPCOM.NS_OK;
3171 }
3172 }
3173
3174 int[] aClientX = new int[1], aClientY = new int[1], aDetail = new int[1]; /* PRInt32 */
3175 rc = domMouseEvent.GetClientX (aClientX);
3176 if (rc !is XPCOM.NS_OK) error (rc);
3177 rc = domMouseEvent.GetClientY (aClientY);
3178 if (rc !is XPCOM.NS_OK) error (rc);
3179 rc = domMouseEvent.GetDetail (aDetail);
3180 if (rc !is XPCOM.NS_OK) error (rc);
3181 short[] aButton = new short[1]; /* PRUint16 */
3182 rc = domMouseEvent.GetButton (aButton);
3183 if (rc !is XPCOM.NS_OK) error (rc);
3184 int[] aAltKey = new int[1], aCtrlKey = new int[1], aShiftKey = new int[1], aMetaKey = new int[1]; /* PRBool */
3185 rc = domMouseEvent.GetAltKey (aAltKey);
3186 if (rc !is XPCOM.NS_OK) error (rc);
3187 rc = domMouseEvent.GetCtrlKey (aCtrlKey);
3188 if (rc !is XPCOM.NS_OK) error (rc);
3189 rc = domMouseEvent.GetShiftKey (aShiftKey);
3190 if (rc !is XPCOM.NS_OK) error (rc);
3191 rc = domMouseEvent.GetMetaKey (aMetaKey);
3192 if (rc !is XPCOM.NS_OK) error (rc);
3193 domMouseEvent.Release ();
3194
3195 Event mouseEvent = new Event ();
3196 mouseEvent.widget = browser;
3197 mouseEvent.x = aClientX[0]; mouseEvent.y = aClientY[0];
3198 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);
3199
3200 if (XPCOM.DOMEVENT_MOUSEDOWN.equals (typeString)) {
3201 delegate.handleMouseDown ();
3202 mouseEvent.type = DWT.MouseDown;
3203 mouseEvent.button = aButton[0] + 1;
3204 mouseEvent.count = aDetail[0];
3205 } else if (XPCOM.DOMEVENT_MOUSEUP.equals (typeString)) {
3206 /*
3207 * Bug on OSX. For some reason multiple mouseup events come from the DOM
3208 * when button 3 is released on OSX. The first of these events has a count
3209 * detail and the others do not. The workaround is to not fire received
3210 * button 3 mouseup events that do not have a count since mouse events
3211 * without a click count are not valid.
3212 */
3213 int button = aButton[0] + 1;
3214 int count = aDetail[0];
3215 if (count is 0 && button is 3) return XPCOM.NS_OK;
3216 mouseEvent.type = DWT.MouseUp;
3217 mouseEvent.button = button;
3218 mouseEvent.count = count;
3219 } else if (XPCOM.DOMEVENT_MOUSEMOVE.equals (typeString)) {
3220 mouseEvent.type = DWT.MouseMove;
3221 } else if (XPCOM.DOMEVENT_MOUSEWHEEL.equals (typeString)) {
3222 mouseEvent.type = DWT.MouseWheel;
3223 mouseEvent.count = -aDetail[0];
3224 } else if (XPCOM.DOMEVENT_MOUSEOVER.equals (typeString)) {
3225 mouseEvent.type = DWT.MouseEnter;
3226 } else if (XPCOM.DOMEVENT_MOUSEOUT.equals (typeString)) {
3227 mouseEvent.type = DWT.MouseExit;
3228 } else if (XPCOM.DOMEVENT_MOUSEDRAG.equals (typeString)) {
3229 mouseEvent.type = DWT.DragDetect;
3230 mouseEvent.button = aButton[0] + 1;
3231 switch (mouseEvent.button) {
3232 case 1: mouseEvent.stateMask |= DWT.BUTTON1; break;
3233 case 2: mouseEvent.stateMask |= DWT.BUTTON2; break;
3234 case 3: mouseEvent.stateMask |= DWT.BUTTON3; break;
3235 case 4: mouseEvent.stateMask |= DWT.BUTTON4; break;
3236 case 5: mouseEvent.stateMask |= DWT.BUTTON5; break;
3237 }
3238 }
3239
3240 browser.notifyListeners (mouseEvent.type, mouseEvent);
3241 if (browser.isDisposed ()) return XPCOM.NS_OK;
3242 if (aDetail[0] is 2 && XPCOM.DOMEVENT_MOUSEDOWN.equals (typeString)) {
3243 mouseEvent = new Event ();
3244 mouseEvent.widget = browser;
3245 mouseEvent.x = aClientX[0]; mouseEvent.y = aClientY[0];
3246 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);
3247 mouseEvent.type = DWT.MouseDoubleClick;
3248 mouseEvent.button = aButton[0] + 1;
3249 mouseEvent.count = aDetail[0];
3250 browser.notifyListeners (mouseEvent.type, mouseEvent);
3251 }
3252 return XPCOM.NS_OK;
3253 }
3254 }