comparison dwt/browser/Mozilla.d @ 278:93409d9838c5

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