/*******************************************************************************
 * Copyright (c) 2011, 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.UnsupportedEncodingException;
import java.util.Enumeration;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.carbon.*;
import org.eclipse.swt.internal.cocoa.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

class WebKit extends WebBrowser {
	
	/* Objective-C WebView delegate */
	int delegate;
	
	/* Carbon HIView handle */
	int webViewHandle, webView;
	int windowBoundsHandler;
	int preferences;
	
	boolean loadingText, hasNewFocusElement, untrustedText;
	String lastHoveredLinkURL, lastNavigateURL;
	String html;
	int identifier;
	int resourceCount;
	int lastMouseMoveX, lastMouseMoveY;
	String url = ""; //$NON-NLS-1$
	Point location;
	Point size;
	boolean statusBar = true, toolBar = true, ignoreDispose;
	//TEMPORARY CODE
//	boolean doit;

	static boolean Initialized;
	static Callback Callback3, Callback7;

	static final int MIN_SIZE = 16;
	static final int MAX_PROGRESS = 100;
	static final String WebElementLinkURLKey = "WebElementLinkURL"; //$NON-NLS-1$
	static final String AGENT_STRING = "Safari/412.0"; /* Safari version on OSX 10.4 initial release */ //$NON-NLS-1$
	static final String URI_FILEROOT = "file:///"; //$NON-NLS-1$
	static final String PROTOCOL_FILE = "file://"; //$NON-NLS-1$
	static final String PROTOCOL_HTTP = "http://"; //$NON-NLS-1$
	static final String URI_APPLEWEBDATA = "applewebdata://"; //$NON-NLS-1$
	static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
	static final String HEADER_SETCOOKIE = "Set-Cookie"; //$NON-NLS-1$
	static final String POST = "POST"; //$NON-NLS-1$
	static final String USER_AGENT = "user-agent"; //$NON-NLS-1$
	static final String ADD_WIDGET_KEY = "org.eclipse.swt.internal.addWidget"; //$NON-NLS-1$
	static final String BROWSER_WINDOW = "org.eclipse.swt.browser.Browser.Window"; //$NON-NLS-1$
	static final String WEBKIT_EVENTS_FIX_KEY = "org.eclipse.swt.internal.webKitEventsFix"; //$NON-NLS-1$

	/* event strings */
	static final String DOMEVENT_KEYUP = "keyup"; //$NON-NLS-1$
	static final String DOMEVENT_KEYDOWN = "keydown"; //$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_MOUSEWHEEL = "mousewheel"; //$NON-NLS-1$
	static final String DOMEVENT_FOCUSIN = "DOMFocusIn"; //$NON-NLS-1$
	static final String DOMEVENT_FOCUSOUT = "DOMFocusOut"; //$NON-NLS-1$

	static {
		Cocoa.WebInitForCarbon();

		NativeClearSessions = new Runnable() {
			public void run() {
				int storage = Cocoa.objc_msgSend (Cocoa.C_NSHTTPCookieStorage, Cocoa.S_sharedHTTPCookieStorage);
				int cookies = Cocoa.objc_msgSend (storage, Cocoa.S_cookies);
				int count = Cocoa.objc_msgSend (cookies, Cocoa.S_count);
				for (int i = 0; i < count; i++) {
					int cookie = Cocoa.objc_msgSend (cookies, Cocoa.S_objectAtIndex, i);
					boolean isSession = Cocoa.objc_msgSend (cookie, Cocoa.S_isSessionOnly) != 0;
					if (isSession) {
						Cocoa.objc_msgSend (storage, Cocoa.S_deleteCookie, cookie);
					}
				}
			}
		};

		NativeGetCookie = new Runnable () {
			public void run () {
				int storage = Cocoa.objc_msgSend (Cocoa.C_NSHTTPCookieStorage, Cocoa.S_sharedHTTPCookieStorage);
				int urlString = createNSString (CookieUrl);
				int url = Cocoa.objc_msgSend (Cocoa.C_NSURL, Cocoa.S_URLWithString, urlString);
				OS.CFRelease (urlString);
				int cookies = Cocoa.objc_msgSend (storage, Cocoa.S_cookiesForURL, url);
				int count = Cocoa.objc_msgSend (cookies, Cocoa.S_count);
				if (count == 0) return;

				int name = createNSString (CookieName);
				for (int i = 0; i < count; i++) {
					int current = Cocoa.objc_msgSend (cookies, Cocoa.S_objectAtIndex, i);
					int currentName = Cocoa.objc_msgSend (current, Cocoa.S_name);
					if (Cocoa.objc_msgSend (currentName, Cocoa.S_compare, name) == Cocoa.NSOrderedSame) {
						int value = Cocoa.objc_msgSend (current, Cocoa.S_value);
						int length = OS.CFStringGetLength (value);
						char[] buffer = new char[length];
						CFRange range = new CFRange ();
						range.length = length;
						OS.CFStringGetCharacters (value, range, buffer);
						CookieValue = new String (buffer);
						OS.CFRelease (name);
						return;
					}
				}
				OS.CFRelease (name);
			}
		};

		NativeSetCookie = new Runnable () {
			public void run () {
				int urlString = createNSString(CookieUrl);
				int url = Cocoa.objc_msgSend (Cocoa.C_NSURL, Cocoa.S_URLWithString, urlString);
				OS.CFRelease (urlString);

				int value = createNSString (CookieValue);
				int key = createNSString (HEADER_SETCOOKIE);
				int headers = Cocoa.objc_msgSend (Cocoa.C_NSMutableDictionary, Cocoa.S_dictionaryWithCapacity, 1);
				Cocoa.objc_msgSend (headers, Cocoa.S_setValue, value, key);
				OS.CFRelease (key);
				OS.CFRelease (value);

				int cookies = Cocoa.objc_msgSend (Cocoa.C_NSHTTPCookie, Cocoa.S_cookiesWithResponseHeaderFields, headers, url);
				if (Cocoa.objc_msgSend (cookies, Cocoa.S_count) == 0) return;
				int cookie = Cocoa.objc_msgSend (cookies, Cocoa.S_objectAtIndex, 0);
				int storage = Cocoa.objc_msgSend (Cocoa.C_NSHTTPCookieStorage, Cocoa.S_sharedHTTPCookieStorage);
				Cocoa.objc_msgSend (storage, Cocoa.S_setCookie, cookie);
				CookieResult = true;
			}
		};

		if (NativePendingCookies != null) {
			SetPendingCookies (NativePendingCookies);
		}
		NativePendingCookies = null;
	}

public void create (Composite parent, int style) {
	/*
	* Note.  Loading the webkit bundle on Jaguar causes a crash.
	* The workaround is to detect any OS prior to 10.30 and fail
	* without crashing.
	*/
	if (OS.VERSION < 0x1030) {
		browser.dispose();
		SWT.error(SWT.ERROR_NO_HANDLES);
	}
	
	/*
	* Bug in WebKit on OSX 10.5 (Leopard) only.  VoiceOver no longer follows focus when
	* HIWebViewCreate is used to create a WebView.  The VoiceOver cursor (activated by
	* Control+Alt+arrows) continues to work, but keyboard focus is not tracked.  The fix
	* is to create the WebView with HICocoaViewCreate (api introduced in OSX 10.5) when
	* running on OSX 10.5.
	*/
	int outControl[] = new int[1];
	if (OS.VERSION >= 0x1050) {
		webView = Cocoa.objc_msgSend(Cocoa.objc_msgSend(Cocoa.C_WebView, Cocoa.S_alloc), Cocoa.S_initWithFrame_frameName_groupName, new NSRect(), 0, 0);
		if (webView != 0) {
			Cocoa.HICocoaViewCreate(webView, 0, outControl);
			webViewHandle = outControl[0];
			Cocoa.objc_msgSend(webView, Cocoa.S_release);
		}
	} else {
		Cocoa.HIWebViewCreate(outControl);
		webViewHandle = outControl[0];
		if (webViewHandle != 0) {
			webView = Cocoa.HIWebViewGetWebView(webViewHandle);
		}
	}
	if (webViewHandle == 0) {
		browser.dispose();
		SWT.error(SWT.ERROR_NO_HANDLES);
	}

	Display display = browser.getDisplay();
	display.setData(ADD_WIDGET_KEY, new Object[] {new Integer(webViewHandle), browser});

	/*
	* WebKit's DOM listener api became functional in OSX 10.4.  If OSX 10.4 or 
	* later is detected then override the default event mechanism to not send key
	* events and some mouse events so that the browser can send them by listening
	* to the DOM instead.
	*/
	if (!(OS.VERSION < 0x1040)) {
		browser.setData(WEBKIT_EVENTS_FIX_KEY);
	}

	/*
	* Bug in WebKit.  For some reason, every application must contain
	* a visible window that has never had a WebView or mouse move events
	* are not delivered.  This seems to happen after a browser has been
	* either hidden or disposed in any window.  The fix is to create a
	* single transparent overlay window that is disposed when the display
	* is disposed.
	*/
	if (display.getData(BROWSER_WINDOW) == null) {
		Rect bounds = new Rect ();
		OS.SetRect (bounds, (short) 0, (short) 0, (short) 1, (short) 1);
		final int[] outWindow = new int[1];
		OS.CreateNewWindow(OS.kOverlayWindowClass, 0, bounds, outWindow);
		OS.ShowWindow(outWindow[0]);
		OS.HIObjectSetAccessibilityIgnored (outWindow[0], true);
		display.disposeExec(new Runnable() {
			public void run() {
				if (outWindow[0] != 0) {
					OS.DisposeWindow(outWindow[0]);
				}
				outWindow[0] = 0;
			}
		});
		display.setData(BROWSER_WINDOW, outWindow);
	}
	
	/*
	* Bug in WebKit. The WebView does not draw properly if it is embedded as
	* sub view of the browser handle.  The fix is to add the web view to the
	* window root control and resize it on top of the browser handle.
	* 
	* Note that when the browser is reparented, the web view has to
	* be reparented by hand by hooking kEventControlOwningWindowChanged.
	*/
	int window = OS.GetControlOwner(browser.handle);
	int[] contentView = new int[1];
	OS.HIViewFindByID(OS.HIViewGetRoot(window), OS.kHIViewWindowContentID(), contentView);
	OS.HIViewAddSubview(contentView[0], webViewHandle);
	OS.HIViewChangeFeatures(webViewHandle, OS.kHIViewFeatureIsOpaque, 0);

	/*
	* Bug in WebKit. The WebView does not receive mouse and key events when it is added
	* to a visible top window.  It is assumed that WebKit hooks its own event listener
	* when the top window emits the kEventWindowShown event. The workaround is to send a
	* fake kEventWindowShown event to the top window after the WebView has been added
	* to the HIView (after the top window is visible) to give WebKit a chance to hook
	* events.
	*/
	OS.HIViewSetVisible(webViewHandle, true);	
	if (browser.getShell().isVisible()) {
		int[] showEvent = new int[1];
		OS.CreateEvent(0, OS.kEventClassWindow, OS.kEventWindowShown, 0.0, OS.kEventAttributeUserEvent, showEvent);
		OS.SetEventParameter(showEvent[0], OS.kEventParamDirectObject, OS.typeWindowRef, 4, new int[] {OS.GetControlOwner(browser.handle)});
		OS.SendEventToEventTarget(showEvent[0], OS.GetWindowEventTarget(window));
		if (showEvent[0] != 0) OS.ReleaseEvent(showEvent[0]);
	}

	/*
	* This code is intentionally commented. Setting a group name is the right thing
	* to do in order to avoid multiple open window requests. For some reason, WebKit
	* crashes when requested to reopen the same window if that window was previously
	* closed. This may be because that window was not correctly closed. 
	*/	
//	String groupName = "MyDocument"; //$NON-NLS-1$
//	int length = groupName.length();
//	char[] buffer = new char[length];
//	groupName.getChars(0, length, buffer, 0);
//	int groupNameString = OS.CFStringCreateWithCharacters(0, buffer, length);
//	// [webView setGroupName:@"MyDocument"];
//	WebKit.objc_msgSend(webView, WebKit.S_setGroupName, groupNameString);
//	OS.CFRelease(groupNameString);
	
	final int notificationCenter = Cocoa.objc_msgSend(Cocoa.C_NSNotificationCenter, Cocoa.S_defaultCenter);

	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 && !browser.isDisposed()) {
						close (false);
					}

					OS.RemoveEventHandler(windowBoundsHandler);
					windowBoundsHandler = 0;

					e.display.setData(ADD_WIDGET_KEY, new Object[] {new Integer(webViewHandle), null});

					Cocoa.objc_msgSend(webView, Cocoa.S_setFrameLoadDelegate, 0);
					Cocoa.objc_msgSend(webView, Cocoa.S_setResourceLoadDelegate, 0);
					Cocoa.objc_msgSend(webView, Cocoa.S_setUIDelegate, 0);
					Cocoa.objc_msgSend(webView, Cocoa.S_setPolicyDelegate, 0);
					Cocoa.objc_msgSend(webView, Cocoa.S_setDownloadDelegate, 0);
					Cocoa.objc_msgSend(notificationCenter, Cocoa.S_removeObserver, delegate);
					
					Cocoa.objc_msgSend(delegate, Cocoa.S_release);
					OS.DisposeControl(webViewHandle);
					webView = webViewHandle = 0;
					html = null;
					lastHoveredLinkURL = lastNavigateURL = null;

					Enumeration elements = functions.elements ();
					while (elements.hasMoreElements ()) {
						((BrowserFunction)elements.nextElement ()).dispose (false);
					}
					functions = null;

					if (preferences != 0) {
						Cocoa.objc_msgSend (preferences, Cocoa.S_release);
					}
					preferences = 0;
					break;
				}
				case SWT.FocusIn: {
					hasNewFocusElement = true;
					OS.SetKeyboardFocus(OS.GetControlOwner(browser.handle), webViewHandle, (short)-1);
					break;
				}
			}
		}
	};
	browser.addListener(SWT.Dispose, listener);
	browser.addListener(SWT.FocusIn, listener);
	browser.addListener(SWT.KeyDown, listener); /* needed to make browser traversable */
	
	if (Callback3 == null) Callback3 = new Callback(this.getClass(), "eventProc3", 3); //$NON-NLS-1$
	int callback3Address = Callback3.getAddress();
	if (callback3Address == 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);

	int[] mask = new int[] {
		OS.kEventClassKeyboard, OS.kEventRawKeyDown,
		OS.kEventClassControl, OS.kEventControlDraw,
		OS.kEventClassControl, OS.kEventControlGetClickActivation,
		OS.kEventClassControl, OS.kEventControlSetCursor,
		OS.kEventClassTextInput, OS.kEventTextInputUnicodeForKeyEvent,
	};
	OS.InstallEventHandler(OS.GetControlEventTarget(webViewHandle), callback3Address, mask.length / 2, mask, webViewHandle, null);
	int[] mask1 = new int[] {
		OS.kEventClassControl, OS.kEventControlBoundsChanged,
		OS.kEventClassControl, OS.kEventControlVisibilityChanged,
		OS.kEventClassControl, OS.kEventControlOwningWindowChanged,
	};
	OS.InstallEventHandler(OS.GetControlEventTarget(browser.handle), callback3Address, mask1.length / 2, mask1, browser.handle, null);
	int[] mask2 = new int[] {
		OS.kEventClassWindow, OS.kEventWindowBoundsChanged,
	};
	int[] outRef = new int[1];
	OS.InstallEventHandler(OS.GetWindowEventTarget(window), callback3Address, mask2.length / 2, mask2, browser.handle, outRef);
	windowBoundsHandler = outRef[0];

	if (Callback7 == null) Callback7 = new Callback(this.getClass(), "eventProc7", 7); //$NON-NLS-1$
	int callback7Address = Callback7.getAddress();
	if (callback7Address == 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
	
	// delegate = [[WebResourceLoadDelegate alloc] init eventProc];
	delegate = Cocoa.objc_msgSend(Cocoa.C_WebKitDelegate, Cocoa.S_alloc);
	delegate = Cocoa.objc_msgSend(delegate, Cocoa.S_initWithProc, callback7Address, webViewHandle);

	// [webView setFrameLoadDelegate:delegate];
	Cocoa.objc_msgSend(webView, Cocoa.S_setFrameLoadDelegate, delegate);
		
	// [webView setResourceLoadDelegate:delegate];
	Cocoa.objc_msgSend(webView, Cocoa.S_setResourceLoadDelegate, delegate);

	// [webView setUIDelegate:delegate];
	Cocoa.objc_msgSend(webView, Cocoa.S_setUIDelegate, delegate);
	
	/* register delegate for all notifications sent out from webview */
	Cocoa.objc_msgSend(notificationCenter, Cocoa.S_addObserver_selector_name_object, delegate, Cocoa.S_handleNotification, 0, webView);
	
	// [webView setPolicyDelegate:delegate];
	Cocoa.objc_msgSend(webView, Cocoa.S_setPolicyDelegate, delegate);

	// [webView setDownloadDelegate:delegate];
	Cocoa.objc_msgSend(webView, Cocoa.S_setDownloadDelegate, delegate);

	// [webView setApplicationNameForUserAgent:applicationName];
	int sHandle = createNSString(AGENT_STRING);
	Cocoa.objc_msgSend(webView, Cocoa.S_setApplicationNameForUserAgent, sHandle);
	OS.CFRelease(sHandle);

	if (OS.VERSION < 0x1050 && display.getActiveShell() == browser.getShell()) {
		Cocoa.objc_msgSend(Cocoa.objc_msgSend(webView, Cocoa.S_window), Cocoa.S_makeKeyWindow);
	}

	if (!Initialized) {
		Initialized = true;
		/* disable applets */
		int preferences = Cocoa.objc_msgSend(Cocoa.C_WebPreferences, Cocoa.S_standardPreferences);
		Cocoa.objc_msgSend(preferences, Cocoa.S_setJavaEnabled, 0);
	}
}

static int eventProc3(int nextHandler, int theEvent, int userData) {
	Widget widget = Display.getCurrent().findWidget(userData);
	if (widget instanceof Browser) {
		return ((WebKit)((Browser)widget).webBrowser).handleCallback(nextHandler, theEvent);
	}
	return OS.eventNotHandledErr;
}

static int eventProc7(int webview, int userData, int selector, int arg0, int arg1, int arg2, int arg3) {
	Widget widget = Display.getCurrent().findWidget(userData);
	if (widget instanceof Browser) {
		return ((WebKit)((Browser)widget).webBrowser).handleCallback(selector, arg0, arg1, arg2, arg3);
	}
	return 0;
}

static int createNSString(String string) {
	int length = string.length ();
	char[] buffer = new char[length];
	string.getChars (0, length, buffer, 0);
	return OS.CFStringCreateWithCharacters (0, buffer, length);
}

static String getString (int ptr) {
	int length = OS.CFStringGetLength (ptr);
	char[] buffer = new char[length];
	CFRange range = new CFRange ();
	range.length = length;
	OS.CFStringGetCharacters (ptr, range, buffer);
	return new String (buffer);
}

public boolean back() {
	html = null;
	return Cocoa.objc_msgSend(webView, Cocoa.S_goBack) != 0;
}

public boolean close () {
	return close (true);
}

boolean close (boolean showPrompters) {
	if (!jsEnabled) return true;

	String functionName = EXECUTE_ID + "CLOSE"; // $NON-NLS-1$
	StringBuffer buffer = new StringBuffer ("function "); // $NON-NLS-1$
	buffer.append (functionName);
	buffer.append ("(win) {\n"); // $NON-NLS-1$
	buffer.append ("var fn = win.onbeforeunload; if (fn != null) {try {var str = fn(); "); // $NON-NLS-1$
	if (showPrompters) {
		buffer.append ("if (str != null) { "); // $NON-NLS-1$
		buffer.append ("var result = window.external.callRunBeforeUnloadConfirmPanelWithMessage(str);"); // $NON-NLS-1$
		buffer.append ("if (!result) return false;}"); // $NON-NLS-1$
	}	
	buffer.append ("} catch (e) {}}"); // $NON-NLS-1$
	buffer.append ("try {for (var i = 0; i < win.frames.length; i++) {var result = "); // $NON-NLS-1$
	buffer.append (functionName);
	buffer.append ("(win.frames[i]); if (!result) return false;}} catch (e) {} return true;"); // $NON-NLS-1$
	buffer.append ("\n};"); // $NON-NLS-1$
	execute (buffer.toString ());

	Boolean result = (Boolean)evaluate ("return " + functionName +"(window);"); // $NON-NLS-1$ // $NON-NLS-2$
	if (result == null) return false;
	return result.booleanValue ();
}

public boolean execute(String script) {
	int frame = Cocoa.objc_msgSend(webView, Cocoa.S_mainFrame);
	int context = Cocoa.objc_msgSend(frame, Cocoa.S_globalContext);

	byte[] bytes = null;
	try {
		bytes = (script + '\0').getBytes("UTF-8"); //$NON-NLS-1$
	} catch (UnsupportedEncodingException e) {
		bytes = (script + '\0').getBytes();
	}
	int scriptString = OS.JSStringCreateWithUTF8CString(bytes);

	try {
		bytes = (getUrl() + '\0').getBytes("UTF-8"); //$NON-NLS-1$
	} catch (UnsupportedEncodingException e) {
		bytes = (getUrl() + '\0').getBytes();
	}
	int urlString = OS.JSStringCreateWithUTF8CString(bytes);

	int result = OS.JSEvaluateScript(context, scriptString, 0, urlString, 0, null);
	OS.JSStringRelease(urlString);
	OS.JSStringRelease(scriptString);
	return result != 0;
}

public boolean forward() {
	html = null;
	return Cocoa.objc_msgSend(webView, Cocoa.S_goForward) != 0;
}

public String getBrowserType () {
	return "webkit"; //$NON-NLS-1$
}

public String getText() {
	int mainFrame = Cocoa.objc_msgSend(webView, Cocoa.S_mainFrame);
	int dataSource = Cocoa.objc_msgSend(mainFrame, Cocoa.S_dataSource);
	if (dataSource == 0) return "";	//$NON-NLS-1$
	int representation = Cocoa.objc_msgSend(dataSource, Cocoa.S_representation);
	if (representation == 0) return "";	//$NON-NLS-1$
	int source = Cocoa.objc_msgSend(representation, Cocoa.S_documentSource);
	if (source == 0) return "";	//$NON-NLS-1$
	int length = OS.CFStringGetLength(source);
	char[] buffer = new char[length];
	CFRange range = new CFRange();
	range.length = length;
	OS.CFStringGetCharacters(source, range, buffer);
	return new String(buffer);
}

public String getUrl() {
	/* WebKit auto-navigates to about:blank at startup */
	if (url.length() == 0) return ABOUT_BLANK;

	return url;
}

int handleCallback(int nextHandler, int theEvent) {
	int eventKind = OS.GetEventKind(theEvent);
	switch (OS.GetEventClass(theEvent)) {
		case OS.kEventClassControl:
			switch (eventKind) {
				case OS.kEventControlGetClickActivation: {
					OS.SetEventParameter (theEvent, OS.kEventParamClickActivation, OS.typeClickActivationResult, 4, new int [] {OS.kActivateAndHandleClick});
					return OS.noErr;
				}
				case OS.kEventControlSetCursor: {
					return OS.noErr;
				}
				case OS.kEventControlDraw: {
					/*
					 * Bug on WebKit. The web view cannot be obscured by other views above it.
					 * This problem is specified in the apple documentation for HiWebViewCreate.
					 * The workaround is to don't draw the web view when it is not visible.
					 */
					if (!browser.isVisible ()) return OS.noErr;
					break;
				}
				case OS.kEventControlOwningWindowChanged: {
					/* Reparent the web view handler */
					int window = OS.GetControlOwner(browser.handle);
					int[] contentView = new int[1];
					OS.HIViewFindByID(OS.HIViewGetRoot(window), OS.kHIViewWindowContentID(), contentView);
					OS.HIViewAddSubview(contentView[0], webViewHandle);
					
					/* Reset the kEventWindowBoundsChanged handler */
					OS.RemoveEventHandler(windowBoundsHandler);
					int[] mask2 = new int[] {
						OS.kEventClassWindow, OS.kEventWindowBoundsChanged,
					};
					int[] outRef = new int[1];
					OS.InstallEventHandler(OS.GetWindowEventTarget(window), Callback3.getAddress(), mask2.length / 2, mask2, browser.handle, outRef);
					windowBoundsHandler = outRef[0];
					break;
				}
				case OS.kEventControlBoundsChanged:
				case OS.kEventControlVisibilityChanged: {
					/*
					 * Bug on WebKit. The web view cannot be obscured by other views above it.
					 * This problem is specified in the apple documentation for HiWebViewCreate.
					 * The workaround is to hook kEventControlVisibilityChanged on the browser
					 * and move the browser out of the screen when hidden and restore its bounds
					 * when shown.
					 */
					CGRect bounds = new CGRect();
					if (!browser.isVisible()) {
						bounds.x = bounds.y = -MIN_SIZE;
						bounds.width = bounds.height = MIN_SIZE;
						OS.HIViewSetFrame(webViewHandle, bounds);
					} else {
						OS.HIViewGetBounds(browser.handle, bounds);
						int[] contentView = new int[1];
						OS.HIViewFindByID(OS.HIViewGetRoot(OS.GetControlOwner(browser.handle)), OS.kHIViewWindowContentID(), contentView);
						OS.HIViewConvertRect(bounds, browser.handle, contentView[0]);
						/* 
						* Bug in WebKit.  For some reason, the web view will display incorrectly or
						* blank depending on its contents, if its size is set to a value smaller than
						* MIN_SIZE. It will not display properly even after the size is made larger.
						* The fix is to avoid setting sizes smaller than MIN_SIZE. 
						*/
						if (bounds.width <= MIN_SIZE) bounds.width = MIN_SIZE;
						if (bounds.height <= MIN_SIZE) bounds.height = MIN_SIZE;
						OS.HIViewSetFrame(webViewHandle, bounds);
					}
					break;
				}
			}
		case OS.kEventClassWindow:
			switch (eventKind) {
				case OS.kEventWindowBoundsChanged:
					/*
					 * Bug on WebKit. Resizing the height of a Shell containing a Browser at
					 * a fixed location causes the Browser to redraw at a wrong location.
					 * The web view is a HIView container that internally hosts
					 * a Cocoa NSView that uses a coordinates system with the origin at the
					 * bottom left corner of a window instead of the coordinates system used
					 * in Carbon that starts at the top left corner. The workaround is to
					 * reposition the web view every time the Shell of the Browser is resized.
					 * 
					 * Note the size should not be updated if the browser is hidden.
					 */
					if (browser.isVisible()) {
						CGRect oldBounds = new CGRect();
						OS.GetEventParameter (theEvent, OS.kEventParamOriginalBounds, OS.typeHIRect, null, CGRect.sizeof, null, oldBounds);
						CGRect bounds = new CGRect();
						OS.GetEventParameter (theEvent, OS.kEventParamCurrentBounds, OS.typeHIRect, null, CGRect.sizeof, null, bounds);
						if (oldBounds.height == bounds.height) break;
						OS.HIViewGetBounds(browser.handle, bounds);
						int[] contentView = new int[1];
						OS.HIViewFindByID(OS.HIViewGetRoot(OS.GetControlOwner(browser.handle)), OS.kHIViewWindowContentID(), contentView);
						OS.HIViewConvertRect(bounds, browser.handle, contentView[0]);
						/* 
						* Bug in WebKit.  For some reason, the web view will display incorrectly or
						* blank depending on its contents, if its size is set to a value smaller than
						* MIN_SIZE. It will not display properly even after the size is made larger.
						* The fix is to avoid setting sizes smaller than MIN_SIZE. 
						*/
						if (bounds.width <= MIN_SIZE) bounds.width = MIN_SIZE;
						if (bounds.height <= MIN_SIZE) bounds.height = MIN_SIZE;
						bounds.x++;
						/* Note that the bounds needs to change */
						OS.HIViewSetFrame(webViewHandle, bounds);
						bounds.x--;
						OS.HIViewSetFrame(webViewHandle, bounds);
					}
			}
		case OS.kEventClassKeyboard:
			switch (eventKind) {
				case OS.kEventRawKeyDown: {
					/*
					* Bug in WebKit. The WebView blocks the propagation of certain Carbon events
					* such as kEventRawKeyDown. On the Mac, Carbon events propagate from the
					* Focus Target Handler to the Control Target Handler, Window Target and finally
					* the Application Target Handler. It is assumed that WebView hooks its events
					* on the Window Target and does not pass kEventRawKeyDown to the next handler.
					* Since kEventRawKeyDown events never make it to the Application Target Handler,
					* the Application Target Handler never gets to emit kEventTextInputUnicodeForKeyEvent
					* used by SWT to send a SWT.KeyDown event.
					* The workaround is to hook kEventRawKeyDown on the Control Target Handler which gets
					* called before the WebView hook on the Window Target Handler. Then, forward this event
					* directly to the Application Target Handler. Note that if in certain conditions WebKit
					* does not block the kEventRawKeyDown, then multiple kEventTextInputUnicodeForKeyEvent
					* events might be generated as a result of this workaround.
					*/
					//TEMPORARY CODE
//					doit = false;
//					OS.SendEventToEventTarget(theEvent, OS.GetApplicationEventTarget());
//					if (!doit) return OS.noErr;

					int[] length = new int[1];
					int status = OS.GetEventParameter (theEvent, OS.kEventParamKeyUnicodes, OS.typeUnicodeText, null, 4, length, (char[])null);
					if (status == OS.noErr && length[0] != 0) {
						int[] modifiers = new int[1];
						OS.GetEventParameter (theEvent, OS.kEventParamKeyModifiers, OS.typeUInt32, null, 4, null, modifiers);
						char[] chars = new char[1];
						OS.GetEventParameter (theEvent, OS.kEventParamKeyUnicodes, OS.typeUnicodeText, null, 2, null, chars);
						if ((modifiers[0] & OS.cmdKey) != 0) {
							switch (chars[0]) {
								case 'v': {
									Cocoa.objc_msgSend (webView, Cocoa.S_paste);
									return OS.noErr;
								}
								case 'c': {
									Cocoa.objc_msgSend (webView, Cocoa.S_copy);
									return OS.noErr;
								}
								case 'x': {
									Cocoa.objc_msgSend (webView, Cocoa.S_cut);
									return OS.noErr;
								}
							}
						}
					}
					/*
					* Bug in Carbon.  OSX crashes if a HICocoaView is disposed during a key event,
					* presumably as a result of attempting to use it after its refcount has reached
					* 0.  The workaround is to temporarily add an extra ref to the view and its
					* ancestor while the DOM listener is handling the event, in case the
					* Browser gets disposed in a callback.
					*/
					int handle = webViewHandle, root = OS.HIViewGetSuperview (webViewHandle);
					OS.CFRetain (handle);
					OS.CFRetain (root);
					int result = OS.CallNextEventHandler (nextHandler, theEvent);
					OS.CFRelease (handle);
					OS.CFRelease (root);
					return result;
				}
			}
		case OS.kEventClassTextInput:
			switch (eventKind) {
				case OS.kEventTextInputUnicodeForKeyEvent: {
					/*
					* Note.  This event is received from the Window Target therefore after it was received
					* by the Focus Target. The SWT.KeyDown event is sent by SWT on the Focus Target. If it
					* is received here, then the SWT.KeyDown doit flag must have been left to the value
					* true.  For package visibility reasons we cannot access the doit flag directly.
					* 
					* Sequence of events when the user presses a key down
					* 
					* .Control Target - kEventRawKeyDown
					* 	.forward to ApplicationEventTarget
					* 		.Focus Target kEventTextInputUnicodeForKeyEvent - SWT emits SWT.KeyDown - 
					* 			blocks further propagation if doit false. Browser does not know directly about
					* 			the doit flag value.
					* 			.Window Target kEventTextInputUnicodeForKeyEvent - if received, Browser knows 
					* 			SWT.KeyDown is not blocked and event should be sent to WebKit
					*  Return from Control Target - kEventRawKeyDown: let the event go to WebKit if doit true 
					*  (eventNotHandledErr) or stop it (noErr).
					*/
					//TEMPORARY CODE
//					doit = true;
					break;
				}
			}
	}
	return OS.eventNotHandledErr;
}

/* Here we dispatch all WebView upcalls. */
int handleCallback(int selector, int arg0, int arg1, int arg2, int arg3) {
	int ret = 0;
	// for meaning of selector see WebKitDelegate methods in webkit.c
	switch (selector) {
		case 1: didFailProvisionalLoadWithError(arg0, arg1); break;
		case 2: didFinishLoadForFrame(arg0); break;
		case 3: didReceiveTitle(arg0, arg1); break;
		case 4: didStartProvisionalLoadForFrame(arg0); break;
		case 5: didFinishLoadingFromDataSource(arg0, arg1); break;
		case 6: didFailLoadingWithError(arg0, arg1, arg2); break;
		case 7: ret = identifierForInitialRequest(arg0, arg1); break;
		case 8: ret = willSendRequest(arg0, arg1, arg2, arg3); break;
		case 9: handleNotification(arg0); break;
		case 10: didCommitLoadForFrame(arg0); break;
		case 11: ret = createWebViewWithRequest(arg0); break;
		case 12: webViewShow(arg0); break;
		case 13: setFrame(arg0); break;
		case 14: webViewClose(); break;
		case 15: ret = contextMenuItemsForElement(arg0, arg1); break;
		case 16: setStatusBarVisible(arg0); break;
		case 17: setResizable(arg0); break;
		case 18: setToolbarsVisible(arg0); break;
		case 19: decidePolicyForMIMEType(arg0, arg1, arg2, arg3); break;
		case 20: decidePolicyForNavigationAction(arg0, arg1, arg2, arg3); break;
		case 21: decidePolicyForNewWindowAction(arg0, arg1, arg2, arg3); break;
		case 22: unableToImplementPolicyWithError(arg0, arg1); break;
		case 23: setStatusText(arg0); break;
		case 24: webViewFocus(); break;
		case 25: webViewUnfocus(); break;
		case 26: runJavaScriptAlertPanelWithMessage(arg0); break;
		case 27: ret = runJavaScriptConfirmPanelWithMessage(arg0); break;
		case 28: runOpenPanelForFileButtonWithResultListener(arg0); break;
		case 29: decideDestinationWithSuggestedFilename(arg0, arg1); break;
		case 30: mouseDidMoveOverElement(arg0, arg1); break;
		case 31: didChangeLocationWithinPageForFrame(arg0); break;
		case 32: handleEvent(arg0); break;
		case 33: windowScriptObjectAvailable(arg0); break;
		case 34: ret = callJava(arg0, arg1, arg2, arg3); break;
		case 35: didReceiveAuthenticationChallengefromDataSource(arg0, arg1, arg2); break;
		case 36: ret = runBeforeUnloadConfirmPanelWithMessage(arg0, arg1); break;
		case 37: ret = callRunBeforeUnloadConfirmPanelWithMessage(arg0, arg1); break;
		case 38: createPanelDidEnd(arg0, arg1, arg2); break;
	}
	return ret;
}

public boolean isBackEnabled() {
	return Cocoa.objc_msgSend(webView, Cocoa.S_canGoBack) != 0;
}

public boolean isForwardEnabled() {
	return Cocoa.objc_msgSend(webView, Cocoa.S_canGoForward) != 0;
}

public void refresh() {
	html = null;
	Cocoa.objc_msgSend(webView, Cocoa.S_reload, 0);
}

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 = this.html != null;
	this.html = html;
	untrustedText = !trusted;
	if (blankLoading) return true;

	int str = createNSString(ABOUT_BLANK);
	int inURL = Cocoa.objc_msgSend(Cocoa.C_NSURL, Cocoa.S_URLWithString, str); /* autoreleased */
	OS.CFRelease (str);
	int request = Cocoa.objc_msgSend(Cocoa.C_NSURLRequest, Cocoa.S_requestWithURL, inURL);
	int mainFrame = Cocoa.objc_msgSend(webView, Cocoa.S_mainFrame);
	Cocoa.objc_msgSend(mainFrame, Cocoa.S_loadRequest, request);
	return true;
}

public boolean setUrl(String url, String postData, String[] headers) {
	html = null;

	if (url.indexOf('/') == 0) {
		url = PROTOCOL_FILE + url;
	} else if (url.indexOf(':') == -1) {
		url = PROTOCOL_HTTP + url;
	}

	int inURL = 0;
	int str = createNSString(url);
	if (str != 0) {
		char[] unescapedChars = new char[] {'%', '#'};
		int unescapedStr = OS.CFStringCreateWithCharacters(0, unescapedChars, unescapedChars.length);
		int escapedStr = OS.CFURLCreateStringByAddingPercentEscapes(OS.kCFAllocatorDefault, str, unescapedStr, 0, OS.kCFStringEncodingUTF8);
		if (escapedStr != 0) {
			inURL = OS.CFURLCreateWithString(OS.kCFAllocatorDefault, escapedStr, 0);
			OS.CFRelease(escapedStr);
		}
		if (unescapedStr != 0) OS.CFRelease(unescapedStr);
		OS.CFRelease(str);
	}
	if (inURL == 0) return false;

	int request = Cocoa.objc_msgSend(Cocoa.C_NSMutableURLRequest, Cocoa.S_requestWithURL, inURL);
	OS.CFRelease(inURL);

	if (postData != null) {
		int post = createNSString(POST);
		Cocoa.objc_msgSend(request, Cocoa.S_setHTTPMethod, post);
		OS.CFRelease (post);
		byte[] bytes = postData.getBytes();
		int data = Cocoa.objc_msgSend(Cocoa.C_NSData, Cocoa.S_dataWithBytes, bytes, bytes.length);
		Cocoa.objc_msgSend(request, Cocoa.S_setHTTPBody, data);
	}
	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) {
						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.
							*/
							int string = createNSString(value);
							Cocoa.objc_msgSend(webView, Cocoa.S_setCustomUserAgent, string);
							OS.CFRelease (string);
						} else {
							int keyString = createNSString(key);
							int valueString = createNSString(value);
							Cocoa.objc_msgSend(request, Cocoa.S_setValueForHTTPHeaderField, valueString, keyString);
							OS.CFRelease (valueString);
							OS.CFRelease (keyString);
						}
					}
				}
			}
		}
	}

	int mainFrame = Cocoa.objc_msgSend(webView, Cocoa.S_mainFrame);
	Cocoa.objc_msgSend(mainFrame, Cocoa.S_loadRequest, request);
	Cocoa.objc_msgSend(webView, Cocoa.S_setCustomUserAgent, 0);
	return true;
}

public void stop() {
	html = null;
	Cocoa.objc_msgSend(webView, Cocoa.S_stopLoading, 0);
}

boolean translateMnemonics() {
	return false;
}

/* WebFrameLoadDelegate */
void didChangeLocationWithinPageForFrame(int frame) {
	//id url= [[[[frame provisionalDataSource] request] URL] absoluteString];
	int dataSource = Cocoa.objc_msgSend(frame, Cocoa.S_dataSource);
	int request = Cocoa.objc_msgSend(dataSource, Cocoa.S_request);
	int url = Cocoa.objc_msgSend(request, Cocoa.S_URL);
	int s = Cocoa.objc_msgSend(url, Cocoa.S_absoluteString);
	int length = OS.CFStringGetLength(s);
	if (length == 0) return;
	char[] buffer = new char[length];
	CFRange range = new CFRange();
	range.length = length;
	OS.CFStringGetCharacters(s, range, buffer);
	String url2 = new String(buffer);
	/*
	 * If the URI indicates that the page is being rendered from memory
	 * (via setText()) then set it to about:blank to be consistent with IE.
	 */
	if (url2.equals (URI_FILEROOT)) {
		url2 = ABOUT_BLANK;
	} else {
		length = URI_FILEROOT.length ();
		if (url2.startsWith (URI_FILEROOT) && url2.charAt (length) == '#') {
			url2 = ABOUT_BLANK + url2.substring (length);
		}
	}

	final Display display = browser.getDisplay();
	boolean top = frame == Cocoa.objc_msgSend(webView, Cocoa.S_mainFrame);
	if (top) {
		StatusTextEvent statusText = new StatusTextEvent(browser);
		statusText.display = display;
		statusText.widget = browser;
		statusText.text = url2;
		for (int i = 0; i < statusTextListeners.length; i++) {
			statusTextListeners[i].changed(statusText);
		}
	}
	LocationEvent location = new LocationEvent(browser);
	location.display = display;
	location.widget = browser;
	location.location = url2;
	location.top = top;
	for (int i = 0; i < locationListeners.length; i++) {
		locationListeners[i].changed(location);
	}
}

void didFailProvisionalLoadWithError(int error, int frame) {
	if (frame == Cocoa.objc_msgSend(webView, Cocoa.S_mainFrame)) {
		/*
		* Feature on WebKit.  The identifier is used here as a marker for the events 
		* related to the top frame and the URL changes related to that top frame as 
		* they should appear on the location bar of a browser.  It is expected to reset
		* the identifier to 0 when the event didFinishLoadingFromDataSource related to 
		* the identifierForInitialRequest event is received.  However, WebKit fires
		* the didFinishLoadingFromDataSource event before the entire content of the
		* top frame is loaded.  It is possible to receive multiple willSendRequest 
		* events in this interval, causing the Browser widget to send unwanted
		* Location.changing events.  For this reason, the identifier is reset to 0
		* when the top frame has either finished loading (didFinishLoadForFrame
		* event) or failed (didFailProvisionalLoadWithError).
		*/
		identifier = 0;
	}

	int errorCode = Cocoa.objc_msgSend(error, Cocoa.S_code);
	if (Cocoa.NSURLErrorBadURL < errorCode) return;

	int failingURL = 0;
	int info = Cocoa.objc_msgSend(error, Cocoa.S_userInfo);
	if (info != 0) {
		int keyString = createNSString("NSErrorFailingURLKey"); //$NON-NLS-1$
		failingURL = Cocoa.objc_msgSend(info, Cocoa.S_valueForKey, keyString);
		OS.CFRelease(keyString);
	}

	if (failingURL != 0 && Cocoa.NSURLErrorServerCertificateNotYetValid <= errorCode && errorCode <= Cocoa.NSURLErrorSecureConnectionFailed) {
		/* handle invalid certificate error */
		int keyString = createNSString("NSErrorPeerCertificateChainKey"); //$NON-NLS-1$
		int certificates = Cocoa.objc_msgSend(info, Cocoa.S_objectForKey, keyString);
		OS.CFRelease(keyString);

		int[] policySearch = new int[1];
		int[] policyRef = new int[1];
		int[] trustRef = new int[1];
		boolean success = false;
		int result = OS.SecPolicySearchCreate(OS.CSSM_CERT_X_509v3, 0, 0, policySearch);
		if (result == 0 && policySearch[0] != 0) {
			result = OS.SecPolicySearchCopyNext(policySearch[0], policyRef);
			if (result == 0 && policyRef[0] != 0) {
				result = OS.SecTrustCreateWithCertificates(certificates, policyRef[0], trustRef);
				if (result == 0 && trustRef[0] != 0) {
					int panel = Cocoa.objc_msgSend(Cocoa.C_SFCertificateTrustPanel, Cocoa.S_sharedCertificateTrustPanel);
					String failingUrlString = getString(Cocoa.objc_msgSend(failingURL, Cocoa.S_absoluteString));
					String message = Compatibility.getMessage("SWT_InvalidCert_Message", new Object[] {failingUrlString}); //$NON-NLS-1$
					int nsString = createNSString(Compatibility.getMessage("SWT_Cancel")); //$NON-NLS-1$
					Cocoa.objc_msgSend(panel, Cocoa.S_setAlternateButtonTitle, nsString);
					OS.CFRelease(nsString);
					Cocoa.objc_msgSend(panel, Cocoa.S_setShowsHelp, 1);
					Cocoa.objc_msgSend(failingURL, Cocoa.S_retain);
					int window = Cocoa.objc_msgSend(webView, Cocoa.S_window);
					nsString = createNSString(message);
					Cocoa.objc_msgSend(panel, Cocoa.S_beginSheetForWindow, window, delegate, Cocoa.S_createPanelDidEnd, failingURL, trustRef[0], nsString);
					OS.CFRelease(nsString);
					success = true;
				}
			}
		}

		if (trustRef[0] != 0) OS.CFRelease(trustRef[0]);
		if (policyRef[0] != 0) OS.CFRelease(policyRef[0]);
		if (policySearch[0] != 0) OS.CFRelease(policySearch[0]);
		if (success) return;
	}

	/* handle other types of errors */
	int description = Cocoa.objc_msgSend(error, Cocoa.S_localizedDescription);
	if (description != 0) {
		String descriptionString = getString(description);
		String message = failingURL != 0 ? getString(Cocoa.objc_msgSend(failingURL, Cocoa.S_absoluteString)) + "\n\n" : ""; //$NON-NLS-1$ //$NON-NLS-2$
		message += Compatibility.getMessage ("SWT_Page_Load_Failed", new Object[] {descriptionString}); //$NON-NLS-1$
		MessageBox messageBox = new MessageBox(browser.getShell(), SWT.OK | SWT.ICON_ERROR);
		messageBox.setMessage(message);
		messageBox.open();
	}
}

void createPanelDidEnd(int sheet, int returnCode, int contextInfo) {
	Cocoa.objc_msgSend(contextInfo, Cocoa.S_autorelease);
	if (returnCode != Cocoa.NSFileHandlingPanelOKButton) return;	/* nothing more to do */

	long /*int*/ method = Cocoa.class_getClassMethod(Cocoa.C_NSURLRequest, Cocoa.S_setAllowsAnyHTTPSCertificate);
	if (method != 0) {
		int host = Cocoa.objc_msgSend(contextInfo, Cocoa.S_host);
		int urlString = Cocoa.objc_msgSend(contextInfo, Cocoa.S_absoluteString);
		Cocoa.objc_msgSend(Cocoa.C_NSURLRequest, Cocoa.S_setAllowsAnyHTTPSCertificate, 1, host);
		setUrl(getString(urlString), null, null);
	}
}

void didFinishLoadForFrame(int frame) {
	if (frame == Cocoa.objc_msgSend(webView, Cocoa.S_mainFrame)) {
		/*
		 * If html is not null then there is html from a previous setText() call
		 * waiting to be set into the about:blank page once it has completed loading. 
		 */
		if (html != null) {
			if (getUrl().startsWith(ABOUT_BLANK)) {
				loadingText = true;
				int htmlString = createNSString(html);
				int urlString;
				if (untrustedText) {
					urlString = createNSString(ABOUT_BLANK);
				} else {
					urlString = createNSString(URI_FILEROOT);
				}
				int url = Cocoa.objc_msgSend(Cocoa.C_NSURL, Cocoa.S_URLWithString, urlString); /* autoreleased */
				int mainFrame = Cocoa.objc_msgSend(webView, Cocoa.S_mainFrame);
				Cocoa.objc_msgSend(mainFrame, Cocoa.S_loadHTMLStringBaseURL, htmlString, url);
				OS.CFRelease(urlString);
				OS.CFRelease(htmlString);
				html = null;
			}
		}

		/*
		* The loadHTMLStringBaseURL invocation above will trigger a second didFinishLoadForFrame
		* callback when it is completed.  If text was just set into the browser then wait
		* for this second callback to come before sending the title or completed events.
		*/
		if (!loadingText) {
			/*
			* To be consistent with other platforms a title event should be fired when a
			* page has completed loading.  A page with a <title> tag will do this
			* automatically when the didReceiveTitle callback is received.  However a page
			* without a <title> tag will not do this by default, so fire the event
			* here with the page's url as the title.
			*/
			final Display display = browser.getDisplay();
			int dataSource = Cocoa.objc_msgSend(frame, Cocoa.S_dataSource);
			if (dataSource != 0) {
				int title = Cocoa.objc_msgSend(dataSource, Cocoa.S_pageTitle);
				if (title == 0) {	/* page has no title */
					final TitleEvent newEvent = new TitleEvent(browser);
					newEvent.display = display;
					newEvent.widget = browser;
					newEvent.title = getUrl();
					for (int i = 0; i < titleListeners.length; i++) {
						titleListeners[i].changed(newEvent);
					}
					if (browser.isDisposed()) return;
				}
			}

			ProgressEvent progress = new ProgressEvent(browser);
			progress.display = display;
			progress.widget = browser;
			progress.current = MAX_PROGRESS;
			progress.total = MAX_PROGRESS;
			for (int i = 0; i < progressListeners.length; i++) {
				progressListeners[i].completed(progress);
			}
		}
		loadingText = false;
		if (browser.isDisposed()) return;

		/*
		* Feature on WebKit.  The identifier is used here as a marker for the events 
		* related to the top frame and the URL changes related to that top frame as 
		* they should appear on the location bar of a browser.  It is expected to reset
		* the identifier to 0 when the event didFinishLoadingFromDataSource related to 
		* the identifierForInitialRequest event is received.  Howeever, WebKit fires
		* the didFinishLoadingFromDataSource event before the entire content of the
		* top frame is loaded.  It is possible to receive multiple willSendRequest 
		* events in this interval, causing the Browser widget to send unwanted
		* Location.changing events.  For this reason, the identifier is reset to 0
		* when the top frame has either finished loading (didFinishLoadForFrame
		* event) or failed (didFailProvisionalLoadWithError).
		*/
		identifier = 0;
	}
}

void hookDOMFocusListeners(int frame) {
	/*
	* These listeners only need to be hooked for OSX 10.4 (Tiger).  The WebKit on
	* OSX < 10.4 does not send these DOM events, and tab traversals that exit
	* WebKit are handled as of OSX 10.5 as a result of using HICocoaViewCreate,
	* which makes these listeners unnecessary.
	*/
	if (!(0x1040 <= OS.VERSION && OS.VERSION < 0x1050)) return;

	int document = Cocoa.objc_msgSend(frame, Cocoa.S_DOMDocument);
	if (document == 0) return;

	int ptr = createNSString(DOMEVENT_FOCUSIN);
	Cocoa.objc_msgSend(document, Cocoa.S_addEventListener, ptr, delegate, 0);
	OS.CFRelease(ptr);

	ptr = createNSString(DOMEVENT_FOCUSOUT);
	Cocoa.objc_msgSend(document, Cocoa.S_addEventListener, ptr, delegate, 0);
	OS.CFRelease(ptr);
}
	
void hookDOMKeyListeners(int frame) {
	/*
	* WebKit's DOM listener api became functional in OSX 10.4, so if an earlier
	* version than this is detected then do not hook the DOM listeners.
	*/
	if (OS.VERSION < 0x1040) return;

	int document = Cocoa.objc_msgSend(frame, Cocoa.S_DOMDocument);
	if (document == 0) return;

	int ptr = createNSString(DOMEVENT_KEYDOWN);
	Cocoa.objc_msgSend(document, Cocoa.S_addEventListener, ptr, delegate, 0);
	OS.CFRelease(ptr);

	ptr = createNSString(DOMEVENT_KEYUP);
	Cocoa.objc_msgSend(document, Cocoa.S_addEventListener, ptr, delegate, 0);
	OS.CFRelease(ptr);
}

void hookDOMMouseListeners(int frame) {
	/*
	* WebKit's DOM listener api became functional in OSX 10.4, so if an earlier
	* version than this is detected then do not hook the DOM listeners.
	*/
	if (OS.VERSION < 0x1040) return;

	int document = Cocoa.objc_msgSend(frame, Cocoa.S_DOMDocument);
	if (document == 0) return;

	int ptr = createNSString(DOMEVENT_MOUSEDOWN);
	Cocoa.objc_msgSend(document, Cocoa.S_addEventListener, ptr, delegate, 0);
	OS.CFRelease(ptr);

	ptr = createNSString(DOMEVENT_MOUSEUP);
	Cocoa.objc_msgSend(document, Cocoa.S_addEventListener, ptr, delegate, 0);
	OS.CFRelease(ptr);

	ptr = createNSString(DOMEVENT_MOUSEMOVE);
	Cocoa.objc_msgSend(document, Cocoa.S_addEventListener, ptr, delegate, 0);
	OS.CFRelease(ptr);

	ptr = createNSString(DOMEVENT_MOUSEWHEEL);
	Cocoa.objc_msgSend(document, Cocoa.S_addEventListener, ptr, delegate, 0);
	OS.CFRelease(ptr);
}

void didReceiveTitle(int title, int frame) {
	if (frame == Cocoa.objc_msgSend(webView, Cocoa.S_mainFrame)) {
		int length = OS.CFStringGetLength(title);
		char[] buffer = new char[length];
		CFRange range = new CFRange();
		range.length = length;
		OS.CFStringGetCharacters(title, range, buffer);
		String newTitle = new String(buffer);
		TitleEvent newEvent = new TitleEvent(browser);
		newEvent.display = browser.getDisplay();
		newEvent.widget = browser;
		newEvent.title = newTitle;
		for (int i = 0; i < titleListeners.length; i++) {
			titleListeners[i].changed(newEvent);
		}
	}
}

void didStartProvisionalLoadForFrame(int frame) {
	/* 
	* This code is intentionally commented.  WebFrameLoadDelegate:didStartProvisionalLoadForFrame is
	* called before WebResourceLoadDelegate:willSendRequest and
	* WebFrameLoadDelegate:didCommitLoadForFrame.  The resource count is reset when didCommitLoadForFrame
	* is received for the top frame.
	*/
//	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
//	if (frame == WebKit.objc_msgSend(webView, WebKit.S_mainFrame)) {
//		/* reset resource status variables */
//		resourceCount= 0;
//	}
}

void didCommitLoadForFrame(int frame) {
	//id url= [[[[frame provisionalDataSource] request] URL] absoluteString];
	int dataSource = Cocoa.objc_msgSend(frame, Cocoa.S_dataSource);
	int request = Cocoa.objc_msgSend(dataSource, Cocoa.S_request);
	int url = Cocoa.objc_msgSend(request, Cocoa.S_URL);
	int s = Cocoa.objc_msgSend(url, Cocoa.S_absoluteString);	
	int length = OS.CFStringGetLength(s);
	if (length == 0) return;
	char[] buffer = new char[length];
	CFRange range = new CFRange();
	range.length = length;
	OS.CFStringGetCharacters(s, range, buffer);
	String url2 = new String(buffer);
	/*
	 * If the URI indicates that the page is being rendered from memory
	 * (via setText()) then set it to about:blank to be consistent with IE.
	 */
	if (url2.equals (URI_FILEROOT)) {
		url2 = ABOUT_BLANK;
	} else {
		length = URI_FILEROOT.length ();
		if (url2.startsWith (URI_FILEROOT) && url2.charAt (length) == '#') {
			url2 = ABOUT_BLANK + url2.substring (length);
		}
	}

	final Display display = browser.getDisplay();
	boolean top = frame == Cocoa.objc_msgSend(webView, Cocoa.S_mainFrame);
	if (top) {
		/* reset resource status variables */
		resourceCount = 0;		
		this.url = url2;

		/*
		* Each invocation of setText() causes didCommitLoadForFrame to be invoked twice,
		* once for the initial navigate to about:blank, and once for the auto-navigate
		* to about:blank that WebKit does when loadHTMLStringBaseURL is invoked.  If
		* this is the first didCommitLoadForFrame callback received for a setText()
		* invocation then do not send any events or re-install registered BrowserFunctions. 
		*/
		if (url2.startsWith(ABOUT_BLANK) && html != null) return;

		Enumeration elements = functions.elements ();
		while (elements.hasMoreElements ()) {
			BrowserFunction function = (BrowserFunction)elements.nextElement ();
			execute (function.functionString);
		}

		final ProgressEvent progress = new ProgressEvent(browser);
		progress.display = display;
		progress.widget = browser;
		progress.current = 1;
		progress.total = MAX_PROGRESS;
		for (int i = 0; i < progressListeners.length; i++) {
			progressListeners[i].changed(progress);
		}
		if (browser.isDisposed()) return;
		
		StatusTextEvent statusText = new StatusTextEvent(browser);
		statusText.display = display;
		statusText.widget = browser;
		statusText.text = url2;
		for (int i = 0; i < statusTextListeners.length; i++) {
			statusTextListeners[i].changed(statusText);
		}
		if (browser.isDisposed()) return;

		hookDOMKeyListeners(frame);
	}

	hookDOMFocusListeners(frame);
	hookDOMMouseListeners(frame);

	LocationEvent location = new LocationEvent(browser);
	location.display = display;
	location.widget = browser;
	location.location = url2;
	location.top = top;
	for (int i = 0; i < locationListeners.length; i++) {
		locationListeners[i].changed(location);
	}
}

void windowScriptObjectAvailable (int windowScriptObject) {
	int str = createNSString("external"); //$NON-NLS-1$
	if (str != 0) {
		Cocoa.objc_msgSend (windowScriptObject, Cocoa.S_setValue, delegate, str);
		OS.CFRelease (str);
	}
}

/* WebResourceLoadDelegate */

void didFinishLoadingFromDataSource(int identifier, int dataSource) {
	/*
	* Feature on WebKit.  The identifier is used here as a marker for the events 
	* related to the top frame and the URL changes related to that top frame as 
	* they should appear on the location bar of a browser.  It is expected to reset
	* the identifier to 0 when the event didFinishLoadingFromDataSource related to 
	* the identifierForInitialRequest event is received.  Howeever, WebKit fires
	* the didFinishLoadingFromDataSource event before the entire content of the
	* top frame is loaded.  It is possible to receive multiple willSendRequest 
	* events in this interval, causing the Browser widget to send unwanted
	* Location.changing events.  For this reason, the identifier is reset to 0
	* when the top frame has either finished loading (didFinishLoadForFrame
	* event) or failed (didFailProvisionalLoadWithError).
	*/
	// this code is intentionally commented
	//if (this.identifier == identifier) this.identifier = 0;
}

void didFailLoadingWithError(int identifier, int error, int dataSource) {
	/*
	* Feature on WebKit.  The identifier is used here as a marker for the events 
	* related to the top frame and the URL changes related to that top frame as 
	* they should appear on the location bar of a browser.  It is expected to reset
	* the identifier to 0 when the event didFinishLoadingFromDataSource related to 
	* the identifierForInitialRequest event is received.  Howeever, WebKit fires
	* the didFinishLoadingFromDataSource event before the entire content of the
	* top frame is loaded.  It is possible to receive multiple willSendRequest 
	* events in this interval, causing the Browser widget to send unwanted
	* Location.changing events.  For this reason, the identifier is reset to 0
	* when the top frame has either finished loading (didFinishLoadForFrame
	* event) or failed (didFailProvisionalLoadWithError).
	*/
	// this code is intentionally commented
	//if (this.identifier == identifier) this.identifier = 0;
}

void didReceiveAuthenticationChallengefromDataSource (int identifier, int challenge, int dataSource) {
	/*
	 * Do not invoke the listeners if this challenge has been failed too many
	 * times because a listener is likely giving incorrect credentials repeatedly
	 * and will do so indefinitely.
	 */
	int count = Cocoa.objc_msgSend (challenge, Cocoa.S_previousFailureCount);
	if (count < 3) {
		for (int i = 0; i < authenticationListeners.length; i++) {
			AuthenticationEvent event = new AuthenticationEvent (browser);
			event.location = lastNavigateURL;
			authenticationListeners[i].authenticate (event);
			if (!event.doit) {
				int challengeSender = Cocoa.objc_msgSend (challenge, Cocoa.S_sender);
				Cocoa.objc_msgSend (challengeSender, Cocoa.S_cancelAuthenticationChallenge, challenge);
				return;
			}
			if (event.user != null && event.password != null) {
				int challengeSender = Cocoa.objc_msgSend (challenge, Cocoa.S_sender);
				int user = createNSString(event.user);
				int password = createNSString(event.password);
				int credential = Cocoa.objc_msgSend (Cocoa.C_NSURLCredential, Cocoa.S_credentialWithUser, user, password, Cocoa.NSURLCredentialPersistenceForSession);
				Cocoa.objc_msgSend (challengeSender, Cocoa.S_useCredential, credential, challenge);
				OS.CFRelease (password);
				OS.CFRelease (user);
				return;
			}
		}
	}

	/* no listener handled the challenge, so try to invoke the native panel */
	int cls = Cocoa.C_WebPanelAuthenticationHandler;
	if (cls != 0) {
		int method = Cocoa.class_getClassMethod (cls, Cocoa.S_sharedHandler);
		if (method != 0) {
			int handler = Cocoa.objc_msgSend (cls, Cocoa.S_sharedHandler);
			if (handler != 0) {
				int window = Cocoa.objc_msgSend (webView, Cocoa.S_window);
				Cocoa.objc_msgSend (handler, Cocoa.S_startAuthentication, challenge, window);
				return;
			}
		}
	}

	/* the native panel was not available, so show a custom dialog */
	String[] userReturn = new String[1], passwordReturn = new String[1];
	int proposedCredential = Cocoa.objc_msgSend (challenge, Cocoa.S_proposedCredential);
	if (proposedCredential != 0) {
		int user = Cocoa.objc_msgSend (proposedCredential, Cocoa.S_user);
		userReturn[0] = getString (user);
		boolean hasPassword = Cocoa.objc_msgSend (proposedCredential, Cocoa.S_hasPassword) != 0;
		if (hasPassword) {
			int password = Cocoa.objc_msgSend (proposedCredential, Cocoa.S_password);
			passwordReturn[0] = getString (password);
		}
	}

	int space = Cocoa.objc_msgSend (challenge, Cocoa.S_protectionSpace);
	int host = Cocoa.objc_msgSend (space, Cocoa.S_host);
	String hostString = getString (host) + ':';
	int port = Cocoa.objc_msgSend (space, Cocoa.S_port);
	hostString += port;
	int realm = Cocoa.objc_msgSend (space, Cocoa.S_realm);
	String realmString = getString (realm);
	boolean result = showAuthenticationDialog (userReturn, passwordReturn, hostString, realmString);
	int challengeSender = Cocoa.objc_msgSend (challenge, Cocoa.S_sender);
	if (!result) {
		Cocoa.objc_msgSend (challengeSender, Cocoa.S_cancelAuthenticationChallenge, challenge);
		return;
	}

	int user = createNSString(userReturn[0]);
	int password = createNSString(passwordReturn[0]);
	int credential = Cocoa.objc_msgSend (Cocoa.C_NSURLCredential, Cocoa.S_credentialWithUser, user, password, Cocoa.NSURLCredentialPersistenceForSession);
	Cocoa.objc_msgSend (challengeSender, Cocoa.S_useCredential, credential, challenge);
	OS.CFRelease (password);
	OS.CFRelease (user);
}

boolean showAuthenticationDialog (final String[] user, final String[] password, String host, String realm) {
	final Shell shell = new Shell (browser.getShell ());
	shell.setLayout (new GridLayout ());
	String title = SWT.getMessage ("SWT_Authentication_Required"); //$NON-NLS-1$
	shell.setText (title);
	Label label = new Label (shell, SWT.WRAP);
	label.setText (Compatibility.getMessage ("SWT_Enter_Username_and_Password", new String[] {realm, host})); //$NON-NLS-1$

	GridData data = new GridData ();
	Monitor monitor = browser.getMonitor ();
	int maxWidth = monitor.getBounds ().width * 2 / 3;
	int width = label.computeSize (SWT.DEFAULT, SWT.DEFAULT).x;
	data.widthHint = Math.min (width, maxWidth);
	data.horizontalAlignment = GridData.FILL;
	data.grabExcessHorizontalSpace = true;
	label.setLayoutData (data);

	Label userLabel = new Label (shell, SWT.NONE);
	userLabel.setText (SWT.getMessage ("SWT_Username")); //$NON-NLS-1$

	final Text userText = new Text (shell, SWT.BORDER);
	if (user[0] != null) userText.setText (user[0]);
	data = new GridData ();
	data.horizontalAlignment = GridData.FILL;
	data.grabExcessHorizontalSpace = true;
	userText.setLayoutData (data);

	Label passwordLabel = new Label (shell, SWT.NONE);
	passwordLabel.setText (SWT.getMessage ("SWT_Password")); //$NON-NLS-1$

	final Text passwordText = new Text (shell, SWT.PASSWORD | SWT.BORDER);
	if (password[0] != null) passwordText.setText (password[0]);
	data = new GridData ();
	data.horizontalAlignment = GridData.FILL;
	data.grabExcessHorizontalSpace = true;
	passwordText.setLayoutData (data);

	final boolean[] result = new boolean[1];
	final Button[] buttons = new Button[2];
	Listener listener = new Listener() {
		public void handleEvent(Event event) {
			user[0] = userText.getText();
			password[0] = passwordText.getText();
			result[0] = event.widget == buttons[1];
			shell.close();
		}	
	};

	Composite composite = new Composite (shell, SWT.NONE);
	data = new GridData ();
	data.horizontalAlignment = GridData.END;
	composite.setLayoutData (data);
	composite.setLayout (new GridLayout (2, true));
	buttons[0] = new Button (composite, SWT.PUSH);
	buttons[0].setText (SWT.getMessage("SWT_Cancel")); //$NON-NLS-1$
	buttons[0].setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
	buttons[0].addListener (SWT.Selection, listener);
	buttons[1] = new Button (composite, SWT.PUSH);
	buttons[1].setText (SWT.getMessage("SWT_OK")); //$NON-NLS-1$
	buttons[1].setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
	buttons[1].addListener (SWT.Selection, listener);

	shell.setDefaultButton (buttons[1]);
	shell.pack ();
	shell.open ();
	Display display = browser.getDisplay ();
	while (!shell.isDisposed ()) {
		if (!display.readAndDispatch ()) display.sleep ();
	}

	return result[0];
}

int identifierForInitialRequest(int request, int dataSource) {
	final Display display = browser.getDisplay();
	final ProgressEvent progress = new ProgressEvent(browser);
	progress.display = display;
	progress.widget = browser;
	progress.current = resourceCount;
	progress.total = Math.max(resourceCount, MAX_PROGRESS);
	for (int i = 0; i < progressListeners.length; i++) {
		progressListeners[i].changed(progress);
	}
	if (browser.isDisposed()) return 0;

	/*
	* Note.  numberWithInt uses autorelease.  The resulting object
	* does not need to be released.
	* identifier = [NSNumber numberWithInt: resourceCount++]
	*/	
	int identifier = Cocoa.objc_msgSend(Cocoa.C_NSNumber, Cocoa.S_numberWithInt, resourceCount++);
		
	if (this.identifier == 0) {
		int frame = Cocoa.objc_msgSend(dataSource, Cocoa.S_webFrame);
		if (frame == Cocoa.objc_msgSend(webView, Cocoa.S_mainFrame)) this.identifier = identifier;
	}
	return identifier;
}

int willSendRequest(int identifier, int request, int redirectResponse, int dataSource) {
	int url = Cocoa.objc_msgSend (request, Cocoa.S_URL);
	boolean isFileURL = Cocoa.objc_msgSend (url, Cocoa.S_isFileURL) != 0;
	if (isFileURL) {
		int newRequest = Cocoa.objc_msgSend (request, Cocoa.S_mutableCopy);
		Cocoa.objc_msgSend (newRequest, Cocoa.S_autorelease);
		Cocoa.objc_msgSend (newRequest, Cocoa.S_setCachePolicy, Cocoa.NSURLRequestReloadIgnoringLocalCacheData);
		return newRequest;
	}
	return request;
}

/* handleNotification */

void handleNotification(int notification) {	
}

/* UIDelegate */
int createWebViewWithRequest(int request) {
	WindowEvent newEvent = new WindowEvent(browser);
	newEvent.display = browser.getDisplay();
	newEvent.widget = browser;
	newEvent.required = true;
	if (openWindowListeners != null) {
		for (int i = 0; i < openWindowListeners.length; i++) {
			openWindowListeners[i].open(newEvent);
		}
	}

	int webView = 0;
	Browser browser = null;
	if (newEvent.browser != null && newEvent.browser.webBrowser instanceof WebKit) {
		browser = newEvent.browser;
	}
	if (browser != null && !browser.isDisposed()) {
		webView = ((WebKit)browser.webBrowser).webView;
		
		if (request != 0) {
			//mainFrame = [webView mainFrame];
			int mainFrame= Cocoa.objc_msgSend(webView, Cocoa.S_mainFrame);

			//[mainFrame loadRequest:request];
			Cocoa.objc_msgSend(mainFrame, Cocoa.S_loadRequest, request);
		}
	}
	return webView;
}

void webViewShow(int sender) {
	/*
	* Feature on WebKit.  WebKit expects the application to
	* create a new Window using the Objective C Cocoa API in response
	* to UIDelegate.createWebViewWithRequest. The application is then
	* expected to use Objective C Cocoa API to make this window visible
	* when receiving the UIDelegate.webViewShow message.  For some reason,
	* a window created with the Carbon API hosting the new browser instance
	* does not redraw until it has been resized.  The fix is to increase the
	* size of the Shell and restore it to its initial size.
	*/
	Shell parent = browser.getShell();
	Point pt = parent.getSize();
	parent.setSize(pt.x+1, pt.y);
	parent.setSize(pt.x, pt.y);
	WindowEvent newEvent = new WindowEvent(browser);
	newEvent.display = browser.getDisplay();
	newEvent.widget = browser;
	if (location != null) newEvent.location = location;
	if (size != null) newEvent.size = size;
	/*
	* Feature in WebKit.  WebKit's tool bar contains
	* the address bar.  The address bar is displayed
	* if the tool bar is displayed. There is no separate
	* notification for the address bar.
	* 
	* Feature of OSX.  The menu bar is always displayed.
	* There is no notification to hide the menu bar.
	*/
	newEvent.addressBar = toolBar;
	newEvent.menuBar = true;
	newEvent.statusBar = statusBar;
	newEvent.toolBar = toolBar;
	for (int i = 0; i < visibilityWindowListeners.length; i++) {
		visibilityWindowListeners[i].show(newEvent);
	}
	location = null;
	size = null;
}

void setFrame(int frame) {
	float[] dest = new float[4];
	OS.memmove(dest, frame, 16);
	/* convert to SWT system coordinates */
	Rectangle bounds = browser.getDisplay().getBounds();
	location = new Point((int)dest[0], bounds.height - (int)dest[1] - (int)dest[3]);
	size = new Point((int)dest[2], (int)dest[3]);
}

void webViewFocus() {
}

void webViewUnfocus() {
}

int callRunBeforeUnloadConfirmPanelWithMessage(long /*int*/ messageID, long /*int*/ arg) {
	int result = runBeforeUnloadConfirmPanelWithMessage (messageID, 0);
	return Cocoa.objc_msgSend (Cocoa.C_NSNumber, Cocoa.S_numberWithBool, result);
}

int runBeforeUnloadConfirmPanelWithMessage(int message, int frame) {
	StringBuffer text = new StringBuffer(Compatibility.getMessage("SWT_OnBeforeUnload_Message1")); //$NON-NLS-1$
	text.append ("\n\n"); //$NON-NLS-1$
	int length = OS.CFStringGetLength(message);
	char[] buffer = new char[length];
	CFRange range = new CFRange();
	range.length = length;
	OS.CFStringGetCharacters(message, range, buffer);
	text.append(new String(buffer));
	text.append("\n\n"); //$NON-NLS-1$
	text.append(Compatibility.getMessage("SWT_OnBeforeUnload_Message2")); //$NON-NLS-1$
	MessageBox messageBox = new MessageBox(browser.getShell(), SWT.OK | SWT.CANCEL | SWT.ICON_QUESTION);
	messageBox.setMessage(text.toString());
	return messageBox.open() == SWT.OK ? 1 : 0;
}

void runJavaScriptAlertPanelWithMessage(int message) {
	int length = OS.CFStringGetLength(message);
	char[] buffer = new char[length];
	CFRange range = new CFRange();
	range.length = length;
	OS.CFStringGetCharacters(message, range, buffer);
	String text = new String(buffer);

	MessageBox messageBox = new MessageBox(browser.getShell(), SWT.OK | SWT.ICON_WARNING);
	messageBox.setText("Javascript");	//$NON-NLS-1$
	messageBox.setMessage(text);
	messageBox.open();
}

int runJavaScriptConfirmPanelWithMessage(int message) {
	int length = OS.CFStringGetLength(message);
	char[] buffer = new char[length];
	CFRange range = new CFRange();
	range.length = length;
	OS.CFStringGetCharacters(message, range, buffer);
	String text = new String(buffer);

	MessageBox messageBox = new MessageBox(browser.getShell(), SWT.OK | SWT.CANCEL | SWT.ICON_QUESTION);
	messageBox.setText("Javascript");	//$NON-NLS-1$
	messageBox.setMessage(text);
	return messageBox.open() == SWT.OK ? 1 : 0;
}

void runOpenPanelForFileButtonWithResultListener(int resultListener) {
	FileDialog dialog = new FileDialog(browser.getShell(), SWT.NONE);
	String result = dialog.open();
	if (result == null) {
		Cocoa.objc_msgSend(resultListener, Cocoa.S_cancel);
		return;
	}
	int filename = createNSString(result);
	Cocoa.objc_msgSend(resultListener, Cocoa.S_chooseFilename, filename);
	OS.CFRelease(filename);
}

void webViewClose() {
	Shell parent = browser.getShell();
	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();
	if (parent.isDisposed()) return;
	/*
	* Feature on WebKit.  WebKit expects the application to
	* create a new Window using the Objective C Cocoa API in response
	* to UIDelegate.createWebViewWithRequest. The application is then
	* expected to use Objective C Cocoa API to make this window visible
	* when receiving the UIDelegate.webViewShow message.  For some reason,
	* a window created with the Carbon API hosting the new browser instance
	* does not redraw until it has been resized.  The fix is to increase the
	* size of the Shell and restore it to its initial size.
	*/
	Point pt = parent.getSize();
	parent.setSize(pt.x+1, pt.y);
	parent.setSize(pt.x, pt.y);
}

int contextMenuItemsForElement(int element, int defaultMenuItems) {
	org.eclipse.swt.internal.carbon.Point pt = new org.eclipse.swt.internal.carbon.Point();
	OS.GetGlobalMouse(pt);
	Event event = new Event();
	event.x = pt.h;
	event.y = pt.v;
	browser.notifyListeners(SWT.MenuDetect, event);
	if (!event.doit || browser.isDisposed()) return 0;
	Menu menu = browser.getMenu();
	if (menu != null && !menu.isDisposed()) {
		if (event.x != pt.h || event.y != pt.v) {
			menu.setLocation(event.x, event.y);
		}
		menu.setVisible(true);
		return 0;
	}
	return defaultMenuItems;
}

void setStatusBarVisible(int visible) {
	/* Note.  Webkit only emits the notification when the status bar should be hidden. */
	statusBar = visible != 0;
}

void setStatusText(int text) {
	int length = OS.CFStringGetLength(text);
	if (length == 0) return;
	char[] buffer = new char[length];
	CFRange range = new CFRange();
	range.length = length;
	OS.CFStringGetCharacters(text, range, buffer);

	StatusTextEvent statusText = new StatusTextEvent(browser);
	statusText.display = browser.getDisplay();
	statusText.widget = browser;
	statusText.text = new String(buffer);
	for (int i = 0; i < statusTextListeners.length; i++) {
		statusTextListeners[i].changed(statusText);
	}
}

void setResizable(int visible) {
}

void setToolbarsVisible(int visible) {
	/* Note.  Webkit only emits the notification when the tool bar should be hidden. */
	toolBar = visible != 0;
}

void mouseDidMoveOverElement (int elementInformation, int modifierFlags) {
	if (elementInformation == 0) return;
	if (!browser.isEnabled ()) return;

	int key = createNSString(WebElementLinkURLKey);
	int value = Cocoa.objc_msgSend(elementInformation, Cocoa.S_valueForKey, key);
	OS.CFRelease(key);
	if (value == 0) {
		/* not currently over a link */
		if (lastHoveredLinkURL == null) return;
		lastHoveredLinkURL = null;
		StatusTextEvent statusText = new StatusTextEvent(browser);
		statusText.display = browser.getDisplay();
		statusText.widget = browser;
		statusText.text = "";	//$NON-NLS-1$
		for (int i = 0; i < statusTextListeners.length; i++) {
			statusTextListeners[i].changed(statusText);
		}
		return;
	}

	int stringPtr = Cocoa.objc_msgSend(value, Cocoa.S_absoluteString);
	int length = OS.CFStringGetLength(stringPtr);
	String urlString;
	if (length == 0) {
		urlString = "";	//$NON-NLS-1$
	} else {
		char[] chars = new char[length];
		CFRange range = new CFRange();
		range.length = length;
		OS.CFStringGetCharacters(stringPtr, range, chars);
		urlString = new String(chars);
	}
	if (urlString.equals(lastHoveredLinkURL)) return;

	lastHoveredLinkURL = urlString;
	StatusTextEvent statusText = new StatusTextEvent(browser);
	statusText.display = browser.getDisplay();
	statusText.widget = browser;
	statusText.text = urlString;
	for (int i = 0; i < statusTextListeners.length; i++) {
		statusTextListeners[i].changed(statusText);
	}
}

/* PolicyDelegate */

void decidePolicyForMIMEType(int type, int request, int frame, int listener) {
	boolean canShow = Cocoa.objc_msgSend(Cocoa.C_WebView, Cocoa.S_canShowMIMEType, type) != 0;
	Cocoa.objc_msgSend(listener, canShow ? Cocoa.S_use : Cocoa.S_download);
}

void decidePolicyForNavigationAction(int actionInformation, int request, int frame, int listener) {
	int url = Cocoa.objc_msgSend(request, Cocoa.S_URL);
	if (loadingText) {
		/* 
		 * WebKit is auto-navigating to about:blank in response to a loadHTMLString()
		 * invocation.  This navigate should always proceed without sending an event
		 * since it is preceded by an explicit navigate to about:blank in setText().
		 */
		Cocoa.objc_msgSend(listener, Cocoa.S_use);
		return;
	}
	if (url == 0) {
		/* indicates that a URL with an invalid format was specified */
		Cocoa.objc_msgSend(listener, Cocoa.S_ignore);
		return;
	}
	boolean isFileURL = Cocoa.objc_msgSend(url, Cocoa.S_isFileURL) != 0;
	if (isFileURL && getUrl().startsWith(ABOUT_BLANK) && untrustedText) {
		/* indicates an attempt to access the local file system from untrusted content */
		Cocoa.objc_msgSend(listener, Cocoa.S_ignore);
		return;
	}
	int s = Cocoa.objc_msgSend(url, Cocoa.S_absoluteString);
	int length = OS.CFStringGetLength(s);
	char[] buffer = new char[length];
	CFRange range = new CFRange();
	range.length = length;
	OS.CFStringGetCharacters(s, range, buffer);
	String url2 = new String(buffer);
	/*
	 * If the URI indicates that the page is being rendered from memory
	 * (via setText()) then set it to about:blank to be consistent with IE.
	 */
	if (url2.equals (URI_FILEROOT)) {
		url2 = ABOUT_BLANK;
	} else {
		length = URI_FILEROOT.length ();
		if (url2.startsWith (URI_FILEROOT) && url2.charAt (length) == '#') {
			url2 = ABOUT_BLANK + url2.substring (length);
		}
	}

	if (url2.startsWith (URI_APPLEWEBDATA)) {
		/* listeners should not be notified of internal transitions like this */
		Cocoa.objc_msgSend(listener, Cocoa.S_use);
	} else {
		LocationEvent newEvent = new LocationEvent(browser);
		newEvent.display = browser.getDisplay();
		newEvent.widget = browser;
		newEvent.location = url2;
		newEvent.doit = true;
		if (locationListeners != null) {
			for (int i = 0; i < locationListeners.length; i++) {
				locationListeners[i].changing(newEvent);
			}
		}
		if (newEvent.doit) {
			if (jsEnabled != jsEnabledOnNextPage) {
				jsEnabled = jsEnabledOnNextPage;
				if (preferences == 0) {
					preferences = Cocoa.objc_msgSend (Cocoa.C_WebPreferences, Cocoa.S_alloc);
					Cocoa.objc_msgSend (preferences, Cocoa.S_init);
					Cocoa.objc_msgSend (webView, Cocoa.S_setPreferences, preferences);
				}
				Cocoa.objc_msgSend (preferences, Cocoa.S_setJavaScriptEnabled, jsEnabled ? 1 : 0);
			}
			lastNavigateURL = url2;
		}
		Cocoa.objc_msgSend(listener, newEvent.doit ? Cocoa.S_use : Cocoa.S_ignore);
	}
}

void decidePolicyForNewWindowAction(int actionInformation, int request, int frameName, int listener) {
	Cocoa.objc_msgSend(listener, Cocoa.S_use);
}

void unableToImplementPolicyWithError(int error, int frame) {
}

/* WebDownload */

void decideDestinationWithSuggestedFilename (int download, int filename) {
	int length = OS.CFStringGetLength(filename);
	char[] buffer = new char[length];
	CFRange range = new CFRange();
	range.length = length;
	OS.CFStringGetCharacters(filename, range, buffer);
	String name = new String(buffer);

	/*
	* Bug in WebKit.  As of OSX 10.5.5, showing the file dialog here invokes this
	* callback a second time when the file dialog runs the event loop, which
	* always leads to a crash.  The workaround is to choose a location to save
	* the file without showing the file dialog. 
	*/
	String path = null;
	if (OS.VERSION >= 0x1055) {
		int array = Cocoa.NSSearchPathForDirectoriesInDomains (Cocoa.NSDesktopDirectory, Cocoa.NSAllDomainsMask, true);
		int count = Cocoa.objc_msgSend (array, Cocoa.S_count);
		if (count == 0) { /* should never happen */
			array = Cocoa.NSSearchPathForDirectoriesInDomains (Cocoa.NSDownloadsDirectory, Cocoa.NSAllDomainsMask, true);
			count = Cocoa.objc_msgSend (array, Cocoa.S_count);
			if (count == 0) {
				array = Cocoa.NSSearchPathForDirectoriesInDomains (Cocoa.NSDocumentDirectory, Cocoa.NSAllDomainsMask, true);
				count = Cocoa.objc_msgSend (array, Cocoa.S_count);
				if (count == 0) {
					Cocoa.objc_msgSend (download, Cocoa.S_cancel);
					return;
				}
			}
		}
		int string = Cocoa.objc_msgSend (array, Cocoa.S_objectAtIndex, 0);
		length = OS.CFStringGetLength (string);
		buffer = new char[length];
		range = new CFRange ();
		range.length = length;
		OS.CFStringGetCharacters (string, range, buffer);
		path = new String (buffer) + '/' + name;
	} else {
		FileDialog dialog = new FileDialog(browser.getShell(), SWT.SAVE);
		dialog.setText(SWT.getMessage ("SWT_FileDownload")); //$NON-NLS-1$
		dialog.setFileName(name);
		path = dialog.open();
	}

	if (path == null) {
		/* cancel pressed */
		Cocoa.objc_msgSend(download, Cocoa.S_cancel);
		return;
	}
	int result = createNSString(path);
	Cocoa.objc_msgSend(download, Cocoa.S_setDestinationAllowOverwrite, result, 1);
	OS.CFRelease(result);
}

/* DOMEventListener */

void handleEvent(int evt) {
	if (!browser.isEnabled ()) return;

	int type = Cocoa.objc_msgSend(evt, Cocoa.S_type);
	int length = OS.CFStringGetLength(type);
	char[] buffer = new char[length];
	CFRange range = new CFRange();
	range.length = length;
	OS.CFStringGetCharacters(type, range, buffer);
	String typeString = new String(buffer);

	if (typeString.equals(DOMEVENT_FOCUSIN)) {
		hasNewFocusElement = true;
		return;
	}
	if (typeString.equals(DOMEVENT_FOCUSOUT)) {
		hasNewFocusElement = false;
		return;
	}

	boolean ctrl = Cocoa.objc_msgSend(evt, Cocoa.S_ctrlKey) != 0;
	boolean shift = Cocoa.objc_msgSend(evt, Cocoa.S_shiftKey) != 0;
	boolean alt = Cocoa.objc_msgSend(evt, Cocoa.S_altKey) != 0;
	boolean meta = Cocoa.objc_msgSend(evt, Cocoa.S_metaKey) != 0;

	if (DOMEVENT_KEYDOWN.equals(typeString) || DOMEVENT_KEYUP.equals(typeString)) {
		int keyCode = Cocoa.objc_msgSend(evt, Cocoa.S_keyCode);
		int charCode = Cocoa.objc_msgSend(evt, Cocoa.S_charCode);

		Event keyEvent = new Event();
		keyEvent.widget = browser;
		if (DOMEVENT_KEYDOWN.equals(typeString)) {
			keyEvent.type = SWT.KeyDown;
		} else {
			keyEvent.type = SWT.KeyUp;
		}
		keyEvent.keyCode = translateKey(keyCode);
		/*
		* WebKit maps the Delete key's character to 0xf728.  Detect
		* this key and set its character to SWT.DEL so that the
		* Browser's key events are consistent with other controls.
		*/
		if (keyEvent.keyCode == SWT.DEL) {
			keyEvent.character = SWT.DEL;
		} else {
			keyEvent.character = (char)charCode;
		}
		keyEvent.stateMask = (alt ? SWT.ALT : 0) | (ctrl ? SWT.CTRL : 0) | (shift ? SWT.SHIFT : 0) | (meta ? SWT.COMMAND : 0);

		boolean doit;
		if (keyEvent.type == SWT.KeyDown) {
			doit = sendKeyEvent(keyEvent);
		} else { /* SWT.KeyUp */
			browser.notifyListeners(keyEvent.type, keyEvent);
			doit = keyEvent.doit;
		}
		if (browser.isDisposed()) {
			Cocoa.objc_msgSend(evt, Cocoa.S_preventDefault);
			return;
		}

		/*
		* Bug in WebKit.  As a result of using HIWebViewCreate on OSX versions < 10.5 (Leopard), attempting
		* to traverse out of WebKit backwards (Shift+Tab) leaves it in a strange state where WebKit no
		* longer has focus but still receives keys.  The Carbon-based WebKit examples have the same
		* problem.  The workaround is to only allow forward Tab traversals in the Browser on OSX < 10.5.
		*/
		if (doit && OS.VERSION < 0x1050 && keyEvent.keyCode == SWT.TAB && (keyEvent.stateMask & SWT.SHIFT) != 0) {
			doit = false;
		}
		if (!doit) {
			Cocoa.objc_msgSend(evt, Cocoa.S_preventDefault);
		} else {
			if (!hasNewFocusElement && keyEvent.keyCode == SWT.TAB && DOMEVENT_KEYUP.equals(typeString)) {
				hasNewFocusElement = false;
			}
		}
		return;
	}

	/* mouse event */

	/*
	 * 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.
	 */
	int screenX = Cocoa.objc_msgSend(evt, Cocoa.S_screenX);
	int screenY = Cocoa.objc_msgSend(evt, Cocoa.S_screenY);
	Point position = new Point(screenX, screenY);
	position = browser.getDisplay().map(null, browser, position);

	int detail = Cocoa.objc_msgSend(evt, Cocoa.S_detail);
	Event mouseEvent = new Event();
	mouseEvent.widget = browser;
	mouseEvent.x = position.x; mouseEvent.y = position.y;
	mouseEvent.stateMask = (alt ? SWT.ALT : 0) | (ctrl ? SWT.CTRL : 0) | (shift ? SWT.SHIFT : 0) | (meta ? SWT.COMMAND : 0);

	if (DOMEVENT_MOUSEDOWN.equals (typeString)) {
		mouseEvent.type = SWT.MouseDown;
		int button = Cocoa.objc_msgSend(evt, Cocoa.S_button);
		mouseEvent.button = button + 1;
		mouseEvent.count = detail;
	} else if (DOMEVENT_MOUSEUP.equals (typeString)) {
		mouseEvent.type = SWT.MouseUp;
		int button = Cocoa.objc_msgSend(evt, Cocoa.S_button);
		mouseEvent.button = button + 1;
		mouseEvent.count = detail;
		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 (DOMEVENT_MOUSEMOVE.equals (typeString)) {
		/*
		* Feature in WebKit.  Spurious and redundant mousemove events are received in
		* various contexts, including following every MouseUp.  The workaround is to
		* not fire MouseMove events whose x and y values match the last MouseMove.  
		*/
		if (mouseEvent.x == lastMouseMoveX && mouseEvent.y == lastMouseMoveY) return;
		mouseEvent.type = SWT.MouseMove;
		lastMouseMoveX = mouseEvent.x; lastMouseMoveY = mouseEvent.y;
	} else if (DOMEVENT_MOUSEWHEEL.equals (typeString)) {
		mouseEvent.type = SWT.MouseWheel;
		int delta = Cocoa.objc_msgSend(evt, Cocoa.S_wheelDelta);
		mouseEvent.count = delta / 120;
	}

	browser.notifyListeners (mouseEvent.type, mouseEvent);
	if (browser.isDisposed()) return;
	if (detail == 2 && DOMEVENT_MOUSEDOWN.equals (typeString)) {
		int button = Cocoa.objc_msgSend(evt, Cocoa.S_button);
		mouseEvent = new Event ();
		mouseEvent.widget = browser;
		mouseEvent.x = position.x; mouseEvent.y = position.y;
		mouseEvent.stateMask = (alt ? SWT.ALT : 0) | (ctrl ? SWT.CTRL : 0) | (shift ? SWT.SHIFT : 0) | (meta ? SWT.COMMAND : 0);
		mouseEvent.type = SWT.MouseDoubleClick;
		mouseEvent.button = button + 1;
		mouseEvent.count = detail;
		browser.notifyListeners (mouseEvent.type, mouseEvent);
	}
}

/* external */

Object convertToJava (int value) {
	if (Cocoa.objc_msgSend (value, Cocoa.S_isKindOfClass, Cocoa.C_NSString) != 0) {
		int length = Cocoa.objc_msgSend (value, Cocoa.S_length);
		char[] buffer = new char[length];
		Cocoa.objc_msgSend (value, Cocoa.S_getCharacters_, buffer);
		return new String (buffer);
	}
	if (Cocoa.objc_msgSend (value, Cocoa.S_isKindOfClass, Cocoa.C_NSNumber) != 0) {
		int ptr = Cocoa.objc_msgSend (value, Cocoa.S_objCType);
		byte[] type = new byte[1];
		OS.memmove (type, ptr, 1);
		if (type[0] == 'c' || type[0] == 'B') {
			int result = Cocoa.objc_msgSend (value, Cocoa.S_boolValue);
			return new Boolean (result != 0);
		}
		if ("islqISLQfd".indexOf (type[0]) != -1) { //$NON-NLS-1$
			double result = Cocoa.objc_msgSend_fpret (value, Cocoa.S_doubleValue);
			return new Double (result);
		}
	}
	if (Cocoa.objc_msgSend (value, Cocoa.S_isKindOfClass, Cocoa.C_WebScriptObject) != 0) {
		int str = createNSString ("length"); //$NON-NLS-1$
		int numberValue = Cocoa.objc_msgSend (value, Cocoa.S_valueForKey, str);
		OS.CFRelease (str);
		int length = Cocoa.objc_msgSend (numberValue, Cocoa.S_intValue);
		Object[] arguments = new Object[length];
		for (int i = 0; i < length; i++) {
			int current = Cocoa.objc_msgSend (value, Cocoa.S_webScriptValueAtIndex, i);
			if (current != 0) {
				arguments[i] = convertToJava (current);
			}
		}
		return arguments;
	}
	if (Cocoa.objc_msgSend (value, Cocoa.S_isKindOfClass, Cocoa.C_WebUndefined) != 0) {
		return null;
	}

	SWT.error (SWT.ERROR_INVALID_ARGUMENT);
	return null;
}

int convertToJS (Object value) {
	if (value == null) {
		return Cocoa.objc_msgSend (Cocoa.C_WebUndefined, Cocoa.S_undefined);
	}
	if (value instanceof String) {
		return createNSString((String)value);
	}
	if (value instanceof Boolean) {
		int booleanValue = ((Boolean)value).booleanValue () ? 1 : 0;
		return Cocoa.objc_msgSend (Cocoa.C_NSNumber, Cocoa.S_numberWithBool, booleanValue);
	}
	if (value instanceof Number) {
		double doubleValue = ((Number)value).doubleValue ();
		return Cocoa.objc_msgSend (Cocoa.C_NSNumber, Cocoa.S_numberWithDouble, doubleValue);
	}
	if (value instanceof Object[]) {
		Object[] arrayValue = (Object[])value;
		int length = arrayValue.length;
		int array = Cocoa.objc_msgSend (Cocoa.C_NSMutableArray, Cocoa.S_arrayWithCapacity, length);
		for (int i = 0; i < length; i++) {
			Object currentObject = arrayValue[i];
			int jsObject = convertToJS (currentObject);
			Cocoa.objc_msgSend (array, Cocoa.S_addObject, jsObject);
		}
		return array;
	}
	SWT.error (SWT.ERROR_INVALID_RETURN_VALUE);
	return 0;
}

long /*int*/ callJava (long /*int*/ index, long /*int*/ token, long /*int*/ args, long /*int*/ arg1) {
	Object returnValue = null;
	if (Cocoa.objc_msgSend (index, Cocoa.S_isKindOfClass, Cocoa.C_NSNumber) != 0) {
		int functionIndex = Cocoa.objc_msgSend (index, Cocoa.S_intValue);
		if (Cocoa.objc_msgSend (token, Cocoa.S_isKindOfClass, Cocoa.C_NSString) != 0) {
			int length = Cocoa.objc_msgSend (token, Cocoa.S_length);
			char[] buffer = new char[length];
			Cocoa.objc_msgSend (token, Cocoa.S_getCharacters_, buffer);
			String tokenString = new String (buffer);
			Object key = new Integer (functionIndex);
			BrowserFunction function = (BrowserFunction)functions.get (key);
			if (function != null && tokenString.equals (function.token)) {
				try {
					Object temp = convertToJava (args);
					if (temp instanceof Object[]) {
						Object[] arguments = (Object[])temp;
						try {
							returnValue = function.function (arguments);
						} catch (Exception e) {
							/* exception during function invocation */
							returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ());
						}
					}
				} catch (IllegalArgumentException e) {
					/* invalid argument value type */
					if (function.isEvaluate) {
						/* notify the evaluate 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 ());
				}
			}
		}
	}
	try {
		return convertToJS (returnValue);
	} catch (SWTException e) {
		return convertToJS (WebBrowser.CreateErrorString (e.getLocalizedMessage ()));
	}
}
}
