Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Gayed2010-06-25 20:49:40 +0000
committerGrant Gayed2010-06-25 20:49:40 +0000
commit7692871f7f787db56ee6d7e9051fd08cd8bb22cb (patch)
treee3bc23c9863c2171803a0e246f46ff70b354357f /bundles/org.eclipse.swt/Eclipse SWT WebKit
parent6c6ae9e56aa891fd3bc758cad0772a1a8cad8c06 (diff)
downloadeclipse.platform.swt-7692871f7f787db56ee6d7e9051fd08cd8bb22cb.tar.gz
eclipse.platform.swt-7692871f7f787db56ee6d7e9051fd08cd8bb22cb.tar.xz
eclipse.platform.swt-7692871f7f787db56ee6d7e9051fd08cd8bb22cb.zip
316811 - change all "Safari" references to "WebKit"
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT WebKit')
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT WebKit/carbon/org/eclipse/swt/browser/WebKit.java2204
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT WebKit/cocoa/org/eclipse/swt/browser/WebKit.java1786
2 files changed, 3990 insertions, 0 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/carbon/org/eclipse/swt/browser/WebKit.java b/bundles/org.eclipse.swt/Eclipse SWT WebKit/carbon/org/eclipse/swt/browser/WebKit.java
new file mode 100755
index 0000000000..6bd8948632
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/carbon/org/eclipse/swt/browser/WebKit.java
@@ -0,0 +1,2204 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 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 boolean 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);
+ }
+
+ return true;
+}
+
+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); 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 */
+
+ int /*long*/ 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(int /*long*/ messageID, int /*long*/ 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 (jsEnabledChanged) {
+ jsEnabledChanged = false;
+ 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;
+}
+
+int /*long*/ callJava (int /*long*/ index, int /*long*/ args, int /*long*/ 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);
+ Object key = new Integer (functionIndex);
+ BrowserFunction function = (BrowserFunction)functions.get (key);
+ if (function != null) {
+ 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 ()));
+ }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/cocoa/org/eclipse/swt/browser/WebKit.java b/bundles/org.eclipse.swt/Eclipse SWT WebKit/cocoa/org/eclipse/swt/browser/WebKit.java
new file mode 100755
index 0000000000..82d38700f8
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/cocoa/org/eclipse/swt/browser/WebKit.java
@@ -0,0 +1,1786 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 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.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.cocoa.*;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+
+class WebKit extends WebBrowser {
+ WebView webView;
+ WebPreferences preferences;
+ SWTWebViewDelegate delegate;
+ boolean loadingText, untrustedText;
+ String lastHoveredLinkURL, lastNavigateURL;
+ String html;
+ int /*long*/ identifier;
+ int resourceCount;
+ String url = ""; //$NON-NLS-1$
+ Point location;
+ Point size;
+ boolean statusBar = true, toolBar = true, ignoreDispose;
+ int lastMouseMoveX, lastMouseMoveY;
+ //TEMPORARY CODE
+// boolean doit;
+
+ static int /*long*/ delegateClass;
+ static boolean Initialized;
+ // the following Callbacks are never freed
+ static Callback Callback3, Callback4, Callback5, Callback6, 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/522.0"; /* Safari version on OSX 10.5 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 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 WEBKIT_EVENTS_FIX_KEY = "org.eclipse.swt.internal.webKitEventsFix"; //$NON-NLS-1$
+ static final byte[] SWT_OBJECT = {'S', 'W', 'T', '_', 'O', 'B', 'J', 'E', 'C', 'T', '\0'};
+
+ /* 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 {
+ NativeClearSessions = new Runnable() {
+ public void run() {
+ NSHTTPCookieStorage storage = NSHTTPCookieStorage.sharedHTTPCookieStorage();
+ NSArray cookies = storage.cookies();
+ int count = (int)/*64*/cookies.count ();
+ for (int i = 0; i < count; i++) {
+ NSHTTPCookie cookie = new NSHTTPCookie(cookies.objectAtIndex(i));
+ if (cookie.isSessionOnly()) {
+ storage.deleteCookie(cookie);
+ }
+ }
+ }
+ };
+
+ NativeGetCookie = new Runnable () {
+ public void run () {
+ NSHTTPCookieStorage storage = NSHTTPCookieStorage.sharedHTTPCookieStorage ();
+ NSURL url = NSURL.URLWithString (NSString.stringWith (CookieUrl));
+ NSArray cookies = storage.cookiesForURL (url);
+ int count = (int)/*64*/cookies.count ();
+ if (count == 0) return;
+
+ NSString name = NSString.stringWith (CookieName);
+ for (int i = 0; i < count; i++) {
+ NSHTTPCookie current = new NSHTTPCookie (cookies.objectAtIndex (i));
+ if (current.name ().compare (name) == OS.NSOrderedSame) {
+ CookieValue = current.value ().getString ();
+ return;
+ }
+ }
+ }
+ };
+
+ NativeSetCookie = new Runnable () {
+ public void run () {
+ NSURL url = NSURL.URLWithString (NSString.stringWith (CookieUrl));
+ NSMutableDictionary headers = NSMutableDictionary.dictionaryWithCapacity (1);
+ headers.setValue (NSString.stringWith (CookieValue), NSString.stringWith (HEADER_SETCOOKIE));
+ NSArray cookies = NSHTTPCookie.cookiesWithResponseHeaderFields (headers, url);
+ if (cookies.count () == 0) return;
+ NSHTTPCookieStorage storage = NSHTTPCookieStorage.sharedHTTPCookieStorage ();
+ NSHTTPCookie cookie = new NSHTTPCookie (cookies.objectAtIndex (0));
+ storage.setCookie (cookie);
+ CookieResult = true;
+ }
+ };
+
+ if (NativePendingCookies != null) {
+ SetPendingCookies (NativePendingCookies);
+ }
+ NativePendingCookies = null;
+ }
+
+public boolean create (Composite parent, int style) {
+ if (delegateClass == 0) {
+ Class webKitClass = this.getClass();
+ Callback3 = new Callback(webKitClass, "browserProc", 3); //$NON-NLS-1$
+ int /*long*/ proc3 = Callback3.getAddress();
+ if (proc3 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+ Callback4 = new Callback(webKitClass, "browserProc", 4); //$NON-NLS-1$
+ int /*long*/ proc4 = Callback4.getAddress();
+ if (proc4 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+ Callback5 = new Callback(webKitClass, "browserProc", 5); //$NON-NLS-1$
+ int /*long*/ proc5 = Callback5.getAddress();
+ if (proc5 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+ Callback6 = new Callback(webKitClass, "browserProc", 6); //$NON-NLS-1$
+ int /*long*/ proc6 = Callback6.getAddress();
+ if (proc6 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+ Callback7 = new Callback(webKitClass, "browserProc", 7); //$NON-NLS-1$
+ int /*long*/ proc7 = Callback7.getAddress();
+ if (proc7 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+ int /*long*/ setFrameProc = OS.CALLBACK_webView_setFrame_(proc4);
+ if (setFrameProc == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+
+ String className = "SWTWebViewDelegate"; //$NON-NLS-1$
+ byte[] types = {'*','\0'};
+ int size = C.PTR_SIZEOF, align = C.PTR_SIZEOF == 4 ? 2 : 3;
+ delegateClass = OS.objc_allocateClassPair (OS.class_NSObject, className, 0);
+
+ OS.class_addIvar(delegateClass, SWT_OBJECT, size, (byte)align, types);
+ OS.class_addMethod(delegateClass, OS.sel_webView_didChangeLocationWithinPageForFrame_, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_didFailProvisionalLoadWithError_forFrame_, proc5, "@:@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_didFinishLoadForFrame_, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_didReceiveTitle_forFrame_, proc5, "@:@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_didStartProvisionalLoadForFrame_, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_didCommitLoadForFrame_, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_resource_didFinishLoadingFromDataSource_, proc5, "@:@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_resource_didReceiveAuthenticationChallenge_fromDataSource_, proc6, "@:@@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_resource_didFailLoadingWithError_fromDataSource_, proc6, "@:@@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_identifierForInitialRequest_fromDataSource_, proc5, "@:@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_resource_willSendRequest_redirectResponse_fromDataSource_, proc7, "@:@@@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_createWebViewWithRequest_, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webViewShow_, proc3, "@:@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webViewClose_, proc3, "@:@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_contextMenuItemsForElement_defaultMenuItems_, proc5, "@:@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_setStatusBarVisible_, proc4, "@:@B"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_setResizable_, proc4, "@:@B"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_setToolbarsVisible_, proc4, "@:@B"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_setStatusText_, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webViewFocus_, proc3, "@:@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webViewUnfocus_, proc3, "@:@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_runBeforeUnloadConfirmPanelWithMessage_initiatedByFrame_, proc5, "@:@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_runJavaScriptAlertPanelWithMessage_, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_runJavaScriptAlertPanelWithMessage_initiatedByFrame_, proc5, "@:@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_runJavaScriptConfirmPanelWithMessage_, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_runJavaScriptConfirmPanelWithMessage_initiatedByFrame_, proc5, "@:@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_runOpenPanelForFileButtonWithResultListener_, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_mouseDidMoveOverElement_modifierFlags_, proc5, "@:@@I"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_printFrameView_, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_decidePolicyForMIMEType_request_frame_decisionListener_, proc7, "@:@@@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_decidePolicyForNavigationAction_request_frame_decisionListener_, proc7, "@:@@@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_decidePolicyForNewWindowAction_request_newFrameName_decisionListener_, proc7, "@:@@@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_unableToImplementPolicyWithError_frame_, proc5, "@:@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_download_decideDestinationWithSuggestedFilename_, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_handleEvent_, proc3, "@:@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_setFrame_, setFrameProc, "@:@{NSRect}"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_webView_windowScriptObjectAvailable_, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_callJava, proc5, "@:@@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_callRunBeforeUnloadConfirmPanelWithMessage, proc4, "@:@@"); //$NON-NLS-1$
+ OS.class_addMethod(delegateClass, OS.sel_createPanelDidEnd, proc5, "@:@@@"); //$NON-NLS-1$
+ OS.objc_registerClassPair(delegateClass);
+
+ int /*long*/ metaClass = OS.objc_getMetaClass (className);
+ OS.class_addMethod(metaClass, OS.sel_isSelectorExcludedFromWebScript_, proc3, "@:@"); //$NON-NLS-1$
+ OS.class_addMethod(metaClass, OS.sel_webScriptNameForSelector_, proc3, "@:@"); //$NON-NLS-1$
+ }
+
+ /*
+ * Override the default event mechanism to not send key events so
+ * that the browser can send them by listening to the DOM instead.
+ */
+ browser.setData(WEBKIT_EVENTS_FIX_KEY);
+
+ WebView webView = (WebView)new WebView().alloc();
+ if (webView == null) SWT.error(SWT.ERROR_NO_HANDLES);
+ webView.initWithFrame(browser.view.frame(), null, null);
+ webView.setAutoresizingMask(OS.NSViewWidthSizable | OS.NSViewHeightSizable);
+ if (webView.respondsToSelector(OS.sel__setDashboardBehavior)) {
+ OS.objc_msgSend(webView.id, OS.sel__setDashboardBehavior, 2, 1);
+ }
+ final SWTWebViewDelegate delegate = (SWTWebViewDelegate)new SWTWebViewDelegate().alloc().init();
+ Display display = browser.getDisplay();
+ display.setData(ADD_WIDGET_KEY, new Object[] {delegate, browser});
+ this.delegate = delegate;
+ this.webView = webView;
+ browser.view.addSubview(webView);
+
+ Listener listener = new Listener() {
+ public void handleEvent(Event e) {
+ switch (e.type) {
+ case SWT.FocusIn:
+ WebKit.this.webView.window().makeFirstResponder(WebKit.this.webView);
+ break;
+ 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;
+
+ /* Browser could have been disposed by one of the Dispose listeners */
+ if (!browser.isDisposed()) {
+ /* invoke onbeforeunload handlers */
+ if (!browser.isClosing) {
+ close (false);
+ }
+
+ e.display.setData(ADD_WIDGET_KEY, new Object[] {delegate, null});
+ }
+
+ WebKit.this.webView.setFrameLoadDelegate(null);
+ WebKit.this.webView.setResourceLoadDelegate(null);
+ WebKit.this.webView.setUIDelegate(null);
+ WebKit.this.webView.setPolicyDelegate(null);
+ WebKit.this.webView.setDownloadDelegate(null);
+
+ WebKit.this.webView.release();
+ WebKit.this.webView = null;
+ WebKit.this.delegate.release();
+ WebKit.this.delegate = null;
+ html = null;
+ lastHoveredLinkURL = lastNavigateURL = null;
+
+ Enumeration elements = functions.elements ();
+ while (elements.hasMoreElements ()) {
+ ((BrowserFunction)elements.nextElement ()).dispose (false);
+ }
+ functions = null;
+
+ if (preferences != null) preferences.release ();
+ preferences = null;
+ break;
+ }
+ }
+ }
+ };
+ browser.addListener(SWT.Dispose, listener);
+ browser.addListener(SWT.KeyDown, listener); /* needed for tabbing into the Browser */
+ browser.addListener(SWT.FocusIn, listener);
+
+ webView.setFrameLoadDelegate(delegate);
+ webView.setResourceLoadDelegate(delegate);
+ webView.setUIDelegate(delegate);
+ webView.setPolicyDelegate(delegate);
+ webView.setDownloadDelegate(delegate);
+ webView.setApplicationNameForUserAgent(NSString.stringWith(AGENT_STRING));
+
+ if (!Initialized) {
+ Initialized = true;
+ /* disable applets */
+ WebPreferences.standardPreferences().setJavaEnabled(false);
+ }
+
+ return true;
+}
+
+public boolean back() {
+ html = null;
+ return webView.goBack();
+}
+
+static int /*long*/ browserProc(int /*long*/ id, int /*long*/ sel, int /*long*/ arg0) {
+ if (id == delegateClass) {
+ if (sel == OS.sel_isSelectorExcludedFromWebScript_) {
+ return isSelectorExcludedFromWebScript (arg0) ? 1 : 0;
+ } else if (sel == OS.sel_webScriptNameForSelector_) {
+ return webScriptNameForSelector (arg0);
+ }
+ }
+
+ Widget widget = Display.getCurrent().findWidget(id);
+ if (widget == null) return 0;
+ WebKit webKit = (WebKit)((Browser)widget).webBrowser;
+ if (sel == OS.sel_webViewShow_) {
+ webKit.webViewShow(arg0);
+ } else if (sel == OS.sel_webViewClose_) {
+ webKit.webViewClose(arg0);
+ } else if (sel == OS.sel_webViewFocus_) {
+ webKit.webViewFocus(arg0);
+ } else if (sel == OS.sel_webViewUnfocus_) {
+ webKit.webViewUnfocus(arg0);
+ } else if (sel == OS.sel_handleEvent_) {
+ webKit.handleEvent(arg0);
+ }
+ return 0;
+}
+
+static int /*long*/ browserProc(int /*long*/ id, int /*long*/ sel, int /*long*/ arg0, int /*long*/ arg1) {
+ Widget widget = Display.getCurrent().findWidget(id);
+ if (widget == null) return 0;
+ WebKit webKit = (WebKit)((Browser)widget).webBrowser;
+ if (sel == OS.sel_webView_didChangeLocationWithinPageForFrame_) {
+ webKit.webView_didChangeLocationWithinPageForFrame(arg0, arg1);
+ } else if (sel == OS.sel_webView_didFinishLoadForFrame_) {
+ webKit.webView_didFinishLoadForFrame(arg0, arg1);
+ } else if (sel == OS.sel_webView_didStartProvisionalLoadForFrame_) {
+ webKit.webView_didStartProvisionalLoadForFrame(arg0, arg1);
+ } else if (sel == OS.sel_webView_didCommitLoadForFrame_) {
+ webKit.webView_didCommitLoadForFrame(arg0, arg1);
+ } else if (sel == OS.sel_webView_setFrame_) {
+ webKit.webView_setFrame(arg0, arg1);
+ } else if (sel == OS.sel_webView_createWebViewWithRequest_) {
+ return webKit.webView_createWebViewWithRequest(arg0, arg1);
+ } else if (sel == OS.sel_webView_setStatusBarVisible_) {
+ webKit.webView_setStatusBarVisible(arg0, arg1 != 0);
+ } else if (sel == OS.sel_webView_setResizable_) {
+ webKit.webView_setResizable(arg0, arg1 != 0);
+ } else if (sel == OS.sel_webView_setStatusText_) {
+ webKit.webView_setStatusText(arg0, arg1);
+ } else if (sel == OS.sel_webView_setToolbarsVisible_) {
+ webKit.webView_setToolbarsVisible(arg0, arg1 != 0);
+ } else if (sel == OS.sel_webView_runJavaScriptAlertPanelWithMessage_) {
+ webKit.webView_runJavaScriptAlertPanelWithMessage(arg0, arg1);
+ } else if (sel == OS.sel_webView_runJavaScriptConfirmPanelWithMessage_) {
+ return webKit.webView_runJavaScriptConfirmPanelWithMessage(arg0, arg1);
+ } else if (sel == OS.sel_webView_runOpenPanelForFileButtonWithResultListener_) {
+ webKit.webView_runOpenPanelForFileButtonWithResultListener(arg0, arg1);
+ } else if (sel == OS.sel_download_decideDestinationWithSuggestedFilename_) {
+ webKit.download_decideDestinationWithSuggestedFilename(arg0, arg1);
+ } else if (sel == OS.sel_webView_printFrameView_) {
+ webKit.webView_printFrameView(arg0, arg1);
+ } else if (sel == OS.sel_webView_windowScriptObjectAvailable_) {
+ webKit.webView_windowScriptObjectAvailable (arg0, arg1);
+ } else if (sel == OS.sel_callRunBeforeUnloadConfirmPanelWithMessage) {
+ return webKit.callRunBeforeUnloadConfirmPanelWithMessage (arg0, arg1).id;
+ }
+ return 0;
+}
+
+static int /*long*/ browserProc(int /*long*/ id, int /*long*/ sel, int /*long*/ arg0, int /*long*/ arg1, int /*long*/ arg2) {
+ Widget widget = Display.getCurrent().findWidget(id);
+ if (widget == null) return 0;
+ WebKit webKit = (WebKit)((Browser)widget).webBrowser;
+ if (sel == OS.sel_webView_didFailProvisionalLoadWithError_forFrame_) {
+ webKit.webView_didFailProvisionalLoadWithError_forFrame(arg0, arg1, arg2);
+ } else if (sel == OS.sel_webView_didReceiveTitle_forFrame_) {
+ webKit.webView_didReceiveTitle_forFrame(arg0, arg1, arg2);
+ } else if (sel == OS.sel_webView_resource_didFinishLoadingFromDataSource_) {
+ webKit.webView_resource_didFinishLoadingFromDataSource(arg0, arg1, arg2);
+ } else if (sel == OS.sel_webView_identifierForInitialRequest_fromDataSource_) {
+ return webKit.webView_identifierForInitialRequest_fromDataSource(arg0, arg1, arg2);
+ } else if (sel == OS.sel_webView_contextMenuItemsForElement_defaultMenuItems_) {
+ return webKit.webView_contextMenuItemsForElement_defaultMenuItems(arg0, arg1, arg2);
+ } else if (sel == OS.sel_webView_mouseDidMoveOverElement_modifierFlags_) {
+ webKit.webView_mouseDidMoveOverElement_modifierFlags(arg0, arg1, arg2);
+ } else if (sel == OS.sel_webView_unableToImplementPolicyWithError_frame_) {
+ webKit.webView_unableToImplementPolicyWithError_frame(arg0, arg1, arg2);
+ } else if (sel == OS.sel_webView_runBeforeUnloadConfirmPanelWithMessage_initiatedByFrame_) {
+ return webKit.webView_runBeforeUnloadConfirmPanelWithMessage_initiatedByFrame(arg0, arg1, arg2) ? 1 : 0;
+ } else if (sel == OS.sel_webView_runJavaScriptAlertPanelWithMessage_initiatedByFrame_) {
+ webKit.webView_runJavaScriptAlertPanelWithMessage(arg0, arg1);
+ } else if (sel == OS.sel_webView_runJavaScriptConfirmPanelWithMessage_initiatedByFrame_) {
+ return webKit.webView_runJavaScriptConfirmPanelWithMessage(arg0, arg1);
+ } else if (sel == OS.sel_callJava) {
+ id result = webKit.callJava(arg0, arg1, arg2);
+ return result == null ? 0 : result.id;
+ } else if (sel == OS.sel_createPanelDidEnd) {
+ webKit.createPanelDidEnd(arg0, arg1, arg2);
+ }
+ return 0;
+}
+
+static int /*long*/ browserProc(int /*long*/ id, int /*long*/ sel, int /*long*/ arg0, int /*long*/ arg1, int /*long*/ arg2, int /*long*/ arg3) {
+ Widget widget = Display.getCurrent().findWidget(id);
+ if (widget == null) return 0;
+ WebKit webKit = (WebKit)((Browser)widget).webBrowser;
+ if (sel == OS.sel_webView_resource_didFailLoadingWithError_fromDataSource_) {
+ webKit.webView_resource_didFailLoadingWithError_fromDataSource(arg0, arg1, arg2, arg3);
+ } else if (sel == OS.sel_webView_resource_didReceiveAuthenticationChallenge_fromDataSource_) {
+ webKit.webView_resource_didReceiveAuthenticationChallenge_fromDataSource(arg0, arg1, arg2, arg3);
+ }
+ return 0;
+}
+
+static int /*long*/ browserProc(int /*long*/ id, int /*long*/ sel, int /*long*/ arg0, int /*long*/ arg1, int /*long*/ arg2, int /*long*/ arg3, int /*long*/ arg4) {
+ Widget widget = Display.getCurrent().findWidget(id);
+ if (widget == null) return 0;
+ WebKit webKit = (WebKit)((Browser)widget).webBrowser;
+ if (sel == OS.sel_webView_resource_willSendRequest_redirectResponse_fromDataSource_) {
+ return webKit.webView_resource_willSendRequest_redirectResponse_fromDataSource(arg0, arg1, arg2, arg3, arg4);
+ } else if (sel == OS.sel_webView_decidePolicyForMIMEType_request_frame_decisionListener_) {
+ webKit.webView_decidePolicyForMIMEType_request_frame_decisionListener(arg0, arg1, arg2, arg3, arg4);
+ } else if (sel == OS.sel_webView_decidePolicyForNavigationAction_request_frame_decisionListener_) {
+ webKit.webView_decidePolicyForNavigationAction_request_frame_decisionListener(arg0, arg1, arg2, arg3, arg4);
+ } else if (sel == OS.sel_webView_decidePolicyForNewWindowAction_request_newFrameName_decisionListener_) {
+ webKit.webView_decidePolicyForNewWindowAction_request_newFrameName_decisionListener(arg0, arg1, arg2, arg3, arg4);
+ }
+ return 0;
+}
+
+static boolean isSelectorExcludedFromWebScript (int /*long*/ aSelector) {
+ return !(aSelector == OS.sel_callJava || aSelector == OS.sel_callRunBeforeUnloadConfirmPanelWithMessage);
+}
+
+static int /*long*/ webScriptNameForSelector (int /*long*/ aSelector) {
+ if (aSelector == OS.sel_callJava) {
+ return NSString.stringWith ("callJava").id; //$NON-NLS-1$
+ }
+ if (aSelector == OS.sel_callRunBeforeUnloadConfirmPanelWithMessage) {
+ return NSString.stringWith ("callRunBeforeUnloadConfirmPanelWithMessage").id; //$NON-NLS-1$
+ }
+ return 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) {
+ WebFrame frame = webView.mainFrame();
+ int /*long*/ context = frame.globalContext();
+
+ byte[] bytes = null;
+ try {
+ bytes = (script + '\0').getBytes("UTF-8"); //$NON-NLS-1$
+ } catch (UnsupportedEncodingException e) {
+ bytes = (script + '\0').getBytes();
+ }
+ int /*long*/ scriptString = OS.JSStringCreateWithUTF8CString(bytes);
+
+ try {
+ bytes = (getUrl() + '\0').getBytes("UTF-8"); //$NON-NLS-1$
+ } catch (UnsupportedEncodingException e) {
+ bytes = (getUrl() + '\0').getBytes();
+ }
+ int /*long*/ urlString = OS.JSStringCreateWithUTF8CString(bytes);
+
+ int /*long*/ result = OS.JSEvaluateScript(context, scriptString, 0, urlString, 0, null);
+ OS.JSStringRelease(urlString);
+ OS.JSStringRelease(scriptString);
+ return result != 0;
+}
+
+public boolean forward () {
+ html = null;
+ return webView.goForward();
+}
+
+public String getBrowserType () {
+ return "webkit"; //$NON-NLS-1$
+}
+
+public String getText() {
+ WebFrame mainFrame = webView.mainFrame();
+ WebDataSource dataSource = mainFrame.dataSource();
+ if (dataSource == null) return ""; //$NON-NLS-1$
+ WebDocumentRepresentation representation = dataSource.representation();
+ if (representation == null) return ""; //$NON-NLS-1$
+ NSString source = representation.documentSource();
+ if (source == null) return ""; //$NON-NLS-1$
+ return source.getString();
+}
+
+public String getUrl() {
+ /* WebKit auto-navigates to about:blank at startup */
+ if (url.length() == 0) return ABOUT_BLANK;
+
+ return url;
+}
+
+public boolean isBackEnabled() {
+ return webView.canGoBack();
+}
+
+public boolean isForwardEnabled() {
+ return webView.canGoForward();
+}
+
+public void refresh() {
+ html = null;
+ webView.reload(null);
+}
+
+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;
+
+ NSURL inURL = NSURL.URLWithString(NSString.stringWith (ABOUT_BLANK));
+ NSURLRequest request = NSURLRequest.requestWithURL(inURL);
+ WebFrame mainFrame = webView.mainFrame();
+ mainFrame.loadRequest(request);
+ return true;
+}
+
+public boolean setUrl(String url, String postData, String[] headers) {
+ html = null;
+ lastNavigateURL = url;
+
+ if (url.indexOf('/') == 0) {
+ url = PROTOCOL_FILE + url;
+ } else if (url.indexOf(':') == -1) {
+ url = PROTOCOL_HTTP + url;
+ }
+
+ NSString str = NSString.stringWith(url);
+ NSString unescapedStr = NSString.stringWith("%#"); //$NON-NLS-1$
+ int /*long*/ ptr = OS.CFURLCreateStringByAddingPercentEscapes(0, str.id, unescapedStr.id, 0, OS.kCFStringEncodingUTF8);
+ NSString escapedString = new NSString(ptr);
+ NSURL inURL = NSURL.URLWithString(escapedString);
+ OS.CFRelease(ptr);
+ NSMutableURLRequest request = (NSMutableURLRequest)NSMutableURLRequest.requestWithURL(inURL);
+ if (postData != null) {
+ request.setHTTPMethod(NSString.stringWith(POST));
+ byte[] bytes = postData.getBytes();
+ NSData data = NSData.dataWithBytes(bytes, bytes.length);
+ request.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.
+ */
+ webView.setCustomUserAgent(NSString.stringWith(value));
+ } else {
+ request.setValue(NSString.stringWith(value), NSString.stringWith(key));
+ }
+ }
+ }
+ }
+ }
+ }
+ WebFrame mainFrame = webView.mainFrame();
+ mainFrame.loadRequest(request);
+ webView.setCustomUserAgent(null);
+ return true;
+}
+
+public void stop() {
+ html = null;
+ webView.stopLoading(null);
+}
+
+boolean translateMnemonics() {
+ return false;
+}
+
+/* WebFrameLoadDelegate */
+
+void webView_didChangeLocationWithinPageForFrame(int /*long*/ sender, int /*long*/ frameID) {
+ WebFrame frame = new WebFrame(frameID);
+ WebDataSource dataSource = frame.dataSource();
+ NSURLRequest request = dataSource.request();
+ NSURL url = request.URL();
+ NSString s = url.absoluteString();
+ int length = (int)/*64*/s.length();
+ if (length == 0) return;
+ String url2 = s.getString();
+ /*
+ * 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 = frameID == webView.mainFrame().id;
+ 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 webView_didFailProvisionalLoadWithError_forFrame(int /*long*/ sender, int /*long*/ error, int /*long*/ frame) {
+ if (frame == webView.mainFrame().id) {
+ /*
+ * 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;
+ }
+
+ NSError nserror = new NSError(error);
+ int /*long*/ errorCode = nserror.code();
+ if (OS.NSURLErrorBadURL < errorCode) return;
+
+ NSURL failingURL = null;
+ NSDictionary info = nserror.userInfo();
+ if (info != null) {
+ id id = info.valueForKey(NSString.stringWith("NSErrorFailingURLKey")); //$NON-NLS-1$
+ if (id != null) failingURL = new NSURL(id);
+ }
+
+ if (failingURL != null && OS.NSURLErrorServerCertificateNotYetValid <= errorCode && errorCode <= OS.NSURLErrorSecureConnectionFailed) {
+ /* handle invalid certificate error */
+ id certificates = info.objectForKey(NSString.stringWith("NSErrorPeerCertificateChainKey")); //$NON-NLS-1$
+
+ int /*long*/[] policySearch = new int /*long*/[1];
+ int /*long*/[] policyRef = new int /*long*/[1];
+ int /*long*/[] trustRef = new int /*long*/[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.id, policyRef[0], trustRef);
+ if (result == 0 && trustRef[0] != 0) {
+ SFCertificateTrustPanel panel = SFCertificateTrustPanel.sharedCertificateTrustPanel();
+ String failingUrlString = failingURL.absoluteString().getString();
+ String message = Compatibility.getMessage("SWT_InvalidCert_Message", new Object[] {failingUrlString}); //$NON-NLS-1$
+ panel.setAlternateButtonTitle(NSString.stringWith(Compatibility.getMessage("SWT_Cancel"))); //$NON-NLS-1$
+ panel.setShowsHelp(true);
+ failingURL.retain();
+ NSWindow window = browser.getShell().view.window();
+ panel.beginSheetForWindow(window, delegate, OS.sel_createPanelDidEnd, failingURL.id, trustRef[0], NSString.stringWith(message));
+ 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 */
+ NSString description = nserror.localizedDescription();
+ if (description != null) {
+ String descriptionString = description.getString();
+ String message = failingURL != null ? failingURL.absoluteString().getString() + "\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 /*long*/ sheet, int /*long*/ returnCode, int /*long*/ contextInfo) {
+ NSURL failingURL = new NSURL(contextInfo);
+ failingURL.autorelease();
+ if (returnCode != OS.NSFileHandlingPanelOKButton) return; /* nothing more to do */
+
+ int /*long*/ method = OS.class_getClassMethod(OS.class_NSURLRequest, OS.sel_setAllowsAnyHTTPSCertificate);
+ if (method != 0) {
+ OS.objc_msgSend(OS.class_NSURLRequest, OS.sel_setAllowsAnyHTTPSCertificate, 1, failingURL.host().id);
+ setUrl(failingURL.absoluteString().getString(), null, null);
+ }
+}
+
+void webView_didFinishLoadForFrame(int /*long*/ sender, int /*long*/ frameID) {
+ if (frameID == webView.mainFrame().id) {
+ /*
+ * 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;
+ NSString string = NSString.stringWith(html);
+ NSString URLString;
+ if (untrustedText) {
+ URLString = NSString.stringWith(ABOUT_BLANK);
+ } else {
+ URLString = NSString.stringWith(URI_FILEROOT);
+ }
+ NSURL URL = NSURL.URLWithString(URLString);
+ WebFrame mainFrame = webView.mainFrame();
+ mainFrame.loadHTMLString(string, URL);
+ html = null;
+ }
+ }
+
+ /*
+ * The loadHTMLString() invocation above will trigger a second webView_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.
+ */
+ Display display = browser.getDisplay();
+ WebFrame frame = new WebFrame(frameID);
+ WebDataSource dataSource = frame.dataSource();
+ if (dataSource != null) {
+ NSString title = dataSource.pageTitle();
+ if (title == null) { /* page has no title */
+ 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. 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;
+ }
+}
+
+void hookDOMKeyListeners(int /*long*/ frameID) {
+ WebFrame frame = new WebFrame(frameID);
+ DOMDocument document = frame.DOMDocument();
+ if (document == null) return;
+
+ NSString type = NSString.stringWith(DOMEVENT_KEYDOWN);
+ document.addEventListener(type, delegate, false);
+
+ type = NSString.stringWith(DOMEVENT_KEYUP);
+ document.addEventListener(type, delegate, false);
+}
+
+void hookDOMMouseListeners(int /*long*/ frameID) {
+ WebFrame frame = new WebFrame(frameID);
+ DOMDocument document = frame.DOMDocument();
+ if (document == null) return;
+
+ NSString type = NSString.stringWith(DOMEVENT_MOUSEDOWN);
+ document.addEventListener(type, delegate, false);
+
+ type = NSString.stringWith(DOMEVENT_MOUSEUP);
+ document.addEventListener(type, delegate, false);
+
+ type = NSString.stringWith(DOMEVENT_MOUSEMOVE);
+ document.addEventListener(type, delegate, false);
+
+ type = NSString.stringWith(DOMEVENT_MOUSEWHEEL);
+ document.addEventListener(type, delegate, false);
+}
+
+void webView_didReceiveTitle_forFrame(int /*long*/ sender, int /*long*/ titleID, int /*long*/ frameID) {
+ if (frameID == webView.mainFrame().id) {
+ NSString title = new NSString(titleID);
+ String newTitle = title.getString();
+ 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 webView_didStartProvisionalLoadForFrame(int /*long*/ sender, int /*long*/ frameID) {
+ /*
+ * 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.
+ */
+// if (frameID == webView.mainFrame().id) {
+// /* reset resource status variables */
+// resourceCount= 0;
+// }
+}
+
+void webView_didCommitLoadForFrame(int /*long*/ sender, int /*long*/ frameID) {
+ WebFrame frame = new WebFrame(frameID);
+ WebDataSource dataSource = frame.dataSource();
+ NSURLRequest request = dataSource.request();
+ NSURL url = request.URL();
+ NSString s = url.absoluteString();
+ int length = (int)/*64*/s.length();
+ if (length == 0) return;
+ String url2 = s.getString();
+ /*
+ * 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);
+ }
+ }
+
+ Display display = browser.getDisplay();
+ boolean top = frameID == webView.mainFrame().id;
+ if (top) {
+ /* reset resource status variables */
+ resourceCount = 0;
+ this.url = url2;
+
+ /*
+ * Each invocation of setText() causes webView_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 loadHTMLString is invoked. If this is the
+ * first webView_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;
+
+ /* re-install registered functions */
+ Enumeration elements = functions.elements ();
+ while (elements.hasMoreElements ()) {
+ BrowserFunction function = (BrowserFunction)elements.nextElement ();
+ execute (function.functionString);
+ }
+
+ 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(frameID);
+ }
+
+ hookDOMMouseListeners(frameID);
+
+ 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 webView_windowScriptObjectAvailable (int /*long*/ webView, int /*long*/ windowScriptObject) {
+ NSObject scriptObject = new NSObject (windowScriptObject);
+ NSString key = NSString.stringWith ("external"); //$NON-NLS-1$
+ scriptObject.setValue (delegate, key);
+}
+
+/* WebResourceLoadDelegate */
+
+void webView_resource_didFinishLoadingFromDataSource(int /*long*/ sender, int /*long*/ identifier, int /*long*/ 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. 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).
+ */
+ // this code is intentionally commented
+ //if (this.identifier == identifier) this.identifier = 0;
+}
+
+void webView_resource_didFailLoadingWithError_fromDataSource(int /*long*/ sender, int /*long*/ identifier, int /*long*/ error, int /*long*/ 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. 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).
+ */
+ // this code is intentionally commented
+ //if (this.identifier == identifier) this.identifier = 0;
+}
+
+void webView_resource_didReceiveAuthenticationChallenge_fromDataSource (int /*long*/ sender, int /*long*/ identifier, int /*long*/ challenge, int /*long*/ dataSource) {
+ NSURLAuthenticationChallenge nsChallenge = new NSURLAuthenticationChallenge (challenge);
+
+ /*
+ * 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.
+ */
+ if (nsChallenge.previousFailureCount () < 3) {
+ for (int i = 0; i < authenticationListeners.length; i++) {
+ AuthenticationEvent event = new AuthenticationEvent (browser);
+ event.location = lastNavigateURL;
+ authenticationListeners[i].authenticate (event);
+ if (!event.doit) {
+ id challengeSender = nsChallenge.sender ();
+ OS.objc_msgSend (challengeSender.id, OS.sel_cancelAuthenticationChallenge_, challenge);
+ return;
+ }
+ if (event.user != null && event.password != null) {
+ id challengeSender = nsChallenge.sender ();
+ NSString user = NSString.stringWith (event.user);
+ NSString password = NSString.stringWith (event.password);
+ NSURLCredential credential = NSURLCredential.credentialWithUser (user, password, OS.NSURLCredentialPersistenceForSession);
+ OS.objc_msgSend (challengeSender.id, OS.sel_useCredential_forAuthenticationChallenge_, credential.id, challenge);
+ return;
+ }
+ }
+ }
+
+ /* no listener handled the challenge, so try to invoke the native panel */
+ int /*long*/ cls = OS.class_WebPanelAuthenticationHandler;
+ if (cls != 0) {
+ int /*long*/ method = OS.class_getClassMethod (cls, OS.sel_sharedHandler);
+ if (method != 0) {
+ int /*long*/ handler = OS.objc_msgSend (cls, OS.sel_sharedHandler);
+ if (handler != 0) {
+ OS.objc_msgSend (handler, OS.sel_startAuthentication, challenge, webView.window ().id);
+ return;
+ }
+ }
+ }
+
+ /* the native panel was not available, so show a custom dialog */
+ String[] userReturn = new String[1], passwordReturn = new String[1];
+ NSURLCredential proposedCredential = nsChallenge.proposedCredential ();
+ if (proposedCredential != null) {
+ userReturn[0] = proposedCredential.user ().getString ();
+ if (proposedCredential.hasPassword ()) {
+ passwordReturn[0] = proposedCredential.password ().getString ();
+ }
+ }
+ NSURLProtectionSpace space = nsChallenge.protectionSpace ();
+ String host = space.host ().getString () + ':' + space.port ();
+ String realm = space.realm ().getString ();
+ boolean result = showAuthenticationDialog (userReturn, passwordReturn, host, realm);
+ if (!result) {
+ id challengeSender = nsChallenge.sender ();
+ OS.objc_msgSend (challengeSender.id, OS.sel_cancelAuthenticationChallenge_, challenge);
+ return;
+ }
+ id challengeSender = nsChallenge.sender ();
+ NSString user = NSString.stringWith (userReturn[0]);
+ NSString password = NSString.stringWith (passwordReturn[0]);
+ NSURLCredential credential = NSURLCredential.credentialWithUser (user, password, OS.NSURLCredentialPersistenceForSession);
+ OS.objc_msgSend (challengeSender.id, OS.sel_useCredential_forAuthenticationChallenge_, credential.id, challenge);
+}
+
+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 /*long*/ webView_identifierForInitialRequest_fromDataSource(int /*long*/ sender, int /*long*/ request, int /*long*/ dataSourceID) {
+ ProgressEvent progress = new ProgressEvent(browser);
+ progress.display = browser.getDisplay();
+ 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;
+
+ NSNumber identifier = NSNumber.numberWithInt(resourceCount++);
+ if (this.identifier == 0) {
+ WebDataSource dataSource = new WebDataSource(dataSourceID);
+ WebFrame frame = dataSource.webFrame();
+ if (frame.id == webView.mainFrame().id) this.identifier = identifier.id;
+ }
+ return identifier.id;
+
+}
+
+int /*long*/ webView_resource_willSendRequest_redirectResponse_fromDataSource(int /*long*/ sender, int /*long*/ identifier, int /*long*/ request, int /*long*/ redirectResponse, int /*long*/ dataSource) {
+ NSURLRequest nsRequest = new NSURLRequest (request);
+ NSURL url = nsRequest.URL ();
+ if (url.isFileURL ()) {
+ NSMutableURLRequest newRequest = new NSMutableURLRequest (nsRequest.mutableCopy ());
+ newRequest.autorelease ();
+ newRequest.setCachePolicy (OS.NSURLRequestReloadIgnoringLocalCacheData);
+ return newRequest.id;
+ }
+ return request;
+}
+
+/* UIDelegate */
+
+int /*long*/ webView_createWebViewWithRequest(int /*long*/ sender, int /*long*/ 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);
+ }
+ }
+ WebView result = null;
+ Browser browser = null;
+ if (newEvent.browser != null && newEvent.browser.webBrowser instanceof WebKit) {
+ browser = newEvent.browser;
+ }
+ if (browser != null && !browser.isDisposed()) {
+ result = ((WebKit)browser.webBrowser).webView;
+ if (request != 0) {
+ WebFrame mainFrame = result.mainFrame();
+ mainFrame.loadRequest(new NSURLRequest(request));
+ }
+ }
+ return result != null ? result.id : 0;
+}
+
+void webViewShow(int /*long*/ 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 webView_setFrame(int /*long*/ sender, int /*long*/ frame) {
+ NSRect rect = new NSRect();
+ OS.memmove(rect, frame, NSRect.sizeof);
+ /* convert to SWT system coordinates */
+ Rectangle bounds = browser.getDisplay().getBounds();
+ location = new Point((int)rect.x, bounds.height - (int)rect.y - (int)rect.height);
+ size = new Point((int)rect.width, (int)rect.height);
+}
+
+void webViewFocus(int /*long*/ sender) {
+}
+
+void webViewUnfocus(int /*long*/ sender) {
+}
+
+NSNumber callRunBeforeUnloadConfirmPanelWithMessage(int /*long*/ messageID, int /*long*/ arg) {
+ boolean result = webView_runBeforeUnloadConfirmPanelWithMessage_initiatedByFrame (0, messageID, 0);
+ return NSNumber.numberWithBool (result);
+}
+
+boolean webView_runBeforeUnloadConfirmPanelWithMessage_initiatedByFrame(int /*long*/ sender, int /*long*/ messageID, int /*long*/ frame) {
+ NSString message = new NSString(messageID);
+ StringBuffer text = new StringBuffer(Compatibility.getMessage("SWT_OnBeforeUnload_Message1")); //$NON-NLS-1$
+ text.append("\n\n"); //$NON-NLS-1$
+ text.append(message.getString());
+ 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 | SWT.SHEET);
+ messageBox.setMessage(text.toString());
+ return messageBox.open() == SWT.OK;
+}
+
+void webView_runJavaScriptAlertPanelWithMessage(int /*long*/ sender, int /*long*/ messageID) {
+ NSString message = new NSString(messageID);
+ String text = message.getString();
+
+ MessageBox messageBox = new MessageBox(browser.getShell(), SWT.OK | SWT.ICON_WARNING);
+ messageBox.setText("Javascript"); //$NON-NLS-1$
+ messageBox.setMessage(text);
+ messageBox.open();
+}
+
+int webView_runJavaScriptConfirmPanelWithMessage(int /*long*/ sender, int /*long*/ messageID) {
+ NSString message = new NSString(messageID);
+ String text = message.getString();
+
+ 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 webView_runOpenPanelForFileButtonWithResultListener(int /*long*/ sender, int /*long*/ resultListenerID) {
+ FileDialog dialog = new FileDialog(browser.getShell(), SWT.NONE);
+ String result = dialog.open();
+ WebOpenPanelResultListener resultListener = new WebOpenPanelResultListener(resultListenerID);
+ if (result == null) {
+ resultListener.cancel();
+ return;
+ }
+ resultListener.chooseFilename(NSString.stringWith(result));
+}
+
+void webViewClose(int /*long*/ sender) {
+ 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 /*long*/ webView_contextMenuItemsForElement_defaultMenuItems(int /*long*/ sender, int /*long*/ element, int /*long*/ defaultMenuItems) {
+ Point pt = browser.getDisplay().getCursorLocation();
+ Event event = new Event();
+ event.x = pt.x;
+ event.y = pt.y;
+ browser.notifyListeners(SWT.MenuDetect, event);
+ Menu menu = browser.getMenu();
+ if (!event.doit) return 0;
+ if (menu != null && !menu.isDisposed()) {
+ if (event.x != pt.x || event.y != pt.y) {
+ menu.setLocation(event.x, event.y);
+ }
+ menu.setVisible(true);
+ return 0;
+ }
+ return defaultMenuItems;
+}
+
+void webView_setStatusBarVisible(int /*long*/ sender, boolean visible) {
+ /* Note. Webkit only emits the notification when the status bar should be hidden. */
+ statusBar = visible;
+}
+
+void webView_setStatusText(int /*long*/ sender, int /*long*/ textID) {
+ NSString text = new NSString(textID);
+ int length = (int)/*64*/text.length();
+ if (length == 0) return;
+
+ StatusTextEvent statusText = new StatusTextEvent(browser);
+ statusText.display = browser.getDisplay();
+ statusText.widget = browser;
+ statusText.text = text.getString();
+ for (int i = 0; i < statusTextListeners.length; i++) {
+ statusTextListeners[i].changed(statusText);
+ }
+}
+
+void webView_setResizable(int /*long*/ sender, boolean visible) {
+}
+
+void webView_setToolbarsVisible(int /*long*/ sender, boolean visible) {
+ /* Note. Webkit only emits the notification when the tool bar should be hidden. */
+ toolBar = visible;
+}
+
+void webView_mouseDidMoveOverElement_modifierFlags (int /*long*/ sender, int /*long*/ elementInformationID, int /*long*/ modifierFlags) {
+ if (elementInformationID == 0) return;
+
+ NSString key = NSString.stringWith(WebElementLinkURLKey);
+ NSDictionary elementInformation = new NSDictionary(elementInformationID);
+ id value = elementInformation.valueForKey(key);
+ if (value == null) {
+ /* 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;
+ }
+
+ NSString url = new NSURL(value.id).absoluteString();
+ int length = (int)/*64*/url.length();
+ String urlString;
+ if (length == 0) {
+ urlString = ""; //$NON-NLS-1$
+ } else {
+ urlString = url.getString();
+ }
+ 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);
+ }
+}
+
+void webView_printFrameView (int /*long*/ sender, int /*long*/ frameViewID) {
+ WebFrameView view = new WebFrameView(frameViewID);
+ boolean viewPrint = view.documentViewShouldHandlePrint();
+ if (viewPrint) {
+ view.printDocumentView();
+ return;
+ }
+ NSPrintInfo info = NSPrintInfo.sharedPrintInfo();
+ NSPrintOperation operation = view.printOperationWithPrintInfo(info);
+ if (operation != null) operation.runOperation();
+}
+
+/* PolicyDelegate */
+
+void webView_decidePolicyForMIMEType_request_frame_decisionListener(int /*long*/ sender, int /*long*/ type, int /*long*/ request, int /*long*/ frame, int /*long*/ listenerID) {
+ boolean canShow = WebView.canShowMIMEType(new NSString(type));
+ WebPolicyDecisionListener listener = new WebPolicyDecisionListener(listenerID);
+ if (canShow) {
+ listener.use();
+ } else {
+ listener.download();
+ }
+}
+
+void webView_decidePolicyForNavigationAction_request_frame_decisionListener(int /*long*/ sender, int /*long*/ actionInformation, int /*long*/ request, int /*long*/ frame, int /*long*/ listenerID) {
+ NSURL url = new NSURLRequest(request).URL();
+ WebPolicyDecisionListener listener = new WebPolicyDecisionListener(listenerID);
+
+ 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().
+ */
+ listener.use();
+ return;
+ }
+ if (url == null) {
+ /* indicates that a URL with an invalid format was specified */
+ listener.ignore();
+ return;
+ }
+ if (url.isFileURL() && getUrl().startsWith(ABOUT_BLANK) && untrustedText) {
+ /* indicates an attempt to access the local file system from untrusted content */
+ listener.ignore();
+ return;
+ }
+ NSString s = url.absoluteString();
+ String url2 = s.getString();
+ /*
+ * 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 {
+ int length = URI_FILEROOT.length ();
+ if (url2.startsWith (URI_FILEROOT) && url2.charAt (length) == '#') {
+ url2 = ABOUT_BLANK + url2.substring (length);
+ }
+ }
+
+ 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 (jsEnabledChanged) {
+ jsEnabledChanged = false;
+ if (preferences == null) {
+ preferences = (WebPreferences)new WebPreferences ().alloc ().init ();
+ webView.setPreferences (preferences);
+ }
+ preferences.setJavaScriptEnabled (jsEnabled);
+ }
+ listener.use();
+ lastNavigateURL = url2;
+ } else {
+ listener.ignore();
+ }
+}
+
+void webView_decidePolicyForNewWindowAction_request_newFrameName_decisionListener(int /*long*/ sender, int /*long*/ actionInformation, int /*long*/ request, int /*long*/ frameName, int /*long*/ listenerID) {
+ WebPolicyDecisionListener listener = new WebPolicyDecisionListener(listenerID);
+ listener.use();
+}
+
+void webView_unableToImplementPolicyWithError_frame(int /*long*/ sender, int /*long*/ error, int /*long*/ frame) {
+}
+
+/* WebDownload */
+
+void download_decideDestinationWithSuggestedFilename(int /*long*/ downloadId, int /*long*/ filename) {
+ NSString string = new NSString(filename);
+ String name = string.getString();
+ FileDialog dialog = new FileDialog(browser.getShell(), SWT.SAVE);
+ dialog.setText(SWT.getMessage ("SWT_FileDownload")); //$NON-NLS-1$
+ dialog.setFileName(name);
+ String path = dialog.open();
+ NSURLDownload download = new NSURLDownload(downloadId);
+ if (path == null) {
+ /* cancel pressed */
+ download.cancel();
+ return;
+ }
+ download.setDestination(NSString.stringWith(path), true);
+}
+
+/* DOMEventListener */
+
+void handleEvent(int /*long*/ evtId) {
+ NSString string = new NSString(OS.objc_msgSend(evtId, OS.sel_type));
+ String type = string.getString();
+
+ if (DOMEVENT_KEYDOWN.equals(type) || DOMEVENT_KEYUP.equals(type)) {
+ DOMKeyboardEvent event = new DOMKeyboardEvent(evtId);
+
+ boolean ctrl = event.ctrlKey();
+ boolean shift = event.shiftKey();
+ boolean alt = event.altKey();
+ boolean meta = event.metaKey();
+ int keyCode = event.keyCode();
+ int charCode = event.charCode();
+
+ Event keyEvent = new Event();
+ keyEvent.widget = browser;
+ int eventType = DOMEVENT_KEYDOWN.equals(type) ? SWT.KeyDown : SWT.KeyUp;
+ keyEvent.type = eventType;
+ int translatedKey = translateKey (keyCode);
+ keyEvent.keyCode = translatedKey;
+ keyEvent.character = (char)charCode;
+ int stateMask = (alt ? SWT.ALT : 0) | (ctrl ? SWT.CTRL : 0) | (shift ? SWT.SHIFT : 0) | (meta ? SWT.COMMAND : 0);
+ keyEvent.stateMask = stateMask;
+
+ boolean doit = true;
+ if (keyEvent.type == SWT.KeyDown) {
+ doit = sendKeyEvent(keyEvent);
+ } else {
+ browser.notifyListeners(keyEvent.type, keyEvent);
+ doit = keyEvent.doit;
+ }
+ if (!doit) {
+ event.preventDefault();
+ } else {
+ if (eventType == SWT.KeyDown && stateMask == SWT.COMMAND) {
+ if (translatedKey == 'v') {
+ webView.paste (webView);
+ } else if (translatedKey == 'c') {
+ webView.copy (webView);
+ } else if (translatedKey == 'x') {
+ webView.cut (webView);
+ }
+ }
+ }
+ return;
+ }
+
+ if (DOMEVENT_MOUSEWHEEL.equals(type)) {
+ DOMWheelEvent event = new DOMWheelEvent(evtId);
+
+ /*
+ * 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 = event.screenX();
+ int screenY = event.screenY();
+ Point position = new Point(screenX, screenY);
+ position = browser.getDisplay().map(null, browser, position);
+
+ int delta = event.wheelDelta();
+ boolean ctrl = event.ctrlKey();
+ boolean shift = event.shiftKey();
+ boolean alt = event.altKey();
+ boolean meta = event.metaKey();
+ Event mouseEvent = new Event();
+ mouseEvent.type = SWT.MouseWheel;
+ mouseEvent.widget = browser;
+ mouseEvent.x = position.x; mouseEvent.y = position.y;
+ mouseEvent.count = delta / 120;
+ mouseEvent.stateMask = (alt ? SWT.ALT : 0) | (ctrl ? SWT.CTRL : 0) | (shift ? SWT.SHIFT : 0) | (meta ? SWT.COMMAND : 0);
+ browser.notifyListeners (mouseEvent.type, mouseEvent);
+ return;
+ }
+
+ /* mouse event */
+
+ DOMMouseEvent event = new DOMMouseEvent(evtId);
+
+ /*
+ * 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 = event.screenX();
+ int screenY = event.screenY();
+ Point position = new Point(screenX, screenY);
+ position = browser.getDisplay().map(null, browser, position);
+
+ int detail = event.detail();
+ int button = event.button();
+ boolean ctrl = event.ctrlKey();
+ boolean shift = event.shiftKey();
+ boolean alt = event.altKey();
+ boolean meta = event.metaKey();
+
+ 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 (type)) {
+ mouseEvent.type = SWT.MouseDown;
+ mouseEvent.button = button + 1;
+ mouseEvent.count = detail;
+ } else if (DOMEVENT_MOUSEUP.equals (type)) {
+ mouseEvent.type = SWT.MouseUp;
+ 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 (type)) {
+ /*
+ * Bug 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;
+ }
+
+ browser.notifyListeners (mouseEvent.type, mouseEvent);
+ if (detail == 2 && DOMEVENT_MOUSEDOWN.equals (type)) {
+ 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 /*long*/ value) {
+ NSObject object = new NSObject (value);
+ int /*long*/ clazz = OS.objc_lookUpClass ("NSString"); //$NON-NLS-1$
+ if (object.isKindOfClass (clazz)) {
+ NSString string = new NSString (value);
+ return string.getString ();
+ }
+ clazz = OS.objc_lookUpClass ("NSNumber"); //$NON-NLS-1$
+ if (object.isKindOfClass (clazz)) {
+ NSNumber number = new NSNumber (value);
+ int /*long*/ ptr = number.objCType ();
+ byte[] type = new byte[1];
+ OS.memmove (type, ptr, 1);
+ if (type[0] == 'c' || type[0] == 'B') {
+ return new Boolean (number.boolValue ());
+ }
+ if ("islqISLQfd".indexOf (type[0]) != -1) { //$NON-NLS-1$
+ return new Double (number.doubleValue ());
+ }
+ }
+ clazz = OS.objc_lookUpClass ("WebScriptObject"); //$NON-NLS-1$
+ if (object.isKindOfClass (clazz)) {
+ WebScriptObject script = new WebScriptObject (value);
+ id id = script.valueForKey (NSString.stringWith ("length")); //$NON-NLS-1$
+ if (id == null) { /* not a JS array */
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int length = new NSNumber (id).intValue ();
+ Object[] arguments = new Object[length];
+ for (int i = 0; i < length; i++) {
+ id current = script.webScriptValueAtIndex (i);
+ if (current != null) {
+ arguments[i] = convertToJava (current.id);
+ }
+ }
+ return arguments;
+ }
+ clazz = OS.objc_lookUpClass ("WebUndefined"); //$NON-NLS-1$
+ if (object.isKindOfClass (clazz)) {
+ return null;
+ }
+
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ return null;
+}
+
+NSObject convertToJS (Object value) {
+ if (value == null) {
+ return WebUndefined.undefined ();
+ }
+ if (value instanceof String) {
+ return NSString.stringWith ((String)value);
+ }
+ if (value instanceof Boolean) {
+ return NSNumber.numberWithBool (((Boolean)value).booleanValue ());
+ }
+ if (value instanceof Number) {
+ return NSNumber.numberWithDouble (((Number)value).doubleValue ());
+ }
+ if (value instanceof Object[]) {
+ Object[] arrayValue = (Object[]) value;
+ int length = arrayValue.length;
+ NSMutableArray array = NSMutableArray.arrayWithCapacity (length);
+ for (int i = 0; i < length; i++) {
+ Object currentObject = arrayValue[i];
+ array.addObject (convertToJS (currentObject));
+ }
+ return array;
+ }
+ SWT.error (SWT.ERROR_INVALID_RETURN_VALUE);
+ return null;
+}
+
+NSObject callJava (int /*long*/ index, int /*long*/ args, int /*long*/ arg1) {
+ Object returnValue = null;
+ NSObject object = new NSObject (index);
+ int /*long*/ clazz = OS.objc_lookUpClass ("NSNumber"); //$NON-NLS-1$
+ if (object.isKindOfClass (clazz)) {
+ NSNumber number = new NSNumber (index);
+ Object key = new Integer (number.intValue ());
+ BrowserFunction function = (BrowserFunction)functions.get (key);
+ if (function != null) {
+ 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) {
+ /* invalid return value type */
+ return convertToJS (WebBrowser.CreateErrorString (e.getLocalizedMessage ()));
+ }
+}
+
+}

Back to the top