X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.eclipse.swt.win32.win32.x86_64%2Fsrc%2Forg%2Feclipse%2Fswt%2Fbrowser%2FWebFrameLoadDelegate.java;fp=bundles%2Forg.eclipse.swt.win32.win32.x86_64%2Fsrc%2Forg%2Feclipse%2Fswt%2Fbrowser%2FWebFrameLoadDelegate.java;h=8fb1426fb7cd4432d9480bd2c8409b63e6b22efb;hb=db618b088560ad9a524dade82a3847f8d08bfb7c;hp=0000000000000000000000000000000000000000;hpb=930da66f9b2d7d1acba3e5dc805a323933abb780;p=simantics%2Fplatform.git diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebFrameLoadDelegate.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebFrameLoadDelegate.java new file mode 100644 index 000000000..8fb1426fb --- /dev/null +++ b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebFrameLoadDelegate.java @@ -0,0 +1,760 @@ +/******************************************************************************* + * Copyright (c) 2010, 2017 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.browser; + + +import java.net.*; +import java.nio.charset.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.internal.*; +import org.eclipse.swt.internal.ole.win32.*; +import org.eclipse.swt.internal.webkit.*; +import org.eclipse.swt.internal.win32.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +class WebFrameLoadDelegate { + COMObject iWebFrameLoadDelegate; + int refCount = 0; + + Browser browser; + String html; + String url; + + static final String OBJECTNAME_EXTERNAL = "external"; //$NON-NLS-1$ + +WebFrameLoadDelegate (Browser browser) { + createCOMInterfaces (); + this.browser = browser; +} + +void addEventHandlers (boolean top) { + if (top) { + StringBuilder buffer = new StringBuilder ("window.SWTkeyhandler = function SWTkeyhandler(e) {"); //$NON-NLS-1$ + buffer.append ("try {e.returnValue = HandleWebKitEvent(e.type, e.keyCode, e.charCode, e.altKey, e.ctrlKey, e.shiftKey, e.metaKey);} catch (e) {}};"); //$NON-NLS-1$ + buffer.append ("document.addEventListener('keydown', SWTkeyhandler, true);"); //$NON-NLS-1$ + buffer.append ("document.addEventListener('keypress', SWTkeyhandler, true);"); //$NON-NLS-1$ + buffer.append ("document.addEventListener('keyup', SWTkeyhandler, true);"); //$NON-NLS-1$ + browser.execute (buffer.toString ()); + + buffer = new StringBuilder ("window.SWTmousehandler = function SWTmousehandler(e) {"); //$NON-NLS-1$ + buffer.append ("try {e.returnValue = HandleWebKitEvent(e.type, e.screenX, e.screenY, e.detail, e.button + 1, e.altKey, e.ctrlKey, e.shiftKey, e.metaKey, e.relatedTarget != null);} catch (e) {}};"); //$NON-NLS-1$ + buffer.append ("document.addEventListener('mousedown', SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ("document.addEventListener('mouseup', SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ("document.addEventListener('mousemove', SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ("document.addEventListener('mousewheel', SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ("document.addEventListener('dragstart', SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ("document.addEventListener('mouseover', SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ("document.addEventListener('mouseout', SWTmousehandler, true);"); //$NON-NLS-1$ + + browser.execute (buffer.toString ()); + } else { + StringBuilder buffer = new StringBuilder ("for (var i = 0; i < frames.length; i++) {"); //$NON-NLS-1$ + buffer.append ("frames[i].document.addEventListener('keydown', window.SWTkeyhandler, true);"); //$NON-NLS-1$ + buffer.append ("frames[i].document.addEventListener('keypress', window.SWTkeyhandler, true);"); //$NON-NLS-1$ + buffer.append ("frames[i].document.addEventListener('keyup', window.SWTkeyhandler, true);"); //$NON-NLS-1$ + buffer.append ("frames[i].document.addEventListener('mousedown', window.SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ("frames[i].document.addEventListener('mouseup', window.SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ("frames[i].document.addEventListener('mousemove', window.SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ("frames[i].document.addEventListener('mouseover', window.SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ("frames[i].document.addEventListener('mouseout', window.SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ("frames[i].document.addEventListener('mousewheel', window.SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ("frames[i].document.addEventListener('dragstart', window.SWTmousehandler, true);"); //$NON-NLS-1$ + buffer.append ('}'); + browser.execute (buffer.toString ()); + } +} + +int AddRef () { + refCount++; + return refCount; +} + +void createCOMInterfaces () { + iWebFrameLoadDelegate = new COMObject (new int[] {2, 0, 0, 2, 2, 3, 2, 3, 3, 2, 3, 2, 5, 2, 2, 3, 4}) { + @Override + public long method0 (long[] args) {return QueryInterface (args[0], args[1]);} + @Override + public long method1 (long[] args) {return AddRef ();} + @Override + public long method2 (long[] args) {return Release ();} + @Override + public long method3 (long[] args) {return didStartProvisionalLoadForFrame (args[0], args[1]);} + @Override + public long method4 (long[] args) {return COM.E_NOTIMPL;} + @Override + public long method5 (long[] args) {return didFailProvisionalLoadWithError (args[0], args[1], args[2]);} + @Override + public long method6 (long[] args) {return didCommitLoadForFrame (args[0], args[1]);} + @Override + public long method7 (long[] args) {return didReceiveTitle (args[0], args[1], args[2]);} + @Override + public long method8 (long[] args) {return COM.E_NOTIMPL;} + @Override + public long method9 (long[] args) {return didFinishLoadForFrame (args[0], args[1]);} + @Override + public long method10 (long[] args){return COM.E_NOTIMPL;} + @Override + public long method11 (long[] args){return didChangeLocationWithinPageForFrame (args[0], args[1]);} + @Override + public long method12 (long[] args){return COM.S_OK;} + @Override + public long method13 (long[] args){return COM.E_NOTIMPL;} + @Override + public long method14 (long[] args){return COM.S_OK;} + @Override + public long method15 (long[] args){return COM.S_OK;} + @Override + public long method16 (long[] args){return didClearWindowObject (args[0], args[1], args[2], args[3]);} + }; + + /* Callbacks that take double parameters require custom callbacks that instead pass pointers to the doubles. */ + long ppVtable = iWebFrameLoadDelegate.ppVtable; + long[] pVtable = new long[1]; + OS.MoveMemory (pVtable, ppVtable, C.PTR_SIZEOF); + long[] funcs = new long[17]; + OS.MoveMemory (funcs, pVtable[0], C.PTR_SIZEOF * funcs.length); + funcs[12] = WebKit_win32.willPerformClientRedirectToURL_CALLBACK (funcs[12]); + OS.MoveMemory (pVtable[0], funcs, C.PTR_SIZEOF * funcs.length); +} + +int didChangeLocationWithinPageForFrame (long webView, long frame) { + IWebFrame iwebframe = new IWebFrame (frame); + long[] result = new long[1]; + int hr = iwebframe.dataSource (result); + if (hr != COM.S_OK || result[0] == 0) { + return COM.S_OK; + } + IWebDataSource dataSource = new IWebDataSource (result[0]); + result[0] = 0; + hr = dataSource.request (result); + dataSource.Release (); + if (hr != COM.S_OK || result[0] == 0) { + return COM.S_OK; + } + IWebURLRequest request = new IWebURLRequest (result[0]); + result[0] = 0; + hr = request.URL (result); + request.Release (); + if (hr != COM.S_OK || result[0] == 0) { + return COM.S_OK; + } + String url2 = WebKit.extractBSTR (result[0]); + COM.SysFreeString (result[0]); + if (url2.length() == 0) return COM.S_OK; + /* + * 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 (WebKit.URI_FILEROOT)) { + url2 = WebKit.ABOUT_BLANK; + } else { + int length = WebKit.URI_FILEROOT.length (); + if (url2.startsWith (WebKit.URI_FILEROOT) && url2.charAt (length) == '#') { + url2 = WebKit.ABOUT_BLANK + url2.substring (length); + } + } + final Display display = browser.getDisplay (); + result[0] = 0; + IWebView iWebView = new IWebView (webView); + hr = iWebView.mainFrame (result); + boolean top = false; + if (hr == COM.S_OK && result[0] != 0) { + top = frame == result[0]; + new IWebFrame (result[0]).Release (); + } + if (top) { + StatusTextEvent statusText = new StatusTextEvent (browser); + statusText.display = display; + statusText.widget = browser; + statusText.text = url2; + StatusTextListener[] statusTextListeners = browser.webBrowser.statusTextListeners; + 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; + LocationListener[] locationListeners = browser.webBrowser.locationListeners; + for (int i = 0; i < locationListeners.length; i++) { + locationListeners[i].changed (location); + } + return COM.S_OK; +} + +int didClearWindowObject (long webView, long context, long windowScriptObject, long frame) { + WebKit_win32.JSGlobalContextRetain (context); + long globalObject = WebKit_win32.JSContextGetGlobalObject (context); + long privateData = ((WebKit)browser.webBrowser).webViewData; + long externalObject = WebKit_win32.JSObjectMake (context, WebKit.ExternalClass, privateData); + byte[] bytes = (OBJECTNAME_EXTERNAL + '\0').getBytes (StandardCharsets.UTF_8); + long name = WebKit_win32.JSStringCreateWithUTF8CString (bytes); + WebKit_win32.JSObjectSetProperty (context, globalObject, name, externalObject, 0, null); + WebKit_win32.JSStringRelease (name); + + for (BrowserFunction current : browser.webBrowser.functions.values()) { + browser.execute (current.functionString); + } + + IWebView iwebView = new IWebView (webView); + long[] mainFrame = new long[1]; + iwebView.mainFrame (mainFrame); + boolean top = mainFrame[0] == frame; + new IWebFrame (mainFrame[0]).Release (); + addEventHandlers (top); + return COM.S_OK; +} + +int didCommitLoadForFrame (long webview, long frame) { + IWebFrame iWebFrame = new IWebFrame (frame); + long[] result = new long[1]; + int hr = iWebFrame.dataSource (result); + if (hr != COM.S_OK || result[0] == 0) { + return COM.S_OK; + } + IWebDataSource dataSource = new IWebDataSource (result[0]); + result[0] = 0; + hr = dataSource.request (result); + dataSource.Release (); + if (hr != COM.S_OK || result[0] == 0) { + return COM.S_OK; + } + IWebMutableURLRequest request = new IWebMutableURLRequest (result[0]); + result[0] = 0; + hr = request.URL (result); + request.Release (); + if (hr != COM.S_OK || result[0] == 0) { + return COM.S_OK; + } + String url2 = WebKit.extractBSTR (result[0]); + COM.SysFreeString (result[0]); + if (url2.length () == 0) return COM.S_OK; + /* + * 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 (WebKit.URI_FILEROOT)) { + url2 = WebKit.ABOUT_BLANK; + } else { + int length = WebKit.URI_FILEROOT.length (); + if (url2.startsWith (WebKit.URI_FILEROOT) && url2.charAt (length) == '#') { + url2 = WebKit.ABOUT_BLANK + url2.substring (length); + } + } + Display display = browser.getDisplay (); + result[0] = 0; + IWebView iwebView = new IWebView (webview); + hr = iwebView.mainFrame (result); + boolean top = false; + if (hr == COM.S_OK && result[0] != 0) { + top = frame == result[0]; + new IWebFrame (result[0]).Release (); + } + if (top) { + /* reset resource status variables */ + 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 (WebKit.ABOUT_BLANK) && html != null) return COM.S_OK; + + /* re-install registered functions */ + for (BrowserFunction function : browser.webBrowser.functions.values()) { + browser.webBrowser.execute (function.functionString); + } + + ProgressEvent progress = new ProgressEvent (browser); + progress.display = display; + progress.widget = browser; + progress.current = 1; + progress.total = WebKit.MAX_PROGRESS; + ProgressListener[] progressListeners = browser.webBrowser.progressListeners; + for (int i = 0; i < progressListeners.length; i++) { + progressListeners[i].changed (progress); + } + if (browser.isDisposed ()) return COM.S_OK; + + StatusTextEvent statusText = new StatusTextEvent (browser); + statusText.display = display; + statusText.widget = browser; + statusText.text = url2; + StatusTextListener[] statusTextListeners = browser.webBrowser.statusTextListeners; + for (int i = 0; i < statusTextListeners.length; i++) { + statusTextListeners[i].changed (statusText); + } + if (browser.isDisposed ()) return COM.S_OK; + } + LocationEvent location = new LocationEvent (browser); + location.display = display; + location.widget = browser; + location.location = url2; + location.top = top; + LocationListener[] locationListeners = browser.webBrowser.locationListeners; + for (int i = 0; i < locationListeners.length; i++) { + locationListeners[i].changed (location); + } + return COM.S_OK; +} + +int didFailProvisionalLoadWithError (long webView, long error, long frame) { + IWebError iweberror = new IWebError (error); + int[] errorCode = new int[1]; + int hr = iweberror.code (errorCode); + if (WebKit_win32.WebURLErrorBadURL < errorCode[0]) return COM.S_OK; + + String failingURLString = null; + long[] failingURL = new long[1]; + hr = iweberror.failingURL (failingURL); + if (hr == COM.S_OK && failingURL[0] != 0) { + failingURLString = WebKit.extractBSTR (failingURL[0]); + COM.SysFreeString (failingURL[0]); + } + if (failingURLString != null && WebKit_win32.WebURLErrorServerCertificateNotYetValid <= errorCode[0] && errorCode[0] <= WebKit_win32.WebURLErrorSecureConnectionFailed) { + /* handle invalid certificate error */ + long[] result = new long[1]; + hr = iweberror.localizedDescription (result); + if (hr != COM.S_OK || result[0] == 0) { + return COM.S_OK; + } + String description = WebKit.extractBSTR (result[0]); + COM.SysFreeString (result[0]); + + result[0] = 0; + hr = iweberror.QueryInterface (WebKit_win32.IID_IWebErrorPrivate, result); + if (hr != COM.S_OK || result[0] == 0) { + return COM.S_OK; + } + + IWebErrorPrivate webErrorPrivate = new IWebErrorPrivate (result[0]); + result[0] = 0; + long[] certificate = new long[1]; + hr = webErrorPrivate.sslPeerCertificate (certificate); + webErrorPrivate.Release (); + if (hr != COM.S_OK || certificate[0] == 0) { + return COM.S_OK; + } + if (showCertificateDialog (webView, failingURLString, description, certificate[0])) { + IWebFrame iWebFrame = new IWebFrame (frame); + hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebMutableURLRequest, 0, WebKit_win32.IID_IWebMutableURLRequest, result); + if (hr != COM.S_OK || result[0] == 0) { + certificate[0] = 0; + return COM.S_OK; + } + IWebMutableURLRequest request = new IWebMutableURLRequest (result[0]); + request.setURL (failingURL[0]); + request.setAllowsAnyHTTPSCertificate (); + iWebFrame.loadRequest (request.getAddress ()); + request.Release (); + } + certificate[0] = 0; + return COM.S_OK; + } + + /* handle other types of errors */ + long[] result = new long[1]; + hr = iweberror.localizedDescription (result); + if (hr != COM.S_OK || result[0] == 0) { + return COM.S_OK; + } + String description = WebKit.extractBSTR (result[0]); + COM.SysFreeString (result[0]); + if (!browser.isDisposed ()) { + String message = failingURLString != null ? failingURLString + "\n\n" : ""; //$NON-NLS-1$ //$NON-NLS-2$ + message += Compatibility.getMessage ("SWT_Page_Load_Failed", new Object[] {description}); //$NON-NLS-1$ + MessageBox messageBox = new MessageBox (browser.getShell (), SWT.OK | SWT.ICON_ERROR); + messageBox.setMessage (message); + messageBox.open (); + } + return COM.S_OK; +} + +int didFinishLoadForFrame (long webview, long frame) { + IWebView iWebView = new IWebView (webview); + long[] iWebFrame = new long[1]; + int hr = iWebView.mainFrame (iWebFrame); + if (hr != COM.S_OK || iWebFrame[0] == 0) { + return COM.S_OK; + } + boolean top = frame == iWebFrame[0]; + new IWebFrame (iWebFrame[0]).Release(); + if (!top) return COM.S_OK; + + /* + * 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 (WebKit.ABOUT_BLANK)) { + ((WebKit)browser.webBrowser).loadingText = true; + long string = WebKit.createBSTR (html); + long URLString; + if (((WebKit)browser.webBrowser).untrustedText) { + URLString = WebKit.createBSTR (WebKit.ABOUT_BLANK); + } else { + URLString = WebKit.createBSTR (WebKit.URI_FILEROOT); + } + IWebFrame mainFrame = new IWebFrame (frame); + mainFrame.loadHTMLString (string, URLString); + html = null; + } + } + + /* + * The loadHTMLString() 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 (!((WebKit)browser.webBrowser).loadingText) { + if (browser.isDisposed ()) return COM.S_OK; + /* + * To be consistent with other platforms a title event should be fired when a + * page has completed loading. A page with a