1 // This Source Code Form is subject to the terms of the Mozilla Public
2 // License, v. 2.0.If a copy of the MPL was not distributed with this
3 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5 #include "WebBrowser.h"
6 #include <mshtmdid.h>
7
WebBrowser(HWND _hWndParent)8 WebBrowser::WebBrowser(HWND _hWndParent) : mHwndParent(_hWndParent) {
9 // Whatever executed this constructor owns our first reference.
10 AddRef();
11
12 HRESULT hr = ::OleCreate(CLSID_WebBrowser, IID_IOleObject, OLERENDER_DRAW, 0,
13 this, this, (void**)&mOleObject);
14 if (FAILED(hr)) {
15 return;
16 }
17
18 RECT posRect;
19 ::GetClientRect(mHwndParent, &posRect);
20
21 hr = mOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, nullptr, this, 0,
22 mHwndParent, &posRect);
23 if (FAILED(hr)) {
24 mOleObject->Release();
25 mOleObject = nullptr;
26 return;
27 }
28
29 SetRect(posRect);
30
31 hr = mOleObject->QueryInterface(&mWebBrowser2);
32 if (FAILED(hr)) {
33 mOleObject->Release();
34 mOleObject = nullptr;
35 return;
36 }
37
38 mWebBrowser2->put_Silent(VARIANT_TRUE);
39 }
40
~WebBrowser()41 WebBrowser::~WebBrowser() {
42 if (mWebBrowser2) {
43 mWebBrowser2->Release();
44 mWebBrowser2 = nullptr;
45 }
46 if (mOleInPlaceActiveObject) {
47 mOleInPlaceActiveObject->Release();
48 mOleInPlaceActiveObject = nullptr;
49 }
50 if (mOleInPlaceObject) {
51 mOleInPlaceObject->Release();
52 mOleInPlaceObject = nullptr;
53 }
54 if (mOleObject) {
55 mOleObject->Release();
56 mOleObject = nullptr;
57 }
58 }
59
Shutdown()60 void WebBrowser::Shutdown() {
61 if (mOleObject) {
62 mOleObject->Close(OLECLOSE_NOSAVE);
63 mOleObject->SetClientSite(nullptr);
64 }
65 }
66
IsInitialized()67 bool WebBrowser::IsInitialized() { return mOleObject != nullptr; }
68
ActiveObjectTranslateAccelerator(bool tab,LPMSG lpmsg)69 HRESULT WebBrowser::ActiveObjectTranslateAccelerator(bool tab, LPMSG lpmsg) {
70 if (IsInitialized() && mOleInPlaceActiveObject) {
71 HRESULT hr = mOleInPlaceActiveObject->TranslateAcceleratorW(lpmsg);
72 if (hr == S_FALSE && tab) {
73 // The browser control will give up focus, but it is the only control so
74 // it would get focus again via IsDialogMessage. This does not result in
75 // the focus returning to the web page, though, so instead let the
76 // control process the tab again.
77 hr = mOleInPlaceActiveObject->TranslateAcceleratorW(lpmsg);
78 }
79 return hr;
80 } else {
81 return S_FALSE;
82 }
83 }
84
SetRect(const RECT & _rc)85 void WebBrowser::SetRect(const RECT& _rc) {
86 mRect = _rc;
87
88 if (mOleInPlaceObject) {
89 mOleInPlaceObject->SetObjectRects(&mRect, &mRect);
90 }
91 }
92
Resize(DWORD width,DWORD height)93 void WebBrowser::Resize(DWORD width, DWORD height) {
94 RECT r = mRect;
95 r.bottom = r.top + height;
96 r.right = r.left + width;
97 SetRect(r);
98 }
99
Navigate(wchar_t * url)100 void WebBrowser::Navigate(wchar_t* url) {
101 if (!IsInitialized()) {
102 return;
103 }
104
105 VARIANT flags;
106 VariantInit(&flags);
107 flags.vt = VT_I4;
108 flags.intVal = navNoHistory | navEnforceRestricted | navUntrustedForDownload |
109 navBlockRedirectsXDomain;
110
111 mWebBrowser2->Navigate(url, &flags, nullptr, nullptr, nullptr);
112 }
113
AddCustomFunction(wchar_t * name,CustomFunction function,void * arg)114 void WebBrowser::AddCustomFunction(wchar_t* name, CustomFunction function,
115 void* arg) {
116 CustomFunctionRecord record = {name, function, arg};
117
118 // We've disabled exceptions but push_back can throw on an allocation
119 // failure, so we need to suppress a warning trying to tell us that
120 // that combination doesn't make any sense.
121 #pragma warning(suppress : 4530)
122 mCustomFunctions.push_back(record);
123 }
124
125 //////////////////////////////////////////////////////////////////////////////
126 // IUnknown
127 //////////////////////////////////////////////////////////////////////////////
128 // This is a standard IUnknown implementation, we don't need anything special.
129
QueryInterface(REFIID riid,void ** ppvObject)130 HRESULT STDMETHODCALLTYPE WebBrowser::QueryInterface(REFIID riid,
131 void** ppvObject) {
132 if (riid == __uuidof(IUnknown)) {
133 *ppvObject = static_cast<IOleClientSite*>(this);
134 } else if (riid == __uuidof(IOleClientSite)) {
135 *ppvObject = static_cast<IOleClientSite*>(this);
136 } else if (riid == __uuidof(IOleInPlaceSite)) {
137 *ppvObject = static_cast<IOleInPlaceSite*>(this);
138 } else if (riid == __uuidof(IDropTarget)) {
139 *ppvObject = static_cast<IDropTarget*>(this);
140 } else if (riid == __uuidof(IStorage)) {
141 *ppvObject = static_cast<IStorage*>(this);
142 } else if (riid == __uuidof(IDocHostUIHandler)) {
143 *ppvObject = static_cast<IDocHostUIHandler*>(this);
144 } else if (riid == __uuidof(IDocHostShowUI)) {
145 *ppvObject = static_cast<IDocHostShowUI*>(this);
146 } else if (riid == __uuidof(IDispatch)) {
147 *ppvObject = static_cast<IDispatch*>(this);
148 } else {
149 *ppvObject = nullptr;
150 return E_NOINTERFACE;
151 }
152
153 AddRef();
154 return S_OK;
155 }
156
AddRef()157 ULONG STDMETHODCALLTYPE WebBrowser::AddRef() {
158 return InterlockedIncrement(&mComRefCount);
159 }
160
Release()161 ULONG STDMETHODCALLTYPE WebBrowser::Release() {
162 ULONG refCount = InterlockedDecrement(&mComRefCount);
163 if (refCount == 0) {
164 delete this;
165 }
166 return refCount;
167 }
168
169 //////////////////////////////////////////////////////////////////////////////
170 // IOleWindow
171 //////////////////////////////////////////////////////////////////////////////
172
173 HRESULT STDMETHODCALLTYPE
GetWindow(__RPC__deref_out_opt HWND * phwnd)174 WebBrowser::GetWindow(__RPC__deref_out_opt HWND* phwnd) {
175 *phwnd = mHwndParent;
176 return S_OK;
177 }
178
ContextSensitiveHelp(BOOL fEnterMode)179 HRESULT STDMETHODCALLTYPE WebBrowser::ContextSensitiveHelp(BOOL fEnterMode) {
180 // We don't provide context-sensitive help.
181 return E_NOTIMPL;
182 }
183
184 //////////////////////////////////////////////////////////////////////////////
185 // IOleInPlaceSite
186 //////////////////////////////////////////////////////////////////////////////
187
CanInPlaceActivate()188 HRESULT STDMETHODCALLTYPE WebBrowser::CanInPlaceActivate() {
189 // We always support in-place activation.
190 return S_OK;
191 }
192
OnInPlaceActivate()193 HRESULT STDMETHODCALLTYPE WebBrowser::OnInPlaceActivate() {
194 OleLockRunning(mOleObject, TRUE, FALSE);
195 mOleObject->QueryInterface(&mOleInPlaceObject);
196 mOleInPlaceObject->QueryInterface(&mOleInPlaceActiveObject);
197 mOleInPlaceObject->SetObjectRects(&mRect, &mRect);
198
199 return S_OK;
200 }
201
OnUIActivate()202 HRESULT STDMETHODCALLTYPE WebBrowser::OnUIActivate() {
203 // Nothing to do before activating the control's UI.
204 return S_OK;
205 }
206
GetWindowContext(__RPC__deref_out_opt IOleInPlaceFrame ** ppFrame,__RPC__deref_out_opt IOleInPlaceUIWindow ** ppDoc,__RPC__out LPRECT lprcPosRect,__RPC__out LPRECT lprcClipRect,__RPC__inout LPOLEINPLACEFRAMEINFO lpFrameInfo)207 HRESULT STDMETHODCALLTYPE WebBrowser::GetWindowContext(
208 __RPC__deref_out_opt IOleInPlaceFrame** ppFrame,
209 __RPC__deref_out_opt IOleInPlaceUIWindow** ppDoc,
210 __RPC__out LPRECT lprcPosRect, __RPC__out LPRECT lprcClipRect,
211 __RPC__inout LPOLEINPLACEFRAMEINFO lpFrameInfo) {
212 *ppFrame = nullptr;
213 *ppDoc = nullptr;
214 *lprcPosRect = mRect;
215 *lprcClipRect = mRect;
216
217 lpFrameInfo->fMDIApp = false;
218 lpFrameInfo->hwndFrame = mHwndParent;
219 lpFrameInfo->haccel = nullptr;
220 lpFrameInfo->cAccelEntries = 0;
221
222 return S_OK;
223 }
224
Scroll(SIZE scrollExtant)225 HRESULT STDMETHODCALLTYPE WebBrowser::Scroll(SIZE scrollExtant) {
226 // We should have disabled all scrollbars.
227 return E_NOTIMPL;
228 }
229
OnUIDeactivate(BOOL fUndoable)230 HRESULT STDMETHODCALLTYPE WebBrowser::OnUIDeactivate(BOOL fUndoable) {
231 // Nothing to do after deactivating the control's UI.
232 return S_OK;
233 }
234
OnInPlaceDeactivate()235 HRESULT STDMETHODCALLTYPE WebBrowser::OnInPlaceDeactivate() {
236 if (mOleInPlaceObject) {
237 mOleInPlaceObject->Release();
238 mOleInPlaceObject = nullptr;
239 }
240
241 return S_OK;
242 }
243
244 // We don't support the concept of undo.
DiscardUndoState()245 HRESULT STDMETHODCALLTYPE WebBrowser::DiscardUndoState() { return E_NOTIMPL; }
246
DeactivateAndUndo()247 HRESULT STDMETHODCALLTYPE WebBrowser::DeactivateAndUndo() { return E_NOTIMPL; }
248
249 // We don't support moving or resizing the control.
250 HRESULT STDMETHODCALLTYPE
OnPosRectChange(__RPC__in LPCRECT lprcPosRect)251 WebBrowser::OnPosRectChange(__RPC__in LPCRECT lprcPosRect) {
252 return E_NOTIMPL;
253 }
254
255 //////////////////////////////////////////////////////////////////////////////
256 // IOleClientSite
257 //////////////////////////////////////////////////////////////////////////////
258 // We don't need anything that IOleClientSite does, because we're doing OLE
259 // only in the most basic sense and we don't support linking (or, indeed,
260 // embedding), but some implementation of this interface is required for
261 // OleCreate to work, so we have to have a stub version.
262
SaveObject()263 HRESULT STDMETHODCALLTYPE WebBrowser::SaveObject() { return E_NOTIMPL; }
264
265 HRESULT STDMETHODCALLTYPE
GetMoniker(DWORD dwAssign,DWORD dwWhichMoniker,__RPC__deref_out_opt IMoniker ** ppmk)266 WebBrowser::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker,
267 __RPC__deref_out_opt IMoniker** ppmk) {
268 return E_NOTIMPL;
269 }
270
271 HRESULT STDMETHODCALLTYPE
GetContainer(__RPC__deref_out_opt IOleContainer ** ppContainer)272 WebBrowser::GetContainer(__RPC__deref_out_opt IOleContainer** ppContainer) {
273 *ppContainer = nullptr;
274 return E_NOINTERFACE;
275 }
276
ShowObject()277 HRESULT STDMETHODCALLTYPE WebBrowser::ShowObject() { return S_OK; }
278
OnShowWindow(BOOL fShow)279 HRESULT STDMETHODCALLTYPE WebBrowser::OnShowWindow(BOOL fShow) { return S_OK; }
280
RequestNewObjectLayout()281 HRESULT STDMETHODCALLTYPE WebBrowser::RequestNewObjectLayout() {
282 return E_NOTIMPL;
283 }
284
285 //////////////////////////////////////////////////////////////////////////////
286 // IDropTarget
287 //////////////////////////////////////////////////////////////////////////////
288 // This is a stub implementation which blocks all dropping. The main reason we
289 // want to do that is prevent accidentally dropping something on the control
290 // and having it navigate, because there's no recovering from that except to
291 // restart the app, and also it would look ridiculous. There could also be
292 // security implications though, which we'd rather just avoid engaging with
293 // altogether if we can.
294
295 HRESULT STDMETHODCALLTYPE
DragEnter(__RPC__in_opt IDataObject * pDataObj,DWORD grfKeyState,POINTL pt,__RPC__inout DWORD * pdwEffect)296 WebBrowser::DragEnter(__RPC__in_opt IDataObject* pDataObj, DWORD grfKeyState,
297 POINTL pt, __RPC__inout DWORD* pdwEffect) {
298 *pdwEffect = DROPEFFECT_NONE;
299 return S_OK;
300 }
301
DragOver(DWORD grfKeyState,POINTL pt,__RPC__inout DWORD * pdwEffect)302 HRESULT STDMETHODCALLTYPE WebBrowser::DragOver(DWORD grfKeyState, POINTL pt,
303 __RPC__inout DWORD* pdwEffect) {
304 *pdwEffect = DROPEFFECT_NONE;
305 return S_OK;
306 }
307
DragLeave()308 HRESULT STDMETHODCALLTYPE WebBrowser::DragLeave() { return S_OK; }
309
Drop(__RPC__in_opt IDataObject * pDataObj,DWORD grfKeyState,POINTL pt,__RPC__inout DWORD * pdwEffect)310 HRESULT STDMETHODCALLTYPE WebBrowser::Drop(__RPC__in_opt IDataObject* pDataObj,
311 DWORD grfKeyState, POINTL pt,
312 __RPC__inout DWORD* pdwEffect) {
313 *pdwEffect = DROPEFFECT_NONE;
314 return S_OK;
315 }
316
317 //////////////////////////////////////////////////////////////////////////////
318 // IStorage
319 //////////////////////////////////////////////////////////////////////////////
320 // We don't need anything that IStorage does, but we have to pass some
321 // implementation of it to OleCreate, so we need to have a stub version.
322
CreateStream(__RPC__in_string const OLECHAR * pwcsName,DWORD grfMode,DWORD reserved1,DWORD reserved2,__RPC__deref_out_opt IStream ** ppstm)323 HRESULT STDMETHODCALLTYPE WebBrowser::CreateStream(
324 __RPC__in_string const OLECHAR* pwcsName, DWORD grfMode, DWORD reserved1,
325 DWORD reserved2, __RPC__deref_out_opt IStream** ppstm) {
326 *ppstm = nullptr;
327 return E_NOTIMPL;
328 }
329
OpenStream(const OLECHAR * pwcsName,void * reserved1,DWORD grfMode,DWORD reserved2,IStream ** ppstm)330 HRESULT STDMETHODCALLTYPE WebBrowser::OpenStream(const OLECHAR* pwcsName,
331 void* reserved1, DWORD grfMode,
332 DWORD reserved2,
333 IStream** ppstm) {
334 *ppstm = nullptr;
335 return E_NOTIMPL;
336 }
337
CreateStorage(__RPC__in_string const OLECHAR * pwcsName,DWORD grfMode,DWORD reserved1,DWORD reserved2,__RPC__deref_out_opt IStorage ** ppstg)338 HRESULT STDMETHODCALLTYPE WebBrowser::CreateStorage(
339 __RPC__in_string const OLECHAR* pwcsName, DWORD grfMode, DWORD reserved1,
340 DWORD reserved2, __RPC__deref_out_opt IStorage** ppstg) {
341 *ppstg = nullptr;
342 return E_NOTIMPL;
343 }
344
345 HRESULT STDMETHODCALLTYPE
OpenStorage(__RPC__in_opt_string const OLECHAR * pwcsName,__RPC__in_opt IStorage * pstgPriority,DWORD grfMode,__RPC__deref_opt_in_opt SNB snbExclude,DWORD reserved,__RPC__deref_out_opt IStorage ** ppstg)346 WebBrowser::OpenStorage(__RPC__in_opt_string const OLECHAR* pwcsName,
347 __RPC__in_opt IStorage* pstgPriority, DWORD grfMode,
348 __RPC__deref_opt_in_opt SNB snbExclude, DWORD reserved,
349 __RPC__deref_out_opt IStorage** ppstg) {
350 return E_NOTIMPL;
351 }
352
CopyTo(DWORD ciidExclude,const IID * rgiidExclude,__RPC__in_opt SNB snbExclude,IStorage * pstgDest)353 HRESULT STDMETHODCALLTYPE WebBrowser::CopyTo(DWORD ciidExclude,
354 const IID* rgiidExclude,
355 __RPC__in_opt SNB snbExclude,
356 IStorage* pstgDest) {
357 return E_NOTIMPL;
358 }
359
MoveElementTo(__RPC__in_string const OLECHAR * pwcsName,__RPC__in_opt IStorage * pstgDest,__RPC__in_string const OLECHAR * pwcsNewName,DWORD grfFlags)360 HRESULT STDMETHODCALLTYPE WebBrowser::MoveElementTo(
361 __RPC__in_string const OLECHAR* pwcsName, __RPC__in_opt IStorage* pstgDest,
362 __RPC__in_string const OLECHAR* pwcsNewName, DWORD grfFlags) {
363 return E_NOTIMPL;
364 }
365
Commit(DWORD grfCommitFlags)366 HRESULT STDMETHODCALLTYPE WebBrowser::Commit(DWORD grfCommitFlags) {
367 return E_NOTIMPL;
368 }
369
Revert()370 HRESULT STDMETHODCALLTYPE WebBrowser::Revert() { return E_NOTIMPL; }
371
EnumElements(DWORD reserved1,void * reserved2,DWORD reserved3,IEnumSTATSTG ** ppenum)372 HRESULT STDMETHODCALLTYPE WebBrowser::EnumElements(DWORD reserved1,
373 void* reserved2,
374 DWORD reserved3,
375 IEnumSTATSTG** ppenum) {
376 return E_NOTIMPL;
377 }
378
379 HRESULT STDMETHODCALLTYPE
DestroyElement(__RPC__in_string const OLECHAR * pwcsName)380 WebBrowser::DestroyElement(__RPC__in_string const OLECHAR* pwcsName) {
381 return E_NOTIMPL;
382 }
383
384 HRESULT STDMETHODCALLTYPE
RenameElement(__RPC__in_string const OLECHAR * pwcsOldName,__RPC__in_string const OLECHAR * pwcsNewName)385 WebBrowser::RenameElement(__RPC__in_string const OLECHAR* pwcsOldName,
386 __RPC__in_string const OLECHAR* pwcsNewName) {
387 return E_NOTIMPL;
388 }
389
SetElementTimes(__RPC__in_opt_string const OLECHAR * pwcsName,__RPC__in_opt const FILETIME * pctime,__RPC__in_opt const FILETIME * patime,__RPC__in_opt const FILETIME * pmtime)390 HRESULT STDMETHODCALLTYPE WebBrowser::SetElementTimes(
391 __RPC__in_opt_string const OLECHAR* pwcsName,
392 __RPC__in_opt const FILETIME* pctime, __RPC__in_opt const FILETIME* patime,
393 __RPC__in_opt const FILETIME* pmtime) {
394 return E_NOTIMPL;
395 }
396
SetClass(__RPC__in REFCLSID clsid)397 HRESULT STDMETHODCALLTYPE WebBrowser::SetClass(__RPC__in REFCLSID clsid) {
398 return S_OK;
399 }
400
SetStateBits(DWORD grfStateBits,DWORD grfMask)401 HRESULT STDMETHODCALLTYPE WebBrowser::SetStateBits(DWORD grfStateBits,
402 DWORD grfMask) {
403 return E_NOTIMPL;
404 }
405
Stat(__RPC__out STATSTG * pstatstg,DWORD grfStatFlag)406 HRESULT STDMETHODCALLTYPE WebBrowser::Stat(__RPC__out STATSTG* pstatstg,
407 DWORD grfStatFlag) {
408 return E_NOTIMPL;
409 }
410
411 //////////////////////////////////////////////////////////////////////////////
412 // IDocHostUIHandler
413 //////////////////////////////////////////////////////////////////////////////
414 // Our implementation for this interface is basically all about disabling
415 // things that we don't want/need.
416
ShowContextMenu(DWORD dwID,POINT * ppt,IUnknown * pcmdtReserved,IDispatch * pdispReserved)417 HRESULT __stdcall WebBrowser::ShowContextMenu(DWORD dwID, POINT* ppt,
418 IUnknown* pcmdtReserved,
419 IDispatch* pdispReserved) {
420 // Returning S_OK signals that we've handled the request for a context menu
421 // (which we did, by doing nothing), so the control won't try to open one.
422 return S_OK;
423 }
424
GetHostInfo(DOCHOSTUIINFO * pInfo)425 HRESULT __stdcall WebBrowser::GetHostInfo(DOCHOSTUIINFO* pInfo) {
426 pInfo->cbSize = sizeof(DOCHOSTUIINFO);
427 pInfo->dwFlags =
428 DOCHOSTUIFLAG_DIALOG | DOCHOSTUIFLAG_DISABLE_HELP_MENU |
429 DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_SCROLL_NO |
430 DOCHOSTUIFLAG_OPENNEWWIN | DOCHOSTUIFLAG_OVERRIDEBEHAVIORFACTORY |
431 DOCHOSTUIFLAG_THEME | DOCHOSTUIFLAG_LOCAL_MACHINE_ACCESS_CHECK |
432 DOCHOSTUIFLAG_DISABLE_UNTRUSTEDPROTOCOL | DOCHOSTUIFLAG_DPI_AWARE;
433 pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
434 pInfo->pchHostCss = nullptr;
435 pInfo->pchHostNS = nullptr;
436 return S_OK;
437 }
438
ShowUI(DWORD dwID,IOleInPlaceActiveObject * pActiveObject,IOleCommandTarget * pCommandTarget,IOleInPlaceFrame * pFrame,IOleInPlaceUIWindow * pDoc)439 HRESULT __stdcall WebBrowser::ShowUI(DWORD dwID,
440 IOleInPlaceActiveObject* pActiveObject,
441 IOleCommandTarget* pCommandTarget,
442 IOleInPlaceFrame* pFrame,
443 IOleInPlaceUIWindow* pDoc) {
444 return E_NOTIMPL;
445 }
446
HideUI()447 HRESULT __stdcall WebBrowser::HideUI() { return E_NOTIMPL; }
448
UpdateUI()449 HRESULT __stdcall WebBrowser::UpdateUI() { return E_NOTIMPL; }
450
EnableModeless(BOOL fEnable)451 HRESULT __stdcall WebBrowser::EnableModeless(BOOL fEnable) { return E_NOTIMPL; }
452
OnDocWindowActivate(BOOL fActivate)453 HRESULT __stdcall WebBrowser::OnDocWindowActivate(BOOL fActivate) {
454 return E_NOTIMPL;
455 }
456
OnFrameWindowActivate(BOOL fActivate)457 HRESULT __stdcall WebBrowser::OnFrameWindowActivate(BOOL fActivate) {
458 return E_NOTIMPL;
459 }
460
ResizeBorder(LPCRECT prcBorder,IOleInPlaceUIWindow * pUIWindow,BOOL fRameWindow)461 HRESULT __stdcall WebBrowser::ResizeBorder(LPCRECT prcBorder,
462 IOleInPlaceUIWindow* pUIWindow,
463 BOOL fRameWindow) {
464 return E_NOTIMPL;
465 }
466
TranslateAccelerator(LPMSG lpMsg,const GUID * pguidCmdGroup,DWORD nCmdID)467 HRESULT __stdcall WebBrowser::TranslateAccelerator(LPMSG lpMsg,
468 const GUID* pguidCmdGroup,
469 DWORD nCmdID) {
470 return S_FALSE;
471 }
472
GetOptionKeyPath(LPOLESTR * pchKey,DWORD dw)473 HRESULT __stdcall WebBrowser::GetOptionKeyPath(LPOLESTR* pchKey, DWORD dw) {
474 return E_NOTIMPL;
475 }
476
GetDropTarget(IDropTarget * pDropTarget,IDropTarget ** ppDropTarget)477 HRESULT __stdcall WebBrowser::GetDropTarget(IDropTarget* pDropTarget,
478 IDropTarget** ppDropTarget) {
479 // The IDropTarget implementation that we need is an empty stub, so we'll do
480 // the easy and convenient thing and just use this object.
481 return QueryInterface(IID_PPV_ARGS(ppDropTarget));
482 }
483
GetExternal(IDispatch ** ppDispatch)484 HRESULT __stdcall WebBrowser::GetExternal(IDispatch** ppDispatch) {
485 // This object has to implement IDispatch anyway so that we can use
486 // DISPID_AMBIENT_DLCONTROL, so we'll make this the external handler also.
487 return QueryInterface(IID_PPV_ARGS(ppDispatch));
488 }
489
TranslateUrl(DWORD dwTranslate,LPWSTR pchURLIn,LPWSTR * ppchURLOut)490 HRESULT __stdcall WebBrowser::TranslateUrl(DWORD dwTranslate, LPWSTR pchURLIn,
491 LPWSTR* ppchURLOut) {
492 *ppchURLOut = nullptr;
493 return E_NOTIMPL;
494 }
495
FilterDataObject(IDataObject * pDO,IDataObject ** ppDORet)496 HRESULT __stdcall WebBrowser::FilterDataObject(IDataObject* pDO,
497 IDataObject** ppDORet) {
498 *ppDORet = nullptr;
499 return E_NOTIMPL;
500 }
501
502 //////////////////////////////////////////////////////////////////////////////
503 // IDocHostShowUI
504 //////////////////////////////////////////////////////////////////////////////
505
ShowMessage(HWND hwnd,LPOLESTR lpstrText,LPOLESTR lpstrCaption,DWORD dwType,LPOLESTR lpstrHelpFile,DWORD dwHelpContext,LRESULT * plResult)506 HRESULT __stdcall WebBrowser::ShowMessage(HWND hwnd, LPOLESTR lpstrText,
507 LPOLESTR lpstrCaption, DWORD dwType,
508 LPOLESTR lpstrHelpFile,
509 DWORD dwHelpContext,
510 LRESULT* plResult) {
511 // Don't allow MSHTML to generate message boxes.
512 return S_OK;
513 }
514
ShowHelp(HWND hwnd,LPOLESTR pszHelpFile,UINT uCommand,DWORD dwData,POINT ptMouse,IDispatch * pDispatchObjectHit)515 HRESULT __stdcall WebBrowser::ShowHelp(HWND hwnd, LPOLESTR pszHelpFile,
516 UINT uCommand, DWORD dwData,
517 POINT ptMouse,
518 IDispatch* pDispatchObjectHit) {
519 // Don't allow MSHTML to show any help.
520 return S_OK;
521 }
522
523 //////////////////////////////////////////////////////////////////////////////
524 // IDispatch
525 //////////////////////////////////////////////////////////////////////////////
526
527 // We're not using a type library.
GetTypeInfoCount(UINT * pctinfo)528 HRESULT __stdcall WebBrowser::GetTypeInfoCount(UINT* pctinfo) {
529 if (pctinfo) {
530 *pctinfo = 0;
531 }
532 return S_OK;
533 }
534
GetTypeInfo(UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)535 HRESULT __stdcall WebBrowser::GetTypeInfo(UINT iTInfo, LCID lcid,
536 ITypeInfo** ppTInfo) {
537 return E_NOTIMPL;
538 }
539
GetIDsOfNames(REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)540 HRESULT __stdcall WebBrowser::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
541 UINT cNames, LCID lcid,
542 DISPID* rgDispId) {
543 if (cNames != 1) {
544 return E_NOTIMPL;
545 }
546
547 for (size_t i = 0; i < mCustomFunctions.size(); ++i) {
548 if (mCustomFunctions[i].mName == rgszNames[0]) {
549 // DISPID values need to be 1-indexed because 0 is reserved
550 // (DISPID_VALUE).
551 *rgDispId = i + 1;
552 return S_OK;
553 }
554 }
555
556 *rgDispId = DISPID_UNKNOWN;
557 return DISP_E_UNKNOWNNAME;
558 }
559
Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)560 HRESULT __stdcall WebBrowser::Invoke(DISPID dispIdMember, REFIID riid,
561 LCID lcid, WORD wFlags,
562 DISPPARAMS* pDispParams,
563 VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
564 UINT* puArgErr) {
565 if (dispIdMember == DISPID_AMBIENT_DLCONTROL && pVarResult) {
566 VariantClear(pVarResult);
567 pVarResult->vt = VT_I4;
568 // As a light security measure, disable a bunch of stuff we don't want
569 // to be able to run in the web control.
570 pVarResult->intVal = DLCTL_NO_JAVA | DLCTL_NO_DLACTIVEXCTLS |
571 DLCTL_NO_RUNACTIVEXCTLS | DLCTL_NO_FRAMEDOWNLOAD |
572 DLCTL_NO_BEHAVIORS | DLCTL_NO_CLIENTPULL |
573 DLCTL_NOFRAMES | DLCTL_FORCEOFFLINE | DLCTL_SILENT |
574 DLCTL_OFFLINE | DLCTL_DLIMAGES;
575 return S_OK;
576 }
577
578 // Otherwise this should be one of our custom functions.
579 // We only support invoking these as methods, not property access.
580 if ((wFlags & DISPATCH_METHOD) == 0) {
581 return DISP_E_TYPEMISMATCH;
582 }
583
584 // Make sure this DISPID is valid in our custom functions list.
585 // DISPID values are 1-indexed because 0 is reserved (DISPID_VALUE).
586 DISPID customFunctionIndex = dispIdMember - 1;
587 if (customFunctionIndex < 0 ||
588 customFunctionIndex >= (DISPID)mCustomFunctions.size()) {
589 return DISP_E_MEMBERNOTFOUND;
590 }
591
592 // If the caller passed an argument to this custom function, use it.
593 // If not, make an empty VARIANT we can pass to it instead.
594 VARIANT argument;
595 VariantInit(&argument);
596 if (pDispParams->cArgs > 0) {
597 argument = pDispParams->rgvarg[0];
598 }
599
600 CustomFunctionRecord foundFunction = mCustomFunctions[customFunctionIndex];
601 foundFunction.mFunction(foundFunction.mArg, argument, pVarResult);
602
603 return S_OK;
604 }
605