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;
17 import org.eclipse.swt.*;
18 import org.eclipse.swt.graphics.*;
19 import org.eclipse.swt.internal.*;
20 import org.eclipse.swt.internal.ole.win32.*;
21 import org.eclipse.swt.internal.webkit.*;
22 import org.eclipse.swt.internal.win32.*;
23 import org.eclipse.swt.layout.*;
24 import org.eclipse.swt.widgets.*;
26 class WebResourceLoadDelegate {
27 COMObject iWebResourceLoadDelegate;
33 WebResourceLoadDelegate (Browser browser) {
34 createCOMInterfaces ();
35 this.browser = browser;
43 void createCOMInterfaces () {
44 iWebResourceLoadDelegate = new COMObject (new int[] {2, 0, 0, 4, 6, 4, 4, 4, 4, 3, 4, 3}) {
46 public long method0 (long[] args) {return QueryInterface (args[0], args[1]);}
48 public long method1 (long[] args) {return AddRef ();}
50 public long method2 (long[] args) {return Release ();}
52 public long method3 (long[] args) {return identifierForInitialRequest (args[0], args[1], args[2], args[3]);}
54 public long method4 (long[] args) {return willSendRequest (args[0], args[1], args[2], args[3], args[4], args[5]);}
56 public long method5 (long[] args) {return didReceiveAuthenticationChallenge (args[0], args[1], args[2], args[3]);}
58 public long method6 (long[] args) {return COM.E_NOTIMPL;}
60 public long method7 (long[] args) {return COM.S_OK;}
62 public long method8 (long[] args) {return COM.S_OK;}
64 public long method9 (long[] args) {return COM.S_OK;}
66 public long method10 (long[] args) {return COM.S_OK;}
68 public long method11 (long[] args) {return COM.E_NOTIMPL;}
72 int didReceiveAuthenticationChallenge (long webView, long identifier, long challenge, long dataSource) {
73 IWebURLAuthenticationChallenge authenticationChallenge = new IWebURLAuthenticationChallenge (challenge);
75 * Do not invoke the listeners if this challenge has been failed too many
76 * times because a listener is likely giving incorrect credentials repeatedly
77 * and will do so indefinitely.
79 int[] count = new int[1];
80 int hr = authenticationChallenge.previousFailureCount (count);
81 long[] result = new long[1];
82 if (hr == COM.S_OK && count[0] < 3) {
83 AuthenticationListener[] authenticationListeners = browser.webBrowser.authenticationListeners;
84 for (int i = 0; i < authenticationListeners.length; i++) {
85 AuthenticationEvent event = new AuthenticationEvent (browser);
86 event.location = ((WebKit)browser.webBrowser).lastNavigateURL;
87 authenticationListeners[i].authenticate (event);
89 hr = authenticationChallenge.sender (result);
90 if (hr != COM.S_OK || result[0] == 0) {
93 IWebURLAuthenticationChallengeSender challengeSender = new IWebURLAuthenticationChallengeSender (result[0]);
94 challengeSender.cancelAuthenticationChallenge (challenge);
95 challengeSender.Release ();
98 if (event.user != null && event.password != null) {
99 hr = authenticationChallenge.sender (result);
100 if (hr != COM.S_OK || result[0] == 0) continue;
102 IWebURLAuthenticationChallengeSender challengeSender = new IWebURLAuthenticationChallengeSender (result[0]);
104 hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebURLCredential, 0, WebKit_win32.IID_IWebURLCredential, result);
105 if (hr == COM.S_OK && result[0] != 0) {
106 IWebURLCredential credential = new IWebURLCredential (result[0]);
107 long user = WebKit.createBSTR (event.user);
108 long password = WebKit.createBSTR (event.password);
109 credential.initWithUser (user, password, WebKit_win32.WebURLCredentialPersistenceForSession);
110 challengeSender.useCredential (credential.getAddress (), challenge);
111 credential.Release ();
113 challengeSender.Release ();
119 /* show a custom authentication dialog */
121 String[] userReturn = new String[1], passwordReturn = new String[1];
123 hr = authenticationChallenge.proposedCredential (result);
124 if (hr == COM.S_OK && result[0] != 0) {
125 IWebURLCredential proposedCredential = new IWebURLCredential(result[0]);
127 hr = proposedCredential.user (result);
128 if (hr == COM.S_OK && result[0] != 0) {
129 userReturn[0] = WebKit.extractBSTR (result[0]);
130 COM.SysFreeString (result[0]);
131 int[] value = new int[1];
132 hr = proposedCredential.hasPassword (value);
133 if (hr == COM.S_OK && value[0] != 0) {
135 hr = proposedCredential.password (result);
136 if (hr == COM.S_OK && result[0] != 0) {
137 passwordReturn[0] = WebKit.extractBSTR (result[0]);
138 COM.SysFreeString (result[0]);
142 proposedCredential.Release ();
145 hr = authenticationChallenge.protectionSpace (result);
146 if (hr != COM.S_OK || result[0] == 0) {
149 IWebURLProtectionSpace space = new IWebURLProtectionSpace (result[0]);
150 String host = null, realm = null;
152 hr = space.host (result);
153 if (hr == COM.S_OK && result[0] != 0) {
154 host = WebKit.extractBSTR (result[0]);
155 COM.SysFreeString (result[0]);
156 int[] port = new int[1];
157 hr = space.port (port);
158 if (hr == COM.S_OK) {
159 host += ":" + port[0]; //$NON-NLS-1$
161 hr = space.realm (result);
162 if (hr == COM.S_OK && result[0] != 0) {
163 realm = WebKit.extractBSTR (result[0]);
164 COM.SysFreeString (result[0]);
169 boolean response = showAuthenticationDialog (userReturn, passwordReturn, host, realm);
171 hr = authenticationChallenge.sender (result);
172 if (hr != COM.S_OK || result[0] == 0) {
175 IWebURLAuthenticationChallengeSender challengeSender = new IWebURLAuthenticationChallengeSender (result[0]);
177 challengeSender.cancelAuthenticationChallenge (challenge);
178 challengeSender.Release ();
182 hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebURLCredential, 0, WebKit_win32.IID_IWebURLCredential, result);
183 if (hr == COM.S_OK && result[0] != 0) {
184 IWebURLCredential credential = new IWebURLCredential (result[0]);
185 long user = WebKit.createBSTR (userReturn[0]);
186 long password = WebKit.createBSTR (passwordReturn[0]);
187 credential.initWithUser (user, password, WebKit_win32.WebURLCredentialPersistenceForSession);
188 challengeSender.useCredential (credential.getAddress (), challenge);
189 credential.Release ();
191 challengeSender.Release ();
195 void disposeCOMInterfaces () {
196 if (iWebResourceLoadDelegate != null) {
197 iWebResourceLoadDelegate.dispose ();
198 iWebResourceLoadDelegate = null;
203 return iWebResourceLoadDelegate.getAddress ();
206 int identifierForInitialRequest (long webView, long request, long dataSource, long identifier) {
207 if (browser.isDisposed ()) return COM.S_OK;
209 /* send progress event iff request is for top-level frame */
211 IWebDataSource source = new IWebDataSource (dataSource);
212 long[] frame = new long[1];
213 int hr = source.webFrame (frame);
214 if (hr != COM.S_OK || frame[0] == 0) {
217 new IWebFrame (frame[0]).Release ();
218 long[] mainFrame = new long[1];
219 IWebView iWebView = new IWebView (webView);
220 hr = iWebView.mainFrame (mainFrame);
221 if (hr != COM.S_OK || mainFrame[0] == 0) {
224 new IWebFrame (mainFrame[0]).Release ();
225 if (frame[0] == mainFrame[0]) {
226 long ptr = C.malloc (8);
227 iWebView.estimatedProgress (ptr);
228 double[] estimate = new double[1];
229 OS.MoveMemory (estimate, ptr, 8);
231 int progress = (int)(estimate[0] * 100);
233 ProgressEvent progressEvent = new ProgressEvent (browser);
234 progressEvent.display = browser.getDisplay ();
235 progressEvent.widget = browser;
236 progressEvent.current = progress;
237 progressEvent.total = Math.max (progress, WebKit.MAX_PROGRESS);
238 ProgressListener[] progressListeners = browser.webBrowser.progressListeners;
239 for (int i = 0; i < progressListeners.length; i++) {
240 progressListeners[i].changed (progressEvent);
246 int QueryInterface (long riid, long ppvObject) {
247 if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
248 GUID guid = new GUID ();
249 COM.MoveMemory (guid, riid, GUID.sizeof);
251 if (COM.IsEqualGUID (guid, COM.IIDIUnknown)) {
252 OS.MoveMemory (ppvObject, new long[] {iWebResourceLoadDelegate.getAddress ()}, C.PTR_SIZEOF);
253 new IUnknown (iWebResourceLoadDelegate.getAddress ()).AddRef ();
256 if (COM.IsEqualGUID (guid, WebKit_win32.IID_IWebResourceLoadDelegate)) {
257 OS.MoveMemory (ppvObject, new long[] {iWebResourceLoadDelegate.getAddress ()}, C.PTR_SIZEOF);
258 new IUnknown (iWebResourceLoadDelegate.getAddress ()).AddRef ();
262 OS.MoveMemory (ppvObject, new long[] {0}, C.PTR_SIZEOF);
263 return COM.E_NOINTERFACE;
269 disposeCOMInterfaces ();
274 boolean showAuthenticationDialog (final String[] user, final String[] password, String host, String realm) {
275 Shell parent = browser.getShell ();
276 final Shell shell = new Shell (parent);
277 shell.setLayout (new GridLayout ());
278 String title = SWT.getMessage ("SWT_Authentication_Required"); //$NON-NLS-1$
279 shell.setText (title);
280 Label label = new Label (shell, SWT.WRAP);
281 label.setText (Compatibility.getMessage ("SWT_Enter_Username_and_Password", new String[] {realm, host})); //$NON-NLS-1$
283 GridData data = new GridData ();
284 Monitor monitor = browser.getMonitor ();
285 int maxWidth = monitor.getBounds ().width * 2 / 3;
286 int width = label.computeSize (SWT.DEFAULT, SWT.DEFAULT).x;
287 data.widthHint = Math.min (width, maxWidth);
288 data.horizontalAlignment = GridData.FILL;
289 data.grabExcessHorizontalSpace = true;
290 label.setLayoutData (data);
292 Label userLabel = new Label (shell, SWT.NONE);
293 userLabel.setText (SWT.getMessage ("SWT_Username")); //$NON-NLS-1$
295 final Text userText = new Text (shell, SWT.BORDER);
296 if (user[0] != null) userText.setText (user[0]);
297 data = new GridData ();
298 data.horizontalAlignment = GridData.FILL;
299 data.grabExcessHorizontalSpace = true;
300 userText.setLayoutData (data);
302 Label passwordLabel = new Label (shell, SWT.NONE);
303 passwordLabel.setText (SWT.getMessage ("SWT_Password")); //$NON-NLS-1$
305 final Text passwordText = new Text (shell, SWT.PASSWORD | SWT.BORDER);
306 if (password[0] != null) passwordText.setText (password[0]);
307 data = new GridData ();
308 data.horizontalAlignment = GridData.FILL;
309 data.grabExcessHorizontalSpace = true;
310 passwordText.setLayoutData (data);
312 final boolean[] result = new boolean[1];
313 final Button[] buttons = new Button[2];
314 Listener listener = event -> {
315 user[0] = userText.getText ();
316 password[0] = passwordText.getText ();
317 result[0] = event.widget == buttons[1];
321 Composite composite = new Composite (shell, SWT.NONE);
322 data = new GridData ();
323 data.horizontalAlignment = GridData.END;
324 composite.setLayoutData (data);
325 composite.setLayout (new GridLayout (2, true));
326 buttons[0] = new Button (composite, SWT.PUSH);
327 buttons[0].setText (SWT.getMessage ("SWT_Cancel")); //$NON-NLS-1$
328 buttons[0].setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
329 buttons[0].addListener (SWT.Selection, listener);
330 buttons[1] = new Button (composite, SWT.PUSH);
331 buttons[1].setText (SWT.getMessage ("SWT_OK")); //$NON-NLS-1$
332 buttons[1].setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
333 buttons[1].addListener (SWT.Selection, listener);
335 shell.setDefaultButton (buttons[1]);
337 Rectangle parentSize = parent.getBounds ();
338 Rectangle shellSize = shell.getBounds ();
339 int x = parent.getLocation().x + (parentSize.width - shellSize.width) / 2;
340 int y = parent.getLocation().y + (parentSize.height - shellSize.height) / 2;
341 shell.setLocation (x, y);
343 Display display = browser.getDisplay ();
344 while (!shell.isDisposed ()) {
345 if (!display.readAndDispatch ()) display.sleep ();
351 int willSendRequest (long webView, long identifier, long request, long redirectResponse, long dataSource, long newRequest) {
352 IWebURLRequest req = new IWebURLRequest (request);
353 long[] result = new long [1];
354 int hr = req.URL (result);
355 if (hr == COM.S_OK && result[0] != 0) {
356 String url = WebKit.extractBSTR (result[0]);
357 COM.SysFreeString (result[0]);
359 * file://c|/ doesn't work on Webkit but works on other browsers.
360 * So change file:// to file:/// to be consistent
362 if (url.startsWith (WebKit.PROTOCOL_FILE) && !url.startsWith (WebKit.URI_FILEROOT)) {
363 int length = WebKit.PROTOCOL_FILE.length ();
364 url = WebKit.URI_FILEROOT + url.substring (length);
367 hr = req.mutableCopy (result);
368 if (hr == COM.S_OK && result[0] != 0) {
369 IWebMutableURLRequest mReq = new IWebMutableURLRequest (result[0]);
370 long urlString = WebKit.createBSTR (url);
371 mReq.setURL (urlString);
372 OS.MoveMemory (newRequest, new long[] {mReq.getAddress ()}, C.PTR_SIZEOF);
378 OS.MoveMemory (newRequest, new long[] {request}, C.PTR_SIZEOF);