1 /*******************************************************************************
2  * Copyright (c) 2000, 2017 IBM Corporation and others.
3  *
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/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.swt.browser;
15 
16 import java.util.*;
17 
18 import org.eclipse.swt.*;
19 import org.eclipse.swt.internal.*;
20 import org.eclipse.swt.internal.ole.win32.*;
21 import org.eclipse.swt.internal.win32.*;
22 import org.eclipse.swt.ole.win32.*;
23 import org.eclipse.swt.widgets.*;
24 
25 class WebSite extends OleControlSite {
26 	COMObject iDocHostUIHandler;
27 	COMObject iDocHostShowUI;
28 	COMObject iServiceProvider;
29 	COMObject iInternetSecurityManager;
30 	COMObject iOleCommandTarget;
31 	COMObject iAuthenticate;
32 	COMObject iDispatch;
33 	boolean ignoreNextMessage, ignoreAllMessages;
34 	boolean isForceTrusted;
35 	Boolean canExecuteApplets;
36 
37 	static final int OLECMDID_SHOWSCRIPTERROR = 40;
38 	static final short [] ACCENTS = new short [] {'~', '`', '\'', '^', '"'};
39 	static final String CONSUME_KEY = "org.eclipse.swt.OleFrame.ConsumeKey"; //$NON-NLS-1$
40 
WebSite(Composite parent, int style, String progId)41 public WebSite(Composite parent, int style, String progId) {
42 	super(parent, style, progId);
43 }
44 
45 @Override
createCOMInterfaces()46 protected void createCOMInterfaces () {
47 	super.createCOMInterfaces();
48 	iDocHostUIHandler = new COMObject(new int[]{2, 0, 0, 4, 1, 5, 0, 0, 1, 1, 1, 3, 3, 2, 2, 1, 3, 2}){
49 		@Override
50 		public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
51 		@Override
52 		public long method1(long[] args) {return AddRef();}
53 		@Override
54 		public long method2(long[] args) {return Release();}
55 		@Override
56 		public long method3(long[] args) {return ShowContextMenu((int)args[0], args[1], args[2], args[3]);}
57 		@Override
58 		public long method4(long[] args) {return GetHostInfo(args[0]);}
59 		@Override
60 		public long method5(long[] args) {return ShowUI((int)args[0], args[1], args[2], args[3], args[4]);}
61 		@Override
62 		public long method6(long[] args) {return HideUI();}
63 		@Override
64 		public long method7(long[] args) {return UpdateUI();}
65 		@Override
66 		public long method8(long[] args) {return EnableModeless((int)args[0]);}
67 		@Override
68 		public long method9(long[] args) {return OnDocWindowActivate((int)args[0]);}
69 		@Override
70 		public long method10(long[] args) {return OnFrameWindowActivate((int)args[0]);}
71 		@Override
72 		public long method11(long[] args) {return ResizeBorder(args[0], args[1], (int)args[2]);}
73 		@Override
74 		public long method12(long[] args) {return TranslateAccelerator(args[0], args[1], (int)args[2]);}
75 		@Override
76 		public long method13(long[] args) {return GetOptionKeyPath(args[0], (int)args[1]);}
77 		@Override
78 		public long method14(long[] args) {return GetDropTarget(args[0], args[1]);}
79 		@Override
80 		public long method15(long[] args) {return GetExternal(args[0]);}
81 		@Override
82 		public long method16(long[] args) {return TranslateUrl((int)args[0], args[1], args[2]);}
83 		@Override
84 		public long method17(long[] args) {return FilterDataObject(args[0], args[1]);}
85 	};
86 	iDocHostShowUI = new COMObject(new int[]{2, 0, 0, 7, 6}){
87 		@Override
88 		public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
89 		@Override
90 		public long method1(long[] args) {return AddRef();}
91 		@Override
92 		public long method2(long[] args) {return Release();}
93 		@Override
94 		public long method3(long[] args) {return ShowMessage(args[0], args[1], args[2], (int)args[3], args[4], (int)args[5], args[6]);}
95 		@Override
96 		public long method4(long[] args) {return ShowHelp(args[0], args[1], (int)args[2], (int)args[3], args[4], args[5]);}
97 	};
98 	iServiceProvider = new COMObject(new int[]{2, 0, 0, 3}){
99 		@Override
100 		public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
101 		@Override
102 		public long method1(long[] args) {return AddRef();}
103 		@Override
104 		public long method2(long[] args) {return Release();}
105 		@Override
106 		public long method3(long[] args) {return QueryService(args[0], args[1], args[2]);}
107 	};
108 	iInternetSecurityManager = new COMObject(new int[]{2, 0, 0, 1, 1, 3, 4, 8, 7, 3, 3}){
109 		@Override
110 		public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
111 		@Override
112 		public long method1(long[] args) {return AddRef();}
113 		@Override
114 		public long method2(long[] args) {return Release();}
115 		@Override
116 		public long method3(long[] args) {return SetSecuritySite(args[0]);}
117 		@Override
118 		public long method4(long[] args) {return GetSecuritySite(args[0]);}
119 		@Override
120 		public long method5(long[] args) {return MapUrlToZone(args[0], args[1], (int)args[2]);}
121 		@Override
122 		public long method6(long[] args) {return GetSecurityId(args[0], args[1], args[2], args[3]);}
123 		@Override
124 		public long method7(long[] args) {return ProcessUrlAction(args[0], (int)args[1], args[2], (int)args[3], args[4], (int)args[5], (int)args[6], (int)args[7]);}
125 		@Override
126 		public long method8(long[] args) {return QueryCustomPolicy(args[0], args[1], args[2], args[3], args[4], (int)args[5], (int)args[6]);}
127 		@Override
128 		public long method9(long[] args) {return SetZoneMapping((int)args[0], args[1], (int)args[2]);}
129 		@Override
130 		public long method10(long[] args) {return GetZoneMappings((int)args[0], args[1], (int)args[2]);}
131 	};
132 	iOleCommandTarget = new COMObject(new int[]{2, 0, 0, 4, 5}) {
133 		@Override
134 		public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
135 		@Override
136 		public long method1(long[] args) {return AddRef();}
137 		@Override
138 		public long method2(long[] args) {return Release();}
139 		@Override
140 		public long method3(long[] args) {return QueryStatus(args[0], (int)args[1], args[2], args[3]);}
141 		@Override
142 		public long method4(long[] args) {return Exec(args[0], (int)args[1], (int)args[2], args[3], args[4]);}
143 	};
144 	iAuthenticate = new COMObject(new int[]{2, 0, 0, 3}){
145 		@Override
146 		public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
147 		@Override
148 		public long method1(long[] args) {return AddRef();}
149 		@Override
150 		public long method2(long[] args) {return Release();}
151 		@Override
152 		public long method3(long[] args) {return Authenticate(args[0], args[1], args[2]);}
153 	};
154 	iDispatch = new COMObject (new int[] {2, 0, 0, 1, 3, 5, 8}) {
155 		@Override
156 		public long method0 (long[] args) {
157 			/*
158 			 * IDispatch check must be done here instead of in the shared QueryInterface
159 			 * implementation, to avoid answering the superclass's IDispatch implementation
160 			 * instead of this one.
161 			 */
162 			GUID guid = new GUID ();
163 			COM.MoveMemory (guid, args[0], GUID.sizeof);
164 			if (COM.IsEqualGUID (guid, COM.IIDIDispatch)) {
165 				OS.MoveMemory (args[1], new long[] {iDispatch.getAddress ()}, C.PTR_SIZEOF);
166 				AddRef ();
167 				return COM.S_OK;
168 			}
169 			return QueryInterface (args[0], args[1]);
170 		}
171 		@Override
172 		public long method1 (long[] args) {return AddRef ();}
173 		@Override
174 		public long method2 (long[] args) {return Release ();}
175 		@Override
176 		public long method3 (long[] args) {return GetTypeInfoCount (args[0]);}
177 		@Override
178 		public long method4 (long[] args) {return GetTypeInfo ((int)args[0], (int)args[1], args[2]);}
179 		@Override
180 		public long method5 (long[] args) {return GetIDsOfNames ((int)args[0], args[1], (int)args[2], (int)args[3], args[4]);}
181 		@Override
182 		public long method6 (long[] args) {return Invoke ((int)args[0], (int)args[1], (int)args[2], (int)args[3], args[4], args[5], args[6], args[7]);}
183 	};
184 }
185 
186 @Override
disposeCOMInterfaces()187 protected void disposeCOMInterfaces() {
188 	super.disposeCOMInterfaces();
189 	if (iDocHostUIHandler != null) {
190 		iDocHostUIHandler.dispose();
191 		iDocHostUIHandler = null;
192 	}
193 	if (iDocHostShowUI != null) {
194 		iDocHostShowUI.dispose();
195 		iDocHostShowUI = null;
196 	}
197 	if (iServiceProvider != null) {
198 		iServiceProvider.dispose();
199 		iServiceProvider = null;
200 	}
201 	if (iInternetSecurityManager != null) {
202 		iInternetSecurityManager.dispose();
203 		iInternetSecurityManager = null;
204 	}
205 	if (iOleCommandTarget != null) {
206 		iOleCommandTarget.dispose();
207 		iOleCommandTarget = null;
208 	}
209 	if (iAuthenticate != null) {
210 		iAuthenticate.dispose();
211 		iAuthenticate = null;
212 	}
213 	if (iDispatch != null) {
214 		iDispatch.dispose ();
215 		iDispatch = null;
216 	}
217 }
218 
219 @Override
AddRef()220 protected int AddRef() {
221 	/* Workaround for javac 1.1.8 bug */
222 	return super.AddRef();
223 }
224 
225 @Override
QueryInterface(long riid, long ppvObject)226 protected int QueryInterface(long riid, long ppvObject) {
227 	int result = super.QueryInterface(riid, ppvObject);
228 	if (result == COM.S_OK) return result;
229 	if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
230 	GUID guid = new GUID();
231 	COM.MoveMemory(guid, riid, GUID.sizeof);
232 	if (COM.IsEqualGUID(guid, COM.IIDIDocHostUIHandler)) {
233 		OS.MoveMemory(ppvObject, new long[] {iDocHostUIHandler.getAddress()}, C.PTR_SIZEOF);
234 		AddRef();
235 		return COM.S_OK;
236 	}
237 	if (COM.IsEqualGUID(guid, COM.IIDIDocHostShowUI)) {
238 		OS.MoveMemory(ppvObject, new long[] {iDocHostShowUI.getAddress()}, C.PTR_SIZEOF);
239 		AddRef();
240 		return COM.S_OK;
241 	}
242 	if (COM.IsEqualGUID(guid, COM.IIDIServiceProvider)) {
243 		OS.MoveMemory(ppvObject, new long[] {iServiceProvider.getAddress()}, C.PTR_SIZEOF);
244 		AddRef();
245 		return COM.S_OK;
246 	}
247 	if (COM.IsEqualGUID(guid, COM.IIDIInternetSecurityManager)) {
248 		OS.MoveMemory(ppvObject, new long[] {iInternetSecurityManager.getAddress()}, C.PTR_SIZEOF);
249 		AddRef();
250 		return COM.S_OK;
251 	}
252 	if (COM.IsEqualGUID(guid, COM.IIDIOleCommandTarget)) {
253 		OS.MoveMemory(ppvObject, new long[] {iOleCommandTarget.getAddress()}, C.PTR_SIZEOF);
254 		AddRef();
255 		return COM.S_OK;
256 	}
257 	OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
258 	return COM.E_NOINTERFACE;
259 }
260 
261 /* IDocHostUIHandler */
262 
EnableModeless(int EnableModeless)263 int EnableModeless(int EnableModeless) {
264 	return COM.E_NOTIMPL;
265 }
266 
FilterDataObject(long pDO, long ppDORet)267 int FilterDataObject(long pDO, long ppDORet) {
268 	return COM.E_NOTIMPL;
269 }
270 
GetDropTarget(long pDropTarget, long ppDropTarget)271 int GetDropTarget(long pDropTarget, long ppDropTarget) {
272 	return COM.E_NOTIMPL;
273 }
274 
GetExternal(long ppDispatch)275 int GetExternal(long ppDispatch) {
276 	OS.MoveMemory (ppDispatch, new long[] {iDispatch.getAddress()}, C.PTR_SIZEOF);
277 	AddRef ();
278 	return COM.S_OK;
279 }
280 
GetHostInfo(long pInfo)281 int GetHostInfo(long pInfo) {
282 	int info = IE.DOCHOSTUIFLAG_THEME | IE.DOCHOSTUIFLAG_ENABLE_REDIRECT_NOTIFICATION | IE.DOCHOSTUIFLAG_DPI_AWARE;
283 	IE browser = (IE)((Browser)getParent().getParent()).webBrowser;
284 	if ((browser.style & SWT.BORDER) == 0) info |= IE.DOCHOSTUIFLAG_NO3DOUTERBORDER;
285 	DOCHOSTUIINFO uiInfo = new DOCHOSTUIINFO ();
286 	OS.MoveMemory(uiInfo, pInfo, DOCHOSTUIINFO.sizeof);
287 	uiInfo.dwFlags = info;
288 	OS.MoveMemory(pInfo, uiInfo, DOCHOSTUIINFO.sizeof);
289 	return COM.S_OK;
290 }
291 
GetOptionKeyPath(long pchKey, int dw)292 int GetOptionKeyPath(long pchKey, int dw) {
293 	return COM.E_NOTIMPL;
294 }
295 
HideUI()296 int HideUI() {
297 	return COM.E_NOTIMPL;
298 }
299 
OnDocWindowActivate(int fActivate)300 int OnDocWindowActivate(int fActivate) {
301 	return COM.E_NOTIMPL;
302 }
303 
OnFrameWindowActivate(int fActivate)304 int OnFrameWindowActivate(int fActivate) {
305 	return COM.E_NOTIMPL;
306 }
307 
308 @Override
Release()309 protected int Release() {
310 	/* Workaround for javac 1.1.8 bug */
311 	return super.Release();
312 }
313 
ResizeBorder(long prcBorder, long pUIWindow, int fFrameWindow)314 int ResizeBorder(long prcBorder, long pUIWindow, int fFrameWindow) {
315 	return COM.E_NOTIMPL;
316 }
317 
ShowContextMenu(int dwID, long ppt, long pcmdtReserved, long pdispReserved)318 int ShowContextMenu(int dwID, long ppt, long pcmdtReserved, long pdispReserved) {
319 	Browser browser = (Browser)getParent().getParent();
320 	Event event = new Event();
321 	POINT pt = new POINT();
322 	OS.MoveMemory(pt, ppt, POINT.sizeof);
323 	pt.x = DPIUtil.autoScaleDown(pt.x); // To Points
324 	pt.y = DPIUtil.autoScaleDown(pt.y); // To Points
325 	event.x = pt.x;
326 	event.y = pt.y;
327 	browser.notifyListeners(SWT.MenuDetect, event);
328 	if (!event.doit) return COM.S_OK;
329 	Menu menu = browser.getMenu();
330 	if (menu != null && !menu.isDisposed ()) {
331 		if (pt.x != event.x || pt.y != event.y) {
332 			menu.setLocation (event.x, event.y);
333 		}
334 		menu.setVisible (true);
335 		return COM.S_OK;
336 	}
337 	/* Show default IE popup menu */
338 	return COM.S_FALSE;
339 }
340 
ShowUI(int dwID, long pActiveObject, long pCommandTarget, long pFrame, long pDoc)341 int ShowUI(int dwID, long pActiveObject, long pCommandTarget, long pFrame, long pDoc) {
342 	return COM.S_FALSE;
343 }
344 
TranslateAccelerator(long lpMsg, long pguidCmdGroup, int nCmdID)345 int TranslateAccelerator(long lpMsg, long pguidCmdGroup, int nCmdID) {
346 	/*
347 	* Feature in Internet Explorer.  By default the embedded Internet Explorer control runs
348 	* the Internet Explorer shortcuts (e.g. Ctrl+F for Find).  This overrides the shortcuts
349 	* defined by SWT.  The workaround is to forward the accelerator keys to the parent window
350 	* and have Internet Explorer ignore the ones handled by the parent window.
351 	*/
352 	Menu menubar = getShell().getMenuBar();
353 	if (menubar != null && !menubar.isDisposed() && menubar.isEnabled()) {
354 		Shell shell = menubar.getShell();
355 		long hwnd = shell.handle;
356 		long hAccel = OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0);
357 		if (hAccel != 0) {
358 			MSG msg = new MSG();
359 			OS.MoveMemory(msg, lpMsg, MSG.sizeof);
360 			if (OS.TranslateAccelerator(hwnd, hAccel, msg) != 0) return COM.S_OK;
361 		}
362 	}
363 	/*
364 	* By default the IE shortcuts are run.  However, the shortcuts below should not run
365 	* in this context.  The workaround is to block IE from handling these shortcuts by
366 	* answering COM.S_OK.
367 	*
368 	* - F5 causes a refresh, which is not appropriate when rendering HTML from memory
369 	* - CTRL+L and CTRL+O show an Open Location dialog in IE8, which is undesirable and
370 	* can crash in some contexts
371 	* - CTRL+N opens a standalone IE, which is undesirable and can crash in some contexts
372 	*/
373 	int result = COM.S_FALSE;
374 	MSG msg = new MSG();
375 	OS.MoveMemory(msg, lpMsg, MSG.sizeof);
376 	if (msg.message == OS.WM_KEYDOWN) {
377 		switch ((int)msg.wParam) {
378 			case OS.VK_F5:
379 				OleAutomation auto = new OleAutomation(this);
380 				int[] rgdispid = auto.getIDsOfNames(new String[] { "LocationURL" }); //$NON-NLS-1$
381 				Variant pVarResult = auto.getProperty(rgdispid[0]);
382 				auto.dispose();
383 				if (pVarResult != null) {
384 					if (pVarResult.getType() == OLE.VT_BSTR) {
385 						String url = pVarResult.getString();
386 						if (url.equals(IE.ABOUT_BLANK)) result = COM.S_OK;
387 					}
388 					pVarResult.dispose();
389 				}
390 				break;
391 			case OS.VK_TAB:
392 				/*
393 				 * Do not interfere with tab traversal since it's not known
394 				 * if it will be within IE or out to another Control.
395 				 */
396 				break;
397 			case OS.VK_UP:
398 			case OS.VK_DOWN:
399 			case OS.VK_LEFT:
400 			case OS.VK_RIGHT:
401 			case OS.VK_HOME:
402 			case OS.VK_END:
403 			case OS.VK_PRIOR:
404 			case OS.VK_NEXT:
405 				/* Do not translate/consume IE's keys for scrolling content. */
406 				break;
407 			case OS.VK_SPACE:
408 			case OS.VK_BACK:
409 			case OS.VK_RETURN:
410 				/*
411 				 * Translating OS.VK_BACK, OS.VK_RETURN or OS.VK_SPACE results in the native
412 				 * control handling them twice (eg.- inserting two lines instead of one). So
413 				 * these keys are not translated here, and instead are explicitly handled
414 				 * in the keypress handler.
415 				 */
416 				break;
417 			case OS.VK_L:
418 			case OS.VK_N:
419 			case OS.VK_O:
420 				if (OS.GetKeyState (OS.VK_CONTROL) < 0 && OS.GetKeyState (OS.VK_MENU) >= 0 && OS.GetKeyState (OS.VK_SHIFT) >= 0) {
421 					if (msg.wParam == OS.VK_N || IE.IEVersion >= 8) {
422 						frame.setData(CONSUME_KEY, "false"); //$NON-NLS-1$
423 						result = COM.S_OK;
424 						break;
425 					}
426 				}
427 				// FALL THROUGH
428 			default:
429 				OS.TranslateMessage(msg);
430 				frame.setData(CONSUME_KEY, "true"); //$NON-NLS-1$
431 				break;
432 		}
433 	}
434 
435 	switch (msg.message) {
436 		case OS.WM_KEYDOWN:
437 		case OS.WM_KEYUP: {
438 			boolean isAccent = false;
439 			switch ((int)msg.wParam) {
440 				case OS.VK_SHIFT:
441 				case OS.VK_MENU:
442 				case OS.VK_CONTROL:
443 				case OS.VK_CAPITAL:
444 				case OS.VK_NUMLOCK:
445 				case OS.VK_SCROLL:
446 					break;
447 				default: {
448 					int mapKey = OS.MapVirtualKey ((int)msg.wParam, 2);
449 					if (mapKey != 0) {
450 						isAccent = (mapKey & 0x80000000) != 0;
451 						if (!isAccent) {
452 							for (short element : ACCENTS) {
453 								int value = OS.VkKeyScan (element);
454 								if (value != -1 && (value & 0xFF) == msg.wParam) {
455 									int state = value >> 8;
456 									if ((OS.GetKeyState (OS.VK_SHIFT) < 0) == ((state & 0x1) != 0) &&
457 										(OS.GetKeyState (OS.VK_CONTROL) < 0) == ((state & 0x2) != 0) &&
458 										(OS.GetKeyState (OS.VK_MENU) < 0) == ((state & 0x4) != 0)) {
459 											if ((state & 0x7) != 0) isAccent = true;
460 											break;
461 									}
462 								}
463 							}
464 						}
465 					}
466 					break;
467 				}
468 			}
469 			if (isAccent) result = COM.S_OK;
470 		}
471 	}
472 	return result;
473 }
474 
TranslateUrl(int dwTranslate, long pchURLIn, long ppchURLOut)475 int TranslateUrl(int dwTranslate, long pchURLIn, long ppchURLOut) {
476 	return COM.E_NOTIMPL;
477 }
478 
UpdateUI()479 int UpdateUI() {
480 	return COM.E_NOTIMPL;
481 }
482 
483 /* IDocHostShowUI */
484 
ShowMessage(long hwnd, long lpstrText, long lpstrCaption, int dwType, long lpstrHelpFile, int dwHelpContext, long plResult)485 int ShowMessage(long hwnd, long lpstrText, long lpstrCaption, int dwType, long lpstrHelpFile, int dwHelpContext, long plResult) {
486 	boolean ignore = ignoreNextMessage || ignoreAllMessages;
487 	ignoreNextMessage = false;
488 	return ignore ? COM.S_OK : COM.S_FALSE;
489 }
490 
ShowHelp(long hwnd, long pszHelpFile, int uCommand, int dwData, long pt, long pDispatchObjectHit)491 int ShowHelp(long hwnd, long pszHelpFile, int uCommand, int dwData, long pt, long pDispatchObjectHit) {
492 	Browser browser = (Browser)getParent().getParent();
493 	Event event = new Event();
494 	event.type = SWT.Help;
495 	event.display = getDisplay();
496 	event.widget = browser;
497 	Shell shell = browser.getShell();
498 	Control control = browser;
499 	do {
500 		if (control.isListening(SWT.Help)) {
501 			control.notifyListeners(SWT.Help, event);
502 			break;
503 		}
504 		if (control == shell) break;
505 		control = control.getParent();
506 	} while (true);
507 	return COM.S_OK;
508 }
509 
510 /* IServiceProvider */
511 
QueryService(long guidService, long riid, long ppvObject)512 int QueryService(long guidService, long riid, long ppvObject) {
513 	if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
514 	GUID guid = new GUID();
515 	COM.MoveMemory(guid, riid, GUID.sizeof);
516 	if (COM.IsEqualGUID(guid, COM.IIDIInternetSecurityManager)) {
517 		OS.MoveMemory(ppvObject, new long[] {iInternetSecurityManager.getAddress()}, C.PTR_SIZEOF);
518 		AddRef();
519 		return COM.S_OK;
520 	}
521 	if (COM.IsEqualGUID(guid, COM.IIDIAuthenticate)) {
522 		OS.MoveMemory(ppvObject, new long[] {iAuthenticate.getAddress()}, C.PTR_SIZEOF);
523 		AddRef();
524 		return COM.S_OK;
525 	}
526 	OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
527 	return COM.E_NOINTERFACE;
528 }
529 
530 /* IInternetSecurityManager */
531 
SetSecuritySite(long pSite)532 int SetSecuritySite(long pSite) {
533 	return IE.INET_E_DEFAULT_ACTION;
534 }
535 
GetSecuritySite(long ppSite)536 int GetSecuritySite(long ppSite) {
537 	return IE.INET_E_DEFAULT_ACTION;
538 }
539 
MapUrlToZone(long pwszUrl, long pdwZone, int dwFlags)540 int MapUrlToZone(long pwszUrl, long pdwZone, int dwFlags) {
541 	/*
542 	* Feature in IE.  HTML rendered in memory does not enable local links
543 	* but the same HTML document loaded through a local file is permitted
544 	* to follow local links.  The workaround is to return URLZONE_INTRANET
545 	* instead of the default value URLZONE_LOCAL_MACHINE.
546 	*/
547 	if (isForceTrusted) {
548 		OS.MoveMemory(pdwZone, new int[] {IE.URLZONE_INTRANET}, 4);
549 		return COM.S_OK;
550 	}
551 	return IE.INET_E_DEFAULT_ACTION;
552 }
553 
GetSecurityId(long pwszUrl, long pbSecurityId, long pcbSecurityId, long dwReserved)554 int GetSecurityId(long pwszUrl, long pbSecurityId, long pcbSecurityId, long dwReserved) {
555 	return IE.INET_E_DEFAULT_ACTION;
556 }
557 
ProcessUrlAction(long pwszUrl, int dwAction, long pPolicy, int cbPolicy, long pContext, int cbContext, int dwFlags, int dwReserved)558 int ProcessUrlAction(long pwszUrl, int dwAction, long pPolicy, int cbPolicy, long pContext, int cbContext, int dwFlags, int dwReserved) {
559 	ignoreNextMessage = false;
560 
561 	/*
562 	* If the current page is about:blank and is trusted then
563 	* override default zone elevation settings to allow the action.
564 	*/
565 	if (dwAction == IE.URLACTION_FEATURE_ZONE_ELEVATION) {
566 		IE ie = (IE)((Browser)getParent().getParent()).webBrowser;
567 		if (ie.auto != null && ie._getUrl().startsWith(IE.ABOUT_BLANK) && !ie.untrustedText) {
568 			if (cbPolicy >= 4) OS.MoveMemory(pPolicy, new int[] {IE.URLPOLICY_ALLOW}, 4);
569 			return COM.S_OK;
570 		}
571 	}
572 
573 	int policy = IE.INET_E_DEFAULT_ACTION;
574 
575 	if (dwAction >= IE.URLACTION_JAVA_MIN && dwAction <= IE.URLACTION_JAVA_MAX) {
576 		if (canExecuteApplets ()) {
577 			policy = IE.URLPOLICY_JAVA_LOW;
578 		} else {
579 			policy = IE.URLPOLICY_JAVA_PROHIBIT;
580 			ignoreNextMessage = true;
581 		}
582 	}
583 	if (dwAction == IE.URLACTION_ACTIVEX_RUN && pContext != 0) {
584 		GUID guid = new GUID();
585 		COM.MoveMemory(guid, pContext, GUID.sizeof);
586 		if (COM.IsEqualGUID(guid, COM.IIDJavaBeansBridge) && !canExecuteApplets ()) {
587 			policy = IE.URLPOLICY_DISALLOW;
588 			ignoreNextMessage = true;
589 		}
590 		if (COM.IsEqualGUID(guid, COM.IIDShockwaveActiveXControl)) {
591 			policy = IE.URLPOLICY_DISALLOW;
592 			ignoreNextMessage = true;
593 		}
594 	}
595 	if (dwAction == IE.URLACTION_SCRIPT_RUN) {
596 		IE browser = (IE)((Browser)getParent ().getParent ()).webBrowser;
597 		policy = browser.jsEnabled ? IE.URLPOLICY_ALLOW : IE.URLPOLICY_DISALLOW;
598 	}
599 
600 	if (policy == IE.INET_E_DEFAULT_ACTION) return IE.INET_E_DEFAULT_ACTION;
601 	if (cbPolicy >= 4) OS.MoveMemory(pPolicy, new int[] {policy}, 4);
602 	return policy == IE.URLPOLICY_ALLOW ? COM.S_OK : COM.S_FALSE;
603 }
604 
canExecuteApplets()605 boolean canExecuteApplets () {
606 	/*
607 	* Executing an applet in embedded IE will crash if IE's Java plug-in
608 	* launches its jre in IE's process, because this new jre conflicts
609 	* with the one running eclipse.  These cases need to be avoided by
610 	* vetoing the running of applets.
611 	*
612 	* However as of Sun jre 1.6u10, applets can be launched in a separate
613 	* process, which avoids the conflict with the jre running eclipse.
614 	* Therefore if this condition is detected, and if the required jar
615 	* libraries are available, then applets can be executed.
616 	*/
617 
618 	/*
619 	* executing applets with IE6 embedded can crash, so do not
620 	* attempt this if the version is less than IE7
621 	*/
622 	if (IE.IEVersion < 7) return false;
623 
624 	if (canExecuteApplets == null) {
625 		WebBrowser webBrowser = ((Browser)getParent ().getParent ()).webBrowser;
626 		String script = "try {var element = document.createElement('object');element.classid='clsid:CAFEEFAC-DEC7-0000-0000-ABCDEFFEDCBA';return element.object.isPlugin2();} catch (err) {};return false;"; //$NON-NLS-1$
627 		canExecuteApplets = ((Boolean)webBrowser.evaluate (script));
628 		if (canExecuteApplets.booleanValue ()) {
629 			try {
630 				Class.forName ("sun.plugin2.main.server.IExplorerPlugin"); /* plugin.jar */	//$NON-NLS-1$
631 				Class.forName ("com.sun.deploy.services.Service"); /* deploy.jar */	//$NON-NLS-1$
632 				Class.forName ("com.sun.javaws.Globals"); /* javaws.jar */	//$NON-NLS-1$
633 			} catch (ClassNotFoundException e) {
634 				/* one or more of the required jar libraries are not available */
635 				canExecuteApplets = Boolean.FALSE;
636 			}
637 		}
638 	}
639 	return canExecuteApplets.booleanValue ();
640 }
641 
QueryCustomPolicy(long pwszUrl, long guidKey, long ppPolicy, long pcbPolicy, long pContext, int cbContext, int dwReserved)642 int QueryCustomPolicy(long pwszUrl, long guidKey, long ppPolicy, long pcbPolicy, long pContext, int cbContext, int dwReserved) {
643 	return IE.INET_E_DEFAULT_ACTION;
644 }
645 
SetZoneMapping(int dwZone, long lpszPattern, int dwFlags)646 int SetZoneMapping(int dwZone, long lpszPattern, int dwFlags) {
647 	return IE.INET_E_DEFAULT_ACTION;
648 }
649 
GetZoneMappings(int dwZone, long ppenumString, int dwFlags)650 int GetZoneMappings(int dwZone, long ppenumString, int dwFlags) {
651 	return COM.E_NOTIMPL;
652 }
653 
654 /* IOleCommandTarget */
QueryStatus(long pguidCmdGroup, int cCmds, long prgCmds, long pCmdText)655 int QueryStatus(long pguidCmdGroup, int cCmds, long prgCmds, long pCmdText) {
656 	return COM.E_NOTSUPPORTED;
657 }
658 
Exec(long pguidCmdGroup, int nCmdID, int nCmdExecOpt, long pvaIn, long pvaOut)659 int Exec(long pguidCmdGroup, int nCmdID, int nCmdExecOpt, long pvaIn, long pvaOut) {
660 	if (pguidCmdGroup != 0) {
661 		GUID guid = new GUID();
662 		COM.MoveMemory(guid, pguidCmdGroup, GUID.sizeof);
663 
664 		/*
665 		* If a javascript error occurred then suppress IE's default script error dialog.
666 		*/
667 		if (COM.IsEqualGUID(guid, COM.CGID_DocHostCommandHandler)) {
668 			if (nCmdID == OLECMDID_SHOWSCRIPTERROR) return COM.S_OK;
669 		}
670 
671 		/*
672 		* Bug in Internet Explorer.  OnToolBar TRUE is also fired when any of the
673 		* address bar or menu bar are requested but not the tool bar.  A workaround
674 		* has been posted by a Microsoft developer on the public webbrowser_ctl
675 		* newsgroup. The workaround is to implement the IOleCommandTarget interface
676 		* to test the argument of an undocumented command.
677 		*/
678 		if (nCmdID == 1 && COM.IsEqualGUID(guid, COM.CGID_Explorer) && ((nCmdExecOpt & 0xFFFF) == 0xA)) {
679 			IE browser = (IE)((Browser)getParent().getParent()).webBrowser;
680 			browser.toolBar = (nCmdExecOpt & 0xFFFF0000) != 0;
681 		}
682 	}
683 	return COM.E_NOTSUPPORTED;
684 }
685 
686 /* IAuthenticate */
687 
Authenticate(long hwnd, long szUsername, long szPassword)688 int Authenticate (long hwnd, long szUsername, long szPassword) {
689 	IE browser = (IE)((Browser)getParent ().getParent ()).webBrowser;
690 	for (AuthenticationListener authenticationListener : browser.authenticationListeners) {
691 		AuthenticationEvent event = new AuthenticationEvent (browser.browser);
692 		event.location = browser.lastNavigateURL;
693 		authenticationListener.authenticate (event);
694 		if (!event.doit) return COM.E_ACCESSDENIED;
695 		if (event.user != null && event.password != null) {
696 			TCHAR user = new TCHAR (0, event.user, true);
697 			int size = user.length () * TCHAR.sizeof;
698 			long userPtr = OS.CoTaskMemAlloc (size);
699 			OS.MoveMemory (userPtr, user, size);
700 			TCHAR password = new TCHAR (0, event.password, true);
701 			size = password.length () * TCHAR.sizeof;
702 			long passwordPtr = OS.CoTaskMemAlloc (size);
703 			OS.MoveMemory (passwordPtr, password, size);
704 			C.memmove (hwnd, new long[] {0}, C.PTR_SIZEOF);
705 			C.memmove (szUsername, new long[] {userPtr}, C.PTR_SIZEOF);
706 			C.memmove (szPassword, new long[] {passwordPtr}, C.PTR_SIZEOF);
707 			return COM.S_OK;
708 		}
709 	}
710 
711 	/* no listener handled the challenge, so defer to the native dialog */
712 	C.memmove (hwnd, new long[] {getShell().handle}, C.PTR_SIZEOF);
713 	return COM.S_OK;
714 }
715 
716 /* IDispatch */
717 
GetTypeInfoCount(long pctinfo)718 int GetTypeInfoCount (long pctinfo) {
719 	C.memmove (pctinfo, new int[] {0}, 4);
720 	return COM.S_OK;
721 }
722 
GetTypeInfo(int iTInfo, int lcid, long ppTInfo)723 int GetTypeInfo (int iTInfo, int lcid, long ppTInfo) {
724 	return COM.S_OK;
725 }
726 
GetIDsOfNames(int riid, long rgszNames, int cNames, int lcid, long rgDispId)727 int GetIDsOfNames (int riid, long rgszNames, int cNames, int lcid, long rgDispId) {
728 	long[] ptr = new long[1];
729 	OS.MoveMemory (ptr, rgszNames, C.PTR_SIZEOF);
730 	int length = OS.wcslen (ptr[0]);
731 	char[] buffer = new char[length];
732 	OS.MoveMemory (buffer, ptr[0], length * 2);
733 	String functionName = String.valueOf (buffer);
734 	int result = COM.S_OK;
735 	int[] ids = new int[cNames];	/* DISPIDs */
736 	if (functionName.equals ("callJava")) { //$NON-NLS-1$
737 		for (int i = 0; i < cNames; i++) {
738 			ids[i] = i + 1;
739 		}
740 	} else {
741 		result = COM.DISP_E_UNKNOWNNAME;
742 		for (int i = 0; i < cNames; i++) {
743 			ids[i] = COM.DISPID_UNKNOWN;
744 		}
745 	}
746 	OS.MoveMemory (rgDispId, ids, cNames * 4);
747 	return result;
748 }
749 
Invoke(int dispIdMember, long riid, int lcid, int dwFlags, long pDispParams, long pVarResult, long pExcepInfo, long pArgErr)750 int Invoke (int dispIdMember, long riid, int lcid, int dwFlags, long pDispParams, long pVarResult, long pExcepInfo, long pArgErr) {
751 	IE ie = (IE)((Browser)getParent ().getParent ()).webBrowser;
752 	Map<Integer, BrowserFunction> functions = ie.functions;
753 	if (functions == null) {
754 		if (pVarResult != 0) {
755 			OS.MoveMemory (pVarResult, new long[] {0}, C.PTR_SIZEOF);
756 		}
757 		return COM.S_OK;
758 	}
759 
760 	DISPPARAMS dispParams = new DISPPARAMS ();
761 	COM.MoveMemory (dispParams, pDispParams, DISPPARAMS.sizeof);
762 	if (dispParams.cArgs != 3) {
763 		if (pVarResult != 0) {
764 			OS.MoveMemory (pVarResult, new long[] {0}, C.PTR_SIZEOF);
765 		}
766 		return COM.S_OK;
767 	}
768 
769 	long ptr = dispParams.rgvarg + 2 * Variant.sizeof;
770 	Variant variant = Variant.win32_new (ptr);
771 	if (variant.getType () != COM.VT_I4) {
772 		variant.dispose ();
773 		if (pVarResult != 0) {
774 			OS.MoveMemory (pVarResult, new long[] {0}, C.PTR_SIZEOF);
775 		}
776 		return COM.S_OK;
777 	}
778 	int index = variant.getInt ();
779 	variant.dispose ();
780 	if (index <= 0) {
781 		if (pVarResult != 0) {
782 			OS.MoveMemory (pVarResult, new long[] {0}, C.PTR_SIZEOF);
783 		}
784 		return COM.S_OK;
785 	}
786 
787 	ptr = dispParams.rgvarg + Variant.sizeof;
788 	variant = Variant.win32_new (ptr);
789 	int type = variant.getType ();
790 	if (type != COM.VT_BSTR) {
791 		variant.dispose ();
792 		if (pVarResult != 0) {
793 			OS.MoveMemory (pVarResult, new long[] {0}, C.PTR_SIZEOF);
794 		}
795 		return COM.S_OK;
796 	}
797 	String token = variant.getString ();
798 	variant.dispose ();
799 
800 	variant = Variant.win32_new (dispParams.rgvarg);
801 	BrowserFunction function = functions.get (index);
802 	Object returnValue = null;
803 	if (function != null && token.equals (function.token)) {
804 		try {
805 			Object temp = convertToJava (variant);
806 			if (temp instanceof Object[]) {
807 				Object[] args = (Object[])temp;
808 				try {
809 					returnValue = function.function (args);
810 				} catch (Exception e) {
811 					/* exception during function invocation */
812 					returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ());
813 				}
814 			}
815 		} catch (IllegalArgumentException e) {
816 			/* invalid argument value type */
817 			if (function.isEvaluate) {
818 				/* notify the function so that a java exception can be thrown */
819 				function.function (new String[] {WebBrowser.CreateErrorString (new SWTException (SWT.ERROR_INVALID_RETURN_VALUE).getLocalizedMessage ())});
820 			}
821 			returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ());
822 		}
823 	}
824 	variant.dispose ();
825 
826 	if (pVarResult != 0) {
827 		try {
828 			variant = convertToJS (returnValue);
829 		} catch (SWTException e) {
830 			/* invalid return value type */
831 			variant = convertToJS (WebBrowser.CreateErrorString (e.getLocalizedMessage ()));
832 		}
833 		Variant.win32_copy (pVarResult, variant);
834 		variant.dispose ();
835 	}
836 	return COM.S_OK;
837 }
838 
convertToJava(Variant variant)839 Object convertToJava (Variant variant) {
840 	switch (variant.getType ()) {
841 		case OLE.VT_EMPTY:
842 		case OLE.VT_NULL: return null;
843 		case OLE.VT_BSTR: return variant.getString ();
844 		case OLE.VT_BOOL: return variant.getBoolean ();
845 		case OLE.VT_I2:
846 		case OLE.VT_I4:
847 		case OLE.VT_I8:
848 		case OLE.VT_R4:
849 		case OLE.VT_R8:
850 			return variant.getDouble ();
851 		case OLE.VT_DISPATCH: {
852 			Object[] args = null;
853 			OleAutomation auto = variant.getAutomation ();
854 			TYPEATTR typeattr = auto.getTypeInfoAttributes ();
855 			if (typeattr != null) {
856 				GUID guid = new GUID ();
857 				guid.Data1 = typeattr.guid_Data1;
858 				guid.Data2 = typeattr.guid_Data2;
859 				guid.Data3 = typeattr.guid_Data3;
860 				guid.Data4 = typeattr.guid_Data4;
861 				if (COM.IsEqualGUID (guid, COM.IIDIJScriptTypeInfo)) {
862 					int[] rgdispid = auto.getIDsOfNames (new String[] {"length"}); //$NON-NLS-1$
863 					if (rgdispid != null) {
864 						Variant varLength = auto.getProperty (rgdispid[0]);
865 						int length = varLength.getInt ();
866 						varLength.dispose ();
867 						args = new Object[length];
868 						for (int i = 0; i < length; i++) {
869 							rgdispid = auto.getIDsOfNames (new String[] {String.valueOf (i)});
870 							if (rgdispid != null) {
871 								Variant current = auto.getProperty (rgdispid[0]);
872 								try {
873 									args[i] = convertToJava (current);
874 									current.dispose ();
875 								} catch (IllegalArgumentException e) {
876 									/* invalid argument value type */
877 									current.dispose ();
878 									auto.dispose ();
879 									throw e;
880 								}
881 							}
882 						}
883 					}
884 				} else {
885 					auto.dispose ();
886 					SWT.error (SWT.ERROR_INVALID_ARGUMENT);
887 				}
888 			}
889 			auto.dispose ();
890 			return args;
891 		}
892 	}
893 	SWT.error (SWT.ERROR_INVALID_ARGUMENT);
894 	return null;
895 }
896 
convertToJS(Object value)897 Variant convertToJS (Object value) {
898 	if (value == null) {
899 		return Variant.NULL;
900 	}
901 	if (value instanceof String) {
902 		return new Variant ((String)value);
903 	}
904 	if (value instanceof Boolean) {
905 		return new Variant (((Boolean)value).booleanValue ());
906 	}
907 	if (value instanceof Number) {
908 		return new Variant (((Number)value).doubleValue ());
909 	}
910 	if (value instanceof Object[]) {
911 		/* get IHTMLDocument2 */
912 		IE browser = (IE)((Browser)getParent ().getParent ()).webBrowser;
913 		OleAutomation auto = browser.auto;
914 		int[] rgdispid = auto.getIDsOfNames (new String[] {"Document"}); //$NON-NLS-1$
915 		if (rgdispid == null) return new Variant ();
916 		Variant pVarResult = auto.getProperty (rgdispid[0]);
917 		if (pVarResult == null) return new Variant ();
918 		if (pVarResult.getType () == COM.VT_EMPTY) {
919 			pVarResult.dispose ();
920 			return new Variant ();
921 		}
922 		OleAutomation document = pVarResult.getAutomation ();
923 		pVarResult.dispose ();
924 
925 		/* get IHTMLWindow2 */
926 		rgdispid = document.getIDsOfNames (new String[] {"parentWindow"}); //$NON-NLS-1$
927 		if (rgdispid == null) {
928 			document.dispose ();
929 			return new Variant ();
930 		}
931 		pVarResult = document.getProperty (rgdispid[0]);
932 		if (pVarResult == null || pVarResult.getType () == COM.VT_EMPTY) {
933 			if (pVarResult != null) pVarResult.dispose ();
934 			document.dispose ();
935 			return new Variant ();
936 		}
937 		OleAutomation ihtmlWindow2 = pVarResult.getAutomation ();
938 		pVarResult.dispose ();
939 		document.dispose ();
940 
941 		/* create a new JS array to be returned */
942 		rgdispid = ihtmlWindow2.getIDsOfNames (new String[] {"Array"}); //$NON-NLS-1$
943 		if (rgdispid == null) {
944 			ihtmlWindow2.dispose ();
945 			return new Variant ();
946 		}
947 		Variant arrayType = ihtmlWindow2.getProperty (rgdispid[0]);
948 		ihtmlWindow2.dispose ();
949 		IDispatch arrayTypeDispatch = arrayType.getDispatch ();
950 		long[] result = new long[1];
951 		int rc = arrayTypeDispatch.QueryInterface (COM.IIDIDispatchEx, result);
952 		arrayType.dispose ();
953 		if (rc != COM.S_OK) return new Variant ();
954 
955 		IDispatchEx arrayTypeDispatchEx = new IDispatchEx (result[0]);
956 		result[0] = 0;
957 		long resultPtr = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
958 		DISPPARAMS params = new DISPPARAMS ();
959 		rc = arrayTypeDispatchEx.InvokeEx (COM.DISPID_VALUE, COM.LOCALE_USER_DEFAULT, COM.DISPATCH_CONSTRUCT, params, resultPtr, null, 0);
960 		if (rc != COM.S_OK) {
961 			OS.GlobalFree (resultPtr);
962 			return new Variant ();
963 		}
964 		Variant array = Variant.win32_new (resultPtr);
965 		OS.GlobalFree (resultPtr);
966 
967 		/* populate the array */
968 		Object[] arrayValue = (Object[])value;
969 		int length = arrayValue.length;
970 		auto = array.getAutomation ();
971 		int[] rgdispids = auto.getIDsOfNames (new String[] {"push"}); //$NON-NLS-1$
972 		if (rgdispids != null) {
973 			for (int i = 0; i < length; i++) {
974 				Object currentObject = arrayValue[i];
975 				try {
976 					Variant variant = convertToJS (currentObject);
977 					auto.invoke (rgdispids[0], new Variant[] {variant});
978 					variant.dispose ();
979 				} catch (SWTException e) {
980 					/* invalid return value type */
981 					auto.dispose ();
982 					array.dispose ();
983 					throw e;
984 				}
985 			}
986 		}
987 		auto.dispose ();
988 		return array;
989 	}
990 	SWT.error (SWT.ERROR_INVALID_RETURN_VALUE);
991 	return null;
992 }
993 
994 }
995