org.eclipse.swt.browser.IE Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.swt.win32.win32.x86 Show documentation
Show all versions of org.eclipse.swt.win32.win32.x86 Show documentation
SWT is an open source widget toolkit for Java designed to provide efficient, portable access to the user-interface facilities of the operating systems on which it is implemented.
The newest version!
/*******************************************************************************
* Copyright (c) 2003, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.browser;
import java.net.*;
import java.util.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.C;
import org.eclipse.swt.internal.ole.win32.*;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.ole.win32.*;
import org.eclipse.swt.widgets.*;
class IE extends WebBrowser {
OleFrame frame;
WebSite site;
OleAutomation auto;
OleListener domListener;
OleAutomation[] documents = new OleAutomation[0];
boolean back, forward, delaySetText, ignoreDispose, ignoreTraverse, performingInitialNavigate;
boolean installFunctionsOnDocumentComplete, untrustedText, isRefresh, isAboutBlank;
Point location;
Point size;
boolean addressBar = true, menuBar = true, statusBar = true, toolBar = true;
int /*long*/ globalDispatch;
String html, lastNavigateURL, uncRedirect;
Object[] pendingText, pendingUrl;
int style, lastKeyCode, lastCharCode;
int lastMouseMoveX, lastMouseMoveY;
static boolean Initialized;
static int IEVersion, PDFCount;
static String ProgId = "Shell.Explorer"; //$NON-NLS-1$
static final int BeforeNavigate2 = 0xfa;
static final int CommandStateChange = 0x69;
static final int DocumentComplete = 0x103;
static final int DownloadComplete = 0x68;
static final int NavigateComplete2 = 0xfc;
static final int NewWindow2 = 0xfb;
static final int OnMenuBar = 0x100;
static final int OnStatusBar = 0x101;
static final int OnToolBar = 0xff;
static final int OnVisible = 0xfe;
static final int ProgressChange = 0x6c;
static final int RegisterAsBrowser = 0x228;
static final int StatusTextChange = 0x66;
static final int TitleChange = 0x71;
static final int WindowClosing = 0x107;
static final int WindowSetHeight = 0x10b;
static final int WindowSetLeft = 0x108;
static final int WindowSetResizable = 0x106;
static final int WindowSetTop = 0x109;
static final int WindowSetWidth = 0x10a;
static final int NavigateError = 0x10f;
static final short CSC_NAVIGATEFORWARD = 1;
static final short CSC_NAVIGATEBACK = 2;
static final int INET_E_DEFAULT_ACTION = 0x800C0011;
static final int INET_E_RESOURCE_NOT_FOUND = 0x800C0005;
static final int READYSTATE_COMPLETE = 4;
static final int URLPOLICY_ALLOW = 0x00;
static final int URLPOLICY_DISALLOW = 0x03;
static final int URLPOLICY_JAVA_PROHIBIT = 0x0;
static final int URLPOLICY_JAVA_LOW = 0x00030000;
static final int URLZONE_LOCAL_MACHINE = 0;
static final int URLZONE_INTRANET = 1;
static final int URLACTION_ACTIVEX_MIN = 0x00001200;
static final int URLACTION_ACTIVEX_MAX = 0x000013ff;
static final int URLACTION_ACTIVEX_RUN = 0x00001200;
static final int URLACTION_FEATURE_ZONE_ELEVATION = 0x00002101;
static final int URLACTION_JAVA_MIN = 0x00001C00;
static final int URLACTION_JAVA_MAX = 0x00001Cff;
static final int URLACTION_SCRIPT_RUN = 0x00001400;
static final int DISPID_AMBIENT_DLCONTROL = -5512;
static final int DLCTL_DLIMAGES = 0x00000010;
static final int DLCTL_VIDEOS = 0x00000020;
static final int DLCTL_BGSOUNDS = 0x00000040;
static final int DLCTL_NO_SCRIPTS = 0x00000080;
static final int DLCTL_NO_JAVA = 0x00000100;
static final int DLCTL_NO_RUNACTIVEXCTLS = 0x00000200;
static final int DLCTL_NO_DLACTIVEXCTLS = 0x00000400;
static final int DLCTL_DOWNLOADONLY = 0x00000800;
static final int DLCTL_NO_FRAMEDOWNLOAD = 0x00001000;
static final int DLCTL_RESYNCHRONIZE = 0x00002000;
static final int DLCTL_PRAGMA_NO_CACHE = 0x00004000;
static final int DLCTL_FORCEOFFLINE = 0x10000000;
static final int DLCTL_NO_CLIENTPULL = 0x20000000;
static final int DLCTL_SILENT = 0x40000000;
static final int DOCHOSTUIFLAG_THEME = 0x00040000;
static final int DOCHOSTUIFLAG_NO3DBORDER = 0x0000004;
static final int DOCHOSTUIFLAG_NO3DOUTERBORDER = 0x00200000;
static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
static final String CLSID_SHELLEXPLORER1 = "{EAB22AC3-30C1-11CF-A7EB-0000C05BAE0B}"; //$NON-NLS-1$
static final int DEFAULT_IE_VERSION = 9000;
static final String EXTENSION_PDF = ".pdf"; //$NON-NLS-1$
static final String HTML_DOCUMENT = "HTML Document"; //$NON-NLS-1$
static final int MAX_PDF = 20;
static final char SEPARATOR_OS = System.getProperty ("file.separator").charAt (0); //$NON-NLS-1$
static final String PROPERTY_IEVERSION = "org.eclipse.swt.browser.IEVersion"; //$NON-NLS-1$
static final String VALUE_DEFAULT = "default"; //$NON-NLS-1$
static final String EVENT_DOUBLECLICK = "dblclick"; //$NON-NLS-1$
static final String EVENT_DRAGEND = "dragend"; //$NON-NLS-1$
static final String EVENT_DRAGSTART = "dragstart"; //$NON-NLS-1$
static final String EVENT_KEYDOWN = "keydown"; //$NON-NLS-1$
static final String EVENT_KEYPRESS = "keypress"; //$NON-NLS-1$
static final String EVENT_KEYUP = "keyup"; //$NON-NLS-1$
static final String EVENT_MOUSEMOVE = "mousemove"; //$NON-NLS-1$
static final String EVENT_MOUSEWHEEL = "mousewheel"; //$NON-NLS-1$
static final String EVENT_MOUSEUP = "mouseup"; //$NON-NLS-1$
static final String EVENT_MOUSEDOWN = "mousedown"; //$NON-NLS-1$
static final String EVENT_MOUSEOUT = "mouseout"; //$NON-NLS-1$
static final String EVENT_MOUSEOVER = "mouseover"; //$NON-NLS-1$
static final String PROTOCOL_FILE = "file://"; //$NON-NLS-1$
static final String PROPERTY_ALTKEY = "altKey"; //$NON-NLS-1$
static final String PROPERTY_BUTTON = "button"; //$NON-NLS-1$
static final String PROPERTY_CTRLKEY = "ctrlKey"; //$NON-NLS-1$
static final String PROPERTY_DOCUMENT = "Document"; //$NON-NLS-1$
static final String PROPERTY_FROMELEMENT = "fromElement"; //$NON-NLS-1$
static final String PROPERTY_KEYCODE = "keyCode"; //$NON-NLS-1$
static final String PROPERTY_REPEAT = "repeat"; //$NON-NLS-1$
static final String PROPERTY_RETURNVALUE = "returnValue"; //$NON-NLS-1$
static final String PROPERTY_SCREENX = "screenX"; //$NON-NLS-1$
static final String PROPERTY_SCREENY = "screenY"; //$NON-NLS-1$
static final String PROPERTY_SHIFTKEY = "shiftKey"; //$NON-NLS-1$
static final String PROPERTY_TOELEMENT = "toElement"; //$NON-NLS-1$
static final String PROPERTY_TYPE = "type"; //$NON-NLS-1$
static final String PROPERTY_WHEELDELTA = "wheelDelta"; //$NON-NLS-1$
static {
NativeClearSessions = new Runnable() {
public void run() {
if (OS.IsPPC) return;
OS.InternetSetOption (0, OS.INTERNET_OPTION_END_BROWSER_SESSION, 0, 0);
}
};
NativeGetCookie = new Runnable () {
public void run () {
if (OS.IsPPC) return;
TCHAR url = new TCHAR (0, CookieUrl, true);
TCHAR cookieData = new TCHAR (0, 8192);
int[] size = new int[] {cookieData.length ()};
if (!OS.InternetGetCookie (url, null, cookieData, size)) {
/* original cookieData size was not large enough */
size[0] /= TCHAR.sizeof;
cookieData = new TCHAR (0, size[0]);
if (!OS.InternetGetCookie (url, null, cookieData, size)) return;
}
String allCookies = cookieData.toString (0, size[0]);
StringTokenizer tokenizer = new StringTokenizer (allCookies, ";"); //$NON-NLS-1$
while (tokenizer.hasMoreTokens ()) {
String cookie = tokenizer.nextToken ();
int index = cookie.indexOf ('=');
if (index != -1) {
String name = cookie.substring (0, index).trim ();
if (name.equals (CookieName)) {
CookieValue = cookie.substring (index + 1).trim ();
return;
}
}
}
}
};
NativeSetCookie = new Runnable () {
public void run () {
if (OS.IsPPC) return;
TCHAR url = new TCHAR (0, CookieUrl, true);
TCHAR value = new TCHAR (0, CookieValue, true);
CookieResult = OS.InternetSetCookie (url, null, value);
}
};
/*
* Registry entry HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Version indicates
* which version of IE is installed. Check this value in order to determine version-specific
* features that can be enabled.
*/
TCHAR key = new TCHAR (0, "Software\\Microsoft\\Internet Explorer", true); //$NON-NLS-1$
int /*long*/ [] phkResult = new int /*long*/ [1];
if (OS.RegOpenKeyEx (OS.HKEY_LOCAL_MACHINE, key, 0, OS.KEY_READ, phkResult) == 0) {
int [] lpcbData = new int [1];
TCHAR buffer = new TCHAR (0, "Version", true); //$NON-NLS-1$
int result = OS.RegQueryValueEx (phkResult [0], buffer, 0, null, (TCHAR) null, lpcbData);
if (result == 0) {
TCHAR lpData = new TCHAR (0, lpcbData [0] / TCHAR.sizeof);
result = OS.RegQueryValueEx (phkResult [0], buffer, 0, null, lpData, lpcbData);
if (result == 0) {
String versionString = lpData.toString (0, lpData.strlen ());
int index = versionString.indexOf ("."); //$NON-NLS-1$
if (index != -1) {
String majorString = versionString.substring (0, index);
try {
IEVersion = Integer.valueOf (majorString).intValue ();
} catch (NumberFormatException e) {
/* just continue, version-specific features will not be enabled */
}
}
}
}
OS.RegCloseKey (phkResult [0]);
}
/*
* Registry entry HKEY_CLASSES_ROOT\Shell.Explorer\CLSID indicates which version of
* Shell.Explorer to use by default. We usually want to use this value because it
* typically points at the newest one that is available. However it is possible for
* this registry entry to be changed by another application to point at some other
* Shell.Explorer version.
*
* The Browser depends on the Shell.Explorer version being at least Shell.Explorer.2.
* If it is detected in the registry to be Shell.Explorer.1 then change the progId that
* will be embedded to explicitly specify Shell.Explorer.2.
*/
key = new TCHAR (0, "Shell.Explorer\\CLSID", true); //$NON-NLS-1$
phkResult = new int /*long*/ [1];
if (OS.RegOpenKeyEx (OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult) == 0) {
int [] lpcbData = new int [1];
int result = OS.RegQueryValueEx (phkResult [0], null, 0, null, (TCHAR) null, lpcbData);
if (result == 0) {
TCHAR lpData = new TCHAR (0, lpcbData [0] / TCHAR.sizeof);
result = OS.RegQueryValueEx (phkResult [0], null, 0, null, lpData, lpcbData);
if (result == 0) {
String clsid = lpData.toString (0, lpData.strlen ());
if (clsid.equals (CLSID_SHELLEXPLORER1)) {
/* Shell.Explorer.1 is the default, ensure that Shell.Explorer.2 is available */
key = new TCHAR (0, "Shell.Explorer.2", true); //$NON-NLS-1$
int /*long*/ [] phkResult2 = new int /*long*/ [1];
if (OS.RegOpenKeyEx (OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult2) == 0) {
/* specify that Shell.Explorer.2 is to be used */
OS.RegCloseKey (phkResult2 [0]);
ProgId = "Shell.Explorer.2"; //$NON-NLS-1$
}
}
}
}
OS.RegCloseKey (phkResult [0]);
}
if (NativePendingCookies != null) {
SetPendingCookies (NativePendingCookies);
}
NativePendingCookies = null;
}
public void create(Composite parent, int style) {
this.style = style;
frame = new OleFrame(browser, SWT.NONE);
try {
site = new WebSite(frame, SWT.NONE, ProgId);
} catch (SWTException e) {
browser.dispose();
SWT.error(SWT.ERROR_NO_HANDLES);
}
if (!Initialized) {
Initialized = true;
int version = 0;
String versionProperty = System.getProperty(PROPERTY_IEVERSION);
if (versionProperty != null) {
if (versionProperty.equalsIgnoreCase(VALUE_DEFAULT)) {
version = -1;
} else {
try {
version = Integer.valueOf(versionProperty).intValue();
} catch (NumberFormatException e) {
/*
* An invalid value was specified for the IEVersion java property. Ignore it
* and continue with the usual steps for determining the version to specify.
*/
}
}
}
if (version == 0) {
if (IEVersion != 0) {
version = IEVersion * 1000;
} else {
version = DEFAULT_IE_VERSION;
}
}
if (version != -1) {
int /*long*/[] key = new int /*long*/[1];
final TCHAR subkey = new TCHAR(0, "Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", true); //$NON-NLS-1$
if (OS.RegCreateKeyEx(OS.HKEY_CURRENT_USER, subkey, 0, null, OS.REG_OPTION_VOLATILE, OS.KEY_WRITE | OS.KEY_QUERY_VALUE, 0, key, null) == 0) {
TCHAR lpszFile = new TCHAR(0, OS.MAX_PATH);
OS.GetModuleFileName(0, lpszFile, lpszFile.length());
String path = lpszFile.toString(0, lpszFile.strlen());
int index = path.lastIndexOf(SEPARATOR_OS);
String executable = index != -1 ? path.substring(index + 1) : path;
final TCHAR lpValueName = new TCHAR(0, executable, true);
if (OS.RegQueryValueEx(key[0], lpValueName, 0, null, (int[])null, null) == OS.ERROR_FILE_NOT_FOUND) {
if (OS.RegSetValueEx(key[0], lpValueName, 0, OS.REG_DWORD, new int[] {version}, 4) == 0) {
parent.getDisplay().addListener(SWT.Dispose, new Listener() {
public void handleEvent(Event event) {
int /*long*/[] key = new int /*long*/[1];
if (OS.RegOpenKeyEx(OS.HKEY_CURRENT_USER, subkey, 0, OS.KEY_WRITE, key) == 0) {
OS.RegDeleteValue(key[0], lpValueName);
}
}
});
}
}
OS.RegCloseKey(key[0]);
}
}
}
site.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
auto = new OleAutomation(site);
domListener = new OleListener() {
public void handleEvent (OleEvent e) {
handleDOMEvent(e);
}
};
Listener listener = new Listener() {
public void handleEvent(Event e) {
switch (e.type) {
case SWT.Dispose: {
/* make this handler run after other dispose listeners */
if (ignoreDispose) {
ignoreDispose = false;
break;
}
ignoreDispose = true;
browser.notifyListeners (e.type, e);
e.type = SWT.NONE;
/* invoke onbeforeunload handlers */
if (!browser.isClosing) {
LocationListener[] oldLocationListeners = locationListeners;
locationListeners = new LocationListener[0];
site.ignoreAllMessages = true;
execute ("window.location.href='about:blank'"); //$NON-NLS-1$
site.ignoreAllMessages = false;
locationListeners = oldLocationListeners;
}
/*
* It is possible for the Browser's OLE frame to have been disposed
* by a Dispose listener that was invoked by notifyListeners above,
* so check for this before unhooking its DOM listeners.
*/
if (!frame.isDisposed ()) unhookDOMListeners(documents);
for (int i = 0; i < documents.length; i++) {
documents[i].dispose();
}
documents = null;
Enumeration elements = functions.elements ();
while (elements.hasMoreElements ()) {
((BrowserFunction)elements.nextElement ()).dispose (false);
}
functions = null;
lastNavigateURL = uncRedirect = null;
domListener = null;
if (auto != null) auto.dispose();
auto = null;
break;
}
case SWT.Resize: {
frame.setBounds(browser.getClientArea());
break;
}
case SWT.MouseWheel: {
/* MouseWheel events come from the DOM */
e.doit = false;
break;
}
case SWT.FocusIn: {
site.setFocus();
break;
}
case SWT.Traverse: {
/*
* Tabbing out of the browser can fail as a result of the WebSite
* control embedded within the Browser. The workaround is to
* listen for traversals and re-perform the traversal on the
* appropriate control.
*/
if (e.detail == SWT.TRAVERSE_TAB_PREVIOUS && e.widget instanceof WebSite) {
/* otherwise will traverse to the Browser control */
browser.traverse(SWT.TRAVERSE_TAB_PREVIOUS, e);
e.doit = false;
}
/*
* Return traversals can sometimes come through TranslateAccelerator,
* depending on where focus is within the Browser. Traversal
* events should always be triggered by a key event from the DOM,
* so if a Traversal from TranslateAccelerator is detected
* (e.doit == true) then stop its propagation.
*/
if (e.detail == SWT.TRAVERSE_RETURN && e.doit && e.widget instanceof Browser) {
e.type = SWT.None;
e.doit = false;
}
break;
}
}
}
};
browser.addListener(SWT.Dispose, listener);
browser.addListener(SWT.FocusIn, listener);
browser.addListener(SWT.Resize, listener);
browser.addListener(SWT.Traverse, listener);
site.addListener(SWT.MouseWheel, listener);
site.addListener(SWT.Traverse, listener);
OleListener oleListener = new OleListener() {
public void handleEvent(OleEvent event) {
/* callbacks are asynchronous, auto could be disposed */
if (auto != null) {
switch (event.type) {
case BeforeNavigate2: {
isRefresh = false; /* refreshes do not come through here */
/* don't send client events if the initial navigate to about:blank has not completed */
if (performingInitialNavigate) break;
Variant varResult = event.arguments[1];
String url = varResult.getString();
if (uncRedirect != null) {
/*
* Silently allow the navigate to proceed if the url is the first segment of a
* UNC path being navigated to (initiated by the NavigateError listener to show
* a name/password prompter), or if the url is the full UNC path (initiated by
* the NavigateComplete listener to redirect from the UNC's first segment to its
* full path).
*/
if (uncRedirect.equals(url) || (uncRedirect.startsWith(url) && uncRedirect.indexOf('\\', 2) == url.length())) {
Variant cancel = event.arguments[6];
if (cancel != null) {
int /*long*/ pCancel = cancel.getByRef();
COM.MoveMemory(pCancel, new short[] {COM.VARIANT_FALSE}, 2);
}
isAboutBlank = false;
break;
} else {
/*
* This navigate does not correspond to the previously-initiated
* UNC navigation so clear this state since it's no longer valid.
*/
uncRedirect = null;
}
}
/*
* Feature in IE. For navigations on the local machine, BeforeNavigate2's url
* field contains a string representation of the file path in a non-URL format.
* In order to be consistent with the other Browser implementations, this
* case is detected and the string is changed to be a proper url string.
*/
if (url.indexOf(":/") == -1 && url.indexOf(":\\") != -1) { //$NON-NLS-1$ //$NON-NLS-2$
TCHAR filePath = new TCHAR(0, url, true);
TCHAR urlResult = new TCHAR(0, OS.INTERNET_MAX_URL_LENGTH);
int[] size = new int[] {urlResult.length()};
if (!OS.IsWinCE && OS.UrlCreateFromPath(filePath, urlResult, size, 0) == COM.S_OK) {
url = urlResult.toString(0, size[0]);
} else {
url = PROTOCOL_FILE + url.replace('\\', '/');
}
}
/* Disallow local file system accesses if the browser content is untrusted */
if (url.startsWith(PROTOCOL_FILE) && _getUrl().startsWith(ABOUT_BLANK) && untrustedText) {
Variant cancel = event.arguments[6];
if (cancel != null) {
int /*long*/ pCancel = cancel.getByRef();
COM.MoveMemory(pCancel, new short[] {COM.VARIANT_TRUE}, 2);
}
break;
}
LocationEvent newEvent = new LocationEvent(browser);
newEvent.display = browser.getDisplay();
newEvent.widget = browser;
newEvent.location = url;
newEvent.doit = true;
for (int i = 0; i < locationListeners.length; i++) {
locationListeners[i].changing(newEvent);
}
boolean doit = newEvent.doit && !browser.isDisposed();
Variant cancel = event.arguments[6];
if (cancel != null) {
int /*long*/ pCancel = cancel.getByRef();
COM.MoveMemory(pCancel, new short[] {doit ? COM.VARIANT_FALSE : COM.VARIANT_TRUE}, 2);
}
if (doit) {
varResult = event.arguments[0];
IDispatch dispatch = varResult.getDispatch();
Variant variant = new Variant(auto); /* does not need to be disposed */
IDispatch top = variant.getDispatch();
if (top.getAddress() == dispatch.getAddress()) {
isAboutBlank = url.startsWith(ABOUT_BLANK);
}
}
break;
}
case CommandStateChange: {
boolean enabled = false;
Variant varResult = event.arguments[0];
int command = varResult.getInt();
varResult = event.arguments[1];
enabled = varResult.getBoolean();
switch (command) {
case CSC_NAVIGATEBACK : back = enabled; break;
case CSC_NAVIGATEFORWARD : forward = enabled; break;
}
break;
}
case DocumentComplete: {
if (performingInitialNavigate) {
/* this event marks the completion of the initial navigate to about:blank */
performingInitialNavigate = false;
/* if browser content has been provided by the client then set it now */
if (pendingText != null) {
setText((String)pendingText[0], ((Boolean)pendingText[1]).booleanValue());
} else if (pendingUrl != null) {
setUrl((String)pendingUrl[0], (String)pendingUrl[1], (String[])pendingUrl[2]);
}
pendingText = pendingUrl = null;
break;
}
Variant varResult = event.arguments[0];
IDispatch dispatch = varResult.getDispatch();
varResult = event.arguments[1];
String url = varResult.getString();
/*
* Feature in IE. For navigations on the local machine, DocumentComplete's url
* field contains a string representation of the file path in a non-URL format.
* In order to be consistent with the other Browser implementations, this
* case is detected and the string is changed to be a proper url string.
*/
if (url.indexOf(":/") == -1 && url.indexOf(":\\") != -1) { //$NON-NLS-1$ //$NON-NLS-2$
TCHAR filePath = new TCHAR(0, url, true);
TCHAR urlResult = new TCHAR(0, OS.INTERNET_MAX_URL_LENGTH);
int[] size = new int[] {urlResult.length()};
if (!OS.IsWinCE && OS.UrlCreateFromPath(filePath, urlResult, size, 0) == COM.S_OK) {
url = urlResult.toString(0, size[0]);
} else {
url = PROTOCOL_FILE + url.replace('\\', '/');
}
}
if (html != null && url.equals(ABOUT_BLANK)) {
if (delaySetText) {
delaySetText = false;
browser.getDisplay().asyncExec(new Runnable() {
public void run() {
if (browser.isDisposed() || html == null) return;
setHTML(html);
html = null;
}
});
} else {
setHTML(html);
html = null;
}
} else {
Variant variant = new Variant(auto); /* does not need to be disposed */
IDispatch top = variant.getDispatch();
LocationEvent locationEvent = new LocationEvent(browser);
locationEvent.display = browser.getDisplay();
locationEvent.widget = browser;
locationEvent.location = url;
locationEvent.top = top.getAddress() == dispatch.getAddress();
for (int i = 0; i < locationListeners.length; i++) {
locationListeners[i].changed(locationEvent);
}
if (browser.isDisposed()) return;
/*
* Note. The completion of the page loading is detected as
* described in the MSDN article "Determine when a page is
* done loading in WebBrowser Control".
*/
if (globalDispatch != 0 && dispatch.getAddress() == globalDispatch) {
/* final document complete */
globalDispatch = 0;
/* re-install registered functions iff needed */
IE ie = (IE)browser.webBrowser;
if (ie.installFunctionsOnDocumentComplete) {
ie.installFunctionsOnDocumentComplete = false;
Enumeration elements = functions.elements ();
while (elements.hasMoreElements ()) {
BrowserFunction function = (BrowserFunction)elements.nextElement ();
execute (function.functionString);
}
}
ProgressEvent progressEvent = new ProgressEvent(browser);
progressEvent.display = browser.getDisplay();
progressEvent.widget = browser;
for (int i = 0; i < progressListeners.length; i++) {
progressListeners[i].completed(progressEvent);
}
}
}
break;
}
case DownloadComplete: {
/*
* IE feature. Some events that swt relies on are not sent when
* a page is refreshed (as opposed to being navigated to). The
* workaround is to use DownloadComplete as an opportunity to
* do this work.
*/
Enumeration elements = functions.elements ();
while (elements.hasMoreElements ()) {
BrowserFunction function = (BrowserFunction)elements.nextElement ();
execute (function.functionString);
}
if (!isRefresh) break;
isRefresh = false;
/*
* DocumentComplete is not received for refreshes, but clients may rely
* on this event for tasks like hooking javascript listeners, so send the
* event here.
*/
ProgressEvent progressEvent = new ProgressEvent(browser);
progressEvent.display = browser.getDisplay();
progressEvent.widget = browser;
for (int i = 0; i < progressListeners.length; i++) {
progressListeners[i].completed(progressEvent);
}
break;
}
case NavigateComplete2: {
jsEnabled = jsEnabledOnNextPage;
Variant varResult = event.arguments[1];
String url = varResult.getString();
if (!performingInitialNavigate) {
varResult = event.arguments[0];
IDispatch dispatch = varResult.getDispatch();
Variant variant = new Variant(auto); /* does not need to be disposed */
IDispatch top = variant.getDispatch();
if (top.getAddress() == dispatch.getAddress()) {
isAboutBlank = url.startsWith(ABOUT_BLANK);
lastNavigateURL = url;
}
}
/*
* Bug in Acrobat Reader. Opening > MAX_PDF PDF files causes Acrobat to not
* clean up its shells properly when the container Browser is disposed.
* This results in Eclipse crashing at shutdown time because the leftover
* shells have invalid references to unloaded Acrobat libraries. The
* workaround is to not unload the Acrobat libraries if > MAX_PDF PDF
* files have been opened.
*/
boolean isPDF = false;
String path = null;
try {
path = new URL(url).getPath();
} catch (MalformedURLException e) {
}
if (path != null) {
int extensionIndex = path.lastIndexOf('.');
if (extensionIndex != -1) {
String extension = path.substring(extensionIndex);
if (extension.equalsIgnoreCase(EXTENSION_PDF)) {
isPDF = true;
PDFCount++;
if (PDFCount > MAX_PDF) {
COM.FreeUnusedLibraries = false;
}
}
}
}
if (uncRedirect != null) {
if (uncRedirect.equals(url)) {
/* full UNC path has been successfully navigated */
uncRedirect = null;
break;
}
if (uncRedirect.startsWith(url)) {
/*
* UNC first segment has been successfully navigated,
* now redirect to the full UNC path.
*/
navigate(uncRedirect, null, null, true);
break;
}
uncRedirect = null;
}
varResult = event.arguments[0];
IDispatch dispatch = varResult.getDispatch();
if (globalDispatch == 0) globalDispatch = dispatch.getAddress();
OleAutomation webBrowser = varResult.getAutomation();
Variant variant = new Variant(auto); /* does not need to be disposed */
IDispatch top = variant.getDispatch();
boolean isTop = top.getAddress() == dispatch.getAddress();
if (isTop) {
/* unhook DOM listeners and unref the last document(s) */
unhookDOMListeners(documents);
for (int i = 0; i < documents.length; i++) {
documents[i].dispose();
}
documents = new OleAutomation[0];
/* re-install registered functions */
Enumeration elements = functions.elements ();
while (elements.hasMoreElements ()) {
BrowserFunction function = (BrowserFunction)elements.nextElement ();
execute (function.functionString);
}
}
if (!isPDF) {
hookDOMListeners(webBrowser, isTop);
}
webBrowser.dispose();
break;
}
case NavigateError: {
if (uncRedirect != null) {
/*
* This is the second error attempting to reach this UNC path, so
* it does not exist. Don't override the default error handling.
*/
uncRedirect = null;
break;
}
Variant varResult = event.arguments[1];
final String url = varResult.getString();
if (url.startsWith("\\\\")) { //$NON-NLS-1$
varResult = event.arguments[3];
int statusCode = varResult.getInt();
if (statusCode == INET_E_RESOURCE_NOT_FOUND) {
int index = url.indexOf('\\', 2);
if (index != -1) {
final String host = url.substring(0, index);
Variant cancel = event.arguments[4];
if (cancel != null) {
int /*long*/ pCancel = cancel.getByRef();
COM.MoveMemory(pCancel, new short[] {COM.VARIANT_TRUE}, 2);
}
browser.getDisplay().asyncExec(new Runnable() {
public void run() {
if (browser.isDisposed()) return;
/*
* Feature of IE. When a UNC path ends with a '\' character IE
* drops this character when providing the path as an argument
* to some IE listeners. Remove this character here too in
* order to match these other listener argument values.
*/
if (url.endsWith("\\")) { //$NON-NLS-1$
uncRedirect = url.substring(0, url.length() - 1);
} else {
uncRedirect = url;
}
navigate(host, null, null, true);
}
});
}
}
}
break;
}
case NewWindow2: {
Variant cancel = event.arguments[1];
int /*long*/ pCancel = cancel.getByRef();
WindowEvent newEvent = new WindowEvent(browser);
newEvent.display = browser.getDisplay();
newEvent.widget = browser;
newEvent.required = false;
for (int i = 0; i < openWindowListeners.length; i++) {
openWindowListeners[i].open(newEvent);
}
IE browser = null;
if (newEvent.browser != null && newEvent.browser.webBrowser instanceof IE) {
browser = (IE)newEvent.browser.webBrowser;
}
boolean doit = browser != null && !browser.browser.isDisposed();
if (doit) {
/*
* When a Browser is opened in a new window, BrowserFunctions that are
* installed in it in the NavigateComplete2 callback are not retained
* through the loading of the page. The workaround is to re-install
* the functions when DocumentComplete is received.
*/
browser.installFunctionsOnDocumentComplete = true;
Variant variant = new Variant(browser.auto); /* does not need to be disposed */
IDispatch iDispatch = variant.getDispatch();
Variant ppDisp = event.arguments[0];
int /*long*/ byref = ppDisp.getByRef();
if (byref != 0) COM.MoveMemory(byref, new int /*long*/[] {iDispatch.getAddress()}, OS.PTR_SIZEOF);
}
if (newEvent.required) {
COM.MoveMemory(pCancel, new short[]{doit ? COM.VARIANT_FALSE : COM.VARIANT_TRUE}, 2);
}
break;
}
case OnMenuBar: {
Variant arg0 = event.arguments[0];
menuBar = arg0.getBoolean();
break;
}
case OnStatusBar: {
Variant arg0 = event.arguments[0];
statusBar = arg0.getBoolean();
break;
}
case OnToolBar: {
Variant arg0 = event.arguments[0];
toolBar = arg0.getBoolean();
/*
* Feature in Internet Explorer. OnToolBar FALSE is emitted
* when both tool bar, address bar and menu bar must not be visible.
* OnToolBar TRUE is emitted when either of tool bar, address bar
* or menu bar is visible.
*/
if (!toolBar) {
addressBar = false;
menuBar = false;
}
break;
}
case OnVisible: {
Variant arg1 = event.arguments[0];
boolean visible = arg1.getBoolean();
WindowEvent newEvent = new WindowEvent(browser);
newEvent.display = browser.getDisplay();
newEvent.widget = browser;
if (visible) {
if (addressBar) {
/*
* Bug in Internet Explorer. There is no distinct notification for
* the address bar. If neither address, menu or tool bars are visible,
* OnToolBar FALSE is emitted. For some reason, querying the value of
* AddressBar in this case returns true even though it should not be
* set visible. The workaround is to only query the value of AddressBar
* when OnToolBar FALSE has not been emitted.
*/
int[] rgdispid = auto.getIDsOfNames(new String[] { "AddressBar" }); //$NON-NLS-1$
Variant pVarResult = auto.getProperty(rgdispid[0]);
if (pVarResult != null) {
if (pVarResult.getType () == OLE.VT_BOOL) {
addressBar = pVarResult.getBoolean ();
}
pVarResult.dispose ();
}
}
newEvent.addressBar = addressBar;
newEvent.menuBar = menuBar;
newEvent.statusBar = statusBar;
newEvent.toolBar = toolBar;
newEvent.location = location;
newEvent.size = size;
for (int i = 0; i < visibilityWindowListeners.length; i++) {
visibilityWindowListeners[i].show(newEvent);
}
location = null;
size = null;
} else {
for (int i = 0; i < visibilityWindowListeners.length; i++) {
visibilityWindowListeners[i].hide(newEvent);
}
}
break;
}
case ProgressChange: {
/* don't send client events if the initial navigate to about:blank has not completed */
if (performingInitialNavigate) break;
Variant arg1 = event.arguments[0];
int nProgress = arg1.getType() != OLE.VT_I4 ? 0 : arg1.getInt(); // may be -1
Variant arg2 = event.arguments[1];
int nProgressMax = arg2.getType() != OLE.VT_I4 ? 0 : arg2.getInt();
ProgressEvent newEvent = new ProgressEvent(browser);
newEvent.display = browser.getDisplay();
newEvent.widget = browser;
newEvent.current = nProgress;
newEvent.total = nProgressMax;
if (nProgress != -1) {
for (int i = 0; i < progressListeners.length; i++) {
progressListeners[i].changed(newEvent);
}
}
break;
}
case StatusTextChange: {
/* don't send client events if the initial navigate to about:blank has not completed */
if (performingInitialNavigate) break;
Variant arg1 = event.arguments[0];
if (arg1.getType() == OLE.VT_BSTR) {
String text = arg1.getString();
StatusTextEvent newEvent = new StatusTextEvent(browser);
newEvent.display = browser.getDisplay();
newEvent.widget = browser;
newEvent.text = text;
for (int i = 0; i < statusTextListeners.length; i++) {
statusTextListeners[i].changed(newEvent);
}
}
break;
}
case TitleChange: {
/* don't send client events if the initial navigate to about:blank has not completed */
if (performingInitialNavigate) break;
Variant arg1 = event.arguments[0];
if (arg1.getType() == OLE.VT_BSTR) {
String title = arg1.getString();
TitleEvent newEvent = new TitleEvent(browser);
newEvent.display = browser.getDisplay();
newEvent.widget = browser;
newEvent.title = title;
for (int i = 0; i < titleListeners.length; i++) {
titleListeners[i].changed(newEvent);
}
}
break;
}
case WindowClosing: {
/*
* Disposing the Browser directly from this callback will crash if the
* Browser has a text field with an active caret. As a workaround fire
* the Close event and dispose the Browser in an async block.
*/
browser.getDisplay().asyncExec(new Runnable() {
public void run() {
if (browser.isDisposed()) return;
WindowEvent newEvent = new WindowEvent(browser);
newEvent.display = browser.getDisplay();
newEvent.widget = browser;
for (int i = 0; i < closeWindowListeners.length; i++) {
closeWindowListeners[i].close(newEvent);
}
browser.dispose();
}
});
Variant cancel = event.arguments[1];
int /*long*/ pCancel = cancel.getByRef();
Variant arg1 = event.arguments[0];
boolean isChildWindow = arg1.getBoolean();
COM.MoveMemory(pCancel, new short[]{isChildWindow ? COM.VARIANT_FALSE : COM.VARIANT_TRUE}, 2);
break;
}
case WindowSetHeight: {
if (size == null) size = new Point(0, 0);
Variant arg1 = event.arguments[0];
size.y = arg1.getInt();
break;
}
case WindowSetLeft: {
if (location == null) location = new Point(0, 0);
Variant arg1 = event.arguments[0];
location.x = arg1.getInt();
break;
}
case WindowSetTop: {
if (location == null) location = new Point(0, 0);
Variant arg1 = event.arguments[0];
location.y = arg1.getInt();
break;
}
case WindowSetWidth: {
if (size == null) size = new Point(0, 0);
Variant arg1 = event.arguments[0];
size.x = arg1.getInt();
break;
}
}
}
}
};
site.addEventListener(BeforeNavigate2, oleListener);
site.addEventListener(CommandStateChange, oleListener);
site.addEventListener(DocumentComplete, oleListener);
site.addEventListener(DownloadComplete, oleListener);
site.addEventListener(NavigateComplete2, oleListener);
site.addEventListener(NavigateError, oleListener);
site.addEventListener(NewWindow2, oleListener);
site.addEventListener(OnMenuBar, oleListener);
site.addEventListener(OnStatusBar, oleListener);
site.addEventListener(OnToolBar, oleListener);
site.addEventListener(OnVisible, oleListener);
site.addEventListener(ProgressChange, oleListener);
site.addEventListener(StatusTextChange, oleListener);
site.addEventListener(TitleChange, oleListener);
site.addEventListener(WindowClosing, oleListener);
site.addEventListener(WindowSetHeight, oleListener);
site.addEventListener(WindowSetLeft, oleListener);
site.addEventListener(WindowSetTop, oleListener);
site.addEventListener(WindowSetWidth, oleListener);
Variant variant = new Variant(true);
auto.setProperty(RegisterAsBrowser, variant);
variant.dispose();
variant = new Variant(false);
int[] rgdispid = auto.getIDsOfNames(new String[] {"RegisterAsDropTarget"}); //$NON-NLS-1$
if (rgdispid != null) auto.setProperty(rgdispid[0], variant);
variant.dispose();
}
public boolean back() {
if (!back) return false;
int[] rgdispid = auto.getIDsOfNames(new String[] { "GoBack" }); //$NON-NLS-1$
Variant pVarResult = auto.invoke(rgdispid[0]);
return pVarResult != null && pVarResult.getType() == OLE.VT_EMPTY;
}
public boolean close() {
boolean result = true;
int[] rgdispid = auto.getIDsOfNames(new String[] {PROPERTY_DOCUMENT});
int dispIdMember = rgdispid[0];
Variant pVarResult = auto.getProperty(dispIdMember);
if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
if (pVarResult != null) pVarResult.dispose();
} else {
OleAutomation document = pVarResult.getAutomation();
pVarResult.dispose();
rgdispid = document.getIDsOfNames(new String[]{"parentWindow"}); //$NON-NLS-1$
/* rgdispid != null implies HTML content */
if (rgdispid != null) {
dispIdMember = rgdispid[0];
pVarResult = document.getProperty(dispIdMember);
if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
if (pVarResult != null) pVarResult.dispose();
} else {
OleAutomation window = pVarResult.getAutomation();
pVarResult.dispose();
rgdispid = window.getIDsOfNames(new String[]{"location"}); //$NON-NLS-1$
dispIdMember = rgdispid[0];
pVarResult = window.getProperty(dispIdMember);
if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
if (pVarResult != null) pVarResult.dispose();
} else {
OleAutomation location = pVarResult.getAutomation();
pVarResult.dispose();
LocationListener[] oldListeners = locationListeners;
locationListeners = new LocationListener[0];
rgdispid = location.getIDsOfNames(new String[]{"replace"}); //$NON-NLS-1$
dispIdMember = rgdispid[0];
Variant[] args = new Variant[] {new Variant("about:blank")}; //$NON-NLS-1$
pVarResult = location.invoke(dispIdMember, args);
if (pVarResult == null) {
/* cancelled by user */
result = false;
} else {
pVarResult.dispose();
}
args[0].dispose();
locationListeners = oldListeners;
location.dispose();
}
window.dispose();
}
}
document.dispose();
}
return result;
}
static Variant createSafeArray(String string) {
/* Create a pointer and copy the data into it */
byte[] bytes = string.getBytes();
int length = bytes.length;
int /*long*/ pvData = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, length);
C.memmove(pvData, bytes, length);
int cElements1 = length;
/* Create a SAFEARRAY in memory */
int /*long*/ pSafeArray = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, SAFEARRAY.sizeof);
SAFEARRAY safeArray = new SAFEARRAY();
safeArray.cDims = 1;
safeArray.fFeatures = OS.FADF_FIXEDSIZE;
safeArray.cbElements = 1;
safeArray.pvData = pvData;
SAFEARRAYBOUND safeArrayBound = new SAFEARRAYBOUND();
safeArray.rgsabound = safeArrayBound;
safeArrayBound.cElements = cElements1;
OS.MoveMemory (pSafeArray, safeArray, SAFEARRAY.sizeof);
/* Return a Variant that holds the SAFEARRAY */
int /*long*/ pVariant = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, Variant.sizeof);
short vt = (short)(OLE.VT_ARRAY | OLE.VT_UI1);
OS.MoveMemory(pVariant, new short[] {vt}, 2);
OS.MoveMemory(pVariant + 8, new int /*long*/[] {pSafeArray}, C.PTR_SIZEOF);
return new Variant(pVariant, (short)(OLE.VT_BYREF | OLE.VT_VARIANT));
}
public boolean execute(String script) {
/* get IHTMLDocument2 */
int[] rgdispid = auto.getIDsOfNames(new String[] {PROPERTY_DOCUMENT});
int dispIdMember = rgdispid[0];
Variant pVarResult = auto.getProperty(dispIdMember);
if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
if (pVarResult != null) pVarResult.dispose ();
return false;
}
OleAutomation document = pVarResult.getAutomation();
pVarResult.dispose();
/* get IHTMLWindow2 */
rgdispid = document.getIDsOfNames(new String[]{"parentWindow"}); //$NON-NLS-1$
if (rgdispid == null) {
/* implies that browser's content is not a IHTMLDocument2 (eg.- acrobat reader) */
document.dispose();
return false;
}
dispIdMember = rgdispid[0];
pVarResult = document.getProperty(dispIdMember);
OleAutomation ihtmlWindow2 = pVarResult.getAutomation();
pVarResult.dispose();
document.dispose();
rgdispid = ihtmlWindow2.getIDsOfNames(new String[] { "execScript", "code" }); //$NON-NLS-1$ //$NON-NLS-2$
Variant[] rgvarg = new Variant[1];
rgvarg[0] = new Variant(script);
int[] rgdispidNamedArgs = new int[1];
rgdispidNamedArgs[0] = rgdispid[1];
pVarResult = ihtmlWindow2.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
rgvarg[0].dispose();
ihtmlWindow2.dispose();
if (pVarResult == null) return false;
pVarResult.dispose();
return true;
}
public boolean forward() {
if (!forward) return false;
int[] rgdispid = auto.getIDsOfNames(new String[] { "GoForward" }); //$NON-NLS-1$
Variant pVarResult = auto.invoke(rgdispid[0]);
return pVarResult != null && pVarResult.getType() == OLE.VT_EMPTY;
}
public String getBrowserType () {
return "ie"; //$NON-NLS-1$
}
String getDeleteFunctionString (String functionName) {
return "window." + functionName + "=undefined"; //$NON-NLS-1$ //$NON-NLS-2$
}
public String getText() {
/* get the document object */
int[] rgdispid = auto.getIDsOfNames(new String[] {PROPERTY_DOCUMENT});
Variant pVarResult = auto.getProperty(rgdispid[0]);
if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
if (pVarResult != null) pVarResult.dispose ();
return ""; //$NON-NLS-1$
}
OleAutomation document = pVarResult.getAutomation();
pVarResult.dispose();
/* get the html object */
rgdispid = document.getIDsOfNames(new String[] {"documentElement"}); //$NON-NLS-1$
if (rgdispid == null) {
/* implies that the browser is displaying non-HTML content */
document.dispose();
return ""; //$NON-NLS-1$
}
pVarResult = document.getProperty(rgdispid[0]);
document.dispose();
if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
if (pVarResult != null) pVarResult.dispose ();
return ""; //$NON-NLS-1$
}
OleAutomation element = pVarResult.getAutomation();
pVarResult.dispose();
/* get its outerHTML property */
rgdispid = element.getIDsOfNames(new String[] {"outerHTML"}); //$NON-NLS-1$
pVarResult = element.getProperty(rgdispid[0]);
element.dispose();
if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
if (pVarResult != null) pVarResult.dispose ();
return ""; //$NON-NLS-1$
}
String result = pVarResult.getString();
pVarResult.dispose();
return result;
}
public String getUrl() {
/*
* If the url is "" then return ABOUT_BLANK in order to be consistent
* with the other Browser implementations which auto-navigate to ABOUT_BLANK
* when opened.
*/
String result = _getUrl();
return result.length() != 0 ? result : ABOUT_BLANK;
}
String _getUrl() {
int[] rgdispid = auto.getIDsOfNames(new String[] { "LocationURL" }); //$NON-NLS-1$
Variant pVarResult = auto.getProperty(rgdispid[0]);
if (pVarResult == null || pVarResult.getType() != OLE.VT_BSTR) return ""; //$NON-NLS-1$
String result = pVarResult.getString();
pVarResult.dispose();
return result;
}
public boolean isBackEnabled() {
return back;
}
public boolean isForwardEnabled() {
return forward;
}
public boolean isFocusControl () {
return site.isFocusControl() || frame.isFocusControl();
}
boolean navigate(String url, String postData, String headers[], boolean silent) {
int count = 1;
if (postData != null) count++;
if (headers != null) count++;
Variant[] rgvarg = new Variant[count];
int[] rgdispidNamedArgs = new int[count];
int[] rgdispid = auto.getIDsOfNames(new String[] { "Navigate", "URL", "PostData", "Headers" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
int index = 0;
rgvarg[index] = new Variant(url);
rgdispidNamedArgs[index++] = rgdispid[1];
if (postData != null) {
rgvarg[index] = createSafeArray(postData);
rgdispidNamedArgs[index++] = rgdispid[2];
}
if (headers != null) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < headers.length; i++) {
String current = headers[i];
if (current != null) {
int sep = current.indexOf(':');
if (sep != -1) {
String key = current.substring(0, sep).trim();
String value = current.substring(sep + 1).trim();
if (key.length() > 0 && value.length() > 0) {
buffer.append(key);
buffer.append(':');
buffer.append(value);
buffer.append("\r\n");
}
}
}
}
rgvarg[index] = new Variant(buffer.toString());
rgdispidNamedArgs[index++] = rgdispid[3];
}
boolean oldValue = false;
if (silent && !OS.IsWinCE && IEVersion >= 7) {
int hResult = OS.CoInternetIsFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.GET_FEATURE_FROM_PROCESS);
oldValue = hResult == COM.S_OK;
OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);
}
Variant pVarResult = auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
if (silent && !OS.IsWinCE && IEVersion >= 7) {
OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, oldValue);
}
for (int i = 0; i < count; i++) {
rgvarg[i].dispose();
}
if (pVarResult == null) return false;
boolean result = pVarResult.getType() == OLE.VT_EMPTY;
pVarResult.dispose();
return result;
}
public void refresh() {
uncRedirect = null;
/*
* Bug in Acrobat Reader. Opening > MAX_PDF PDF files causes Acrobat to not
* clean up its shells properly when the container Browser is disposed.
* This results in Eclipse crashing at shutdown time because the leftover
* shells have invalid references to unloaded Acrobat libraries. The
* workaround is to not unload the Acrobat libraries if > MAX_PDF PDF
* files have been opened.
*/
String url = _getUrl();
int extensionIndex = url.lastIndexOf('.');
if (extensionIndex != -1) {
String extension = url.substring(extensionIndex);
if (extension.equalsIgnoreCase (EXTENSION_PDF)) {
PDFCount++;
if (PDFCount > MAX_PDF) {
COM.FreeUnusedLibraries = false;
}
}
}
isRefresh = true;
int[] rgdispid = auto.getIDsOfNames(new String[] { "Refresh" }); //$NON-NLS-1$
auto.invoke(rgdispid[0]);
}
void setHTML (String string) {
int charCount = string.length();
char[] chars = new char[charCount];
string.getChars(0, charCount, chars, 0);
int byteCount = OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, charCount, null, 0, null, null);
/*
* Internet Explorer appears to treat the data loaded with
* nsIPersistStreamInit.Load as if it were encoded using the default
* local charset. There does not seem to be an API to set the
* desired charset explicitly in this case. The fix is to
* prepend the UTF-8 Byte Order Mark signature to the data.
*/
byte[] UTF8BOM = {(byte)0xEF, (byte)0xBB, (byte)0xBF};
int /*long*/ hGlobal = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, UTF8BOM.length + byteCount);
if (hGlobal != 0) {
OS.MoveMemory(hGlobal, UTF8BOM, UTF8BOM.length);
OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, charCount, hGlobal + UTF8BOM.length, byteCount, null, null);
int /*long*/ [] ppstm = new int /*long*/ [1];
/*
* CreateStreamOnHGlobal is called with the flag fDeleteOnRelease.
* If the call succeeds the buffer hGlobal is freed automatically
* when the IStream object is released. If the call fails, free the
* buffer hGlobal.
*/
if (OS.CreateStreamOnHGlobal(hGlobal, true, ppstm) == OS.S_OK) {
int[] rgdispid = auto.getIDsOfNames(new String[] {PROPERTY_DOCUMENT});
Variant pVarResult = auto.getProperty(rgdispid[0]);
IDispatch dispatchDocument = pVarResult.getDispatch();
int /*long*/ [] ppvObject = new int /*long*/ [1];
int result = dispatchDocument.QueryInterface(COM.IIDIPersistStreamInit, ppvObject);
if (result == OS.S_OK) {
IPersistStreamInit persistStreamInit = new IPersistStreamInit(ppvObject[0]);
if (persistStreamInit.InitNew() == OS.S_OK) {
persistStreamInit.Load(ppstm[0]);
}
persistStreamInit.Release();
}
pVarResult.dispose();
IUnknown stream = new IUnknown(ppstm[0]);
stream.Release();
} else {
OS.GlobalFree(hGlobal);
}
}
}
public boolean setText(final String html, boolean trusted) {
/*
* If the browser is navigating to about:blank in response to its first
* setUrl() invocation then delay setting this text content until the
* navigate has completed. about:blank will be re-navigated to in order
* to ensure that all expected client events are sent.
*/
if (performingInitialNavigate) {
pendingText = new Object[] {html, new Boolean (trusted)};
pendingUrl = null;
return true;
}
/*
* If the html field is non-null then the about:blank page is already being
* loaded from a previous setText() invocation, so no Stop or Navigate is
* required. Just set the html that is to be shown.
*/
boolean blankLoading = this.html != null;
this.html = html;
untrustedText = !trusted;
if (blankLoading) return true;
/*
* Navigate to the blank page and insert the given html when
* receiving the next DocumentComplete notification. See the
* MSDN article "Loading HTML content from a Stream".
*
* Note. Stop any pending request. This is required to avoid displaying a
* blank page as a result of consecutive calls to setUrl and/or setText.
* The previous request would otherwise render the new html content and
* reset the html field before the browser actually navigates to the blank
* page as requested below.
*
* Feature in Internet Explorer. Stopping pending requests when no request
* is pending causes a default page 'Action cancelled' to be displayed. The
* workaround is to not invoke 'stop' when no request has been set since
* that instance was created.
*/
/*
* Stopping the loading of a page causes DocumentComplete events from previous
* requests to be received before the DocumentComplete for this page. In such
* cases we must be sure to not set the html into the browser too soon, since
* doing so could result in its page being cleared out by a subsequent
* DocumentComplete. The Browser's ReadyState can be used to determine whether
* these extra events will be received or not.
*/
if (_getUrl().length() != 0) {
int[] rgdispid = auto.getIDsOfNames(new String[] { "ReadyState" }); //$NON-NLS-1$
Variant pVarResult = auto.getProperty(rgdispid[0]);
if (pVarResult == null) return false;
delaySetText = pVarResult.getInt() != READYSTATE_COMPLETE;
pVarResult.dispose();
rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
auto.invoke(rgdispid[0]);
}
int[] rgdispid = auto.getIDsOfNames(new String[] { "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
Variant[] rgvarg = new Variant[1];
rgvarg[0] = new Variant(ABOUT_BLANK);
int[] rgdispidNamedArgs = new int[1];
rgdispidNamedArgs[0] = rgdispid[1];
boolean oldValue = false;
if (!OS.IsWinCE && IEVersion >= 7) {
int hResult = OS.CoInternetIsFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.GET_FEATURE_FROM_PROCESS);
oldValue = hResult == COM.S_OK;
OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);
}
Variant pVarResult = auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
if (!OS.IsWinCE && IEVersion >= 7) {
OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, oldValue);
}
rgvarg[0].dispose();
if (pVarResult == null) return false;
boolean result = pVarResult.getType() == OLE.VT_EMPTY;
pVarResult.dispose();
return result;
}
public boolean setUrl(String url, String postData, String headers[]) {
html = uncRedirect = null;
/*
* If the browser has not shown any content yet then first navigate to
* about:blank to work around IE bug http://support.microsoft.com/kb/320153,
* then navigate to the requested url once about:blank has loaded.
*/
if (_getUrl().length() == 0 && !ABOUT_BLANK.equalsIgnoreCase(url)) {
pendingText = null;
pendingUrl = new Object[] {url, postData, headers};
performingInitialNavigate = true;
navigate (ABOUT_BLANK, null, null, true);
return true;
}
/*
* Bug in Internet Explorer. For some reason, Navigating to an xml document before
* a previous Navigate has completed will leave the Browser in a bad state if the
* Navigate to the xml document does not complete. This bad state causes a GP when
* the parent window is eventually disposed. The workaround is to issue a Stop before
* navigating to any xml document.
*/
if (url.endsWith(".xml")) { //$NON-NLS-1$
int[] rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
auto.invoke(rgdispid[0]);
}
return navigate(url, postData, headers, false);
}
public void stop() {
/*
* If the browser has not completed its initial navigate to about:blank
* then do not issue Stop here, as this will display the IE error page.
* Just clear the pending url and text fields so that any pending content
* will not be set into the browser when the about:blank navigate completes.
*/
if (performingInitialNavigate) {
pendingText = pendingUrl = null;
return;
}
/*
* Feature of IE. Invoking Stop in IE before any content has been shown
* displays a Navigation Cancelled error page. The workaround is to not
* invoke Stop if no content has been shown yet.
*/
if (_getUrl().length() == 0) return;
/*
* Ensure that isAboutBlank is set accurately since Stop can be issued at
* any stage in the page load cycle.
*/
isAboutBlank = getUrl().startsWith(ABOUT_BLANK);
uncRedirect = null;
int[] rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
auto.invoke(rgdispid[0]);
}
boolean translateMnemonics () {
return false;
}
void handleDOMEvent (OleEvent e) {
if (e.arguments == null || e.arguments.length == 0) return; /* for IE5 */
Variant arg = e.arguments[0];
OleAutomation event = arg.getAutomation();
int[] rgdispid = event.getIDsOfNames(new String[]{ PROPERTY_TYPE });
int dispIdMember = rgdispid[0];
Variant pVarResult = event.getProperty(dispIdMember);
String eventType = pVarResult.getString();
pVarResult.dispose();
if (eventType.equals(EVENT_KEYDOWN)) {
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_KEYCODE });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
lastKeyCode = translateKey (pVarResult.getInt());
pVarResult.dispose();
rgdispid = event.getIDsOfNames (new String[] {PROPERTY_RETURNVALUE});
pVarResult = event.getProperty (rgdispid[0]);
boolean consume = pVarResult != null && pVarResult.getType () == OLE.VT_BOOL && !pVarResult.getBoolean ();
pVarResult.dispose ();
MSG msg = new MSG ();
int flags = OS.PM_NOYIELD | (consume ? OS.PM_REMOVE : OS.PM_NOREMOVE);
if (OS.PeekMessage (msg, frame.handle, OS.WM_CHAR, OS.WM_CHAR, flags)) {
/* a keypress will be received for this key so don't send KeyDown here */
event.dispose();
return;
}
if (consume) {
/*
* an event should not be sent if another listener has vetoed the
* KeyDown (this is for non-character cases like arrow keys, etc.)
*/
event.dispose();
return;
}
/* if this is a repeating key then an event should not be fired for it */
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_REPEAT });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
boolean repeating = pVarResult.getBoolean();
pVarResult.dispose();
if (repeating) {
event.dispose();
return;
}
int mask = 0;
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_ALTKEY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
if (pVarResult.getBoolean()) mask |= SWT.ALT;
pVarResult.dispose();
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_CTRLKEY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
if (pVarResult.getBoolean()) mask |= SWT.CTRL;
pVarResult.dispose();
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SHIFTKEY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
pVarResult.dispose();
Event keyEvent = new Event ();
keyEvent.widget = browser;
keyEvent.type = SWT.KeyDown;
keyEvent.keyCode = lastKeyCode;
keyEvent.stateMask = mask;
keyEvent.stateMask &= ~lastKeyCode; /* remove current keydown if it's a state key */
/*
* keypress events are not received for Backspace, Enter, Delete and
* Tab, so KeyDown events are sent for them here. Set the KeyDown
* event's character field and IE's lastCharCode field for these keys
* so that the Browser's key events are consistent with other controls.
*/
switch (lastKeyCode) {
case SWT.BS: lastCharCode = keyEvent.character = SWT.BS; break;
case SWT.CR: lastCharCode = keyEvent.character = SWT.CR; break;
case SWT.DEL: lastCharCode = keyEvent.character = SWT.DEL; break;
case SWT.TAB: lastCharCode = keyEvent.character = SWT.TAB; break;
}
if (!sendKeyEvent(keyEvent)) {
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_RETURNVALUE });
dispIdMember = rgdispid[0];
Variant pVarFalse = new Variant(false);
event.setProperty(dispIdMember, pVarFalse);
pVarFalse.dispose();
}
/*
* Pressing F5 refreshes the current page. If this is about to happen
* then set isRefresh to true so that received IE events will be treated
* accordingly.
*/
if (lastKeyCode == SWT.F5) isRefresh = true;
event.dispose();
return;
}
if (eventType.equals(EVENT_KEYPRESS)) {
int mask = 0;
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_CTRLKEY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
if (pVarResult.getBoolean()) mask |= SWT.CTRL;
pVarResult.dispose();
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SHIFTKEY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
pVarResult.dispose();
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_ALTKEY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
if (pVarResult.getBoolean()) mask |= SWT.ALT;
pVarResult.dispose();
/* in the keypress event the keyCode actually corresponds to the character code */
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_KEYCODE });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
lastCharCode = pVarResult.getInt();
pVarResult.dispose();
/*
* WebSite.TranslateAccelerator() explicitly does not translate OS.VK_RETURN
* keys, so the PeekMessage check in the keydown handler always allows a
* KeyDown to be sent for this key. However, keydown and keypress events are
* both sometimes received for OS.VK_RETURN, depending on the page's focus
* control. To handle this, do not send a KeyDown for CR or LF here since
* one is always sent for it from the keydown handler.
*/
if (lastCharCode == SWT.CR || lastCharCode == SWT.LF) {
event.dispose();
return;
}
Event keyEvent = new Event ();
keyEvent.widget = browser;
keyEvent.type = SWT.KeyDown;
keyEvent.keyCode = lastKeyCode;
keyEvent.character = (char)lastCharCode;
keyEvent.stateMask = mask;
if (!sendKeyEvent(keyEvent)) {
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_RETURNVALUE });
dispIdMember = rgdispid[0];
Variant pVarFalse = new Variant(false);
event.setProperty(dispIdMember, pVarFalse);
pVarFalse.dispose();
}
event.dispose();
return;
}
if (eventType.equals(EVENT_KEYUP)) {
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_KEYCODE });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
int keyCode = translateKey (pVarResult.getInt());
pVarResult.dispose();
/*
* if a key code could not be determined for this key then it's a
* key for which key events are not sent (eg.- the Windows key)
*/
if (keyCode == 0) {
lastKeyCode = lastCharCode = 0;
event.dispose();
return;
}
if (keyCode != lastKeyCode) {
/* keyup does not correspond to the last keydown */
lastKeyCode = keyCode;
lastCharCode = 0;
}
int mask = 0;
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_CTRLKEY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
if (pVarResult.getBoolean()) mask |= SWT.CTRL;
pVarResult.dispose();
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_ALTKEY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
if (pVarResult.getBoolean()) mask |= SWT.ALT;
pVarResult.dispose();
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SHIFTKEY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
pVarResult.dispose();
Event keyEvent = new Event ();
keyEvent.widget = browser;
keyEvent.type = SWT.KeyUp;
keyEvent.keyCode = lastKeyCode;
keyEvent.character = (char)lastCharCode;
keyEvent.stateMask = mask;
switch (lastKeyCode) {
case SWT.SHIFT:
case SWT.CONTROL:
case SWT.ALT:
case SWT.COMMAND: {
keyEvent.stateMask |= lastKeyCode;
}
}
browser.notifyListeners (keyEvent.type, keyEvent);
if (!keyEvent.doit) {
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_RETURNVALUE });
dispIdMember = rgdispid[0];
Variant pVarFalse = new Variant(false);
event.setProperty(dispIdMember, pVarFalse);
pVarFalse.dispose();
}
lastKeyCode = lastCharCode = 0;
event.dispose();
return;
}
/*
* Feature in IE. MouseOver/MouseOut events are fired any time the mouse enters
* or exits any element within the Browser. To ensure that SWT events are only
* fired for mouse movements into or out of the Browser, do not fire an event if
* the element being exited (on MouseOver) or entered (on MouseExit) is within
* the Browser.
*/
if (eventType.equals(EVENT_MOUSEOVER)) {
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_FROMELEMENT });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
boolean isInternal = pVarResult.getType() != COM.VT_EMPTY;
pVarResult.dispose();
if (isInternal) {
event.dispose();
return;
}
}
if (eventType.equals(EVENT_MOUSEOUT)) {
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_TOELEMENT });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
boolean isInternal = pVarResult.getType() != COM.VT_EMPTY;
pVarResult.dispose();
if (isInternal) {
event.dispose();
return;
}
}
int mask = 0;
Event newEvent = new Event();
newEvent.widget = browser;
/*
* The position of mouse events is received in screen-relative coordinates
* in order to handle pages with frames, since frames express their event
* coordinates relative to themselves rather than relative to their top-
* level page. Convert screen-relative coordinates to be browser-relative.
*/
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SCREENX });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
int screenX = pVarResult.getInt();
pVarResult.dispose();
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SCREENY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
int screenY = pVarResult.getInt();
pVarResult.dispose();
Point position = new Point(screenX, screenY);
position = browser.getDisplay().map(null, browser, position);
newEvent.x = position.x; newEvent.y = position.y;
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_CTRLKEY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
if (pVarResult.getBoolean()) mask |= SWT.CTRL;
pVarResult.dispose();
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_ALTKEY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
if (pVarResult.getBoolean()) mask |= SWT.ALT;
pVarResult.dispose();
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SHIFTKEY });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
pVarResult.dispose();
newEvent.stateMask = mask;
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_BUTTON });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
int button = pVarResult.getInt();
pVarResult.dispose();
switch (button) {
case 1: button = 1; break;
case 2: button = 3; break;
case 4: button = 2; break;
}
if (eventType.equals(EVENT_MOUSEDOWN)) {
newEvent.type = SWT.MouseDown;
newEvent.button = button;
newEvent.count = 1;
} else if (eventType.equals(EVENT_MOUSEUP) || eventType.equals(EVENT_DRAGEND)) {
newEvent.type = SWT.MouseUp;
newEvent.button = button != 0 ? button : 1; /* button assumed to be 1 for dragends */
newEvent.count = 1;
switch (newEvent.button) {
case 1: newEvent.stateMask |= SWT.BUTTON1; break;
case 2: newEvent.stateMask |= SWT.BUTTON2; break;
case 3: newEvent.stateMask |= SWT.BUTTON3; break;
case 4: newEvent.stateMask |= SWT.BUTTON4; break;
case 5: newEvent.stateMask |= SWT.BUTTON5; break;
}
} else if (eventType.equals(EVENT_MOUSEWHEEL)) {
newEvent.type = SWT.MouseWheel;
rgdispid = event.getIDsOfNames(new String[] { PROPERTY_WHEELDELTA });
dispIdMember = rgdispid[0];
pVarResult = event.getProperty(dispIdMember);
newEvent.count = pVarResult.getInt () / 120 * 3;
pVarResult.dispose();
} else if (eventType.equals(EVENT_MOUSEMOVE)) {
/*
* Feature in IE. Spurious and redundant mousemove events are often received. The workaround
* is to not fire MouseMove events whose x and y values match the last MouseMove.
*/
if (newEvent.x == lastMouseMoveX && newEvent.y == lastMouseMoveY) {
event.dispose();
return;
}
newEvent.type = SWT.MouseMove;
lastMouseMoveX = newEvent.x; lastMouseMoveY = newEvent.y;
} else if (eventType.equals(EVENT_MOUSEOVER)) {
newEvent.type = SWT.MouseEnter;
} else if (eventType.equals(EVENT_MOUSEOUT)) {
newEvent.type = SWT.MouseExit;
} else if (eventType.equals(EVENT_DRAGSTART)) {
newEvent.type = SWT.DragDetect;
newEvent.button = 1; /* button assumed to be 1 for dragstarts */
newEvent.stateMask |= SWT.BUTTON1;
}
event.dispose();
browser.notifyListeners(newEvent.type, newEvent);
if (eventType.equals(EVENT_DOUBLECLICK)) {
newEvent = new Event ();
newEvent.widget = browser;
newEvent.type = SWT.MouseDoubleClick;
newEvent.x = position.x; newEvent.y = position.y;
newEvent.stateMask = mask;
newEvent.type = SWT.MouseDoubleClick;
newEvent.button = 1; /* dblclick only comes for button 1 and does not set the button property */
newEvent.count = 2;
browser.notifyListeners (newEvent.type, newEvent);
}
}
void hookDOMListeners(OleAutomation webBrowser, final boolean isTop) {
int[] rgdispid = webBrowser.getIDsOfNames(new String[] { PROPERTY_DOCUMENT });
int dispIdMember = rgdispid[0];
Variant pVarResult = webBrowser.getProperty(dispIdMember);
if (pVarResult == null) return;
if (pVarResult.getType() == COM.VT_EMPTY) {
pVarResult.dispose();
return;
}
final OleAutomation document = pVarResult.getAutomation();
pVarResult.dispose();
/*
* In some cases, such as setting the Browser's content from a string,
* NavigateComplete2 is received multiple times for a top-level document.
* For cases like this, any previously-hooked DOM listeners must be
* removed from the document before hooking the new set of listeners,
* otherwise multiple sets of events will be received.
*/
unhookDOMListeners (new OleAutomation[] {document});
site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN, domListener);
site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS, domListener);
site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYUP, domListener);
site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN, domListener);
site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP, domListener);
site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEWHEEL, domListener);
site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK, domListener);
site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE, domListener);
site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART, domListener);
site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGEND, domListener);
/* ensure that enter/exit are only fired once, by the top-level document */
if (isTop) {
site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER, domListener);
site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT, domListener);
}
OleAutomation[] newDocuments = new OleAutomation[documents.length + 1];
System.arraycopy(documents, 0, newDocuments, 0, documents.length);
newDocuments[documents.length] = document;
documents = newDocuments;
}
void unhookDOMListeners(OleAutomation[] documents) {
char[] buffer = (COM.IIDIHTMLDocumentEvents2 + '\0').toCharArray();
GUID guid = new GUID();
if (COM.IIDFromString(buffer, guid) == COM.S_OK) {
for (int i = 0; i < documents.length; i++) {
OleAutomation document = documents[i];
site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN, domListener);
site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS, domListener);
site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYUP, domListener);
site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN, domListener);
site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP, domListener);
site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEWHEEL, domListener);
site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK, domListener);
site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE, domListener);
site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART, domListener);
site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGEND, domListener);
site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER, domListener);
site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT, domListener);
}
}
}
}