1 /*******************************************************************************
2 * Copyright (c) 2010, 2017 IBM Corporation and others.
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.swt.browser;
18 import java.nio.charset.*;
20 import org.eclipse.swt.*;
21 import org.eclipse.swt.events.*;
22 import org.eclipse.swt.graphics.*;
23 import org.eclipse.swt.internal.*;
24 import org.eclipse.swt.internal.ole.win32.*;
25 import org.eclipse.swt.internal.webkit.*;
26 import org.eclipse.swt.internal.win32.*;
27 import org.eclipse.swt.layout.*;
28 import org.eclipse.swt.widgets.*;
30 class WebFrameLoadDelegate {
31 COMObject iWebFrameLoadDelegate;
38 static final String OBJECTNAME_EXTERNAL = "external"; //$NON-NLS-1$
40 WebFrameLoadDelegate (Browser browser) {
41 createCOMInterfaces ();
42 this.browser = browser;
45 void addEventHandlers (boolean top) {
47 StringBuilder buffer = new StringBuilder ("window.SWTkeyhandler = function SWTkeyhandler(e) {"); //$NON-NLS-1$
48 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$
49 buffer.append ("document.addEventListener('keydown', SWTkeyhandler, true);"); //$NON-NLS-1$
50 buffer.append ("document.addEventListener('keypress', SWTkeyhandler, true);"); //$NON-NLS-1$
51 buffer.append ("document.addEventListener('keyup', SWTkeyhandler, true);"); //$NON-NLS-1$
52 browser.execute (buffer.toString ());
54 buffer = new StringBuilder ("window.SWTmousehandler = function SWTmousehandler(e) {"); //$NON-NLS-1$
55 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$
56 buffer.append ("document.addEventListener('mousedown', SWTmousehandler, true);"); //$NON-NLS-1$
57 buffer.append ("document.addEventListener('mouseup', SWTmousehandler, true);"); //$NON-NLS-1$
58 buffer.append ("document.addEventListener('mousemove', SWTmousehandler, true);"); //$NON-NLS-1$
59 buffer.append ("document.addEventListener('mousewheel', SWTmousehandler, true);"); //$NON-NLS-1$
60 buffer.append ("document.addEventListener('dragstart', SWTmousehandler, true);"); //$NON-NLS-1$
61 buffer.append ("document.addEventListener('mouseover', SWTmousehandler, true);"); //$NON-NLS-1$
62 buffer.append ("document.addEventListener('mouseout', SWTmousehandler, true);"); //$NON-NLS-1$
64 browser.execute (buffer.toString ());
66 StringBuilder buffer = new StringBuilder ("for (var i = 0; i < frames.length; i++) {"); //$NON-NLS-1$
67 buffer.append ("frames[i].document.addEventListener('keydown', window.SWTkeyhandler, true);"); //$NON-NLS-1$
68 buffer.append ("frames[i].document.addEventListener('keypress', window.SWTkeyhandler, true);"); //$NON-NLS-1$
69 buffer.append ("frames[i].document.addEventListener('keyup', window.SWTkeyhandler, true);"); //$NON-NLS-1$
70 buffer.append ("frames[i].document.addEventListener('mousedown', window.SWTmousehandler, true);"); //$NON-NLS-1$
71 buffer.append ("frames[i].document.addEventListener('mouseup', window.SWTmousehandler, true);"); //$NON-NLS-1$
72 buffer.append ("frames[i].document.addEventListener('mousemove', window.SWTmousehandler, true);"); //$NON-NLS-1$
73 buffer.append ("frames[i].document.addEventListener('mouseover', window.SWTmousehandler, true);"); //$NON-NLS-1$
74 buffer.append ("frames[i].document.addEventListener('mouseout', window.SWTmousehandler, true);"); //$NON-NLS-1$
75 buffer.append ("frames[i].document.addEventListener('mousewheel', window.SWTmousehandler, true);"); //$NON-NLS-1$
76 buffer.append ("frames[i].document.addEventListener('dragstart', window.SWTmousehandler, true);"); //$NON-NLS-1$
78 browser.execute (buffer.toString ());
87 void createCOMInterfaces () {
88 iWebFrameLoadDelegate = new COMObject (new int[] {2, 0, 0, 2, 2, 3, 2, 3, 3, 2, 3, 2, 5, 2, 2, 3, 4}) {
90 public long method0 (long[] args) {return QueryInterface (args[0], args[1]);}
92 public long method1 (long[] args) {return AddRef ();}
94 public long method2 (long[] args) {return Release ();}
96 public long method3 (long[] args) {return didStartProvisionalLoadForFrame (args[0], args[1]);}
98 public long method4 (long[] args) {return COM.E_NOTIMPL;}
100 public long method5 (long[] args) {return didFailProvisionalLoadWithError (args[0], args[1], args[2]);}
102 public long method6 (long[] args) {return didCommitLoadForFrame (args[0], args[1]);}
104 public long method7 (long[] args) {return didReceiveTitle (args[0], args[1], args[2]);}
106 public long method8 (long[] args) {return COM.E_NOTIMPL;}
108 public long method9 (long[] args) {return didFinishLoadForFrame (args[0], args[1]);}
110 public long method10 (long[] args){return COM.E_NOTIMPL;}
112 public long method11 (long[] args){return didChangeLocationWithinPageForFrame (args[0], args[1]);}
114 public long method12 (long[] args){return COM.S_OK;}
116 public long method13 (long[] args){return COM.E_NOTIMPL;}
118 public long method14 (long[] args){return COM.S_OK;}
120 public long method15 (long[] args){return COM.S_OK;}
122 public long method16 (long[] args){return didClearWindowObject (args[0], args[1], args[2], args[3]);}
125 /* Callbacks that take double parameters require custom callbacks that instead pass pointers to the doubles. */
126 long ppVtable = iWebFrameLoadDelegate.ppVtable;
127 long[] pVtable = new long[1];
128 OS.MoveMemory (pVtable, ppVtable, C.PTR_SIZEOF);
129 long[] funcs = new long[17];
130 OS.MoveMemory (funcs, pVtable[0], C.PTR_SIZEOF * funcs.length);
131 funcs[12] = WebKit_win32.willPerformClientRedirectToURL_CALLBACK (funcs[12]);
132 OS.MoveMemory (pVtable[0], funcs, C.PTR_SIZEOF * funcs.length);
135 int didChangeLocationWithinPageForFrame (long webView, long frame) {
136 IWebFrame iwebframe = new IWebFrame (frame);
137 long[] result = new long[1];
138 int hr = iwebframe.dataSource (result);
139 if (hr != COM.S_OK || result[0] == 0) {
142 IWebDataSource dataSource = new IWebDataSource (result[0]);
144 hr = dataSource.request (result);
145 dataSource.Release ();
146 if (hr != COM.S_OK || result[0] == 0) {
149 IWebURLRequest request = new IWebURLRequest (result[0]);
151 hr = request.URL (result);
153 if (hr != COM.S_OK || result[0] == 0) {
156 String url2 = WebKit.extractBSTR (result[0]);
157 COM.SysFreeString (result[0]);
158 if (url2.length() == 0) return COM.S_OK;
160 * If the URI indicates that the page is being rendered from memory
161 * (via setText()) then set it to about:blank to be consistent with IE.
163 if (url2.equals (WebKit.URI_FILEROOT)) {
164 url2 = WebKit.ABOUT_BLANK;
166 int length = WebKit.URI_FILEROOT.length ();
167 if (url2.startsWith (WebKit.URI_FILEROOT) && url2.charAt (length) == '#') {
168 url2 = WebKit.ABOUT_BLANK + url2.substring (length);
171 final Display display = browser.getDisplay ();
173 IWebView iWebView = new IWebView (webView);
174 hr = iWebView.mainFrame (result);
176 if (hr == COM.S_OK && result[0] != 0) {
177 top = frame == result[0];
178 new IWebFrame (result[0]).Release ();
181 StatusTextEvent statusText = new StatusTextEvent (browser);
182 statusText.display = display;
183 statusText.widget = browser;
184 statusText.text = url2;
185 StatusTextListener[] statusTextListeners = browser.webBrowser.statusTextListeners;
186 for (int i = 0; i < statusTextListeners.length; i++) {
187 statusTextListeners[i].changed (statusText);
191 LocationEvent location = new LocationEvent (browser);
192 location.display = display;
193 location.widget = browser;
194 location.location = url2;
196 LocationListener[] locationListeners = browser.webBrowser.locationListeners;
197 for (int i = 0; i < locationListeners.length; i++) {
198 locationListeners[i].changed (location);
203 int didClearWindowObject (long webView, long context, long windowScriptObject, long frame) {
204 WebKit_win32.JSGlobalContextRetain (context);
205 long globalObject = WebKit_win32.JSContextGetGlobalObject (context);
206 long privateData = ((WebKit)browser.webBrowser).webViewData;
207 long externalObject = WebKit_win32.JSObjectMake (context, WebKit.ExternalClass, privateData);
208 byte[] bytes = (OBJECTNAME_EXTERNAL + '\0').getBytes (StandardCharsets.UTF_8);
209 long name = WebKit_win32.JSStringCreateWithUTF8CString (bytes);
210 WebKit_win32.JSObjectSetProperty (context, globalObject, name, externalObject, 0, null);
211 WebKit_win32.JSStringRelease (name);
213 for (BrowserFunction current : browser.webBrowser.functions.values()) {
214 browser.execute (current.functionString);
217 IWebView iwebView = new IWebView (webView);
218 long[] mainFrame = new long[1];
219 iwebView.mainFrame (mainFrame);
220 boolean top = mainFrame[0] == frame;
221 new IWebFrame (mainFrame[0]).Release ();
222 addEventHandlers (top);
226 int didCommitLoadForFrame (long webview, long frame) {
227 IWebFrame iWebFrame = new IWebFrame (frame);
228 long[] result = new long[1];
229 int hr = iWebFrame.dataSource (result);
230 if (hr != COM.S_OK || result[0] == 0) {
233 IWebDataSource dataSource = new IWebDataSource (result[0]);
235 hr = dataSource.request (result);
236 dataSource.Release ();
237 if (hr != COM.S_OK || result[0] == 0) {
240 IWebMutableURLRequest request = new IWebMutableURLRequest (result[0]);
242 hr = request.URL (result);
244 if (hr != COM.S_OK || result[0] == 0) {
247 String url2 = WebKit.extractBSTR (result[0]);
248 COM.SysFreeString (result[0]);
249 if (url2.length () == 0) return COM.S_OK;
251 * If the URI indicates that the page is being rendered from memory
252 * (via setText()) then set it to about:blank to be consistent with IE.
254 if (url2.equals (WebKit.URI_FILEROOT)) {
255 url2 = WebKit.ABOUT_BLANK;
257 int length = WebKit.URI_FILEROOT.length ();
258 if (url2.startsWith (WebKit.URI_FILEROOT) && url2.charAt (length) == '#') {
259 url2 = WebKit.ABOUT_BLANK + url2.substring (length);
262 Display display = browser.getDisplay ();
264 IWebView iwebView = new IWebView (webview);
265 hr = iwebView.mainFrame (result);
267 if (hr == COM.S_OK && result[0] != 0) {
268 top = frame == result[0];
269 new IWebFrame (result[0]).Release ();
272 /* reset resource status variables */
276 * Each invocation of setText() causes webView_didCommitLoadForFrame to be invoked
277 * twice, once for the initial navigate to about:blank, and once for the auto-navigate
278 * to about:blank that WebKit does when loadHTMLString is invoked. If this is the
279 * first webView_didCommitLoadForFrame callback received for a setText() invocation
280 * then do not send any events or re-install registered BrowserFunctions.
282 if (url2.startsWith (WebKit.ABOUT_BLANK) && html != null) return COM.S_OK;
284 /* re-install registered functions */
285 for (BrowserFunction function : browser.webBrowser.functions.values()) {
286 browser.webBrowser.execute (function.functionString);
289 ProgressEvent progress = new ProgressEvent (browser);
290 progress.display = display;
291 progress.widget = browser;
292 progress.current = 1;
293 progress.total = WebKit.MAX_PROGRESS;
294 ProgressListener[] progressListeners = browser.webBrowser.progressListeners;
295 for (int i = 0; i < progressListeners.length; i++) {
296 progressListeners[i].changed (progress);
298 if (browser.isDisposed ()) return COM.S_OK;
300 StatusTextEvent statusText = new StatusTextEvent (browser);
301 statusText.display = display;
302 statusText.widget = browser;
303 statusText.text = url2;
304 StatusTextListener[] statusTextListeners = browser.webBrowser.statusTextListeners;
305 for (int i = 0; i < statusTextListeners.length; i++) {
306 statusTextListeners[i].changed (statusText);
308 if (browser.isDisposed ()) return COM.S_OK;
310 LocationEvent location = new LocationEvent (browser);
311 location.display = display;
312 location.widget = browser;
313 location.location = url2;
315 LocationListener[] locationListeners = browser.webBrowser.locationListeners;
316 for (int i = 0; i < locationListeners.length; i++) {
317 locationListeners[i].changed (location);
322 int didFailProvisionalLoadWithError (long webView, long error, long frame) {
323 IWebError iweberror = new IWebError (error);
324 int[] errorCode = new int[1];
325 int hr = iweberror.code (errorCode);
326 if (WebKit_win32.WebURLErrorBadURL < errorCode[0]) return COM.S_OK;
328 String failingURLString = null;
329 long[] failingURL = new long[1];
330 hr = iweberror.failingURL (failingURL);
331 if (hr == COM.S_OK && failingURL[0] != 0) {
332 failingURLString = WebKit.extractBSTR (failingURL[0]);
333 COM.SysFreeString (failingURL[0]);
335 if (failingURLString != null && WebKit_win32.WebURLErrorServerCertificateNotYetValid <= errorCode[0] && errorCode[0] <= WebKit_win32.WebURLErrorSecureConnectionFailed) {
336 /* handle invalid certificate error */
337 long[] result = new long[1];
338 hr = iweberror.localizedDescription (result);
339 if (hr != COM.S_OK || result[0] == 0) {
342 String description = WebKit.extractBSTR (result[0]);
343 COM.SysFreeString (result[0]);
346 hr = iweberror.QueryInterface (WebKit_win32.IID_IWebErrorPrivate, result);
347 if (hr != COM.S_OK || result[0] == 0) {
351 IWebErrorPrivate webErrorPrivate = new IWebErrorPrivate (result[0]);
353 long[] certificate = new long[1];
354 hr = webErrorPrivate.sslPeerCertificate (certificate);
355 webErrorPrivate.Release ();
356 if (hr != COM.S_OK || certificate[0] == 0) {
359 if (showCertificateDialog (webView, failingURLString, description, certificate[0])) {
360 IWebFrame iWebFrame = new IWebFrame (frame);
361 hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebMutableURLRequest, 0, WebKit_win32.IID_IWebMutableURLRequest, result);
362 if (hr != COM.S_OK || result[0] == 0) {
366 IWebMutableURLRequest request = new IWebMutableURLRequest (result[0]);
367 request.setURL (failingURL[0]);
368 request.setAllowsAnyHTTPSCertificate ();
369 iWebFrame.loadRequest (request.getAddress ());
376 /* handle other types of errors */
377 long[] result = new long[1];
378 hr = iweberror.localizedDescription (result);
379 if (hr != COM.S_OK || result[0] == 0) {
382 String description = WebKit.extractBSTR (result[0]);
383 COM.SysFreeString (result[0]);
384 if (!browser.isDisposed ()) {
385 String message = failingURLString != null ? failingURLString + "\n\n" : ""; //$NON-NLS-1$ //$NON-NLS-2$
386 message += Compatibility.getMessage ("SWT_Page_Load_Failed", new Object[] {description}); //$NON-NLS-1$
387 MessageBox messageBox = new MessageBox (browser.getShell (), SWT.OK | SWT.ICON_ERROR);
388 messageBox.setMessage (message);
394 int didFinishLoadForFrame (long webview, long frame) {
395 IWebView iWebView = new IWebView (webview);
396 long[] iWebFrame = new long[1];
397 int hr = iWebView.mainFrame (iWebFrame);
398 if (hr != COM.S_OK || iWebFrame[0] == 0) {
401 boolean top = frame == iWebFrame[0];
402 new IWebFrame (iWebFrame[0]).Release();
403 if (!top) return COM.S_OK;
406 * If html is not null then there is html from a previous setText() call
407 * waiting to be set into the about:blank page once it has completed loading.
410 if (getUrl ().startsWith (WebKit.ABOUT_BLANK)) {
411 ((WebKit)browser.webBrowser).loadingText = true;
412 long string = WebKit.createBSTR (html);
414 if (((WebKit)browser.webBrowser).untrustedText) {
415 URLString = WebKit.createBSTR (WebKit.ABOUT_BLANK);
417 URLString = WebKit.createBSTR (WebKit.URI_FILEROOT);
419 IWebFrame mainFrame = new IWebFrame (frame);
420 mainFrame.loadHTMLString (string, URLString);
426 * The loadHTMLString() invocation above will trigger a second didFinishLoadForFrame
427 * callback when it is completed. If text was just set into the browser then wait for this
428 * second callback to come before sending the title or completed events.
430 if (!((WebKit)browser.webBrowser).loadingText) {
431 if (browser.isDisposed ()) return COM.S_OK;
433 * To be consistent with other platforms a title event should be fired when a
434 * page has completed loading. A page with a <title> tag will do this
435 * automatically when the didReceiveTitle callback is received. However a page
436 * without a <title> tag will not do this by default, so fire the event
437 * here with the page's url as the title.
439 Display display = browser.getDisplay ();
440 IWebFrame mainFrame = new IWebFrame (frame);
441 long[] result = new long[1];
442 hr = mainFrame.dataSource (result);
443 if (hr != COM.S_OK || result[0] == 0) {
446 IWebDataSource dataSource = new IWebDataSource (result[0]);
448 hr = dataSource.pageTitle (result);
449 dataSource.Release ();
450 if (hr != COM.S_OK) {
454 if (result[0] != 0) {
455 title = WebKit.extractBSTR (result[0]);
456 COM.SysFreeString (result[0]);
458 if (title == null || title.length () == 0) { /* page has no title */
459 TitleEvent newEvent = new TitleEvent (browser);
460 newEvent.display = display;
461 newEvent.widget = browser;
462 newEvent.title = getUrl ();
463 TitleListener[] titleListeners = browser.webBrowser.titleListeners;
464 for (int i = 0; i < titleListeners.length; i++) {
465 titleListeners[i].changed (newEvent);
467 if (browser.isDisposed ()) return COM.S_OK;
470 ProgressEvent progress = new ProgressEvent (browser);
471 progress.display = display;
472 progress.widget = browser;
473 progress.current = WebKit.MAX_PROGRESS;
474 progress.total = WebKit.MAX_PROGRESS;
475 ProgressListener[] progressListeners = browser.webBrowser.progressListeners;
476 for (int i = 0; i < progressListeners.length; i++) {
477 progressListeners[i].completed (progress);
479 if (browser.isDisposed ()) return COM.S_OK;
481 ((WebKit)browser.webBrowser).loadingText = false;
485 int didReceiveTitle (long webView, long title, long frame) {
486 long[] mainFrame = new long[1];
487 IWebView iWebView = new IWebView (webView);
488 int hr = iWebView.mainFrame (mainFrame);
489 if (hr != COM.S_OK || frame == 0) {
492 if (frame == mainFrame[0]) {
493 String newTitle = WebKit.extractBSTR (title);
494 TitleEvent newEvent = new TitleEvent (browser);
495 newEvent.display = browser.getDisplay ();
496 newEvent.widget = browser;
497 newEvent.title = newTitle;
498 TitleListener[] titleListeners = browser.webBrowser.titleListeners;
499 for (int i = 0; i < titleListeners.length; i++) {
500 titleListeners[i].changed (newEvent);
503 new IWebFrame (mainFrame[0]).Release ();
507 int didStartProvisionalLoadForFrame (long webView, long frame) {
511 void disposeCOMInterfaces () {
512 if (iWebFrameLoadDelegate != null) {
513 iWebFrameLoadDelegate.dispose ();
514 iWebFrameLoadDelegate = null;
519 return iWebFrameLoadDelegate.getAddress ();
523 /* WebKit auto-navigates to about:blank at startup */
524 if (url == null || url.length () == 0) return WebKit.ABOUT_BLANK;
528 int QueryInterface (long riid, long ppvObject) {
529 if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
530 GUID guid = new GUID ();
531 COM.MoveMemory (guid, riid, GUID.sizeof);
533 if (COM.IsEqualGUID (guid, COM.IIDIUnknown)) {
534 OS.MoveMemory (ppvObject, new long[] {iWebFrameLoadDelegate.getAddress ()}, C.PTR_SIZEOF);
535 new IUnknown (iWebFrameLoadDelegate.getAddress ()).AddRef ();
538 if (COM.IsEqualGUID (guid, WebKit_win32.IID_IWebFrameLoadDelegate)) {
539 OS.MoveMemory (ppvObject, new long[] {iWebFrameLoadDelegate.getAddress ()}, C.PTR_SIZEOF);
540 new IUnknown (iWebFrameLoadDelegate.getAddress ()).AddRef ();
544 OS.MoveMemory (ppvObject, new long[] {0}, C.PTR_SIZEOF);
545 return COM.E_NOINTERFACE;
551 disposeCOMInterfaces ();
556 boolean showCertificateDialog (long webView, final String failingUrlString, final String description, final long certificate) {
557 Shell parent = browser.getShell ();
558 final Shell shell = new Shell (parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
559 shell.setText (Compatibility.getMessage ("SWT_InvalidCert_Title")); //$NON-NLS-1$
560 shell.setLayout (new GridLayout ());
561 Label label = new Label (shell, SWT.WRAP);
564 host = new URL (failingUrlString).getHost ();
565 } catch (MalformedURLException e) {
566 /* show the url instead */
567 host = failingUrlString;
569 StringBuilder message = new StringBuilder ("\n"); //$NON-NLS-1$
570 message.append (Compatibility.getMessage ("SWT_InvalidCert_Message", new String[] {host})); //$NON-NLS-1$
571 message.append ("\n\n"); //$NON-NLS-1$
572 message.append (Compatibility.getMessage (description));
573 message.append ("\n"); //$NON-NLS-1$
574 message.append (Compatibility.getMessage ("SWT_InvalidCert_Connect")); //$NON-NLS-1$
575 message.append ("\n"); //$NON-NLS-1$
576 label.setText(message.toString ());
578 GridData data = new GridData ();
579 Monitor monitor = browser.getMonitor ();
580 int maxWidth = monitor.getBounds ().width * 2 / 3;
581 int width = label.computeSize (SWT.DEFAULT, SWT.DEFAULT).x;
582 data.widthHint = Math.min (width, maxWidth);
583 data.horizontalAlignment = GridData.FILL;
584 data.grabExcessHorizontalSpace = true;
585 label.setLayoutData (data);
587 final boolean[] result = new boolean[1];
588 final Button[] buttons = new Button[3];
589 Listener listener = event -> {
590 if (event.widget == buttons[2]) {
591 showCertificate (shell, certificate);
593 result[0] = event.widget == buttons[0];
598 Composite composite = new Composite (shell, SWT.NONE);
599 data = new GridData ();
600 data.horizontalAlignment = GridData.END;
601 composite.setLayoutData (data);
602 composite.setLayout (new GridLayout (3, true));
603 buttons[0] = new Button (composite, SWT.PUSH);
604 buttons[0].setText (SWT.getMessage("SWT_Continue")); //$NON-NLS-1$
605 buttons[0].setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
606 buttons[0].addListener (SWT.Selection, listener);
607 buttons[1] = new Button (composite, SWT.PUSH);
608 buttons[1].setText (SWT.getMessage("SWT_Cancel")); //$NON-NLS-1$
609 buttons[1].setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
610 buttons[1].addListener (SWT.Selection, listener);
611 buttons[2] = new Button (composite, SWT.PUSH);
612 buttons[2].setText (SWT.getMessage("SWT_ViewCertificate")); //$NON-NLS-1$
613 buttons[2].setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
614 buttons[2].addListener (SWT.Selection, listener);
616 shell.setDefaultButton (buttons[0]);
619 Rectangle parentSize = parent.getBounds ();
620 Rectangle shellSize = shell.getBounds ();
621 int x = parent.getLocation ().x + (parentSize.width - shellSize.width) / 2;
622 int y = parent.getLocation ().y + (parentSize.height - shellSize.height) / 2;
623 shell.setLocation (x, y);
625 Display display = browser.getDisplay ();
626 while (!shell.isDisposed ()) {
627 if (!display.readAndDispatch ()) display.sleep ();
632 void showCertificate (Shell parent, long certificate) {
633 CERT_CONTEXT context = new CERT_CONTEXT ();
634 OS.MoveMemory (context, certificate, CERT_CONTEXT.sizeof);
635 CERT_INFO info = new CERT_INFO ();
636 OS.MoveMemory (info, context.pCertInfo, CERT_INFO.sizeof);
638 int length = OS.CertNameToStr (OS.X509_ASN_ENCODING, info.Issuer, OS.CERT_SIMPLE_NAME_STR, null, 0);
639 char [] buffer = new char [length];
640 OS.CertNameToStr (OS.X509_ASN_ENCODING, info.Issuer, OS.CERT_SIMPLE_NAME_STR, buffer, length);
641 String issuer = new String (buffer, 0, length - 1);
643 length = OS.CertNameToStr (OS.X509_ASN_ENCODING, info.Subject, OS.CERT_SIMPLE_NAME_STR, null, 0);
644 buffer = new char [length];
645 OS.CertNameToStr (OS.X509_ASN_ENCODING, info.Subject, OS.CERT_SIMPLE_NAME_STR, buffer, length);
646 String subject = new String (buffer, 0, length - 1);
648 final String SEPARATOR_DATE = "/"; //$NON-NLS-1$
649 final String SEPARATOR_TIME = ":"; //$NON-NLS-1$
650 SYSTEMTIME systemTime = new SYSTEMTIME ();
651 OS.FileTimeToSystemTime (info.NotBefore, systemTime);
652 String validFrom = systemTime.wDay + SEPARATOR_DATE + systemTime.wMonth + SEPARATOR_DATE + systemTime.wYear;
653 String validFromTime = systemTime.wHour + SEPARATOR_TIME + systemTime.wMinute + SEPARATOR_TIME + systemTime.wSecond;
655 systemTime = new SYSTEMTIME ();
656 OS.FileTimeToSystemTime (info.NotAfter, systemTime);
657 String validTo = systemTime.wDay + SEPARATOR_DATE + systemTime.wMonth + SEPARATOR_DATE + systemTime.wYear;
658 String validToTime = systemTime.wHour + SEPARATOR_TIME + systemTime.wMinute + SEPARATOR_TIME + systemTime.wSecond;
660 length = info.SerialNumber.cbData;
661 byte[] serialNumber = new byte[length];
662 OS.MoveMemory (serialNumber, info.SerialNumber.pbData, length);
663 String hexSerialNumber = new String ();
664 for (int i = length - 1; i >= 0; i--) {
665 int number = 0xFF & serialNumber[i];
666 String hex = Integer.toHexString (number);
667 if (hex.length () == 1) hexSerialNumber += "0"; //$NON-NLS-1$
668 hexSerialNumber += hex + " "; //$NON-NLS-1$
671 final Shell dialog = new Shell (parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
672 dialog.setText (SWT.getMessage ("SWT_Certificate")); //$NON-NLS-1$
673 dialog.setLayout (new GridLayout (1, false));
675 TabFolder tabFolder = new TabFolder (dialog, SWT.NONE);
676 tabFolder.setLayoutData (new GridData (SWT.FILL, SWT.FILL, true, true, 1, 1));
677 tabFolder.setLayout (new FillLayout ());
679 TabItem general = new TabItem (tabFolder, SWT.NONE);
680 general.setText (SWT.getMessage ("SWT_General")); //$NON-NLS-1$
681 Composite composite = new Composite (tabFolder, SWT.BORDER);
682 composite.setLayout (new GridLayout (1, false));
683 Label issuedTo = new Label (composite, SWT.NONE);
684 issuedTo.setLayoutData (new GridData (SWT.BEGINNING, SWT.CENTER, false, false));
685 issuedTo.setText (Compatibility.getMessage ("SWT_IssuedTo", new Object[] {subject})); //$NON-NLS-1$
686 Label issuedBy = new Label (composite, SWT.NONE);
687 issuedBy.setLayoutData (new GridData (SWT.BEGINNING, SWT.CENTER, false, false));
688 issuedBy.setText (Compatibility.getMessage ("SWT_IssuedFrom", new Object[] {issuer})); //$NON-NLS-1$
689 Label valid = new Label (composite, SWT.NONE);
690 valid.setLayoutData (new GridData (SWT.BEGINNING, SWT.CENTER, false, false));
691 valid.setText (Compatibility.getMessage ("SWT_ValidFromTo", new Object[] {validFrom, validTo})); //$NON-NLS-1$
692 general.setControl (composite);
694 TabItem details = new TabItem (tabFolder, SWT.NONE);
695 details.setText (SWT.getMessage ("SWT_Details")); //$NON-NLS-1$
696 Table table = new Table (tabFolder, SWT.SINGLE | SWT.BORDER| SWT.FULL_SELECTION);
697 table.setHeaderVisible (true);
698 TableColumn tableColumn = new TableColumn (table, SWT.LEAD);
699 tableColumn.setText (SWT.getMessage ("SWT_Field")); //$NON-NLS-1$
700 tableColumn = new TableColumn (table, SWT.NONE);
701 tableColumn.setText (SWT.getMessage ("SWT_Value")); //$NON-NLS-1$
702 TableItem tableItem = new TableItem(table, SWT.NONE);
703 String version = "V" + String.valueOf (info.dwVersion + 1); //$NON-NLS-1$
704 tableItem.setText (new String[]{SWT.getMessage ("SWT_Version"), version}); //$NON-NLS-1$
705 tableItem = new TableItem (table, SWT.NONE);
706 tableItem.setText (new String[] {SWT.getMessage ("SWT_SerialNumber"), hexSerialNumber}); //$NON-NLS-1$
707 tableItem = new TableItem (table, SWT.NONE);
708 tableItem.setText (new String[] {SWT.getMessage ("SWT_Issuer"), issuer}); //$NON-NLS-1$
710 tableItem = new TableItem (table, SWT.NONE);
711 StringBuilder stringBuilder2 = new StringBuilder ();
712 stringBuilder2.append (validFrom);
713 stringBuilder2.append (", "); //$NON-NLS-1$
714 stringBuilder2.append (validFromTime);
715 stringBuilder2.append (" GMT"); //$NON-NLS-1$
716 tableItem.setText (new String[] {SWT.getMessage ("SWT_ValidFrom"), stringBuilder2.toString ()}); //$NON-NLS-1$
718 tableItem = new TableItem (table, SWT.NONE);
719 StringBuilder stringBuilder = new StringBuilder ();
720 stringBuilder.append (validTo);
721 stringBuilder.append (", "); //$NON-NLS-1$
722 stringBuilder.append (validToTime);
723 stringBuilder.append (" GMT"); //$NON-NLS-1$
724 tableItem.setText (new String[] {SWT.getMessage ("SWT_ValidTo"), stringBuilder.toString ()}); //$NON-NLS-1$
726 tableItem = new TableItem (table, SWT.NONE);
727 tableItem.setText (new String[] {SWT.getMessage ("SWT_Subject"), subject}); //$NON-NLS-1$
728 for (int i = 0; i < table.getColumnCount (); i++) {
729 table.getColumn (i).pack ();
731 details.setControl (table);
733 Button ok = new Button (dialog, SWT.PUSH);
734 GridData layoutData = new GridData (SWT.END, SWT.CENTER, false, false);
735 layoutData.widthHint = 75;
736 ok.setLayoutData (layoutData);
737 ok.setText (SWT.getMessage ("SWT_OK")); //$NON-NLS-1$
738 ok.addSelectionListener (new SelectionAdapter() {
740 public void widgetSelected (SelectionEvent e) {
745 dialog.setDefaultButton (ok);
747 Rectangle parentSize = parent.getBounds ();
748 Rectangle dialogSize = dialog.getBounds ();
749 int x = parent.getLocation ().x + (parentSize.width - dialogSize.width) / 2;
750 int y = parent.getLocation ().y + (parentSize.height - dialogSize.height) / 2;
751 dialog.setLocation (x, y);
753 Display display = browser.getDisplay ();
754 while (!dialog.isDisposed ()) {
755 if (!display.readAndDispatch ()) display.sleep ();