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 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 (); + IWebFrame mainFrame = new IWebFrame (frame); + long[] result = new long[1]; + hr = mainFrame.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.pageTitle (result); + dataSource.Release (); + if (hr != COM.S_OK) { + return COM.S_OK; + } + String title = null; + if (result[0] != 0) { + title = WebKit.extractBSTR (result[0]); + COM.SysFreeString (result[0]); + } + if (title == null || title.length () == 0) { /* page has no title */ + TitleEvent newEvent = new TitleEvent (browser); + newEvent.display = display; + newEvent.widget = browser; + newEvent.title = getUrl (); + TitleListener[] titleListeners = browser.webBrowser.titleListeners; + for (int i = 0; i < titleListeners.length; i++) { + titleListeners[i].changed (newEvent); + } + if (browser.isDisposed ()) return COM.S_OK; + } + + ProgressEvent progress = new ProgressEvent (browser); + progress.display = display; + progress.widget = browser; + progress.current = WebKit.MAX_PROGRESS; + progress.total = WebKit.MAX_PROGRESS; + ProgressListener[] progressListeners = browser.webBrowser.progressListeners; + for (int i = 0; i < progressListeners.length; i++) { + progressListeners[i].completed (progress); + } + if (browser.isDisposed ()) return COM.S_OK; + } + ((WebKit)browser.webBrowser).loadingText = false; + return COM.S_OK; +} + +int didReceiveTitle (long webView, long title, long frame) { + long[] mainFrame = new long[1]; + IWebView iWebView = new IWebView (webView); + int hr = iWebView.mainFrame (mainFrame); + if (hr != COM.S_OK || frame == 0) { + return COM.S_OK; + } + if (frame == mainFrame[0]) { + String newTitle = WebKit.extractBSTR (title); + TitleEvent newEvent = new TitleEvent (browser); + newEvent.display = browser.getDisplay (); + newEvent.widget = browser; + newEvent.title = newTitle; + TitleListener[] titleListeners = browser.webBrowser.titleListeners; + for (int i = 0; i < titleListeners.length; i++) { + titleListeners[i].changed (newEvent); + } + } + new IWebFrame (mainFrame[0]).Release (); + return COM.S_OK; +} + +int didStartProvisionalLoadForFrame (long webView, long frame) { + return COM.S_OK; +} + +void disposeCOMInterfaces () { + if (iWebFrameLoadDelegate != null) { + iWebFrameLoadDelegate.dispose (); + iWebFrameLoadDelegate = null; + } +} + +long getAddress () { + return iWebFrameLoadDelegate.getAddress (); +} + +String getUrl () { + /* WebKit auto-navigates to about:blank at startup */ + if (url == null || url.length () == 0) return WebKit.ABOUT_BLANK; + return url; +} + +int QueryInterface (long riid, long ppvObject) { + if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG; + GUID guid = new GUID (); + COM.MoveMemory (guid, riid, GUID.sizeof); + + if (COM.IsEqualGUID (guid, COM.IIDIUnknown)) { + OS.MoveMemory (ppvObject, new long[] {iWebFrameLoadDelegate.getAddress ()}, C.PTR_SIZEOF); + new IUnknown (iWebFrameLoadDelegate.getAddress ()).AddRef (); + return COM.S_OK; + } + if (COM.IsEqualGUID (guid, WebKit_win32.IID_IWebFrameLoadDelegate)) { + OS.MoveMemory (ppvObject, new long[] {iWebFrameLoadDelegate.getAddress ()}, C.PTR_SIZEOF); + new IUnknown (iWebFrameLoadDelegate.getAddress ()).AddRef (); + return COM.S_OK; + } + + OS.MoveMemory (ppvObject, new long[] {0}, C.PTR_SIZEOF); + return COM.E_NOINTERFACE; +} + +int Release () { + refCount--; + if (refCount == 0) { + disposeCOMInterfaces (); + } + return refCount; +} + +boolean showCertificateDialog (long webView, final String failingUrlString, final String description, final long certificate) { + Shell parent = browser.getShell (); + final Shell shell = new Shell (parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); + shell.setText (Compatibility.getMessage ("SWT_InvalidCert_Title")); //$NON-NLS-1$ + shell.setLayout (new GridLayout ()); + Label label = new Label (shell, SWT.WRAP); + String host = null; + try { + host = new URL (failingUrlString).getHost (); + } catch (MalformedURLException e) { + /* show the url instead */ + host = failingUrlString; + } + StringBuilder message = new StringBuilder ("\n"); //$NON-NLS-1$ + message.append (Compatibility.getMessage ("SWT_InvalidCert_Message", new String[] {host})); //$NON-NLS-1$ + message.append ("\n\n"); //$NON-NLS-1$ + message.append (Compatibility.getMessage (description)); + message.append ("\n"); //$NON-NLS-1$ + message.append (Compatibility.getMessage ("SWT_InvalidCert_Connect")); //$NON-NLS-1$ + message.append ("\n"); //$NON-NLS-1$ + label.setText(message.toString ()); + + 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); + + final boolean[] result = new boolean[1]; + final Button[] buttons = new Button[3]; + Listener listener = event -> { + if (event.widget == buttons[2]) { + showCertificate (shell, certificate); + } else { + result[0] = event.widget == buttons[0]; + shell.close(); + } + }; + + Composite composite = new Composite (shell, SWT.NONE); + data = new GridData (); + data.horizontalAlignment = GridData.END; + composite.setLayoutData (data); + composite.setLayout (new GridLayout (3, true)); + buttons[0] = new Button (composite, SWT.PUSH); + buttons[0].setText (SWT.getMessage("SWT_Continue")); //$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_Cancel")); //$NON-NLS-1$ + buttons[1].setLayoutData (new GridData (GridData.FILL_HORIZONTAL)); + buttons[1].addListener (SWT.Selection, listener); + buttons[2] = new Button (composite, SWT.PUSH); + buttons[2].setText (SWT.getMessage("SWT_ViewCertificate")); //$NON-NLS-1$ + buttons[2].setLayoutData (new GridData (GridData.FILL_HORIZONTAL)); + buttons[2].addListener (SWT.Selection, listener); + + shell.setDefaultButton (buttons[0]); + shell.pack (); + + Rectangle parentSize = parent.getBounds (); + Rectangle shellSize = shell.getBounds (); + int x = parent.getLocation ().x + (parentSize.width - shellSize.width) / 2; + int y = parent.getLocation ().y + (parentSize.height - shellSize.height) / 2; + shell.setLocation (x, y); + shell.open (); + Display display = browser.getDisplay (); + while (!shell.isDisposed ()) { + if (!display.readAndDispatch ()) display.sleep (); + } + return result[0]; +} + +void showCertificate (Shell parent, long certificate) { + CERT_CONTEXT context = new CERT_CONTEXT (); + OS.MoveMemory (context, certificate, CERT_CONTEXT.sizeof); + CERT_INFO info = new CERT_INFO (); + OS.MoveMemory (info, context.pCertInfo, CERT_INFO.sizeof); + + int length = OS.CertNameToStr (OS.X509_ASN_ENCODING, info.Issuer, OS.CERT_SIMPLE_NAME_STR, null, 0); + char [] buffer = new char [length]; + OS.CertNameToStr (OS.X509_ASN_ENCODING, info.Issuer, OS.CERT_SIMPLE_NAME_STR, buffer, length); + String issuer = new String (buffer, 0, length - 1); + + length = OS.CertNameToStr (OS.X509_ASN_ENCODING, info.Subject, OS.CERT_SIMPLE_NAME_STR, null, 0); + buffer = new char [length]; + OS.CertNameToStr (OS.X509_ASN_ENCODING, info.Subject, OS.CERT_SIMPLE_NAME_STR, buffer, length); + String subject = new String (buffer, 0, length - 1); + + final String SEPARATOR_DATE = "/"; //$NON-NLS-1$ + final String SEPARATOR_TIME = ":"; //$NON-NLS-1$ + SYSTEMTIME systemTime = new SYSTEMTIME (); + OS.FileTimeToSystemTime (info.NotBefore, systemTime); + String validFrom = systemTime.wDay + SEPARATOR_DATE + systemTime.wMonth + SEPARATOR_DATE + systemTime.wYear; + String validFromTime = systemTime.wHour + SEPARATOR_TIME + systemTime.wMinute + SEPARATOR_TIME + systemTime.wSecond; + + systemTime = new SYSTEMTIME (); + OS.FileTimeToSystemTime (info.NotAfter, systemTime); + String validTo = systemTime.wDay + SEPARATOR_DATE + systemTime.wMonth + SEPARATOR_DATE + systemTime.wYear; + String validToTime = systemTime.wHour + SEPARATOR_TIME + systemTime.wMinute + SEPARATOR_TIME + systemTime.wSecond; + + length = info.SerialNumber.cbData; + byte[] serialNumber = new byte[length]; + OS.MoveMemory (serialNumber, info.SerialNumber.pbData, length); + String hexSerialNumber = new String (); + for (int i = length - 1; i >= 0; i--) { + int number = 0xFF & serialNumber[i]; + String hex = Integer.toHexString (number); + if (hex.length () == 1) hexSerialNumber += "0"; //$NON-NLS-1$ + hexSerialNumber += hex + " "; //$NON-NLS-1$ + } + + final Shell dialog = new Shell (parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); + dialog.setText (SWT.getMessage ("SWT_Certificate")); //$NON-NLS-1$ + dialog.setLayout (new GridLayout (1, false)); + + TabFolder tabFolder = new TabFolder (dialog, SWT.NONE); + tabFolder.setLayoutData (new GridData (SWT.FILL, SWT.FILL, true, true, 1, 1)); + tabFolder.setLayout (new FillLayout ()); + + TabItem general = new TabItem (tabFolder, SWT.NONE); + general.setText (SWT.getMessage ("SWT_General")); //$NON-NLS-1$ + Composite composite = new Composite (tabFolder, SWT.BORDER); + composite.setLayout (new GridLayout (1, false)); + Label issuedTo = new Label (composite, SWT.NONE); + issuedTo.setLayoutData (new GridData (SWT.BEGINNING, SWT.CENTER, false, false)); + issuedTo.setText (Compatibility.getMessage ("SWT_IssuedTo", new Object[] {subject})); //$NON-NLS-1$ + Label issuedBy = new Label (composite, SWT.NONE); + issuedBy.setLayoutData (new GridData (SWT.BEGINNING, SWT.CENTER, false, false)); + issuedBy.setText (Compatibility.getMessage ("SWT_IssuedFrom", new Object[] {issuer})); //$NON-NLS-1$ + Label valid = new Label (composite, SWT.NONE); + valid.setLayoutData (new GridData (SWT.BEGINNING, SWT.CENTER, false, false)); + valid.setText (Compatibility.getMessage ("SWT_ValidFromTo", new Object[] {validFrom, validTo})); //$NON-NLS-1$ + general.setControl (composite); + + TabItem details = new TabItem (tabFolder, SWT.NONE); + details.setText (SWT.getMessage ("SWT_Details")); //$NON-NLS-1$ + Table table = new Table (tabFolder, SWT.SINGLE | SWT.BORDER| SWT.FULL_SELECTION); + table.setHeaderVisible (true); + TableColumn tableColumn = new TableColumn (table, SWT.LEAD); + tableColumn.setText (SWT.getMessage ("SWT_Field")); //$NON-NLS-1$ + tableColumn = new TableColumn (table, SWT.NONE); + tableColumn.setText (SWT.getMessage ("SWT_Value")); //$NON-NLS-1$ + TableItem tableItem = new TableItem(table, SWT.NONE); + String version = "V" + String.valueOf (info.dwVersion + 1); //$NON-NLS-1$ + tableItem.setText (new String[]{SWT.getMessage ("SWT_Version"), version}); //$NON-NLS-1$ + tableItem = new TableItem (table, SWT.NONE); + tableItem.setText (new String[] {SWT.getMessage ("SWT_SerialNumber"), hexSerialNumber}); //$NON-NLS-1$ + tableItem = new TableItem (table, SWT.NONE); + tableItem.setText (new String[] {SWT.getMessage ("SWT_Issuer"), issuer}); //$NON-NLS-1$ + + tableItem = new TableItem (table, SWT.NONE); + StringBuilder stringBuilder2 = new StringBuilder (); + stringBuilder2.append (validFrom); + stringBuilder2.append (", "); //$NON-NLS-1$ + stringBuilder2.append (validFromTime); + stringBuilder2.append (" GMT"); //$NON-NLS-1$ + tableItem.setText (new String[] {SWT.getMessage ("SWT_ValidFrom"), stringBuilder2.toString ()}); //$NON-NLS-1$ + + tableItem = new TableItem (table, SWT.NONE); + StringBuilder stringBuilder = new StringBuilder (); + stringBuilder.append (validTo); + stringBuilder.append (", "); //$NON-NLS-1$ + stringBuilder.append (validToTime); + stringBuilder.append (" GMT"); //$NON-NLS-1$ + tableItem.setText (new String[] {SWT.getMessage ("SWT_ValidTo"), stringBuilder.toString ()}); //$NON-NLS-1$ + + tableItem = new TableItem (table, SWT.NONE); + tableItem.setText (new String[] {SWT.getMessage ("SWT_Subject"), subject}); //$NON-NLS-1$ + for (int i = 0; i < table.getColumnCount (); i++) { + table.getColumn (i).pack (); + } + details.setControl (table); + + Button ok = new Button (dialog, SWT.PUSH); + GridData layoutData = new GridData (SWT.END, SWT.CENTER, false, false); + layoutData.widthHint = 75; + ok.setLayoutData (layoutData); + ok.setText (SWT.getMessage ("SWT_OK")); //$NON-NLS-1$ + ok.addSelectionListener (new SelectionAdapter() { + @Override + public void widgetSelected (SelectionEvent e) { + dialog.dispose (); + } + }); + + dialog.setDefaultButton (ok); + dialog.pack (); + Rectangle parentSize = parent.getBounds (); + Rectangle dialogSize = dialog.getBounds (); + int x = parent.getLocation ().x + (parentSize.width - dialogSize.width) / 2; + int y = parent.getLocation ().y + (parentSize.height - dialogSize.height) / 2; + dialog.setLocation (x, y); + dialog.open (); + Display display = browser.getDisplay (); + while (!dialog.isDisposed ()) { + if (!display.readAndDispatch ()) display.sleep (); + } + +} + +}