blob: 53350d6552fa1ceaa5cc9339b6f5673553ad000d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2012 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.io.*;
import java.net.*;
import java.util.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.ole.win32.*;
import org.eclipse.swt.internal.webkit.*;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.widgets.*;
@SuppressWarnings("rawtypes")
class WebKit extends WebBrowser {
IWebView webView;
long /*int*/ webViewWindowHandle, webViewData;
int refCount = 0;
int lastKeyCode, lastCharCode;
WebDownloadDelegate webDownloadDelegate;
WebFrameLoadDelegate webFrameLoadDelegate;
WebPolicyDelegate webPolicyDelegate;
WebResourceLoadDelegate webResourceLoadDelegate;
WebUIDelegate webUIDelegate;
boolean ignoreDispose;
boolean loadingText = false;
boolean traverseNext = true;
boolean traverseOut = false;
boolean untrustedText;
String lastNavigateURL;
BrowserFunction eventFunction;
static int prefsIdentifier;
static long /*int*/ ExternalClass;
static boolean LibraryLoaded = false;
static String LibraryLoadError;
static Callback JSObjectHasPropertyProc;
static Callback JSObjectGetPropertyProc;
static Callback JSObjectCallAsFunctionProc;
static final int MAX_PROGRESS = 100;
static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
static final String CHARSET_UTF8 = "UTF-8"; //$NON-NLS-1$
static final String CLASSNAME_EXTERNAL = "External"; //$NON-NLS-1$
static final String EMPTY_STRING = ""; //$NON-NLS-1$
static final String FUNCTIONNAME_CALLJAVA = "callJava"; //$NON-NLS-1$
static final String HEADER_SETCOOKIE = "Set-Cookie"; //$NON-NLS-1$
static final String POST = "POST"; //$NON-NLS-1$
static final String PROPERTY_LENGTH = "length"; //$NON-NLS-1$
static final String PROTOCOL_HTTPS = "https://"; //$NON-NLS-1$
static final String PROTOCOL_FILE = "file://"; //$NON-NLS-1$
static final String PROTOCOL_HTTP = "http://"; //$NON-NLS-1$
static final String USER_AGENT = "user-agent"; //$NON-NLS-1$
static final String URI_FILEROOT = "file:///"; //$NON-NLS-1$
/* event strings */
static final String DOMEVENT_DRAGSTART = "dragstart"; //$NON-NLS-1$
static final String DOMEVENT_KEYDOWN = "keydown"; //$NON-NLS-1$
static final String DOMEVENT_KEYPRESS = "keypress"; //$NON-NLS-1$
static final String DOMEVENT_KEYUP = "keyup"; //$NON-NLS-1$
static final String DOMEVENT_MOUSEDOWN = "mousedown"; //$NON-NLS-1$
static final String DOMEVENT_MOUSEUP = "mouseup"; //$NON-NLS-1$
static final String DOMEVENT_MOUSEMOVE = "mousemove"; //$NON-NLS-1$
static final String DOMEVENT_MOUSEOUT = "mouseout"; //$NON-NLS-1$
static final String DOMEVENT_MOUSEOVER = "mouseover"; //$NON-NLS-1$
static final String DOMEVENT_MOUSEWHEEL = "mousewheel"; //$NON-NLS-1$
static {
/*
* Attempt to load the swt-webkit library. This will only succeed if the Apple
* Application Support package is on the user's Windows Path environment variable.
*/
try {
Library.loadLibrary ("swt-webkit"); // $NON-NLS-1$
LibraryLoaded = true;
} catch (Throwable e) {
}
/*
* If needed, add the Apple Application Support package's directory to the library
* lookup path and try to load the swt-webkit library again.
*/
if (!LibraryLoaded) {
/*
* Locate the Apple Application Support directory (if installed) and add its path to the library lookup path.
*
* As of Safari 5.1.4, the Apple Application Support directory is in the Safari installation directory,
* which is pointed to by registry entry "HKEY_LOCAL_MACHINE\SOFTWARE\Apple Computer, Inc.\Safari".
*
* With earlier versions of Safari the Apple Application Support is installed in a stand-alone location, which
* is pointed to by registry entry "HKEY_LOCAL_MACHINE\SOFTWARE\Apple Inc.\Apple Application Support\InstallDir".
*/
String AASDirectory = readInstallDir ("SOFTWARE\\Apple Computer, Inc.\\Safari"); //$NON-NLS-1$
if (AASDirectory != null) {
AASDirectory += "\\Apple Application Support"; //$NON-NLS-1$
if (!new File(AASDirectory).exists()) {
AASDirectory = null;
}
}
if (AASDirectory == null) {
AASDirectory = readInstallDir ("SOFTWARE\\Apple Inc.\\Apple Application Support"); //$NON-NLS-1$
}
if (AASDirectory != null) {
TCHAR buffer = new TCHAR (0, AASDirectory, true);
boolean success = OS.SetDllDirectory (buffer); /* should succeed on XP+SP1 and newer */
if (success) {
try {
Library.loadLibrary ("swt-webkit"); //$NON-NLS-1$
LibraryLoaded = true;
} catch (Throwable e) {
LibraryLoadError = "Failed to load the swt-webkit library"; //$NON-NLS-1$
if (Device.DEBUG) System.out.println ("Failed to load swt-webkit library. Apple Application Support directory path: " + AASDirectory); //$NON-NLS-1$
}
} else {
LibraryLoadError = "Failed to add the Apple Application Support package to the library lookup path. "; //$NON-NLS-1$
LibraryLoadError += "To use a SWT.WEBKIT-style Browser prepend " + AASDirectory + " to your Windows 'Path' environment variable and restart."; //$NON-NLS-1$ //$NON-NLS-2$
}
} else {
LibraryLoadError = "Safari must be installed to use a SWT.WEBKIT-style Browser"; //$NON-NLS-1$
}
}
if (LibraryLoaded) {
JSObjectHasPropertyProc = new Callback (WebKit.class, "JSObjectHasPropertyProc", 3); //$NON-NLS-1$
if (JSObjectHasPropertyProc.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
JSObjectGetPropertyProc = new Callback (WebKit.class, "JSObjectGetPropertyProc", 4); //$NON-NLS-1$
if (JSObjectGetPropertyProc.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
JSObjectCallAsFunctionProc = new Callback (WebKit.class, "JSObjectCallAsFunctionProc", 6); //$NON-NLS-1$
if (JSObjectCallAsFunctionProc.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
NativeClearSessions = new Runnable () {
public void run () {
long /*int*/[] result = new long /*int*/[1];
int hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebCookieManager, 0, WebKit_win32.IID_IWebCookieManager, result);
if (hr != COM.S_OK || result[0] == 0) {
return;
}
IWebCookieManager cookieManager = new IWebCookieManager (result[0]);
long /*int*/[] storage = new long /*int*/[1];
hr = cookieManager.cookieStorage (storage);
cookieManager.Release ();
if (hr != COM.S_OK || storage[0] == 0) {
return;
}
long /*int*/ cookies = WebKit_win32.CFHTTPCookieStorageCopyCookies (storage[0]);
if (cookies != 0) {
int count = WebKit_win32.CFArrayGetCount (cookies);
for (int i = 0; i < count; i++) {
long /*int*/ cookie = WebKit_win32.CFArrayGetValueAtIndex (cookies, i);
long /*int*/ flags = WebKit_win32.CFHTTPCookieGetFlags (cookie);
if ((flags & WebKit_win32.CFHTTPCookieSessionOnlyFlag) != 0) {
WebKit_win32.CFHTTPCookieStorageDeleteCookie (storage[0], cookie);
}
}
WebKit_win32.CFRelease (cookies);
}
// WebKit_win32.CFRelease (storage[0]); //intentionally commented, causes crash
}
};
NativeGetCookie = new Runnable () {
public void run () {
long /*int*/[] result = new long /*int*/[1];
int hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebCookieManager, 0, WebKit_win32.IID_IWebCookieManager, result);
if (hr != COM.S_OK || result[0] == 0) {
return;
}
IWebCookieManager cookieManager = new IWebCookieManager (result[0]);
long /*int*/[] storage = new long /*int*/[1];
hr = cookieManager.cookieStorage (storage);
cookieManager.Release ();
if (hr != COM.S_OK || storage[0] == 0) {
return;
}
char[] chars = CookieUrl.toCharArray ();
long /*int*/ string = WebKit_win32.CFStringCreateWithCharacters (0, chars, chars.length);
if (string != 0) {
long /*int*/ cfUrl = WebKit_win32.CFURLCreateWithString (0, string, 0);
if (cfUrl != 0) {
boolean secure = CookieUrl.startsWith (PROTOCOL_HTTPS);
long /*int*/ cookiesArray = WebKit_win32.CFHTTPCookieStorageCopyCookiesForURL (storage[0], cfUrl, secure);
if (cookiesArray != 0) {
int count = WebKit_win32.CFArrayGetCount (cookiesArray);
for (int i = 0; i < count; i++) {
long /*int*/ cookie = WebKit_win32.CFArrayGetValueAtIndex (cookiesArray, i);
if (cookie != 0) {
long /*int*/ cookieName = WebKit_win32.CFHTTPCookieGetName (cookie);
if (cookieName != 0) {
String name = stringFromCFString (cookieName);
if (CookieName.equals (name)) {
long /*int*/ value = WebKit_win32.CFHTTPCookieGetValue (cookie);
if (value != 0) CookieValue = stringFromCFString (value);
break;
}
}
}
}
WebKit_win32.CFRelease (cookiesArray);
}
WebKit_win32.CFRelease (cfUrl);
}
WebKit_win32.CFRelease (string);
}
// WebKit_win32.CFRelease (storage[0]); //intentionally commented, causes crash
}
};
NativeSetCookie = new Runnable () {
public void run () {
long /*int*/[] result = new long /*int*/[1];
int hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebCookieManager, 0, WebKit_win32.IID_IWebCookieManager, result);
if (hr != COM.S_OK || result[0] == 0) {
return;
}
IWebCookieManager cookieManager = new IWebCookieManager (result[0]);
long /*int*/[] storage = new long /*int*/[1];
hr = cookieManager.cookieStorage (storage);
cookieManager.Release ();
if (hr != COM.S_OK || storage[0] == 0) {
return;
}
char[] chars = CookieUrl.toCharArray ();
long /*int*/ string = WebKit_win32.CFStringCreateWithCharacters (0, chars, chars.length);
if (string != 0) {
long /*int*/ cfUrl = WebKit_win32.CFURLCreateWithString (0, string, 0);
if (cfUrl != 0) {
chars = CookieValue.toCharArray ();
long /*int*/ value = WebKit_win32.CFStringCreateWithCharacters (0, chars, chars.length);
if (value != 0) {
chars = HEADER_SETCOOKIE.toCharArray ();
long /*int*/ key = WebKit_win32.CFStringCreateWithCharacters (0, chars, chars.length);
if (key != 0) {
long /*int*/ headers = WebKit_win32.CFDictionaryCreate (0, new long /*int*/[] {key}, new long /*int*/[] {value}, 1, WebKit_win32.kCFCopyStringDictionaryKeyCallBacks (), WebKit_win32.kCFTypeDictionaryValueCallBacks ());
if (headers != 0) {
long /*int*/ cookies = WebKit_win32.CFHTTPCookieCreateWithResponseHeaderFields (0, headers, cfUrl);
if (cookies != 0) {
long /*int*/ cookie = WebKit_win32.CFArrayGetValueAtIndex (cookies, 0);
if (cookie != 0) {
WebKit_win32.CFHTTPCookieStorageSetCookie (storage[0], cookie);
CookieResult = true;
}
WebKit_win32.CFRelease (cookies);
}
WebKit_win32.CFRelease (headers);
}
WebKit_win32.CFRelease (key);
}
WebKit_win32.CFRelease (value);
}
WebKit_win32.CFRelease (cfUrl);
}
WebKit_win32.CFRelease (string);
}
// WebKit_win32.CFRelease (storage[0]); //intentionally commented, causes crash
}
};
if (NativePendingCookies != null) {
SetPendingCookies (NativePendingCookies);
}
NativePendingCookies = null;
}
}
static long /*int*/ createBSTR (String string) {
char[] data = (string + '\0').toCharArray ();
return COM.SysAllocString (data);
}
static String error (int code) {
throw new SWTError ("WebKit error " + code); //$NON-NLS-1$
}
static String extractBSTR (long /*int*/ bstrString) {
int size = COM.SysStringByteLen (bstrString);
if (size == 0) return EMPTY_STRING;
char[] buffer = new char[(size + 1) / 2]; // add one to avoid rounding errors
COM.MoveMemory (buffer, bstrString, size);
return new String (buffer);
}
static Browser findBrowser (long /*int*/ webView) {
if (webView == 0) return null;
IWebView iwebView = new IWebView (webView);
long /*int*/[] result = new long /*int*/[1];
int hr = iwebView.hostWindow (result);
if (hr == COM.S_OK && result[0] != 0) {
Widget widget = Display.getCurrent ().findWidget (result[0]);
if (widget != null && widget instanceof Browser) return (Browser)widget;
}
return null;
}
static long /*int*/ JSObjectCallAsFunctionProc (long /*int*/ ctx, long /*int*/ function, long /*int*/ thisObject, long /*int*/ argumentCount, long /*int*/ arguments, long /*int*/ exception) {
WebKit_win32.JSGlobalContextRetain (ctx);
if (WebKit_win32.JSValueIsObjectOfClass (ctx, thisObject, ExternalClass) == 0) {
return WebKit_win32.JSValueMakeUndefined (ctx);
}
long /*int*/ ptr = WebKit_win32.JSObjectGetPrivate (thisObject);
long /*int*/[] handle = new long /*int*/[1];
C.memmove (handle, ptr, C.PTR_SIZEOF);
Browser browser = findBrowser (handle[0]);
if (browser == null) return WebKit_win32.JSValueMakeUndefined (ctx);
WebKit webkit = (WebKit)browser.webBrowser;
return webkit.callJava (ctx, function, thisObject, argumentCount, arguments, exception);
}
static long /*int*/ JSObjectGetPropertyProc (long /*int*/ ctx, long /*int*/ object, long /*int*/ propertyName, long /*int*/ exception) {
byte[] bytes = null;
try {
bytes = (FUNCTIONNAME_CALLJAVA + '\0').getBytes (CHARSET_UTF8);
} catch (UnsupportedEncodingException e) {
bytes = (FUNCTIONNAME_CALLJAVA + '\0').getBytes ();
}
long /*int*/ name = WebKit_win32.JSStringCreateWithUTF8CString (bytes);
long /*int*/ addr = WebKit_win32.JSObjectCallAsFunctionProc_CALLBACK (WebKit.JSObjectCallAsFunctionProc.getAddress ());
long /*int*/ function = WebKit_win32.JSObjectMakeFunctionWithCallback (ctx, name, addr);
WebKit_win32.JSStringRelease (name);
return function;
}
static long /*int*/ JSObjectHasPropertyProc (long /*int*/ ctx, long /*int*/ object, long /*int*/ propertyName) {
byte[] bytes = null;
try {
bytes = (FUNCTIONNAME_CALLJAVA + '\0').getBytes (CHARSET_UTF8);
} catch (UnsupportedEncodingException e) {
bytes = (FUNCTIONNAME_CALLJAVA + '\0').getBytes ();
}
return WebKit_win32.JSStringIsEqualToUTF8CString (propertyName, bytes);
}
static String readInstallDir (String keyString) {
long /*int*/[] phkResult = new long /*int*/[1];
TCHAR key = new TCHAR (0, keyString, true);
if (OS.RegOpenKeyEx (OS.HKEY_LOCAL_MACHINE, key, 0, OS.KEY_READ, phkResult) == 0) {
int[] lpcbData = new int[1];
TCHAR buffer = new TCHAR (0, "InstallDir", 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) {
OS.RegCloseKey (phkResult[0]);
return lpData.toString (0, lpData.strlen ());
}
}
OS.RegCloseKey (phkResult[0]);
}
return null;
}
static String stringFromCFString (long /*int*/ cfString) {
if (cfString == 0) return null;
int length = WebKit_win32.CFStringGetLength (cfString);
long /*int*/ ptr = WebKit_win32.CFStringGetCharactersPtr (cfString);
char[] chars = new char[length];
if (ptr != 0) {
OS.MoveMemory (chars, ptr, length);
} else {
for (int j = 0; j < length; j++) {
chars[j] = WebKit_win32.CFStringGetCharacterAtIndex (cfString, j);
}
}
return new String (chars);
}
static String stringFromJSString (long /*int*/ jsString) {
if (jsString == 0) return null;
int length = WebKit_win32.JSStringGetLength (jsString);
byte[] bytes = new byte[length + 1];
WebKit_win32.JSStringGetUTF8CString (jsString, bytes, length + 1);
return new String (bytes);
}
@Override
public boolean back () {
int[] result = new int[1];
webView.goBack (result);
return result[0] != 0;
}
long /*int*/ callJava (long /*int*/ ctx, long /*int*/ func, long /*int*/ thisObject, long /*int*/ argumentCount, long /*int*/ arguments, long /*int*/ exception) {
Object returnValue = null;
if (argumentCount == 3) {
long /*int*/[] result = new long /*int*/[1];
C.memmove (result, arguments, C.PTR_SIZEOF);
int type = WebKit_win32.JSValueGetType (ctx, result[0]);
if (type == WebKit_win32.kJSTypeNumber) {
int index = ((Double)convertToJava (ctx, result[0])).intValue ();
result[0] = 0;
if (index > 0) {
Object key = new Integer (index);
C.memmove (result, arguments + C.PTR_SIZEOF, C.PTR_SIZEOF);
type = WebKit_win32.JSValueGetType (ctx, result[0]);
if (type == WebKit_win32.kJSTypeString) {
String token = (String)convertToJava (ctx, result[0]);
BrowserFunction function = (BrowserFunction)functions.get (key);
if (function != null && token.equals (function.token)) {
try {
C.memmove (result, arguments + 2 * C.PTR_SIZEOF, C.PTR_SIZEOF);
Object temp = convertToJava (ctx, result[0]);
if (temp instanceof Object[]) {
Object[] args = (Object[])temp;
try {
returnValue = function.function (args);
} catch (Exception e) {
/* exception during function invocation */
returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ());
}
}
} catch (IllegalArgumentException e) {
/* invalid argument value type */
if (function.isEvaluate) {
/* notify the function so that a java exception can be thrown */
function.function (new String[] {WebBrowser.CreateErrorString (new SWTException (SWT.ERROR_INVALID_RETURN_VALUE).getLocalizedMessage ())});
}
returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ());
}
}
}
}
}
}
return convertToJS (ctx, returnValue);
}
@Override
public boolean close () {
return shouldClose ();
}
Object convertToJava (long /*int*/ ctx, long /*int*/ value) {
int type = WebKit_win32.JSValueGetType (ctx, value);
switch (type) {
case WebKit_win32.kJSTypeBoolean: {
int result = (int)WebKit_win32.JSValueToNumber (ctx, value, null);
return new Boolean (result != 0);
}
case WebKit_win32.kJSTypeNumber: {
double result = WebKit_win32.JSValueToNumber (ctx, value, null);
return new Double (result);
}
case WebKit_win32.kJSTypeString: {
long /*int*/ string = WebKit_win32.JSValueToStringCopy (ctx, value, null);
if (string == 0) return ""; //$NON-NLS-1$
long /*int*/ length = WebKit_win32.JSStringGetMaximumUTF8CStringSize (string);
byte[] bytes = new byte[(int)/*64*/length];
length = WebKit_win32.JSStringGetUTF8CString (string, bytes, length);
WebKit_win32.JSStringRelease (string);
try {
/* length-1 is needed below to exclude the terminator character */
return new String (bytes, 0, (int)/*64*/length - 1, CHARSET_UTF8);
} catch (UnsupportedEncodingException e) {
return new String (bytes);
}
}
case WebKit_win32.kJSTypeNull:
// FALL THROUGH
case WebKit_win32.kJSTypeUndefined: return null;
case WebKit_win32.kJSTypeObject: {
byte[] bytes = null;
try {
bytes = (PROPERTY_LENGTH + '\0').getBytes (CHARSET_UTF8);
} catch (UnsupportedEncodingException e) {
bytes = (PROPERTY_LENGTH + '\0').getBytes ();
}
long /*int*/ propertyName = WebKit_win32.JSStringCreateWithUTF8CString (bytes);
long /*int*/ valuePtr = WebKit_win32.JSObjectGetProperty (ctx, value, propertyName, null);
WebKit_win32.JSStringRelease (propertyName);
type = WebKit_win32.JSValueGetType (ctx, valuePtr);
if (type == WebKit_win32.kJSTypeNumber) {
int length = (int)WebKit_win32.JSValueToNumber (ctx, valuePtr, null);
Object[] result = new Object[length];
for (int i = 0; i < length; i++) {
long /*int*/ current = WebKit_win32.JSObjectGetPropertyAtIndex (ctx, value, i, null);
if (current != 0) {
result[i] = convertToJava (ctx, current);
}
}
return result;
}
}
}
SWT.error (SWT.ERROR_INVALID_ARGUMENT);
return null;
}
long /*int*/ convertToJS (long /*int*/ ctx, Object value) {
if (value == null) {
return WebKit_win32.JSValueMakeNull (ctx);
}
if (value instanceof String) {
byte[] bytes = null;
try {
bytes = ((String)value + '\0').getBytes (CHARSET_UTF8);
} catch (UnsupportedEncodingException e) {
bytes = ((String)value + '\0').getBytes ();
}
long /*int*/ stringRef = WebKit_win32.JSStringCreateWithUTF8CString (bytes);
long /*int*/ result = WebKit_win32.JSValueMakeString (ctx, stringRef);
WebKit_win32.JSStringRelease (stringRef);
return result;
}
if (value instanceof Boolean) {
return WebKit_win32.JSValueMakeBoolean (ctx, ((Boolean)value).booleanValue () ? 1 : 0);
}
if (value instanceof Number) {
return WebKit_win32.JSValueMakeNumber (ctx, ((Number)value).doubleValue ());
}
if (value instanceof Object[]) {
Object[] arrayValue = (Object[]) value;
int length = arrayValue.length;
long /*int*/[] arguments = new long /*int*/[length];
for (int i = 0; i < length; i++) {
Object javaObject = arrayValue[i];
long /*int*/ jsObject = convertToJS (ctx, javaObject);
arguments[i] = jsObject;
}
return WebKit_win32.JSObjectMakeArray (ctx, length, arguments, null);
}
SWT.error (SWT.ERROR_INVALID_RETURN_VALUE);
return 0;
}
@Override
public void create (Composite parent, int style) {
if (!LibraryLoaded) {
browser.dispose ();
SWT.error (SWT.ERROR_NO_HANDLES, null, LibraryLoadError == null ? null : " [" + LibraryLoadError + ']'); //$NON-NLS-1$
}
if (ExternalClass == 0) {
JSClassDefinition jsClassDefinition = new JSClassDefinition ();
byte[] bytes = (CLASSNAME_EXTERNAL + '\0').getBytes ();
jsClassDefinition.className = C.malloc (bytes.length);
OS.memmove (jsClassDefinition.className, bytes, bytes.length);
/* custom callbacks for hasProperty, getProperty and callAsFunction */
long /*int*/ addr = WebKit_win32.JSObjectHasPropertyProc_CALLBACK (JSObjectHasPropertyProc.getAddress ());
jsClassDefinition.hasProperty = addr;
addr = WebKit_win32.JSObjectGetPropertyProc_CALLBACK (JSObjectGetPropertyProc.getAddress ());
jsClassDefinition.getProperty = addr;
long /*int*/ classDefinitionPtr = C.malloc (JSClassDefinition.sizeof);
WebKit_win32.memmove (classDefinitionPtr, jsClassDefinition, JSClassDefinition.sizeof);
ExternalClass = WebKit_win32.JSClassCreate (classDefinitionPtr);
WebKit_win32.JSClassRetain (ExternalClass);
}
long /*int*/[] result = new long /*int*/[1];
int hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebView, 0, WebKit_win32.IID_IWebView, result);
if (hr != COM.S_OK || result[0] == 0) {
browser.dispose ();
error (hr);
}
webView = new IWebView (result[0]);
webViewData = C.malloc (C.PTR_SIZEOF);
C.memmove (webViewData, new long /*int*/[] {webView.getAddress ()}, C.PTR_SIZEOF);
hr = webView.setHostWindow (browser.handle);
if (hr != COM.S_OK) {
browser.dispose ();
error (hr);
}
hr = webView.initWithFrame (new RECT (), 0, 0);
if (hr != COM.S_OK) {
browser.dispose ();
error (hr);
}
result[0] = 0;
hr = webView.QueryInterface (WebKit_win32.IID_IWebViewPrivate, result);
if (hr != COM.S_OK || result[0] == 0) {
browser.dispose ();
error (hr);
}
IWebViewPrivate webViewPrivate = new IWebViewPrivate (result[0]);
result[0] = 0;
hr = webViewPrivate.viewWindow (result);
if (hr != COM.S_OK || result[0] == 0) {
browser.dispose ();
error (hr);
}
webViewPrivate.Release ();
webViewWindowHandle = result[0];
webFrameLoadDelegate = new WebFrameLoadDelegate (browser);
hr = webView.setFrameLoadDelegate (webFrameLoadDelegate.getAddress ());
if (hr != COM.S_OK) {
browser.dispose ();
error (hr);
}
webUIDelegate = new WebUIDelegate (browser);
hr = webView.setUIDelegate (webUIDelegate.getAddress ());
if (hr != COM.S_OK) {
browser.dispose ();
error (hr);
}
webResourceLoadDelegate = new WebResourceLoadDelegate (browser);
hr = webView.setResourceLoadDelegate (webResourceLoadDelegate.getAddress ());
if (hr != COM.S_OK) {
browser.dispose ();
error (hr);
}
webDownloadDelegate = new WebDownloadDelegate (browser);
hr = webView.setDownloadDelegate (webDownloadDelegate.getAddress ());
if (hr != COM.S_OK) {
browser.dispose ();
error (hr);
}
webPolicyDelegate = new WebPolicyDelegate (browser);
hr = webView.setPolicyDelegate (webPolicyDelegate.getAddress ());
if (hr != COM.S_OK) {
browser.dispose ();
error (hr);
}
initializeWebViewPreferences ();
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;
onDispose ();
break;
}
case SWT.FocusIn: {
OS.SetFocus (webViewWindowHandle);
break;
}
case SWT.Resize: {
Rectangle bounds = browser.getClientArea ();
OS.SetWindowPos (webViewWindowHandle, 0, bounds.x, bounds.y, bounds.width, bounds.height, OS.SWP_DRAWFRAME);
break;
}
case SWT.Traverse: {
if (traverseOut) {
e.doit = true;
traverseOut = false;
} else {
e.doit = false;
}
break;
}
}
}
};
browser.addListener (SWT.Dispose, listener);
browser.addListener (SWT.KeyDown, listener); /* needed for tabbing into the Browser */
browser.addListener (SWT.FocusIn, listener);
browser.addListener (SWT.Resize, listener);
browser.addListener (SWT.Traverse, listener);
eventFunction = new BrowserFunction (browser, "HandleWebKitEvent") { //$NON-NLS-1$
@Override
public Object function (Object[] arguments) {
return handleEvent (arguments) ? Boolean.TRUE : Boolean.FALSE;
};
};
}
@Override
public boolean execute (String script) {
long /*int*/[] result = new long /*int*/[1];
int hr = webView.mainFrame (result);
if (hr != COM.S_OK || result[0] == 0) {
return false;
}
IWebFrame frame = new IWebFrame (result[0]);
long /*int*/ context = frame.globalContext ();
frame.Release ();
if (context == 0) {
return false;
}
byte[] bytes = null;
try {
bytes = (script + '\0').getBytes ("UTF-8"); //$NON-NLS-1$
} catch (UnsupportedEncodingException e) {
bytes = (script + '\0').getBytes ();
}
long /*int*/ scriptString = WebKit_win32.JSStringCreateWithUTF8CString (bytes);
if (scriptString == 0) return false;
try {
bytes = (getUrl () + '\0').getBytes ("UTF-8"); //$NON-NLS-1$
} catch (UnsupportedEncodingException e) {
bytes = (getUrl () + '\0').getBytes ();
}
long /*int*/ urlString = WebKit_win32.JSStringCreateWithUTF8CString (bytes);
if (urlString == 0) {
WebKit_win32.JSStringRelease (scriptString);
return false;
}
long /*int*/ evalResult = WebKit_win32.JSEvaluateScript (context, scriptString, 0, urlString, 0, null);
WebKit_win32.JSStringRelease (urlString);
WebKit_win32.JSStringRelease (scriptString);
return evalResult != 0;
}
@Override
public boolean forward () {
int[] result = new int[1];
webView.goForward (result);
return result[0] != 0;
}
@Override
public String getBrowserType () {
return "webkit"; //$NON-NLS-1$
}
@Override
public String getText () {
long /*int*/[] result = new long /*int*/[1];
int hr = webView.mainFrame (result);
if (hr != COM.S_OK || result[0] == 0) {
return EMPTY_STRING;
}
IWebFrame mainFrame = new IWebFrame (result[0]);
result[0] = 0;
hr = mainFrame.dataSource (result);
mainFrame.Release ();
if (hr != COM.S_OK || result[0] == 0) {
return EMPTY_STRING;
}
IWebDataSource dataSource = new IWebDataSource (result[0]);
result[0] = 0;
hr = dataSource.representation (result);
dataSource.Release ();
if (hr != COM.S_OK || result[0] == 0) {
return EMPTY_STRING;
}
IWebDocumentRepresentation representation = new IWebDocumentRepresentation (result[0]);
result[0] = 0;
hr = representation.documentSource (result);
representation.Release ();
if (hr != COM.S_OK || result[0] == 0) {
return EMPTY_STRING;
}
String source = extractBSTR (result[0]);
COM.SysFreeString (result[0]);
return source;
}
@Override
public String getUrl () {
return webFrameLoadDelegate.getUrl ();
}
boolean handleEvent (Object[] arguments) {
/*
* DOM events are currently received by hooking DOM listeners
* in javascript that invoke this method via a BrowserFunction.
* Document.addListener is not implemented on WebKit on windows.
* The argument lists received here are:
*
* For key events:
* argument 0: type (String)
* argument 1: keyCode (Double)
* argument 2: charCode (Double)
* argument 3: altKey (Boolean)
* argument 4: ctrlKey (Boolean)
* argument 5: shiftKey (Boolean)
* argument 6: metaKey (Boolean)
* returns doit
*
* For mouse events
* argument 0: type (String)
* argument 1: screenX (Double)
* argument 2: screenY (Double)
* argument 3: detail (Double)
* argument 4: button (Double)
* argument 5: altKey (Boolean)
* argument 6: ctrlKey (Boolean)
* argument 7: shiftKey (Boolean)
* argument 8: metaKey (Boolean)
* argument 9: hasRelatedTarget (Boolean)
* returns doit
*/
String type = (String)arguments[0];
if (type.equals (DOMEVENT_KEYDOWN)) {
int keyCode = translateKey (((Double)arguments[1]).intValue ());
lastKeyCode = keyCode;
switch (keyCode) {
case SWT.SHIFT:
case SWT.CONTROL:
case SWT.ALT:
case SWT.CAPS_LOCK:
case SWT.NUM_LOCK:
case SWT.SCROLL_LOCK:
case SWT.COMMAND:
// case SWT.ESC:
case SWT.TAB:
case SWT.PAUSE:
// case SWT.BS:
case SWT.INSERT:
case SWT.DEL:
case SWT.HOME:
case SWT.END:
case SWT.PAGE_UP:
case SWT.PAGE_DOWN:
case SWT.ARROW_DOWN:
case SWT.ARROW_UP:
case SWT.ARROW_LEFT:
case SWT.ARROW_RIGHT:
case SWT.F1:
case SWT.F2:
case SWT.F3:
case SWT.F4:
case SWT.F5:
case SWT.F6:
case SWT.F7:
case SWT.F8:
case SWT.F9:
case SWT.F10:
case SWT.F11:
case SWT.F12: {
/* keypress events will not be received for these keys, so send KeyDowns for them now */
Event keyEvent = new Event ();
keyEvent.widget = browser;
keyEvent.type = type.equals (DOMEVENT_KEYDOWN) ? SWT.KeyDown : SWT.KeyUp;
keyEvent.keyCode = keyCode;
switch (keyCode) {
case SWT.BS: keyEvent.character = SWT.BS; break;
case SWT.DEL: keyEvent.character = SWT.DEL; break;
case SWT.ESC: keyEvent.character = SWT.ESC; break;
case SWT.TAB: keyEvent.character = SWT.TAB; break;
}
lastCharCode = keyEvent.character;
keyEvent.stateMask =
(((Boolean)arguments[3]).booleanValue () ? SWT.ALT : 0) |
(((Boolean)arguments[4]).booleanValue () ? SWT.CTRL : 0) |
(((Boolean)arguments[5]).booleanValue () ? SWT.SHIFT : 0) |
(((Boolean)arguments[6]).booleanValue () ? SWT.COMMAND : 0);
keyEvent.stateMask &= ~keyCode; /* remove current keydown if it's a state key */
if (!sendKeyEvent (keyEvent) || browser.isDisposed ()) return false;
break;
}
}
return true;
}
if (type.equals (DOMEVENT_KEYPRESS)) {
/*
* if keydown could not determine a keycode for this key then it's a
* key for which key events are not sent (eg.- the Windows key)
*/
if (lastKeyCode == 0) return true;
lastCharCode = ((Double)arguments[2]).intValue ();
if (((Boolean)arguments[4]).booleanValue () && (0 <= lastCharCode && lastCharCode <= 0x7F)) {
if ('a' <= lastCharCode && lastCharCode <= 'z') lastCharCode -= 'a' - 'A';
if (64 <= lastCharCode && lastCharCode <= 95) lastCharCode -= 64;
}
Event keyEvent = new Event ();
keyEvent.widget = browser;
keyEvent.type = SWT.KeyDown;
keyEvent.keyCode = lastKeyCode;
keyEvent.character = (char)lastCharCode;
keyEvent.stateMask =
(((Boolean)arguments[3]).booleanValue () ? SWT.ALT : 0) |
(((Boolean)arguments[4]).booleanValue () ? SWT.CTRL : 0) |
(((Boolean)arguments[5]).booleanValue () ? SWT.SHIFT : 0) |
(((Boolean)arguments[6]).booleanValue () ? SWT.COMMAND : 0);
return sendKeyEvent (keyEvent) && !browser.isDisposed ();
}
if (type.equals (DOMEVENT_KEYUP)) {
int keyCode = translateKey (((Double)arguments[1]).intValue ());
if (keyCode == 0) {
/* indicates a key for which key events are not sent */
return true;
}
if (keyCode != lastKeyCode) {
/* keyup does not correspond to the last keydown */
lastKeyCode = keyCode;
lastCharCode = 0;
}
Event keyEvent = new Event ();
keyEvent.widget = browser;
keyEvent.type = SWT.KeyUp;
keyEvent.keyCode = lastKeyCode;
keyEvent.character = (char)lastCharCode;
keyEvent.stateMask =
(((Boolean)arguments[3]).booleanValue () ? SWT.ALT : 0) |
(((Boolean)arguments[4]).booleanValue () ? SWT.CTRL : 0) |
(((Boolean)arguments[5]).booleanValue () ? SWT.SHIFT : 0) |
(((Boolean)arguments[6]).booleanValue () ? SWT.COMMAND : 0);
switch (lastKeyCode) {
case SWT.SHIFT:
case SWT.CONTROL:
case SWT.ALT:
case SWT.COMMAND: {
keyEvent.stateMask |= lastKeyCode;
}
}
browser.notifyListeners (keyEvent.type, keyEvent);
lastKeyCode = lastCharCode = 0;
return keyEvent.doit && !browser.isDisposed ();
}
/* mouse events */
/*
* MouseOver and 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 there is a related target element.
*/
if (type.equals (DOMEVENT_MOUSEOVER) || type.equals (DOMEVENT_MOUSEOUT)) {
if (((Boolean)arguments[9]).booleanValue ()) return true;
}
/*
* 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.
*/
Point position = new Point (((Double)arguments[1]).intValue (), ((Double)arguments[2]).intValue ());
position = browser.getDisplay ().map (null, browser, position);
Event mouseEvent = new Event ();
mouseEvent.widget = browser;
mouseEvent.x = position.x;
mouseEvent.y = position.y;
int mask =
(((Boolean)arguments[5]).booleanValue () ? SWT.ALT : 0) |
(((Boolean)arguments[6]).booleanValue () ? SWT.CTRL : 0) |
(((Boolean)arguments[7]).booleanValue () ? SWT.SHIFT : 0);
mouseEvent.stateMask = mask;
if (type.equals (DOMEVENT_MOUSEDOWN)) {
mouseEvent.type = SWT.MouseDown;
mouseEvent.count = ((Double)arguments[3]).intValue ();
mouseEvent.button = ((Double)arguments[4]).intValue ();
browser.notifyListeners (mouseEvent.type, mouseEvent);
if (browser.isDisposed ()) return true;
if (((Double)arguments[3]).intValue () == 2) {
mouseEvent = new Event ();
mouseEvent.type = SWT.MouseDoubleClick;
mouseEvent.widget = browser;
mouseEvent.x = position.x;
mouseEvent.y = position.y;
mouseEvent.stateMask = mask;
mouseEvent.count = ((Double)arguments[3]).intValue ();
mouseEvent.button = ((Double)arguments[4]).intValue ();
browser.notifyListeners (mouseEvent.type, mouseEvent);
}
return true;
}
if (type.equals (DOMEVENT_MOUSEUP)) {
mouseEvent.type = SWT.MouseUp;
mouseEvent.count = ((Double)arguments[3]).intValue ();
mouseEvent.button = ((Double)arguments[4]).intValue ();
switch (mouseEvent.button) {
case 1: mouseEvent.stateMask |= SWT.BUTTON1; break;
case 2: mouseEvent.stateMask |= SWT.BUTTON2; break;
case 3: mouseEvent.stateMask |= SWT.BUTTON3; break;
case 4: mouseEvent.stateMask |= SWT.BUTTON4; break;
case 5: mouseEvent.stateMask |= SWT.BUTTON5; break;
}
} else if (type.equals (DOMEVENT_MOUSEMOVE)) {
mouseEvent.type = SWT.MouseMove;
} else if (type.equals (DOMEVENT_MOUSEWHEEL)) {
mouseEvent.type = SWT.MouseWheel;
mouseEvent.count = ((Double)arguments[3]).intValue ();
} else if (type.equals (DOMEVENT_MOUSEOVER)) {
mouseEvent.type = SWT.MouseEnter;
} else if (type.equals (DOMEVENT_MOUSEOUT)) {
mouseEvent.type = SWT.MouseExit;
if (mouseEvent.x < 0) mouseEvent.x = -1;
if (mouseEvent.y < 0) mouseEvent.y = -1;
} else if (type.equals (DOMEVENT_DRAGSTART)) {
mouseEvent.type = SWT.DragDetect;
mouseEvent.button = ((Double)arguments[4]).intValue () + 1;
switch (mouseEvent.button) {
case 1: mouseEvent.stateMask |= SWT.BUTTON1; break;
case 2: mouseEvent.stateMask |= SWT.BUTTON2; break;
case 3: mouseEvent.stateMask |= SWT.BUTTON3; break;
case 4: mouseEvent.stateMask |= SWT.BUTTON4; break;
case 5: mouseEvent.stateMask |= SWT.BUTTON5; break;
}
}
browser.notifyListeners (mouseEvent.type, mouseEvent);
return true;
}
@Override
public boolean isBackEnabled () {
long /*int*/[] address = new long /*int*/[1];
int hr = webView.QueryInterface (WebKit_win32.IID_IWebIBActions, address);
if (hr != COM.S_OK || address[0] == 0) {
return false;
}
IWebIBActions webIBActions = new IWebIBActions (address[0]);
int[] result = new int[1];
webIBActions.canGoBack (webView.getAddress (), result);
webIBActions.Release ();
return result[0] != 0;
}
@Override
public boolean isFocusControl () {
long /*int*/ hwndFocus = OS.GetFocus ();
return hwndFocus != 0 && hwndFocus == webViewWindowHandle;
}
@Override
public boolean isForwardEnabled () {
long /*int*/[] address = new long /*int*/[1];
int hr = webView.QueryInterface (WebKit_win32.IID_IWebIBActions, address);
if (hr != COM.S_OK || address[0] == 0) {
return false;
}
IWebIBActions webIBActions = new IWebIBActions (address[0]);
int[] result = new int[1];
webIBActions.canGoForward (webView.getAddress (), result);
webIBActions.Release ();
return result[0] != 0;
}
void onDispose () {
/* Browser could have been disposed by one of the Dispose listeners */
if (!browser.isDisposed ()) {
/* invoke onbeforeunload handlers but don't prompt with message box */
if (!browser.isClosing) {
webUIDelegate.prompt = false;
shouldClose ();
webUIDelegate.prompt = true;
}
}
Enumeration elements = functions.elements ();
while (elements.hasMoreElements ()) {
((BrowserFunction)elements.nextElement ()).dispose (false);
}
functions = null;
eventFunction.dispose();
eventFunction = null;
C.free (webViewData);
webView.setPreferences (0);
webView.setHostWindow (0);
webView.setFrameLoadDelegate (0);
webView.setResourceLoadDelegate (0);
webView.setUIDelegate (0);
webView.setPolicyDelegate (0);
webView.setDownloadDelegate (0);
webView.Release();
webView = null;
webDownloadDelegate = null;
webFrameLoadDelegate = null;
webPolicyDelegate = null;
webResourceLoadDelegate = null;
webUIDelegate = null;
lastNavigateURL = null;
}
@Override
public void refresh () {
webFrameLoadDelegate.html = null;
long /*int*/[] result = new long /*int*/[1];
int hr = webView.QueryInterface (WebKit_win32.IID_IWebIBActions, result);
if (hr != COM.S_OK || result[0] == 0) {
return;
}
IWebIBActions webIBActions = new IWebIBActions (result[0]);
webIBActions.reload (webView.getAddress ());
webIBActions.Release ();
}
@Override
boolean sendKeyEvent (Event event) {
/*
* browser.traverse() is called through dislay.translateTraversal() for all
* traversal types except SWT.TRAVERSE_MNEMONIC. So, override
* WebBrowser.sendKeyEvent() so that when it is called from handleEvent(),
* browser.traverse() is not called again.
*/
boolean doit = true;
switch (event.keyCode) {
case SWT.ESC:
case SWT.CR:
case SWT.ARROW_DOWN:
case SWT.ARROW_RIGHT:
case SWT.ARROW_UP:
case SWT.ARROW_LEFT:
case SWT.TAB:
case SWT.PAGE_DOWN:
case SWT.PAGE_UP:
break;
default: {
if (translateMnemonics ()) {
if (event.character != 0 && (event.stateMask & (SWT.ALT | SWT.CTRL)) == SWT.ALT) {
int traversal = SWT.TRAVERSE_MNEMONIC;
boolean oldEventDoit = event.doit;
event.doit = true;
doit = !browser.traverse (traversal, event);
event.doit = oldEventDoit;
}
}
break;
}
}
if (doit) {
browser.notifyListeners (event.type, event);
doit = event.doit;
}
return doit;
}
@Override
public boolean setText (String html, boolean trusted) {
/*
* If this.html is not null then the about:blank page is already being loaded,
* so no navigate is required. Just set the html that is to be shown.
*/
boolean blankLoading = webFrameLoadDelegate.html != null;
webFrameLoadDelegate.html = html;
untrustedText = !trusted;
if (blankLoading) return true;
long /*int*/[] result = new long /*int*/[1];
int hr = webView.mainFrame (result);
if (hr != COM.S_OK || result[0] == 0) {
return false;
}
IWebFrame frame = new IWebFrame (result[0]);
result[0] = 0;
hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebMutableURLRequest, 0, WebKit_win32.IID_IWebMutableURLRequest, result);
if (hr != COM.S_OK || result[0] == 0) {
frame.Release ();
return false;
}
IWebMutableURLRequest request = new IWebMutableURLRequest (result[0]);
long /*int*/ urlString = createBSTR (ABOUT_BLANK);
hr = request.setURL (urlString);
COM.SysFreeString (urlString);
if (hr == COM.S_OK) {
hr = frame.loadRequest (request.getAddress ());
}
frame.Release ();
request.Release ();
return hr == COM.S_OK;
}
@Override
public boolean setUrl (String url, String postData, String[] headers) {
if (url.length () == 0) return false;
/*
* WebKit attempts to open the exact url string that is passed to it and
* will not infer a protocol if it's not specified. Detect the case of an
* invalid URL string and try to fix it by prepending an appropriate protocol.
*/
try {
new URL (url);
} catch (MalformedURLException e) {
String testUrl = null;
if (new File (url).isAbsolute ()) {
/* appears to be a local file */
testUrl = PROTOCOL_FILE + url;
} else {
testUrl = PROTOCOL_HTTP + url;
}
try {
new URL (testUrl);
url = testUrl; /* adding the protocol made the url valid */
} catch (MalformedURLException e2) {
/* adding the protocol did not make the url valid, so do nothing */
}
}
webFrameLoadDelegate.html = null;
lastNavigateURL = url;
long /*int*/[] result = new long /*int*/[1];
int hr = webView.mainFrame (result);
if (hr != COM.S_OK || result[0] == 0) {
return false;
}
IWebFrame frame = new IWebFrame (result[0]);
result[0] = 0;
hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebMutableURLRequest, 0, WebKit_win32.IID_IWebMutableURLRequest, result);
if (hr != COM.S_OK || result[0] == 0) {
frame.Release ();
return false;
}
IWebMutableURLRequest request = new IWebMutableURLRequest (result[0]);
if (postData != null) { //TODO: POST
// webResourceLoadDelegate.postData = postData;
// long /*int*/ postString = createBSTR (POST);
// hr = request.setHTTPMethod (postString);
// COM.SysFreeString (postString);
//
// result[0] = 0;
// hr = request.QueryInterface (WebKit_win32.IID_IWebMutableURLRequestPrivate, result);
// if (hr == COM.S_OK && result[0] != 0) {
// IWebMutableURLRequestPrivate requestPrivate = new IWebMutableURLRequestPrivate(result[0]);
// int cfRequest = requestPrivate.cfRequest();
// byte[] bytes = postData.getBytes();
// long /*int*/ data = WebKit_win32.CFDataCreate(0, bytes, bytes.length);
// if (data != 0)WebKit_win32.CFURLRequestSetHTTPRequestBody(cfRequest, data);
//
// long /*int*/ dataGet = WebKit_win32.CFURLRequestCopyHTTPRequestBody(cfRequest);
// int length = WebKit_win32.CFDataGetLength(dataGet);
// long /*int*/ bytePtr = WebKit_win32.CFDataGetBytePtr(dataGet);
// }
}
hr = COM.S_OK; //TODO: once post code is completed, remove this line if not required
if (headers != null) {
for (int i = 0; i < headers.length; i++) {
String current = headers[i];
if (current != null) {
int index = current.indexOf (':');
if (index != -1) {
String key = current.substring (0, index).trim ();
String value = current.substring (index + 1).trim ();
if (key.length () > 0 && value.length () > 0) {
long /*int*/ valueString = createBSTR (value);
if (key.equalsIgnoreCase (USER_AGENT)) {
/*
* Feature of WebKit. The user-agent header value cannot be overridden
* here. The workaround is to temporarily set the value on the WebView
* and then remove it after the loading of the request has begun.
*/
hr = webView.setCustomUserAgent (valueString);
} else {
long /*int*/ keyString = createBSTR (key);
hr = request.setValue (valueString, keyString);
COM.SysFreeString (keyString);
}
COM.SysFreeString (valueString);
}
}
}
}
}
if (hr == COM.S_OK) {
long /*int*/ urlString = createBSTR (url);
hr = request.setURL (urlString);
COM.SysFreeString (urlString);
if (hr == COM.S_OK) {
hr = frame.loadRequest (request.getAddress ());
}
webView.setCustomUserAgent (0);
}
frame.Release ();
request.Release ();
return hr == COM.S_OK;
}
boolean shouldClose () {
if (!jsEnabled) return true;
long /*int*/[] address = new long /*int*/[1];
int hr = webView.QueryInterface (WebKit_win32.IID_IWebViewPrivate, address);
if (hr != COM.S_OK || address[0] == 0) {
return false;
}
IWebViewPrivate webViewPrivate = new IWebViewPrivate (address[0]);
int[] result = new int[1];
/* This function will fire the before unload handler for a page */
webViewPrivate.shouldClose (result);
webViewPrivate.Release ();
return result[0] != 0;
}
@Override
public void stop () {
webFrameLoadDelegate.html = null;
long /*int*/[] result = new long /*int*/[1];
int hr = webView.QueryInterface (WebKit_win32.IID_IWebIBActions, result);
if (hr != COM.S_OK || result[0] == 0) {
return;
}
IWebIBActions webIBActions = new IWebIBActions (result[0]);
webIBActions.stopLoading (webView.getAddress ());
webIBActions.Release ();
}
void initializeWebViewPreferences () {
/*
* Try to create separate preferences for each webview using different identifier for each webview.
* Otherwise all the webviews use the shared preferences.
*/
long /*int*/[] result = new long /*int*/[1];
int hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebPreferences, 0, WebKit_win32.IID_IWebPreferences, result);
if (hr == COM.S_OK && result[0] != 0) {
IWebPreferences preferences = new IWebPreferences (result[0]);
result[0] = 0;
hr = preferences.initWithIdentifier (createBSTR (String.valueOf (prefsIdentifier++)), result);
preferences.Release ();
if (hr == COM.S_OK && result[0] != 0) {
preferences = new IWebPreferences (result[0]);
webView.setPreferences (preferences.getAddress());
preferences.Release ();
}
}
result[0] = 0;
hr = webView.preferences (result);
if (hr == COM.S_OK && result[0] != 0) {
IWebPreferences preferences = new IWebPreferences (result[0]);
preferences.setJavaScriptEnabled (1);
preferences.setJavaScriptCanOpenWindowsAutomatically (1);
preferences.setJavaEnabled (0); /* disable applets */
preferences.setTabsToLinks (1);
preferences.setFontSmoothing (WebKit_win32.FontSmoothingTypeWindows);
preferences.Release ();
}
}
}