KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > browser > IE


1 /*******************************************************************************
2  * Copyright (c) 2003, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.swt.browser;
12
13 import org.eclipse.swt.*;
14 import org.eclipse.swt.graphics.*;
15 import org.eclipse.swt.internal.ole.win32.*;
16 import org.eclipse.swt.internal.win32.*;
17 import org.eclipse.swt.ole.win32.*;
18 import org.eclipse.swt.widgets.*;
19
20 class IE extends WebBrowser {
21
22     OleFrame frame;
23     OleControlSite site;
24     OleAutomation auto;
25     OleListener mouseListener;
26     OleAutomation[] documents = new OleAutomation[0];
27
28     boolean back, forward, navigate, delaySetText, ignoreDispose;
29     Point location;
30     Point size;
31     boolean addressBar = true, menuBar = true, statusBar = true, toolBar = true;
32     int info;
33     int globalDispatch;
34     String JavaDoc html;
35
36     static final int BeforeNavigate2 = 0xfa;
37     static final int CommandStateChange = 0x69;
38     static final int DocumentComplete = 0x103;
39     static final int NavigateComplete2 = 0xfc;
40     static final int NewWindow2 = 0xfb;
41     static final int OnMenuBar = 0x100;
42     static final int OnStatusBar = 0x101;
43     static final int OnToolBar = 0xff;
44     static final int OnVisible = 0xfe;
45     static final int ProgressChange = 0x6c;
46     static final int RegisterAsBrowser = 0x228;
47     static final int StatusTextChange = 0x66;
48     static final int TitleChange = 0x71;
49     static final int WindowClosing = 0x107;
50     static final int WindowSetHeight = 0x10b;
51     static final int WindowSetLeft = 0x108;
52     static final int WindowSetResizable = 0x106;
53     static final int WindowSetTop = 0x109;
54     static final int WindowSetWidth = 0x10a;
55
56     static final short CSC_NAVIGATEFORWARD = 1;
57     static final short CSC_NAVIGATEBACK = 2;
58     static final int INET_E_DEFAULT_ACTION = 0x800C0011;
59     static final int READYSTATE_COMPLETE = 4;
60     static final int URLPOLICY_ALLOW = 0x00;
61     static final int URLPOLICY_DISALLOW = 0x03;
62     static final int URLPOLICY_JAVA_PROHIBIT = 0x0;
63     static final int URLZONE_LOCAL_MACHINE = 0;
64     static final int URLZONE_INTRANET = 1;
65     static final int URLACTION_ACTIVEX_MIN = 0x00001200;
66     static final int URLACTION_ACTIVEX_MAX = 0x000013ff;
67     static final int URLACTION_ACTIVEX_RUN = 0x00001200;
68     static final int URLACTION_JAVA_MIN = 0x00001C00;
69     static final int URLPOLICY_JAVA_LOW = 0x00030000;
70     static final int URLACTION_JAVA_MAX = 0x00001Cff;
71     
72     static final int DISPID_AMBIENT_DLCONTROL = -5512;
73     static final int DLCTL_DLIMAGES = 0x00000010;
74     static final int DLCTL_VIDEOS = 0x00000020;
75     static final int DLCTL_BGSOUNDS = 0x00000040;
76     static final int DLCTL_NO_SCRIPTS = 0x00000080;
77     static final int DLCTL_NO_JAVA = 0x00000100;
78     static final int DLCTL_NO_RUNACTIVEXCTLS = 0x00000200;
79     static final int DLCTL_NO_DLACTIVEXCTLS = 0x00000400;
80     static final int DLCTL_DOWNLOADONLY = 0x00000800;
81     static final int DLCTL_NO_FRAMEDOWNLOAD = 0x00001000;
82     static final int DLCTL_RESYNCHRONIZE = 0x00002000;
83     static final int DLCTL_PRAGMA_NO_CACHE = 0x00004000;
84     static final int DLCTL_FORCEOFFLINE = 0x10000000;
85     static final int DLCTL_NO_CLIENTPULL = 0x20000000;
86     static final int DLCTL_SILENT = 0x40000000;
87     static final int DOCHOSTUIFLAG_THEME = 0x00040000;
88     static final int DOCHOSTUIFLAG_NO3DBORDER = 0x0000004;
89     static final int DOCHOSTUIFLAG_NO3DOUTERBORDER = 0x00200000;
90     
91     static final String JavaDoc ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
92
static final String JavaDoc CLSID_SHELLEXPLORER1 = "{EAB22AC3-30C1-11CF-A7EB-0000C05BAE0B}";
93     static final String JavaDoc URL_DIRECTOR = "http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab"; //$NON-NLS-1$
94

95     static {
96         NativeClearSessions = new Runnable JavaDoc() {
97             public void run() {
98                 OS.InternetSetOption (0, OS.INTERNET_OPTION_END_BROWSER_SESSION, 0, 0); }
99         };
100     }
101
102 public void create(Composite parent, int style) {
103     info = IE.DOCHOSTUIFLAG_THEME;
104     if ((style & SWT.BORDER) == 0) info |= IE.DOCHOSTUIFLAG_NO3DOUTERBORDER;
105     frame = new OleFrame(browser, SWT.NONE);
106
107     /*
108     * Registry entry HKEY_CLASSES_ROOT\Shell.Explorer\CLSID indicates which version of
109     * Shell.Explorer to use by default. We usually want to use this value because it
110     * typically points at the newest one that is available. However it is possible for
111     * this registry entry to be changed by another application to point at some other
112     * Shell.Explorer version.
113     *
114     * The Browser depends on the Shell.Explorer version being at least Shell.Explorer.2.
115     * If it is detected in the registry to be Shell.Explorer.1 then change the progId that
116     * will be embedded to explicitly specify Shell.Explorer.2.
117     */

118     String JavaDoc progId = "Shell.Explorer"; //$NON-NLS-1$
119
TCHAR key = new TCHAR (0, "Shell.Explorer\\CLSID", true); //$NON-NLS-1$
120
int [] phkResult = new int [1];
121     if (OS.RegOpenKeyEx (OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult) == 0) {
122         int [] lpcbData = new int [1];
123         int result = OS.RegQueryValueEx (phkResult [0], null, 0, null, (TCHAR) null, lpcbData);
124         if (result == 0) {
125             TCHAR lpData = new TCHAR (0, lpcbData [0] / TCHAR.sizeof);
126             result = OS.RegQueryValueEx (phkResult [0], null, 0, null, lpData, lpcbData);
127             if (result == 0) {
128                 String JavaDoc clsid = lpData.toString (0, lpData.strlen ());
129                 if (clsid.equals (CLSID_SHELLEXPLORER1)) {
130                     /* Shell.Explorer.1 is the default, ensure that Shell.Explorer.2 is available */
131                     key = new TCHAR (0, "Shell.Explorer.2", true); //$NON-NLS-1$
132
int [] phkResult2 = new int [1];
133                     if (OS.RegOpenKeyEx (OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult2) == 0) {
134                         /* specify that Shell.Explorer.2 is to be used */
135                         OS.RegCloseKey (phkResult2 [0]);
136                         progId = "Shell.Explorer.2"; //$NON-NLS-1$
137
}
138                 }
139             }
140         }
141         OS.RegCloseKey (phkResult [0]);
142     }
143     try {
144         site = new WebSite(frame, SWT.NONE, progId); //$NON-NLS-1$
145
} catch (SWTException e) {
146         browser.dispose();
147         SWT.error(SWT.ERROR_NO_HANDLES);
148     }
149     
150     site.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
151     auto = new OleAutomation(site);
152
153     mouseListener = new OleListener() {
154         public void handleEvent (OleEvent e) {
155             handleMouseEvent(e);
156         }
157     };
158
159     Listener listener = new Listener() {
160         public void handleEvent(Event e) {
161             switch (e.type) {
162                 case SWT.Dispose: {
163                     /* make this handler run after other dispose listeners */
164                     if (ignoreDispose) {
165                         ignoreDispose = false;
166                         break;
167                     }
168                     ignoreDispose = true;
169                     browser.notifyListeners (e.type, e);
170                     e.type = SWT.NONE;
171                     unhookMouseListeners(documents);
172                     for (int i = 0; i < documents.length; i++) {
173                         documents[i].dispose();
174                     }
175                     documents = null;
176                     mouseListener = null;
177                     if (auto != null) auto.dispose();
178                     auto = null;
179                     break;
180                 }
181                 case SWT.Resize: {
182                     frame.setBounds(browser.getClientArea());
183                     break;
184                 }
185                 case SWT.KeyDown:
186                 case SWT.KeyUp: {
187                     browser.notifyListeners(e.type, e);
188                     break;
189                 }
190             }
191         }
192     };
193     browser.addListener(SWT.Dispose, listener);
194     browser.addListener(SWT.Resize, listener);
195     site.addListener(SWT.KeyDown, listener);
196     site.addListener(SWT.KeyUp, listener);
197     
198     OleListener oleListener = new OleListener() {
199         public void handleEvent(OleEvent event) {
200             /* callbacks are asynchronous, auto could be disposed */
201             if (auto != null) {
202                 switch (event.type) {
203                     case BeforeNavigate2: {
204                         Variant varResult = event.arguments[1];
205                         String JavaDoc url = varResult.getString();
206                         LocationEvent newEvent = new LocationEvent(browser);
207                         newEvent.display = browser.getDisplay();
208                         newEvent.widget = browser;
209                         newEvent.location = url;
210                         newEvent.doit = true;
211                         for (int i = 0; i < locationListeners.length; i++) {
212                             locationListeners[i].changing(newEvent);
213                         }
214                         Variant cancel = event.arguments[6];
215                         if (cancel != null) {
216                             int pCancel = cancel.getByRef();
217                             COM.MoveMemory(pCancel, new short[] {newEvent.doit ? COM.VARIANT_FALSE : COM.VARIANT_TRUE}, 2);
218                         }
219                         if (newEvent.doit) {
220                             varResult = event.arguments[0];
221                             IDispatch dispatch = varResult.getDispatch();
222                             Variant variant = new Variant(auto);
223                             IDispatch top = variant.getDispatch();
224                             boolean isTop = top.getAddress() == dispatch.getAddress();
225                             if (isTop) {
226                                 /* unhook mouse listeners and unref the last document(s) */
227                                 unhookMouseListeners(documents);
228                                 for (int i = 0; i < documents.length; i++) {
229                                     documents[i].dispose();
230                                 }
231                                 documents = new OleAutomation[0];
232                             }
233                         }
234                         break;
235                     }
236                     case CommandStateChange: {
237                         boolean enabled = false;
238                         Variant varResult = event.arguments[0];
239                         int command = varResult.getInt();
240                         varResult = event.arguments[1];
241                         enabled = varResult.getBoolean();
242                         switch (command) {
243                             case CSC_NAVIGATEBACK : back = enabled; break;
244                             case CSC_NAVIGATEFORWARD : forward = enabled; break;
245                         }
246                         break;
247                     }
248                     case DocumentComplete: {
249                         Variant varResult = event.arguments[0];
250                         IDispatch dispatch = varResult.getDispatch();
251     
252                         varResult = event.arguments[1];
253                         String JavaDoc url = varResult.getString();
254                         if (html != null && url.equals(ABOUT_BLANK)) {
255                             Runnable JavaDoc runnable = new Runnable JavaDoc () {
256                                 public void run() {
257                                     if (browser.isDisposed() || html == null) return;
258                                     int charCount = html.length();
259                                     char[] chars = new char[charCount];
260                                     html.getChars(0, charCount, chars, 0);
261                                     html = null;
262                                     int byteCount = OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, charCount, null, 0, null, null);
263                                     /*
264                                     * Note. Internet Explorer appears to treat the data loaded with
265                                     * nsIPersistStreamInit.Load as if it were encoded using the default
266                                     * local charset. There does not seem to be an API to set the
267                                     * desired charset explicitly in this case. The fix is to
268                                     * prepend the UTF-8 Byte Order Mark signature to the data.
269                                     */

270                                     byte[] UTF8BOM = {(byte)0xEF, (byte)0xBB, (byte)0xBF};
271                                     int hGlobal = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, UTF8BOM.length + byteCount);
272                                     if (hGlobal != 0) {
273                                         OS.MoveMemory(hGlobal, UTF8BOM, UTF8BOM.length);
274                                         OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, charCount, hGlobal + UTF8BOM.length, byteCount, null, null);
275                                         int[] ppstm = new int[1];
276                                         /*
277                                         * Note. CreateStreamOnHGlobal is called with the flag fDeleteOnRelease.
278                                         * If the call succeeds the buffer hGlobal is freed automatically
279                                         * when the IStream object is released. If the call fails, free the buffer
280                                         * hGlobal.
281                                         */

282                                         if (OS.CreateStreamOnHGlobal(hGlobal, true, ppstm) == OS.S_OK) {
283                                             int[] rgdispid = auto.getIDsOfNames(new String JavaDoc[] {"Document"}); //$NON-NLS-1$
284
Variant pVarResult = auto.getProperty(rgdispid[0]);
285                                             IDispatch dispatchDocument = pVarResult.getDispatch();
286                                             int[] ppvObject = new int[1];
287                                             int result = dispatchDocument.QueryInterface(COM.IIDIPersistStreamInit, ppvObject);
288                                             if (result == OS.S_OK) {
289                                                 IPersistStreamInit persistStreamInit = new IPersistStreamInit(ppvObject[0]);
290                                                 if (persistStreamInit.InitNew() == OS.S_OK) {
291                                                     persistStreamInit.Load(ppstm[0]);
292                                                 }
293                                                 persistStreamInit.Release();
294                                             }
295                                             pVarResult.dispose();
296                                             /*
297                                             * This code is intentionally commented. The IDispatch obtained from a Variant
298                                             * did not increase the reference count for the enclosed interface.
299                                             */

300                                             //dispatchDocument.Release();
301
IUnknown stream = new IUnknown(ppstm[0]);
302                                             stream.Release();
303                                         } else {
304                                             OS.GlobalFree(hGlobal);
305                                         }
306                                     }
307                                 }
308                             };
309                             if (delaySetText) {
310                                 delaySetText = false;
311                                 browser.getDisplay().asyncExec(runnable);
312                             } else {
313                                 runnable.run();
314                             }
315                         } else {
316                             Variant variant = new Variant(auto);
317                             IDispatch top = variant.getDispatch();
318                             LocationEvent locationEvent = new LocationEvent(browser);
319                             locationEvent.display = browser.getDisplay();
320                             locationEvent.widget = browser;
321                             locationEvent.location = url;
322                             locationEvent.top = top.getAddress() == dispatch.getAddress();
323                             for (int i = 0; i < locationListeners.length; i++) {
324                                 locationListeners[i].changed(locationEvent);
325                             }
326                             if (browser.isDisposed()) return;
327                             /*
328                              * This code is intentionally commented. A Variant constructed from an
329                              * OleAutomation object does not increase its reference count. The IDispatch
330                              * obtained from this Variant did not increase the reference count for the
331                              * OleAutomation instance either.
332                              */

333                             //top.Release();
334
//variant.dispose();
335
/*
336                              * Note. The completion of the page loading is detected as
337                              * described in the MSDN article "Determine when a page is
338                              * done loading in WebBrowser Control".
339                              */

340                             if (globalDispatch != 0 && dispatch.getAddress() == globalDispatch) {
341                                 /* final document complete */
342                                 globalDispatch = 0;
343                                 ProgressEvent progressEvent = new ProgressEvent(browser);
344                                 progressEvent.display = browser.getDisplay();
345                                 progressEvent.widget = browser;
346                                 for (int i = 0; i < progressListeners.length; i++) {
347                                     progressListeners[i].completed(progressEvent);
348                                 }
349                             }
350                         }
351                                                 
352                         /*
353                         * This code is intentionally commented. This IDispatch was received
354                         * as an argument from the OleEvent and it will be disposed along with
355                         * the other arguments.
356                         */

357                         //dispatch.Release();
358
break;
359                     }
360                     case NavigateComplete2: {
361                         Variant varResult = event.arguments[0];
362                         IDispatch dispatch = varResult.getDispatch();
363                         if (globalDispatch == 0) globalDispatch = dispatch.getAddress();
364     
365                         OleAutomation webBrowser = varResult.getAutomation();
366                         varResult = event.arguments[1];
367                         Variant variant = new Variant(auto);
368                         IDispatch top = variant.getDispatch();
369                         boolean isTop = top.getAddress() == dispatch.getAddress();
370                         hookMouseListeners(webBrowser, isTop);
371                         webBrowser.dispose();
372                         break;
373                     }
374                     case NewWindow2: {
375                         Variant cancel = event.arguments[1];
376                         int pCancel = cancel.getByRef();
377                         WindowEvent newEvent = new WindowEvent(browser);
378                         newEvent.display = browser.getDisplay();
379                         newEvent.widget = browser;
380                         newEvent.required = false;
381                         for (int i = 0; i < openWindowListeners.length; i++) {
382                             openWindowListeners[i].open(newEvent);
383                         }
384                         IE browser = null;
385                         if (newEvent.browser != null && newEvent.browser.webBrowser instanceof IE) {
386                             browser = (IE)newEvent.browser.webBrowser;
387                         }
388                         boolean doit = browser != null && !browser.browser.isDisposed();
389                         if (doit) {
390                             Variant variant = new Variant(browser.auto);
391                             IDispatch iDispatch = variant.getDispatch();
392                             Variant ppDisp = event.arguments[0];
393                             int byref = ppDisp.getByRef();
394                             if (byref != 0) COM.MoveMemory(byref, new int[] {iDispatch.getAddress()}, 4);
395                             /*
396                             * This code is intentionally commented. A Variant constructed from an
397                             * OleAutomation object does not increase its reference count. The IDispatch
398                             * obtained from this Variant did not increase the reference count for the
399                             * OleAutomation instance either.
400                             */

401                             //variant.dispose();
402
//iDispatch.Release();
403
}
404                         if (newEvent.required) {
405                             COM.MoveMemory(pCancel, new short[]{doit ? COM.VARIANT_FALSE : COM.VARIANT_TRUE}, 2);
406                         }
407                         break;
408                     }
409                     case OnMenuBar: {
410                         Variant arg0 = event.arguments[0];
411                         menuBar = arg0.getBoolean();
412                         break;
413                     }
414                     case OnStatusBar: {
415                         Variant arg0 = event.arguments[0];
416                         statusBar = arg0.getBoolean();
417                         break;
418                     }
419                     case OnToolBar: {
420                         Variant arg0 = event.arguments[0];
421                         toolBar = arg0.getBoolean();
422                         /*
423                         * Feature in Internet Explorer. OnToolBar FALSE is emitted
424                         * when both tool bar, address bar and menu bar must not be visible.
425                         * OnToolBar TRUE is emitted when either of tool bar, address bar
426                         * or menu bar is visible.
427                         */

428                         if (!toolBar) {
429                             addressBar = false;
430                             menuBar = false;
431                         }
432                         break;
433                     }
434                     case OnVisible: {
435                         Variant arg1 = event.arguments[0];
436                         boolean visible = arg1.getBoolean();
437                         WindowEvent newEvent = new WindowEvent(browser);
438                         newEvent.display = browser.getDisplay();
439                         newEvent.widget = browser;
440                         if (visible) {
441                             if (addressBar) {
442                                 /*
443                                 * Bug in Internet Explorer. There is no distinct notification for
444                                 * the address bar. If neither address, menu or tool bars are visible,
445                                 * OnToolBar FALSE is emitted. For some reason, querying the value of
446                                 * AddressBar in this case returns true even though it should not be
447                                 * set visible. The workaround is to only query the value of AddressBar
448                                 * when OnToolBar FALSE has not been emitted.
449                                 */

450                                 int[] rgdispid = auto.getIDsOfNames(new String JavaDoc[] { "AddressBar" }); //$NON-NLS-1$
451
Variant pVarResult = auto.getProperty(rgdispid[0]);
452                                 if (pVarResult != null && pVarResult.getType() == OLE.VT_BOOL) addressBar = pVarResult.getBoolean();
453                             }
454                             newEvent.addressBar = addressBar;
455                             newEvent.menuBar = menuBar;
456                             newEvent.statusBar = statusBar;
457                             newEvent.toolBar = toolBar;
458                             newEvent.location = location;
459                             newEvent.size = size;
460                             for (int i = 0; i < visibilityWindowListeners.length; i++) {
461                                 visibilityWindowListeners[i].show(newEvent);
462                             }
463                             location = null;
464                             size = null;
465                         } else {
466                             for (int i = 0; i < visibilityWindowListeners.length; i++) {
467                                 visibilityWindowListeners[i].hide(newEvent);
468                             }
469                         }
470                         break;
471                     }
472                     case ProgressChange: {
473                         Variant arg1 = event.arguments[0];
474                         int nProgress = arg1.getType() != OLE.VT_I4 ? 0 : arg1.getInt(); // may be -1
475
Variant arg2 = event.arguments[1];
476                         int nProgressMax = arg2.getType() != OLE.VT_I4 ? 0 : arg2.getInt();
477                         ProgressEvent newEvent = new ProgressEvent(browser);
478                         newEvent.display = browser.getDisplay();
479                         newEvent.widget = browser;
480                         newEvent.current = nProgress;
481                         newEvent.total = nProgressMax;
482                         if (nProgress != -1) {
483                             for (int i = 0; i < progressListeners.length; i++) {
484                                 progressListeners[i].changed(newEvent);
485                             }
486                         }
487                         break;
488                     }
489                     case StatusTextChange: {
490                         Variant arg1 = event.arguments[0];
491                         if (arg1.getType() == OLE.VT_BSTR) {
492                             String JavaDoc text = arg1.getString();
493                             StatusTextEvent newEvent = new StatusTextEvent(browser);
494                             newEvent.display = browser.getDisplay();
495                             newEvent.widget = browser;
496                             newEvent.text = text;
497                             for (int i = 0; i < statusTextListeners.length; i++) {
498                                 statusTextListeners[i].changed(newEvent);
499                             }
500                         }
501                         break;
502                     }
503                     case TitleChange: {
504                         Variant arg1 = event.arguments[0];
505                         if (arg1.getType() == OLE.VT_BSTR) {
506                             String JavaDoc title = arg1.getString();
507                             TitleEvent newEvent = new TitleEvent(browser);
508                             newEvent.display = browser.getDisplay();
509                             newEvent.widget = browser;
510                             newEvent.title = title;
511                             for (int i = 0; i < titleListeners.length; i++) {
512                                 titleListeners[i].changed(newEvent);
513                             }
514                         }
515                         break;
516                     }
517                     case WindowClosing: {
518                         /*
519                         * Disposing the Browser directly from this callback will crash if the
520                         * Browser has a text field with an active caret. As a workaround fire
521                         * the Close event and dispose the Browser in an async block.
522                         */

523                         browser.getDisplay().asyncExec(new Runnable JavaDoc() {
524                             public void run() {
525                                 if (browser.isDisposed()) return;
526                                 WindowEvent newEvent = new WindowEvent(browser);
527                                 newEvent.display = browser.getDisplay();
528                                 newEvent.widget = browser;
529                                 for (int i = 0; i < closeWindowListeners.length; i++) {
530                                     closeWindowListeners[i].close(newEvent);
531                                 }
532                                 browser.dispose();
533                             }
534                         });
535                         Variant cancel = event.arguments[1];
536                         int pCancel = cancel.getByRef();
537                         Variant arg1 = event.arguments[0];
538                         boolean isChildWindow = arg1.getBoolean();
539                         COM.MoveMemory(pCancel, new short[]{isChildWindow ? COM.VARIANT_FALSE : COM.VARIANT_TRUE}, 2);
540                         break;
541                     }
542                     case WindowSetHeight: {
543                         if (size == null) size = new Point(0, 0);
544                         Variant arg1 = event.arguments[0];
545                         size.y = arg1.getInt();
546                         break;
547                     }
548                     case WindowSetLeft: {
549                         if (location == null) location = new Point(0, 0);
550                         Variant arg1 = event.arguments[0];
551                         location.x = arg1.getInt();
552                         break;
553                     }
554                     case WindowSetTop: {
555                         if (location == null) location = new Point(0, 0);
556                         Variant arg1 = event.arguments[0];
557                         location.y = arg1.getInt();
558                         break;
559                     }
560                     case WindowSetWidth: {
561                         if (size == null) size = new Point(0, 0);
562                         Variant arg1 = event.arguments[0];
563                         size.x = arg1.getInt();
564                         break;
565                     }
566                 }
567             }
568             /*
569             * Dispose all arguments passed in the OleEvent. This must be
570             * done to properly release any IDispatch reference that was
571             * automatically addRef'ed when constructing the OleEvent.
572             */

573             Variant[] arguments = event.arguments;
574             for (int i = 0; i < arguments.length; i++) arguments[i].dispose();
575         }
576     };
577     site.addEventListener(BeforeNavigate2, oleListener);
578     site.addEventListener(CommandStateChange, oleListener);
579     site.addEventListener(DocumentComplete, oleListener);
580     site.addEventListener(NavigateComplete2, oleListener);
581     site.addEventListener(NewWindow2, oleListener);
582     site.addEventListener(OnMenuBar, oleListener);
583     site.addEventListener(OnStatusBar, oleListener);
584     site.addEventListener(OnToolBar, oleListener);
585     site.addEventListener(OnVisible, oleListener);
586     site.addEventListener(ProgressChange, oleListener);
587     site.addEventListener(StatusTextChange, oleListener);
588     site.addEventListener(TitleChange, oleListener);
589     site.addEventListener(WindowClosing, oleListener);
590     site.addEventListener(WindowSetHeight, oleListener);
591     site.addEventListener(WindowSetLeft, oleListener);
592     site.addEventListener(WindowSetTop, oleListener);
593     site.addEventListener(WindowSetWidth, oleListener);
594     
595     Variant variant = new Variant(true);
596     auto.setProperty(RegisterAsBrowser, variant);
597     variant.dispose();
598     
599     variant = new Variant(false);
600     int[] rgdispid = auto.getIDsOfNames(new String JavaDoc[] {"RegisterAsDropTarget"}); //$NON-NLS-1$
601
if (rgdispid != null) auto.setProperty(rgdispid[0], variant);
602     variant.dispose();
603 }
604
605 public boolean back() {
606     if (!back) return false;
607     int[] rgdispid = auto.getIDsOfNames(new String JavaDoc[] { "GoBack" }); //$NON-NLS-1$
608
Variant pVarResult = auto.invoke(rgdispid[0]);
609     return pVarResult != null && pVarResult.getType() == OLE.VT_EMPTY;
610 }
611
612 public boolean execute(String JavaDoc script) {
613     /* get IHTMLDocument2 */
614     int[] rgdispid = auto.getIDsOfNames(new String JavaDoc[]{"Document"}); //$NON-NLS-1$
615
int dispIdMember = rgdispid[0];
616     Variant pVarResult = auto.getProperty(dispIdMember);
617     if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) return false;
618     OleAutomation document = pVarResult.getAutomation();
619     pVarResult.dispose();
620
621     /* get IHTMLWindow2 */
622     rgdispid = document.getIDsOfNames(new String JavaDoc[]{"parentWindow"}); //$NON-NLS-1$
623
if (rgdispid == null) {
624         /* implies that browser's content is not a IHTMLDocument2 (eg.- acrobat reader) */
625         document.dispose();
626         return false;
627     }
628     dispIdMember = rgdispid[0];
629     pVarResult = document.getProperty(dispIdMember);
630     OleAutomation ihtmlWindow2 = pVarResult.getAutomation();
631     pVarResult.dispose();
632     document.dispose();
633     
634     rgdispid = ihtmlWindow2.getIDsOfNames(new String JavaDoc[] { "execScript", "code" }); //$NON-NLS-1$ //$NON-NLS-2$
635
Variant[] rgvarg = new Variant[1];
636     rgvarg[0] = new Variant(script);
637     int[] rgdispidNamedArgs = new int[1];
638     rgdispidNamedArgs[0] = rgdispid[1];
639     pVarResult = ihtmlWindow2.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
640     rgvarg[0].dispose();
641     ihtmlWindow2.dispose();
642     if (pVarResult == null) return false;
643     pVarResult.dispose();
644     return true;
645 }
646
647 public boolean forward() {
648     if (!forward) return false;
649     int[] rgdispid = auto.getIDsOfNames(new String JavaDoc[] { "GoForward" }); //$NON-NLS-1$
650
Variant pVarResult = auto.invoke(rgdispid[0]);
651     return pVarResult != null && pVarResult.getType() == OLE.VT_EMPTY;
652 }
653
654 public String JavaDoc getUrl() {
655     int[] rgdispid = auto.getIDsOfNames(new String JavaDoc[] { "LocationURL" }); //$NON-NLS-1$
656
Variant pVarResult = auto.getProperty(rgdispid[0]);
657     if (pVarResult == null || pVarResult.getType() != OLE.VT_BSTR)
658         return "";
659     String JavaDoc result = pVarResult.getString();
660     pVarResult.dispose();
661     return result;
662 }
663
664 public boolean isBackEnabled() {
665     return back;
666 }
667
668 public boolean isForwardEnabled() {
669     return forward;
670 }
671
672 public boolean isFocusControl () {
673     return site.isFocusControl() || frame.isFocusControl();
674 }
675
676 public void refresh() {
677     int[] rgdispid = auto.getIDsOfNames(new String JavaDoc[] { "Refresh" }); //$NON-NLS-1$
678
auto.invoke(rgdispid[0]);
679 }
680
681 public boolean setText(String JavaDoc html) {
682     /*
683     * If the html field is non-null then the about:blank page is already being
684     * loaded, so no Stop or Navigate is required. Just set the html that is to
685     * be shown.
686     */

687     boolean blankLoading = this.html != null;
688     this.html = html;
689     if (blankLoading) return true;
690     
691     /*
692     * Navigate to the blank page and insert the given html when
693     * receiving the next DocumentComplete notification. See the
694     * MSDN article "Loading HTML content from a Stream".
695     *
696     * Note. Stop any pending request. This is required to avoid displaying a
697     * blank page as a result of consecutive calls to setUrl and/or setText.
698     * The previous request would otherwise render the new html content and
699     * reset the html field before the browser actually navigates to the blank
700     * page as requested below.
701     *
702     * Feature in Internet Explorer. Stopping pending requests when no request
703     * is pending causes a default page 'Action cancelled' to be displayed. The
704     * workaround is to not invoke 'stop' when no request has been set since
705     * that instance was created.
706     */

707     int[] rgdispid;
708     if (navigate) {
709         /*
710         * Stopping the loading of a page causes DocumentComplete events from previous
711         * requests to be received before the DocumentComplete for this page. In such
712         * cases we must be sure to not set the html into the browser too soon, since
713         * doing so could result in its page being cleared out by a subsequent
714         * DocumentComplete. The Browser's ReadyState can be used to determine whether
715         * these extra events will be received or not.
716         */

717         rgdispid = auto.getIDsOfNames(new String JavaDoc[] { "ReadyState" }); //$NON-NLS-1$
718
Variant pVarResult = auto.getProperty(rgdispid[0]);
719         if (pVarResult == null) return false;
720         delaySetText = pVarResult.getInt() != READYSTATE_COMPLETE;
721         pVarResult.dispose();
722         rgdispid = auto.getIDsOfNames(new String JavaDoc[] { "Stop" }); //$NON-NLS-1$
723
auto.invoke(rgdispid[0]);
724     }
725     rgdispid = auto.getIDsOfNames(new String JavaDoc[] { "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
726
navigate = true;
727     Variant[] rgvarg = new Variant[1];
728     rgvarg[0] = new Variant(ABOUT_BLANK);
729     int[] rgdispidNamedArgs = new int[1];
730     rgdispidNamedArgs[0] = rgdispid[1];
731     boolean oldValue = false;
732     if (!OS.IsWinCE) {
733         int hResult = OS.CoInternetIsFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.GET_FEATURE_FROM_PROCESS);
734         oldValue = hResult == COM.S_OK;
735         OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);
736     }
737     Variant pVarResult = auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
738     if (!OS.IsWinCE) {
739         OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, oldValue);
740     }
741     rgvarg[0].dispose();
742     if (pVarResult == null) return false;
743     boolean result = pVarResult.getType() == OLE.VT_EMPTY;
744     pVarResult.dispose();
745     return result;
746 }
747
748 public boolean setUrl(String JavaDoc url) {
749     html = null;
750
751     /*
752     * Bug in Internet Explorer. For some reason, Navigating to an xml document before
753     * a previous Navigate has completed will leave the Browser in a bad state if the
754     * Navigate to the xml document does not complete. This bad state causes a GP when
755     * the parent window is eventually disposed. The workaround is to issue a Stop before
756     * navigating to any xml document.
757     */

758     if (url.endsWith(".xml")) { //$NON-NLS-1$
759
/*
760         * Feature in Internet Explorer. Stopping pending requests when no request has been
761         * issued causes a default 'Action cancelled' page to be displayed. Since Stop must
762         * be issued here, the workaround is to first Navigate to the about:blank page before
763         * issuing Stop so that the 'Action cancelled' page is not displayed.
764         */

765         if (!navigate) {
766             int[] rgdispid = auto.getIDsOfNames(new String JavaDoc[] { "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
767
Variant[] rgvarg = new Variant[1];
768             rgvarg[0] = new Variant(ABOUT_BLANK);
769             int[] rgdispidNamedArgs = new int[1];
770             rgdispidNamedArgs[0] = rgdispid[1];
771             boolean oldValue = false;
772             if (!OS.IsWinCE) {
773                 int hResult = OS.CoInternetIsFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.GET_FEATURE_FROM_PROCESS);
774                 oldValue = hResult == COM.S_OK;
775                 OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);
776             }
777             auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
778             if (!OS.IsWinCE) {
779                 OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, oldValue);
780             }
781             rgvarg[0].dispose();
782         }
783         int[] rgdispid = auto.getIDsOfNames(new String JavaDoc[] { "Stop" }); //$NON-NLS-1$
784
auto.invoke(rgdispid[0]);
785     }
786
787     int[] rgdispid = auto.getIDsOfNames(new String JavaDoc[] { "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
788
navigate = true;
789     Variant[] rgvarg = new Variant[1];
790     rgvarg[0] = new Variant(url);
791     int[] rgdispidNamedArgs = new int[1];
792     rgdispidNamedArgs[0] = rgdispid[1];
793     Variant pVarResult = auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
794     rgvarg[0].dispose();
795     if (pVarResult == null) return false;
796     boolean result = pVarResult.getType() == OLE.VT_EMPTY;
797     pVarResult.dispose();
798     return result;
799 }
800
801 public void stop() {
802     int[] rgdispid = auto.getIDsOfNames(new String JavaDoc[] { "Stop" }); //$NON-NLS-1$
803
auto.invoke(rgdispid[0]);
804 }
805
806 void handleMouseEvent (OleEvent e) {
807     Variant arg = e.arguments[0];
808     OleAutomation event = arg.getAutomation();
809     int[] rgdispid = event.getIDsOfNames(new String JavaDoc[]{ "type" }); //$NON-NLS-1$
810
int dispIdMember = rgdispid[0];
811     Variant pVarResult = event.getProperty(dispIdMember);
812     String JavaDoc eventType = pVarResult.getString();
813     pVarResult.dispose();
814
815     /*
816      * Feature in IE. MouseOver/MouseOut events are fired any time the mouse enters
817      * or exits any element within the Browser. To ensure that SWT events are only
818      * fired for mouse movements into or out of the Browser, do not fire an event if
819      * the element being exited (on MouseOver) or entered (on MouseExit) is within
820      * the Browser.
821      */

822     if (eventType.equals("mouseover")) { //$NON-NLS-1$
823
rgdispid = event.getIDsOfNames(new String JavaDoc[] { "fromElement" }); //$NON-NLS-1$
824
dispIdMember = rgdispid[0];
825         pVarResult = event.getProperty(dispIdMember);
826         boolean isInternal = pVarResult.getType() != COM.VT_EMPTY;
827         pVarResult.dispose();
828         if (isInternal) {
829             event.dispose();
830             return;
831         }
832     }
833     if (eventType.equals("mouseout")) { //$NON-NLS-1$
834
rgdispid = event.getIDsOfNames(new String JavaDoc[] { "toElement" }); //$NON-NLS-1$
835
dispIdMember = rgdispid[0];
836         pVarResult = event.getProperty(dispIdMember);
837         boolean isInternal = pVarResult.getType() != COM.VT_EMPTY;
838         pVarResult.dispose();
839         if (isInternal) {
840             event.dispose();
841             return;
842         }
843     }
844
845     int x, y, mask = 0;
846     Event newEvent = new Event();
847     newEvent.widget = browser;
848
849     rgdispid = event.getIDsOfNames(new String JavaDoc[] { "clientX" }); //$NON-NLS-1$
850
dispIdMember = rgdispid[0];
851     pVarResult = event.getProperty(dispIdMember);
852     x = pVarResult.getInt();
853     newEvent.x = x;
854     pVarResult.dispose();
855
856     rgdispid = event.getIDsOfNames(new String JavaDoc[] { "clientY" }); //$NON-NLS-1$
857
dispIdMember = rgdispid[0];
858     pVarResult = event.getProperty(dispIdMember);
859     y = pVarResult.getInt();
860     newEvent.y = y;
861     pVarResult.dispose();
862
863     rgdispid = event.getIDsOfNames(new String JavaDoc[] { "ctrlKey" }); //$NON-NLS-1$
864
dispIdMember = rgdispid[0];
865     pVarResult = event.getProperty(dispIdMember);
866     if (pVarResult.getBoolean()) mask |= SWT.CTRL;
867     pVarResult.dispose();
868
869     rgdispid = event.getIDsOfNames(new String JavaDoc[] { "altKey" }); //$NON-NLS-1$
870
dispIdMember = rgdispid[0];
871     pVarResult = event.getProperty(dispIdMember);
872     if (pVarResult.getBoolean()) mask |= SWT.ALT;
873     pVarResult.dispose();
874
875     rgdispid = event.getIDsOfNames(new String JavaDoc[] { "shiftKey" }); //$NON-NLS-1$
876
dispIdMember = rgdispid[0];
877     pVarResult = event.getProperty(dispIdMember);
878     if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
879     pVarResult.dispose();
880
881     newEvent.stateMask = mask;
882
883     rgdispid = event.getIDsOfNames(new String JavaDoc[] { "button" }); //$NON-NLS-1$
884
dispIdMember = rgdispid[0];
885     pVarResult = event.getProperty(dispIdMember);
886     int button = pVarResult.getInt();
887     pVarResult.dispose();
888     switch (button) {
889         case 1: button = 1; break;
890         case 2: button = 3; break;
891         case 4: button = 2; break;
892     };
893
894     event.dispose();
895
896     if (eventType.equals("mousedown")) { //$NON-NLS-1$
897
newEvent.type = SWT.MouseDown;
898         newEvent.button = button;
899         newEvent.count = 1;
900     } else if (eventType.equals("mouseup")) { //$NON-NLS-1$
901
newEvent.type = SWT.MouseUp;
902         newEvent.button = button;
903         newEvent.count = 1;
904     } else if (eventType.equals("mousemove")) { //$NON-NLS-1$
905
newEvent.type = SWT.MouseMove;
906     } else if (eventType.equals("mouseover")) { //$NON-NLS-1$
907
newEvent.type = SWT.MouseEnter;
908     } else if (eventType.equals("mouseout")) { //$NON-NLS-1$
909
newEvent.type = SWT.MouseExit;
910     } else if (eventType.equals("dragstart")) { //$NON-NLS-1$
911
newEvent.type = SWT.DragDetect;
912     }
913
914     browser.notifyListeners(newEvent.type, newEvent);
915     
916     if (eventType.equals("dblclick")) { //$NON-NLS-1$
917
newEvent = new Event ();
918         newEvent.widget = browser;
919         newEvent.type = SWT.MouseDoubleClick;
920         newEvent.x = x; newEvent.y = y;
921         newEvent.stateMask = mask;
922         newEvent.type = SWT.MouseDoubleClick;
923         newEvent.button = 1; /* dblclick only comes for button 1 and does not set the button property */
924         newEvent.count = 2;
925         browser.notifyListeners (newEvent.type, newEvent);
926     }
927 }
928
929 void hookMouseListeners(OleAutomation webBrowser, final boolean isTop) {
930     int[] rgdispid = webBrowser.getIDsOfNames(new String JavaDoc[]{ "Document" }); //$NON-NLS-1$
931
int dispIdMember = rgdispid[0];
932     Variant pVarResult = webBrowser.getProperty(dispIdMember);
933     if (pVarResult == null) return;
934     if (pVarResult.getType() == COM.VT_EMPTY) {
935         pVarResult.dispose();
936         return;
937     }
938     final OleAutomation document = pVarResult.getAutomation();
939     pVarResult.dispose();
940
941     /*
942      * In some cases, such as setting the Browser's content from a string,
943      * NavigateComplete2 is received multiple times for a top-level document.
944      * For cases like this, any previously-hooked mouse listeners must be
945      * removed from the document before hooking the new set of listeners,
946      * otherwise multiple sets of events will be received.
947      */

948     unhookMouseListeners (new OleAutomation[] {document});
949
950     site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN, mouseListener);
951     site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP, mouseListener);
952     site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK, mouseListener);
953     site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE, mouseListener);
954     site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART, mouseListener);
955     /* ensure that enter/exit are only fired once, by the top-level document */
956     if (isTop) {
957         site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER, mouseListener);
958         site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT, mouseListener);
959     }
960
961     OleAutomation[] newDocuments = new OleAutomation[documents.length + 1];
962     System.arraycopy(documents, 0, newDocuments, 0, documents.length);
963     newDocuments[documents.length] = document;
964     documents = newDocuments;
965 }
966
967 void unhookMouseListeners(OleAutomation[] documents) {
968     char[] buffer = (COM.IIDIHTMLDocumentEvents2 + '\0').toCharArray();
969     GUID guid = new GUID();
970     if (COM.IIDFromString(buffer, guid) == COM.S_OK) {
971         for (int i = 0; i < documents.length; i++) {
972             OleAutomation document = documents[i];
973             site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN, mouseListener);
974             site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP, mouseListener);
975             site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK, mouseListener);
976             site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE, mouseListener);
977             site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART, mouseListener);
978             site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER, mouseListener);
979             site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT, mouseListener);
980         }
981     }
982 }
983 }
984
Popular Tags