/*******************************************************************************
 * Copyright (c) 2000, 2006 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
 *******************************************************************************/
// Modified by Google
package org.eclipse.swt.browser;

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

/**
 * Instances of this class implement the browser user interface
 * metaphor.  It allows the user to visualize and navigate through
 * HTML documents.
 * <p>
 * Note that although this class is a subclass of <code>Composite</code>,
 * it does not make sense to set a layout on it.
 * </p><p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 * 
 * @since 3.0
 */
public class Browser extends Composite {
	
	/* Package Name */
	static final String PACKAGE_PREFIX = "org.eclipse.swt.browser."; //$NON-NLS-1$
	static final String ADD_WIDGET_KEY = "org.eclipse.swt.internal.addWidget"; //$NON-NLS-1$
	// GOOGLE: patched in from https://bugs.eclipse.org/bugs/show_bug.cgi?id=161259
	static final String CLEAR_GRAB_BIT = "org.eclipse.swt.internal.carbon.clearGrabBit"; //$NON-NLS-1$
	static final String BROWSER_WINDOW = "org.eclipse.swt.browser.Browser.Window"; //$NON-NLS-1$
	static final int MAX_PROGRESS = 100;
	
	/* External Listener management */
	CloseWindowListener[] closeWindowListeners = new CloseWindowListener[0];
	LocationListener[] locationListeners = new LocationListener[0];
	OpenWindowListener[] openWindowListeners = new OpenWindowListener[0];
	ProgressListener[] progressListeners = new ProgressListener[0];
	StatusTextListener[] statusTextListeners = new StatusTextListener[0];
	TitleListener[] titleListeners = new TitleListener[0];
	VisibilityWindowListener[] visibilityWindowListeners = new VisibilityWindowListener[0];
	
	static Callback Callback3, Callback7;

	/* Objective-C WebView delegate */
	int delegate;
	
	/* Carbon HIView handle */
	int webViewHandle;
	
	boolean changingLocation;
	String html;
	int identifier;
	int resourceCount;
	String url = "";
	Point location;
	Point size;
	boolean statusBar = true, toolBar = true, ignoreDispose;
	//TEMPORARY CODE
//	boolean doit;

	static final int MIN_SIZE = 16;

/**
 * Constructs a new instance of this class given its parent
 * and a style value describing its behavior and appearance.
 * <p>
 * The style value is either one of the style constants defined in
 * class <code>SWT</code> which is applicable to instances of this
 * class, or must be built by <em>bitwise OR</em>'ing together 
 * (that is, using the <code>int</code> "|" operator) two or more
 * of those <code>SWT</code> style constants. The class description
 * lists the style constants that are applicable to the class.
 * Style bits are also inherited from superclasses.
 * </p>
 *
 * @param parent a widget which will be the parent of the new instance (cannot be null)
 * @param style the style of widget to construct
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 * </ul>
 * @exception SWTError <ul>
 *    <li>ERROR_NO_HANDLES if a handle could not be obtained for browser creation</li>
 * </ul>
 * 
 * @see Widget#getStyle
 * 
 * @since 3.0
 */
public Browser(Composite parent, int style) {
	super(parent, 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) {
		dispose();
		SWT.error(SWT.ERROR_NO_HANDLES);
	}
	int outControl[] = new int[1];
	try {
		WebKit.HIWebViewCreate(outControl);
	} catch (UnsatisfiedLinkError e) {
		dispose();
		SWT.error(SWT.ERROR_NO_HANDLES);
	}
	webViewHandle = outControl[0];
	if (webViewHandle == 0) {
		dispose();
		SWT.error(SWT.ERROR_NO_HANDLES);		
	}
	Display display = getDisplay();
	display.setData(ADD_WIDGET_KEY, new Object[] {new Integer(webViewHandle), this});
	// GOOGLE: patched in from https://bugs.eclipse.org/bugs/show_bug.cgi?id=161259
	setData(CLEAR_GRAB_BIT, null);

	/*
	* Bug in Safari.  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]);
		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 Safari. The WebView does not receive mouse and key events when it is added
	 * to a visible top window.  It is assumed that Safari 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 Safari a chance to hook
	 * events.
	 */
	int window = OS.GetControlOwner(handle);
	if (OS.HIVIEW) {
		int[] contentView = new int[1];
		OS.HIViewFindByID(OS.HIViewGetRoot(window), OS.kHIViewWindowContentID(), contentView);
		OS.HIViewAddSubview(contentView[0], webViewHandle);
		OS.HIViewChangeFeatures(webViewHandle, OS.kHIViewFeatureIsOpaque, 0);
	} else {
		OS.HIViewAddSubview(handle, webViewHandle);
	}
	OS.HIViewSetVisible(webViewHandle, true);	
	if (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(handle)});
		OS.SendEventToEventTarget(showEvent[0], OS.GetWindowEventTarget(window));
		if (showEvent[0] != 0) OS.ReleaseEvent(showEvent[0]);
	}

	final int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	/*
	* 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, Safari
	* 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 = WebKit.objc_msgSend(WebKit.C_NSNotificationCenter, WebKit.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;
					notifyListeners (e.type, e);
					e.type = SWT.NONE;

					Shell shell = getShell();
					shell.removeListener(SWT.Resize, this);
					shell.removeListener(SWT.Show, this);
					shell.removeListener(SWT.Hide, this);
					Control c = Browser.this;
					do {
						c.removeListener(SWT.Show, this);
						c.removeListener(SWT.Hide, this);
						c = c.getParent();
					} while (c != shell);

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

					WebKit.objc_msgSend(webView, WebKit.S_setFrameLoadDelegate, 0);
					WebKit.objc_msgSend(webView, WebKit.S_setResourceLoadDelegate, 0);
					WebKit.objc_msgSend(webView, WebKit.S_setUIDelegate, 0);
					WebKit.objc_msgSend(webView, WebKit.S_setPolicyDelegate, 0);
					WebKit.objc_msgSend(notificationCenter, WebKit.S_removeObserver, delegate);
					
					WebKit.objc_msgSend(delegate, WebKit.S_release);
					if (OS.HIVIEW) OS.DisposeControl(webViewHandle);
					html = null;
					break;
				}
				case SWT.Hide: {
					/*
					* Bug on Safari. 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 Hide and Show events on the browser's parents
					* and set its size to 0 in Hide and to restore its size in Show.
					*/
					CGRect bounds = new CGRect();
					bounds.x = bounds.y = -MIN_SIZE;
					bounds.width = bounds.height = MIN_SIZE;
					OS.HIViewSetFrame(webViewHandle, bounds);
					break;
				}
				case SWT.Show: {
					/*
					* Do not update size when it is not visible. Note that isVisible()
					* cannot be used because SWT.Show is sent before the widget is
					* actually visible. 
					*/
					Shell shell = getShell();
					Composite parent = Browser.this;
					while (parent != shell && (parent.getVisible() || parent == e.widget)) {
						parent = parent.getParent();
					}
					if (!(parent.getVisible() || parent == e.widget)) return;

					/*
					* Bug on Safari. 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 Hide and Show events on the browser's parents
					* and set its size to 0 in Hide and to restore its size in Show.
					*/
					CGRect bounds = new CGRect();
					if (OS.HIVIEW) {
						OS.HIViewGetBounds(handle, bounds);
						int[] contentView = new int[1];
						OS.HIViewFindByID(OS.HIViewGetRoot(OS.GetControlOwner(handle)), OS.kHIViewWindowContentID(), contentView);
						OS.HIViewConvertRect(bounds, handle, contentView[0]);
					} else {
						OS.HIViewGetFrame(handle, bounds);
					}
					/* 
					* Bug in Safari.  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 SWT.Resize: {
					/* Do not update size when it is not visible */
					if (!isVisible()) return;
					/*
					* Bug on Safari. 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.
					*/
					CGRect bounds = new CGRect();
					if (OS.HIVIEW) {
						OS.HIViewGetBounds(handle, bounds);
						int[] contentView = new int[1];
						OS.HIViewFindByID(OS.HIViewGetRoot(OS.GetControlOwner(handle)), OS.kHIViewWindowContentID(), contentView);
						OS.HIViewConvertRect(bounds, handle, contentView[0]);
					} else {
						OS.HIViewGetFrame(handle, bounds);
					}
					/* 
					* Bug in Safari.  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;
					if (e.widget == getShell()) {
						bounds.x++;
						/* Note that the bounds needs to change */
						OS.HIViewSetFrame(webViewHandle, bounds);
						bounds.x--;
					}
					OS.HIViewSetFrame(webViewHandle, bounds);
					break;
				}
			}
		}
	};
	addListener(SWT.Dispose, listener);
	addListener(SWT.Resize, listener);
	Shell shell = getShell();
	shell.addListener(SWT.Resize, listener);
	shell.addListener(SWT.Show, listener);
	shell.addListener(SWT.Hide, listener);
	Control c = this;
	do {
		c.addListener(SWT.Show, listener);
		c.addListener(SWT.Hide, listener);
		c = c.getParent();
	} while (c != shell);
	
	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.kEventClassTextInput, OS.kEventTextInputUnicodeForKeyEvent,
	};
	int controlTarget = OS.GetControlEventTarget(webViewHandle);
	OS.InstallEventHandler(controlTarget, callback3Address, mask.length / 2, mask, webViewHandle, null);

	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 = WebKit.objc_msgSend(WebKit.C_WebKitDelegate, WebKit.S_alloc);
	delegate = WebKit.objc_msgSend(delegate, WebKit.S_initWithProc, callback7Address, webViewHandle);
				
	// [webView setFrameLoadDelegate:delegate];
	WebKit.objc_msgSend(webView, WebKit.S_setFrameLoadDelegate, delegate);
		
	// [webView setResourceLoadDelegate:delegate];
	WebKit.objc_msgSend(webView, WebKit.S_setResourceLoadDelegate, delegate);

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

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

/**
 * Clears all session cookies from all current Browser instances.
 * 
 * @since 3.2
 */
public static void clearSessions () {
	int storage = WebKit.objc_msgSend (WebKit.C_NSHTTPCookieStorage, WebKit.S_sharedHTTPCookieStorage);
	int cookies = WebKit.objc_msgSend (storage, WebKit.S_cookies);
	int count = WebKit.objc_msgSend (cookies, WebKit.S_count);
	for (int i = 0; i < count; i++) {
		int cookie = WebKit.objc_msgSend (cookies, WebKit.S_objectAtIndex, i);
		boolean isSession = WebKit.objc_msgSend (cookie, WebKit.S_isSessionOnly) != 0;
		if (isSession) {
			WebKit.objc_msgSend (storage, WebKit.S_deleteCookie, cookie);
		}
	}
}

static int eventProc3(int nextHandler, int theEvent, int userData) {
	Widget widget = Display.getCurrent().findWidget(userData);
	if (widget instanceof Browser)
		return ((Browser)widget).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 ((Browser)widget).handleCallback(selector, arg0, arg1, arg2, arg3);
	return 0;
}

/**	 
 * Adds the listener to the collection of listeners who will be
 * notified when the window hosting the receiver should be closed.
 * <p>
 * This notification occurs when a javascript command such as
 * <code>window.close</code> gets executed by a <code>Browser</code>.
 * </p>
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *
 * @since 3.0
 */
public void addCloseWindowListener(CloseWindowListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);	
	CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length + 1];
	System.arraycopy(closeWindowListeners, 0, newCloseWindowListeners, 0, closeWindowListeners.length);
	closeWindowListeners = newCloseWindowListeners;
	closeWindowListeners[closeWindowListeners.length - 1] = listener;
}

/**	 
 * Adds the listener to the collection of listeners who will be
 * notified when the current location has changed or is about to change.
 * <p>
 * This notification typically occurs when the application navigates
 * to a new location with {@link #setUrl(String)} or when the user
 * activates a hyperlink.
 * </p>
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *
 * @since 3.0
 */
public void addLocationListener(LocationListener listener) {
	checkWidget();
	if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	LocationListener[] newLocationListeners = new LocationListener[locationListeners.length + 1];
	System.arraycopy(locationListeners, 0, newLocationListeners, 0, locationListeners.length);
	locationListeners = newLocationListeners;
	locationListeners[locationListeners.length - 1] = listener;
}

/**	 
 * Adds the listener to the collection of listeners who will be
 * notified when a new window needs to be created.
 * <p>
 * This notification occurs when a javascript command such as
 * <code>window.open</code> gets executed by a <code>Browser</code>.
 * </p>
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *
 * @since 3.0
 */
public void addOpenWindowListener(OpenWindowListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length + 1];
	System.arraycopy(openWindowListeners, 0, newOpenWindowListeners, 0, openWindowListeners.length);
	openWindowListeners = newOpenWindowListeners;
	openWindowListeners[openWindowListeners.length - 1] = listener;
}

/**	 
 * Adds the listener to the collection of listeners who will be
 * notified when a progress is made during the loading of the current 
 * URL or when the loading of the current URL has been completed.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *
 * @since 3.0
 */
public void addProgressListener(ProgressListener listener) {
	checkWidget();
	if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length + 1];
	System.arraycopy(progressListeners, 0, newProgressListeners, 0, progressListeners.length);
	progressListeners = newProgressListeners;
	progressListeners[progressListeners.length - 1] = listener;
}

/**	 
 * Adds the listener to the collection of listeners who will be
 * notified when the status text is changed.
 * <p>
 * The status text is typically displayed in the status bar of
 * a browser application.
 * </p>
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *
 * @since 3.0
 */
public void addStatusTextListener(StatusTextListener listener) {
	checkWidget();
	if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length + 1];
	System.arraycopy(statusTextListeners, 0, newStatusTextListeners, 0, statusTextListeners.length);
	statusTextListeners = newStatusTextListeners;
	statusTextListeners[statusTextListeners.length - 1] = listener;
}

/**	 
 * Adds the listener to the collection of listeners who will be
 * notified when the title of the current document is available
 * or has changed.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *
 * @since 3.0
 */
public void addTitleListener(TitleListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	TitleListener[] newTitleListeners = new TitleListener[titleListeners.length + 1];
	System.arraycopy(titleListeners, 0, newTitleListeners, 0, titleListeners.length);
	titleListeners = newTitleListeners;
	titleListeners[titleListeners.length - 1] = listener;
}

/**	 
 * Adds the listener to the collection of listeners who will be
 * notified when a window hosting the receiver needs to be displayed
 * or hidden.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *
 * @since 3.0
 */
public void addVisibilityWindowListener(VisibilityWindowListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length + 1];
	System.arraycopy(visibilityWindowListeners, 0, newVisibilityWindowListeners, 0, visibilityWindowListeners.length);
	visibilityWindowListeners = newVisibilityWindowListeners;
	visibilityWindowListeners[visibilityWindowListeners.length - 1] = listener;
}

/**
 * Navigate to the previous session history item.
 *
 * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
 *
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *
 * @see #forward
 * 
 * @since 3.0
 */
public boolean back() {
	checkWidget();
	html = null;
	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	return WebKit.objc_msgSend(webView, WebKit.S_goBack) != 0;
}

protected void checkSubclass () {
	String name = getClass().getName();
	int index = name.lastIndexOf('.');
	if (!name.substring(0, index + 1).equals(PACKAGE_PREFIX)) {
		SWT.error(SWT.ERROR_INVALID_SUBCLASS);
	}
}

/**
 * Execute the specified script.
 *
 * <p>
 * Execute a script containing javascript commands in the context of the current document. 
 * 
 * @param script the script with javascript commands
 *  
 * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the script is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *
 * @since 3.1
 */
public boolean execute(String script) {
	checkWidget();
	if (script == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);

	int length = script.length();
	char[] buffer = new char[length];
	script.getChars(0, length, buffer, 0);
	int string = OS.CFStringCreateWithCharacters(0, buffer, length);

	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	int value = WebKit.objc_msgSend(webView, WebKit.S_stringByEvaluatingJavaScriptFromString, string);
	OS.CFRelease(string);
	return value != 0;
}

/**
 * Navigate to the next session history item.
 *
 * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
 *
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 * 
 * @see #back
 * 
 * @since 3.0
 */
public boolean forward() {
	checkWidget();
	html = null;
	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	return WebKit.objc_msgSend(webView, WebKit.S_goForward) != 0;
}

/**
 * Returns the current URL.
 *
 * @return the current URL or an empty <code>String</code> if there is no current URL
 *
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *
 * @see #setUrl
 * 
 * @since 3.0
 */
public String getUrl() {
	checkWidget();
	return url;
}

int handleCallback(int nextHandler, int theEvent) {
	int eventKind = OS.GetEventKind(theEvent);
	switch (eventKind) {
		case OS.kEventControlDraw: {          
			/*
			* Bug on Safari. 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 (!isVisible ()) return OS.noErr;
            
			/*
			* GOOGLE: HACK - SWT does not properly push repaint events back to
			* WebKit, so we actually naively tell webkit to repaint it's entire
			* client area.
			*/
			setNeedsDisplay(true);            
			
			break;
		}
		case OS.kEventRawKeyDown: {
			/*
			* Bug in Safari. 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 Safari
			* 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;
			break;
		}
		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;
        // GOOGLE
		case 99: fireWindowScriptObjectListeners(arg0); break;
	}
	return ret;
}

/**
 * Returns <code>true</code> if the receiver can navigate to the 
 * previous session history item, and <code>false</code> otherwise.
 *
 * @return the receiver's back command enabled state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * 
 * @see #back
 */
public boolean isBackEnabled() {
	checkWidget();
	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	return WebKit.objc_msgSend(webView, WebKit.S_canGoBack) != 0;
}

/**
 * Returns <code>true</code> if the receiver can navigate to the 
 * next session history item, and <code>false</code> otherwise.
 *
 * @return the receiver's forward command enabled state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * 
 * @see #forward
 */
public boolean isForwardEnabled() {
	checkWidget();
	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	return WebKit.objc_msgSend(webView, WebKit.S_canGoForward) != 0;
}

/**
 * Refresh the current page.
 *
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *
 * @since 3.0
 */
public void refresh() {
	checkWidget();
	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	WebKit.objc_msgSend(webView, WebKit.S_reload, 0);
}

/**	 
 * Removes the listener from the collection of listeners who will
 * be notified when the window hosting the receiver should be closed.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 * 
 * @since 3.0
 */
public void removeCloseWindowListener(CloseWindowListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	if (closeWindowListeners.length == 0) return;
	int index = -1;
	for (int i = 0; i < closeWindowListeners.length; i++) {
		if (listener == closeWindowListeners[i]){
			index = i;
			break;
		}
	}
	if (index == -1) return;
	if (closeWindowListeners.length == 1) {
		closeWindowListeners = new CloseWindowListener[0];
		return;
	}
	CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length - 1];
	System.arraycopy(closeWindowListeners, 0, newCloseWindowListeners, 0, index);
	System.arraycopy(closeWindowListeners, index + 1, newCloseWindowListeners, index, closeWindowListeners.length - index - 1);
	closeWindowListeners = newCloseWindowListeners;
}

/**	 
 * Removes the listener from the collection of listeners who will
 * be notified when the current location is changed or about to be changed.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 * 
 * @since 3.0
 */
public void removeLocationListener(LocationListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	if (locationListeners.length == 0) return;
	int index = -1;
	for (int i = 0; i < locationListeners.length; i++) {
		if (listener == locationListeners[i]){
			index = i;
			break;
		}
	}
	if (index == -1) return;
	if (locationListeners.length == 1) {
		locationListeners = new LocationListener[0];
		return;
	}
	LocationListener[] newLocationListeners = new LocationListener[locationListeners.length - 1];
	System.arraycopy(locationListeners, 0, newLocationListeners, 0, index);
	System.arraycopy(locationListeners, index + 1, newLocationListeners, index, locationListeners.length - index - 1);
	locationListeners = newLocationListeners;
}

/**	 
 * Removes the listener from the collection of listeners who will
 * be notified when a new window needs to be created.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 * 
 * @since 3.0
 */
public void removeOpenWindowListener(OpenWindowListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	if (openWindowListeners.length == 0) return;
	int index = -1;
	for (int i = 0; i < openWindowListeners.length; i++) {
		if (listener == openWindowListeners[i]){
			index = i;
			break;
		}
	}
	if (index == -1) return;
	if (openWindowListeners.length == 1) {
		openWindowListeners = new OpenWindowListener[0];
		return;
	}
	OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length - 1];
	System.arraycopy(openWindowListeners, 0, newOpenWindowListeners, 0, index);
	System.arraycopy(openWindowListeners, index + 1, newOpenWindowListeners, index, openWindowListeners.length - index - 1);
	openWindowListeners = newOpenWindowListeners;
}

/**	 
 * Removes the listener from the collection of listeners who will
 * be notified when a progress is made during the loading of the current 
 * URL or when the loading of the current URL has been completed.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 * 
 * @since 3.0
 */
public void removeProgressListener(ProgressListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	if (progressListeners.length == 0) return;
	int index = -1;
	for (int i = 0; i < progressListeners.length; i++) {
		if (listener == progressListeners[i]){
			index = i;
			break;
		}
	}
	if (index == -1) return;
	if (progressListeners.length == 1) {
		progressListeners = new ProgressListener[0];
		return;
	}
	ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length - 1];
	System.arraycopy(progressListeners, 0, newProgressListeners, 0, index);
	System.arraycopy(progressListeners, index + 1, newProgressListeners, index, progressListeners.length - index - 1);
	progressListeners = newProgressListeners;
}

/**	 
 * Removes the listener from the collection of listeners who will
 * be notified when the status text is changed.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 * 
 * @since 3.0
 */
public void removeStatusTextListener(StatusTextListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	if (statusTextListeners.length == 0) return;
	int index = -1;
	for (int i = 0; i < statusTextListeners.length; i++) {
		if (listener == statusTextListeners[i]){
			index = i;
			break;
		}
	}
	if (index == -1) return;
	if (statusTextListeners.length == 1) {
		statusTextListeners = new StatusTextListener[0];
		return;
	}
	StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length - 1];
	System.arraycopy(statusTextListeners, 0, newStatusTextListeners, 0, index);
	System.arraycopy(statusTextListeners, index + 1, newStatusTextListeners, index, statusTextListeners.length - index - 1);
	statusTextListeners = newStatusTextListeners;
}

/**	 
 * Removes the listener from the collection of listeners who will
 * be notified when the title of the current document is available
 * or has changed.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 * 
 * @since 3.0
 */
public void removeTitleListener(TitleListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	if (titleListeners.length == 0) return;
	int index = -1;
	for (int i = 0; i < titleListeners.length; i++) {
		if (listener == titleListeners[i]){
			index = i;
			break;
		}
	}
	if (index == -1) return;
	if (titleListeners.length == 1) {
		titleListeners = new TitleListener[0];
		return;
	}
	TitleListener[] newTitleListeners = new TitleListener[titleListeners.length - 1];
	System.arraycopy(titleListeners, 0, newTitleListeners, 0, index);
	System.arraycopy(titleListeners, index + 1, newTitleListeners, index, titleListeners.length - index - 1);
	titleListeners = newTitleListeners;
}

/**	 
 * Removes the listener from the collection of listeners who will
 * be notified when a window hosting the receiver needs to be displayed
 * or hidden.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 * 
 * @since 3.0
 */
public void removeVisibilityWindowListener(VisibilityWindowListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	if (visibilityWindowListeners.length == 0) return;
	int index = -1;
	for (int i = 0; i < visibilityWindowListeners.length; i++) {
		if (listener == visibilityWindowListeners[i]){
			index = i;
			break;
		}
	}
	if (index == -1) return;
	if (visibilityWindowListeners.length == 1) {
		visibilityWindowListeners = new VisibilityWindowListener[0];
		return;
	}
	VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length - 1];
	System.arraycopy(visibilityWindowListeners, 0, newVisibilityWindowListeners, 0, index);
	System.arraycopy(visibilityWindowListeners, index + 1, newVisibilityWindowListeners, index, visibilityWindowListeners.length - index - 1);
	visibilityWindowListeners = newVisibilityWindowListeners;
}

/**
 * Renders HTML.
 * 
 * <p>
 * The html parameter is Unicode encoded since it is a java <code>String</code>.
 * As a result, the HTML meta tag charset should not be set. The charset is implied
 * by the <code>String</code> itself.
 * 
 * @param html the HTML content to be rendered
 *
 * @return true if the operation was successful and false otherwise.
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the html is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *  
 * @see #setUrl
 * 
 * @since 3.0
 */
public boolean setText(String html) {
	checkWidget();
	if (html == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	/*
	* Bug in Safari.  The web view segment faults in some circunstances
	* when the text changes during the location changing callback.  The
	* fix is to defer the work until the callback is done. 
	*/
	if (changingLocation) {
		this.html = html;
	} else {
		_setText(html);
	}
	return true;
}
	
void _setText(String html) {	
	int length = html.length();
	char[] buffer = new char[length];
	html.getChars(0, length, buffer, 0);
	int string = OS.CFStringCreateWithCharacters(0, buffer, length);

	String baseURL = "about:blank"; //$NON-NLS-1$
	length = baseURL.length();
	buffer = new char[length];
	baseURL.getChars(0, length, buffer, 0);
	int URLString = OS.CFStringCreateWithCharacters(0, buffer, length);
	
	/*
	* Note.  URLWithString uses autorelease.  The resulting URL
	* does not need to be released.
	* URL = [NSURL URLWithString:(NSString *)URLString]
	*/	
	int URL = WebKit.objc_msgSend(WebKit.C_NSURL, WebKit.S_URLWithString, URLString);
	OS.CFRelease(URLString);

	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	
	//mainFrame = [webView mainFrame];
	int mainFrame = WebKit.objc_msgSend(webView, WebKit.S_mainFrame);
	
	//[mainFrame loadHTMLString:(NSString *) string baseURL:(NSURL *)URL];
	WebKit.objc_msgSend(mainFrame, WebKit.S_loadHTMLStringbaseURL, string, URL);
	OS.CFRelease(string);
}

/**
 * Loads a URL.
 * 
 * @param url the URL to be loaded
 *
 * @return true if the operation was successful and false otherwise.
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the url is null</li>
 * </ul>
 * 
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *  
 * @see #getUrl
 * 
 * @since 3.0
 */
public boolean setUrl(String url) {
	checkWidget();
	if (url == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);

	html = null;

	StringBuffer buffer = new StringBuffer();
	if (url.indexOf('/') == 0) buffer.append("file://"); //$NON-NLS-1$  //$NON-NLS-2$
	else if (url.indexOf(':') == -1) buffer.append("http://");	 //$NON-NLS-1$
	for (int i = 0; i < url.length(); i++) {
		char c = url.charAt(i);
		if (c == ' ') buffer.append("%20"); //$NON-NLS-1$  //$NON-NLS-2$
		else buffer.append(c);
	}
	
	int length = buffer.length();
	char[] chars = new char[length];
	buffer.getChars(0, length, chars, 0);
	int sHandle = OS.CFStringCreateWithCharacters(0, chars, length);

	/*
	* Note.  URLWithString uses autorelease.  The resulting URL
	* does not need to be released.
	* inURL = [NSURL URLWithString:(NSString *)sHandle]
	*/	
	int inURL= WebKit.objc_msgSend(WebKit.C_NSURL, WebKit.S_URLWithString, sHandle);
	OS.CFRelease(sHandle);
		
	//request = [NSURLRequest requestWithURL:(NSURL*)inURL];
	int request= WebKit.objc_msgSend(WebKit.C_NSURLRequest, WebKit.S_requestWithURL, inURL);
	
	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	
	//mainFrame = [webView mainFrame];
	int mainFrame= WebKit.objc_msgSend(webView, WebKit.S_mainFrame);

	//[mainFrame loadRequest:request];
	WebKit.objc_msgSend(mainFrame, WebKit.S_loadRequest, request);

	return true;
}

/**
 * Stop any loading and rendering activity.
 *
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
 *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
 * </ul>
 *
 * @since 3.0
 */
public void stop() {
	checkWidget();
	html = null;
	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	WebKit.objc_msgSend(webView, WebKit.S_stopLoading, 0);
}

/* WebFrameLoadDelegate */
  
void didFailProvisionalLoadWithError(int error, int frame) {
	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	if (frame == WebKit.objc_msgSend(webView, WebKit.S_mainFrame)) {
		/*
		* Feature on Safari.  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, Safari 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 didFinishLoadForFrame(int frame) {
	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	if (frame == WebKit.objc_msgSend(webView, WebKit.S_mainFrame)) {
		final Display display= getDisplay();
		final ProgressEvent progress = new ProgressEvent(this);
		progress.display = getDisplay();
		progress.widget = this;
		progress.current = MAX_PROGRESS;
		progress.total = MAX_PROGRESS;
		for (int i = 0; i < progressListeners.length; i++) {
			final ProgressListener listener = progressListeners[i];
			/*
			* Note on WebKit.  Running the event loop from a Browser
			* delegate callback breaks the WebKit (stop loading or
			* crash).  The widget ProgressBar currently touches the
			* event loop every time the method setSelection is called.  
			* The workaround is to invoke Display.asyncexec so that
			* the Browser does not crash when the user updates the 
			* selection of the ProgressBar.
			*/
			display.asyncExec(
				new Runnable() {
					public void run() {
						if (!display.isDisposed() && !isDisposed())
							listener.completed(progress);
					}
				}
			);
		}
		/*
		* Feature on Safari.  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, Safari 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 didReceiveTitle(int title, int frame) {
	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	if (frame == WebKit.objc_msgSend(webView, WebKit.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.this);
		newEvent.display = getDisplay();
		newEvent.widget = this;
		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) {
	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	//id url= [[[[frame provisionalDataSource] request] URL] absoluteString];
	int dataSource = WebKit.objc_msgSend(frame, WebKit.S_dataSource);
	int request = WebKit.objc_msgSend(dataSource, WebKit.S_request);
	int url = WebKit.objc_msgSend(request, WebKit.S_URL);
	int s = WebKit.objc_msgSend(url, WebKit.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);
	final Display display = getDisplay();

	boolean top = frame == WebKit.objc_msgSend(webView, WebKit.S_mainFrame);
	if (top) {
		/* reset resource status variables */
		resourceCount = 0;		
		this.url = url2;
		
		final ProgressEvent progress = new ProgressEvent(this);
		progress.display = display;
		progress.widget = this;
		progress.current = 1;
		progress.total = MAX_PROGRESS;
		for (int i = 0; i < progressListeners.length; i++) {
			final ProgressListener listener = progressListeners[i];
			/*
			* Note on WebKit.  Running the event loop from a Browser
			* delegate callback breaks the WebKit (stop loading or
			* crash).  The widget ProgressBar currently touches the
			* event loop every time the method setSelection is called.  
			* The workaround is to invoke Display.asyncexec so that
			* the Browser does not crash when the user updates the 
			* selection of the ProgressBar.
			*/
			display.asyncExec(
				new Runnable() {
					public void run() {
						if (!display.isDisposed() && !isDisposed())
							listener.changed(progress);
					}
				}
			);
		}
		
		StatusTextEvent statusText = new StatusTextEvent(this);
		statusText.display = display;
		statusText.widget = this;
		statusText.text = url2;
		for (int i = 0; i < statusTextListeners.length; i++)
			statusTextListeners[i].changed(statusText);
	}
	LocationEvent location = new LocationEvent(Browser.this);
	location.display = display;
	location.widget = this;
	location.location = url2;
	location.top = top;
	for (int i = 0; i < locationListeners.length; i++)
		locationListeners[i].changed(location);
}

/* WebResourceLoadDelegate */

void didFinishLoadingFromDataSource(int identifier, int dataSource) {
	/*
	* Feature on Safari.  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, Safari 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 Safari.  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, Safari 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;
}

int identifierForInitialRequest(int request, int dataSource) {
	final Display display = getDisplay();
	final ProgressEvent progress = new ProgressEvent(this);
	progress.display = display;
	progress.widget = this;
	progress.current = resourceCount;
	progress.total = Math.max(resourceCount, MAX_PROGRESS);
	for (int i = 0; i < progressListeners.length; i++) {
		final ProgressListener listener = progressListeners[i];
		/*
		* Note on WebKit.  Running the event loop from a Browser
		* delegate callback breaks the WebKit (stop loading or
		* crash).  The widget ProgressBar currently touches the
		* event loop every time the method setSelection is called.  
		* The workaround is to invoke Display.asyncexec so that
		* the Browser does not crash when the user updates the 
		* selection of the ProgressBar.
		*/
		display.asyncExec(
			new Runnable() {
				public void run() {
					if (!display.isDisposed() && !isDisposed())
						listener.changed(progress);
				}
			}
		);
	}

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

int willSendRequest(int identifier, int request, int redirectResponse, int dataSource) {
	return request;
}

/* handleNotification */

void handleNotification(int notification) {	
}

/* UIDelegate */
int createWebViewWithRequest(int request) {
	WindowEvent newEvent = new WindowEvent(Browser.this);
	newEvent.display = getDisplay();
	newEvent.widget = this;
	newEvent.required = true;
	if (openWindowListeners != null) {
		for (int i = 0; i < openWindowListeners.length; i++)
			openWindowListeners[i].open(newEvent);
	}
	int webView = 0;
	Browser browser = newEvent.browser;
	if (browser != null && !browser.isDisposed()) {
		webView = WebKit.HIWebViewGetWebView(browser.webViewHandle);
		
		if (request != 0) {
			//mainFrame = [webView mainFrame];
			int mainFrame= WebKit.objc_msgSend(webView, WebKit.S_mainFrame);

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

void webViewShow(int sender) {
	/*
	* Feature on WebKit.  The Safari 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 = getShell();
	Point pt = parent.getSize();
	parent.setSize(pt.x+1, pt.y);
	parent.setSize(pt.x, pt.y);
	WindowEvent newEvent = new WindowEvent(this);
	newEvent.display = getDisplay();
	newEvent.widget = this;
	if (location != null) newEvent.location = location;
	if (size != null) newEvent.size = size;
	/*
	* Feature in Safari.  Safari'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 in Safari.  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.memcpy(dest, frame, 16);
	/* convert to SWT system coordinates */
	Rectangle bounds = 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() {
}

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(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(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(getShell(), SWT.NONE);
	String result = dialog.open();
	if (result == null) {
		WebKit.objc_msgSend(resultListener, WebKit.S_cancel);
		return;
	}
	int length = result.length();
	char[] buffer = new char[length];
	result.getChars(0, length, buffer, 0);
	int filename = OS.CFStringCreateWithCharacters(0, buffer, length);
	WebKit.objc_msgSend(resultListener, WebKit.S_chooseFilename, filename);
	OS.CFRelease(filename);
}
void webViewClose() {
	Shell parent = getShell();
	WindowEvent newEvent = new WindowEvent(this);
	newEvent.display = getDisplay();
	newEvent.widget = this;
	for (int i = 0; i < closeWindowListeners.length; i++)
		closeWindowListeners[i].close(newEvent);	
	dispose();
	if (parent.isDisposed()) return;
	/*
	* Feature on WebKit.  The Safari 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;
	notifyListeners(SWT.MenuDetect, event);
	Menu menu = getMenu();
	if (!event.doit) return 0;
	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(this);
	statusText.display = getDisplay();
	statusText.widget = this;
	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;
}

/* PolicyDelegate */

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

void decidePolicyForNavigationAction(int actionInformation, int request, int frame, int listener) {
	int url = WebKit.objc_msgSend(request, WebKit.S_URL);
	if (url == 0) {
		/* indicates that a URL with an invalid format was specified */
		WebKit.objc_msgSend(listener, WebKit.S_ignore);
		return;
	}
	int s = WebKit.objc_msgSend(url, WebKit.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);

	LocationEvent newEvent = new LocationEvent(this);
	newEvent.display = getDisplay();
	newEvent.widget = this;
	newEvent.location = url2;
	newEvent.doit = true;
	if (locationListeners != null) {
		changingLocation = true;
		for (int i = 0; i < locationListeners.length; i++) 
			locationListeners[i].changing(newEvent);
		changingLocation = false;
	}

	WebKit.objc_msgSend(listener, newEvent.doit ? WebKit.S_use : WebKit.S_ignore);

	if (html != null && !isDisposed()) {
		String html = this.html;
		this.html = null;
		_setText(html);
	}
}

void decidePolicyForNewWindowAction(int actionInformation, int request, int frameName, int listener) {
	WebKit.objc_msgSend(listener, WebKit.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);
	FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
	dialog.setText(SWT.getMessage ("SWT_FileDownload")); //$NON-NLS-1$
	dialog.setFileName(name);
	String path = dialog.open();
	if (path == null) {
		/* cancel pressed */
		WebKit.objc_msgSend(download, WebKit.S_release);
		return;
	}
	length = path.length();
	char[] chars = new char[length];
	path.getChars(0, length, chars, 0);
	int result = OS.CFStringCreateWithCharacters(0, chars, length);
	WebKit.objc_msgSend(download, WebKit.S_setDestinationAllowOverwrite, result, 1);
	OS.CFRelease(result);
}

// GOOGLE: we need a notification when the window object is available so we can
// setup our own hooks before any JavaScript runs.
public interface WindowScriptObjectListener {
	public void windowScriptObjectAvailable(int windowScriptObject);
}

public void addWindowScriptObjectListener(WindowScriptObjectListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	WindowScriptObjectListener[] newWindowScriptObjectListeners = new WindowScriptObjectListener[windowScriptObjectListeners.length + 1];
	System.arraycopy(windowScriptObjectListeners, 0, newWindowScriptObjectListeners, 0, windowScriptObjectListeners.length);
	windowScriptObjectListeners = newWindowScriptObjectListeners;
	windowScriptObjectListeners[windowScriptObjectListeners.length - 1] = listener;
}

public void removeWindowScriptObjectListener(WindowScriptObjectListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	if (windowScriptObjectListeners.length == 0) return;
	int index = -1;
	for (int i = 0; i < windowScriptObjectListeners.length; i++) {
		if (listener == windowScriptObjectListeners[i]) {
			index = i;
			break;
		}
	}
	if (index == -1) return;
	if (windowScriptObjectListeners.length == 1) {
		windowScriptObjectListeners = new WindowScriptObjectListener[0];
		return;
	}
	WindowScriptObjectListener[] newWindowScriptObjectListeners = new WindowScriptObjectListener[windowScriptObjectListeners.length - 1];
	System.arraycopy(windowScriptObjectListeners, 0, newWindowScriptObjectListeners, 0, index);
	System.arraycopy(windowScriptObjectListeners, index + 1, newWindowScriptObjectListeners, index, windowScriptObjectListeners.length - index - 1);
	windowScriptObjectListeners = newWindowScriptObjectListeners;
}

void fireWindowScriptObjectListeners(int windowScriptObject) {
	for (int i = 0; i < windowScriptObjectListeners.length; i++) {
		windowScriptObjectListeners[i].windowScriptObjectAvailable(windowScriptObject);
	}
}

public static void setWebInspectorEnabled(boolean isEnabled) {
	char[] name = "WebKitDeveloperExtras".toCharArray();
	int clsId = WebKit.objc_getClass("NSUserDefaults");
	if (clsId == 0) return;
	int sel_sud = WebKit.sel_registerName("standardUserDefaults");
	if (sel_sud == 0) return;
	int objId = WebKit.objc_msgSend(clsId, sel_sud);
	if (objId == 0) return;
	int sel_sbfk = WebKit.sel_registerName("setBool:forKey:");
	if (sel_sbfk == 0) return;
	int cfName = OS.CFStringCreateWithCharacters(0,name,name.length);
	if (cfName == 0) return;
	try {
		WebKit.objc_msgSend(objId, sel_sbfk, isEnabled ? 1 : 0, cfName);
	} finally {
		OS.CFRelease(cfName);
	}
}

public void setNeedsDisplay(boolean value) {
	int webView = WebKit.HIWebViewGetWebView(webViewHandle);
	if (webView == 0) return;
	int sel = WebKit.sel_registerName("setNeedsDisplay:");
	if (sel == 0) return;
	WebKit.objc_msgSend(webView, sel, (value)?1:0);
}

private static int getGlobalContextForWindowObject(int frame,
    int windowObject, int childFramesSel, int countSel, int windowObjectSel,
    int objectAtIndexSel) {
  int frameWindowObject = WebKit.objc_msgSend(frame, windowObjectSel);
  if (frameWindowObject == 0) return 0;
  if (frameWindowObject == windowObject) return frame;

  int childFrames = WebKit.objc_msgSend(frame, childFramesSel);
  int count = WebKit.objc_msgSend(childFrames, countSel);
  for (int i = 0; i < count; ++i) {
    int child = WebKit.objc_msgSend(childFrames, objectAtIndexSel, i);
    if (child == 0) continue;
    int foundFrame = getGlobalContextForWindowObject(child, windowObject,
        childFramesSel, countSel, windowObjectSel, objectAtIndexSel);
    if (foundFrame != 0)  return foundFrame;
  }
  return 0;
}

// Finds a JSGlobalContextRef by searching the WebFrame tree for
// a particular WebScriptObject (objective-c wrapper around the
// global object).
public int getGlobalContextForWindowObject(int windowObject) {
  int childFramesSel = WebKit.sel_registerName("childFrames");
  int countSel = WebKit.sel_registerName("count");
  int windowObjectSel = WebKit.sel_registerName("windowObject");
  int objectAtIndexSel = WebKit.sel_registerName("objectAtIndex:");
  int mainFrameSel = WebKit.sel_registerName("mainFrame");
  int globalContextSel = WebKit.sel_registerName("globalContext");
  if (childFramesSel == 0 || countSel == 0 || windowObjectSel == 0
      || objectAtIndexSel == 0 || mainFrameSel == 0 || globalContextSel == 0)
    return 0;
  int webViewRef = WebKit.HIWebViewGetWebView(webViewHandle);
  if (webViewRef == 0) return 0;
  int mainFrame = WebKit.objc_msgSend(webViewRef, mainFrameSel);
  if (mainFrame == 0) return 0;
  int frame = getGlobalContextForWindowObject(mainFrame, windowObject, childFramesSel,
      countSel, windowObjectSel, objectAtIndexSel);
  if (frame == 0) return 0;
  return WebKit.objc_msgSend(frame, globalContextSel);
}

WindowScriptObjectListener[] windowScriptObjectListeners = new WindowScriptObjectListener[0];
// end GOOGLE
}
