1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/webview_ie.cpp
3 // Purpose:     wxMSW wxWebViewIE class implementation for web view component
4 // Author:      Marianne Gagnon
5 // Copyright:   (c) 2010 Marianne Gagnon, 2011 Steven Lamerton
6 // Licence:     wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8 
9 // For compilers that support precompilation, includes "wx.h".
10 #include "wx/wxprec.h"
11 
12 
13 #include "wx/msw/webview_ie.h"
14 
15 #if wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE
16 
17 #include "wx/msw/registry.h"
18 #include "wx/msw/ole/safearray.h"
19 #include "wx/filesys.h"
20 #include "wx/dynlib.h"
21 #include "wx/scopeguard.h"
22 #include "wx/tokenzr.h"
23 
24 #include "wx/msw/missing.h"
25 #include "wx/msw/private.h"
26 #include "wx/msw/private/webview_ie.h"
27 #include "wx/private/jsscriptwrapper.h"
28 
29 #include <initguid.h>
30 #include <exdispid.h>
31 #include <mshtml.h>
32 
33 /* These GUID definitions are our own implementation to support interfaces
34  * normally in urlmon.h. See include/wx/msw/webview_ie.h
35  */
36 
37 namespace {
38 
39 DEFINE_GUID(wxIID_IInternetProtocolRoot,0x79eac9e3,0xbaf9,0x11ce,0x8c,0x82,0,0xaa,0,0x4b,0xa9,0xb);
40 DEFINE_GUID(wxIID_IInternetProtocol,0x79eac9e4,0xbaf9,0x11ce,0x8c,0x82,0,0xaa,0,0x4b,0xa9,0xb);
41 DEFINE_GUID(wxIID_IInternetProtocolInfo,0x79eac9ec,0xbaf9,0x11ce,0x8c, 0x82,0,0xaa,0,0x4b,0xa9,0x0b);
42 DEFINE_GUID(wxIID_IDocHostUIHandler, 0xbd3f23c0, 0xd43e, 0x11cf, 0x89, 0x3b, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x1a);
43 DEFINE_GUID(wxIID_IHTMLElement2,0x3050f434,0x98b5,0x11cf,0xbb,0x82,0,0xaa,0,0xbd,0xce,0x0b);
44 DEFINE_GUID(wxIID_IMarkupServices,0x3050f4a0,0x98b5,0x11cf,0xbb,0x82,0,0xaa,0,0xbd,0xce,0x0b);
45 DEFINE_GUID(wxIID_IMarkupContainer,0x3050f5f9,0x98b5,0x11cf,0xbb,0x82,0,0xaa,0,0xbd,0xce,0x0b);
46 
47 enum //Internal find flags
48 {
49     wxWEBVIEW_FIND_ADD_POINTERS =      0x0001,
50     wxWEBVIEW_FIND_REMOVE_HIGHLIGHT =  0x0002
51 };
52 
53 }
54 
55 // wxWebViewFactoryIE
GetVersionInfo()56 wxVersionInfo wxWebViewFactoryIE::GetVersionInfo()
57 {
58     wxRegKey key(wxRegKey::HKLM, "Software\\Microsoft\\Internet Explorer");
59     wxString value;
60     key.QueryValue("Version", value);
61     long major = 0,
62          minor = 0,
63          micro = 0;
64     wxStringTokenizer tk(value, ". ");
65     // Ignore the return value because if the version component is missing
66     // or invalid (i.e. non-numeric), the only thing we can do is to ignore
67     // it anyhow.
68     tk.GetNextToken().ToLong(&major);
69     tk.GetNextToken().ToLong(&minor);
70     tk.GetNextToken().ToLong(&micro);
71     return wxVersionInfo("Internet Explorer", major, minor, micro);
72 }
73 
74 //Convenience function for error conversion
75 #define WX_ERROR_CASE(error, wxerror) \
76         case error: \
77             event.SetString(#error); \
78             event.SetInt(wxerror); \
79             break;
80 
81 wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewIE, wxWebView);
82 
wxBEGIN_EVENT_TABLE(wxWebViewIE,wxControl)83 wxBEGIN_EVENT_TABLE(wxWebViewIE, wxControl)
84     EVT_ACTIVEX(wxID_ANY, wxWebViewIE::onActiveXEvent)
85     EVT_ERASE_BACKGROUND(wxWebViewIE::onEraseBg)
86 wxEND_EVENT_TABLE()
87 
88 bool wxWebViewIE::Create(wxWindow* parent,
89            wxWindowID id,
90            const wxString& url,
91            const wxPoint& pos,
92            const wxSize& size,
93            long style,
94            const wxString& name)
95 {
96     if (!wxControl::Create(parent, id, pos, size, style,
97                            wxDefaultValidator, name))
98     {
99         return false;
100     }
101 
102     m_impl = new wxWebViewIEImpl(this);
103     if ( !m_impl->Create() )
104         return false;
105 
106     // Make behaviour consistent with the other backends when loading localhost
107     // pages without any physical network connection.
108     SetOfflineMode(false);
109 
110     LoadURL(url);
111     return true;
112 }
113 
wxWebViewIEImpl(wxWebViewIE * webview)114 wxWebViewIEImpl::wxWebViewIEImpl(wxWebViewIE* webview)
115     : m_webview(webview)
116 {
117 }
118 
Create()119 bool wxWebViewIEImpl::Create()
120 {
121     m_webBrowser = NULL;
122     m_isBusy = false;
123     m_historyLoadingFromList = false;
124     m_historyEnabled = true;
125     m_historyPosition = -1;
126     m_zoomType = wxWEBVIEW_ZOOM_TYPE_TEXT;
127     FindClear();
128 
129     if (::CoCreateInstance(CLSID_WebBrowser, NULL,
130                            CLSCTX_INPROC_SERVER, // CLSCTX_INPROC,
131                            IID_IWebBrowser2 , (void**)&m_webBrowser) != 0)
132     {
133         wxLogError("Failed to initialize IE, CoCreateInstance returned an error");
134         return false;
135     }
136 
137     m_ie.SetDispatchPtr(m_webBrowser); // wxAutomationObject will release itself
138 
139     m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
140     m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
141 
142     m_uiHandler = new DocHostUIHandler(m_webview);
143 
144     m_container = new wxIEContainer(m_webview, IID_IWebBrowser2, m_webBrowser, m_uiHandler);
145 
146     EnableControlFeature(21 /* FEATURE_DISABLE_NAVIGATION_SOUNDS */);
147 
148     return true;
149 }
150 
~wxWebViewIE()151 wxWebViewIE::~wxWebViewIE()
152 {
153     delete m_impl;
154 }
155 
~wxWebViewIEImpl()156 wxWebViewIEImpl::~wxWebViewIEImpl()
157 {
158     wxDynamicLibrary urlMon(wxT("urlmon.dll"));
159     if(urlMon.HasSymbol(wxT("CoInternetGetSession")))
160     {
161         typedef HRESULT (WINAPI *CoInternetGetSession_t)(DWORD,
162                                                          wxIInternetSession**,
163                                                          DWORD);
164         wxDYNLIB_FUNCTION(CoInternetGetSession_t, CoInternetGetSession, urlMon);
165 
166         wxIInternetSession* session;
167         HRESULT res = (*pfnCoInternetGetSession)(0, &session, 0);
168         if(FAILED(res))
169         {
170             wxFAIL_MSG("Could not retrive internet session");
171         }
172 
173         for(unsigned int i = 0; i < m_factories.size(); i++)
174         {
175             session->UnregisterNameSpace(m_factories[i],
176                                         (m_factories[i]->GetName()).wc_str());
177             m_factories[i]->Release();
178         }
179     }
180     FindClear();
181 }
182 
LoadURL(const wxString & url)183 void wxWebViewIE::LoadURL(const wxString& url)
184 {
185     m_impl->m_ie.CallMethod("Navigate", wxConvertStringToOle(url));
186 }
187 
188 namespace
189 {
190 
191 // Helper function: wrap the given string in a SAFEARRAY<VARIANT> of size 1.
MakeOneElementVariantSafeArray(const wxString & str)192 SAFEARRAY* MakeOneElementVariantSafeArray(const wxString& str)
193 {
194     wxSafeArray<VT_VARIANT> sa;
195     if ( !sa.Create(1) )
196     {
197         wxLogLastError(wxT("SafeArrayCreateVector"));
198         return NULL;
199     }
200 
201     long ind = 0;
202     if ( !sa.SetElement(&ind, str) )
203     {
204         wxLogLastError(wxT("SafeArrayPtrOfIndex"));
205         return NULL;
206     }
207 
208     return sa.Detach();
209 }
210 
211 } // anonymous namespace
212 
DoSetPage(const wxString & html,const wxString & baseUrl)213 void wxWebViewIE::DoSetPage(const wxString& html, const wxString& baseUrl)
214 {
215     {
216         SAFEARRAY* const psaStrings = MakeOneElementVariantSafeArray(wxString());
217         if ( !psaStrings )
218             return;
219 
220         wxON_BLOCK_EXIT1(SafeArrayDestroy, psaStrings);
221 
222         wxCOMPtr<IHTMLDocument2> document(m_impl->GetDocument());
223 
224         if(!document)
225             return;
226 
227         document->write(psaStrings);
228         document->close();
229     }
230 
231     {
232         SAFEARRAY* const psaStrings = MakeOneElementVariantSafeArray(html);
233 
234         if ( !psaStrings )
235             return;
236 
237         wxON_BLOCK_EXIT1(SafeArrayDestroy, psaStrings);
238 
239         wxCOMPtr<IHTMLDocument2> document(m_impl->GetDocument());
240 
241         if(!document)
242             return;
243 
244         document->write(psaStrings);
245 
246         //We send the events when we are done to mimic webkit
247         //Navigated event
248         wxWebViewEvent event(wxEVT_WEBVIEW_NAVIGATED,
249                              GetId(), baseUrl, "");
250         event.SetEventObject(this);
251         HandleWindowEvent(event);
252 
253         //Document complete event
254         event.SetEventType(wxEVT_WEBVIEW_LOADED);
255         event.SetEventObject(this);
256         HandleWindowEvent(event);
257     }
258 }
259 
GetPageSource() const260 wxString wxWebViewIE::GetPageSource() const
261 {
262     wxCOMPtr<IHTMLDocument2> document(m_impl->GetDocument());
263 
264     if(document)
265     {
266         wxCOMPtr<IHTMLElement> bodyTag;
267         wxCOMPtr<IHTMLElement> htmlTag;
268         wxString source;
269         HRESULT hr = document->get_body(&bodyTag);
270         if(SUCCEEDED(hr))
271         {
272             hr = bodyTag->get_parentElement(&htmlTag);
273             if(SUCCEEDED(hr))
274             {
275                 wxBasicString bstr;
276                 if ( htmlTag->get_outerHTML(bstr.ByRef()) == S_OK )
277                     source = bstr;
278             }
279         }
280         return source;
281     }
282     else
283     {
284         return "";
285     }
286 }
287 
GetZoom() const288 wxWebViewZoom wxWebViewIE::GetZoom() const
289 {
290     switch( m_impl->m_zoomType )
291     {
292         case wxWEBVIEW_ZOOM_TYPE_LAYOUT:
293             return GetIEOpticalZoom();
294         case wxWEBVIEW_ZOOM_TYPE_TEXT:
295             return GetIETextZoom();
296         default:
297             wxFAIL;
298     }
299 
300     //Dummy return to stop compiler warnings
301     return wxWEBVIEW_ZOOM_MEDIUM;
302 
303 }
304 
GetZoomFactor() const305 float wxWebViewIE::GetZoomFactor() const
306 {
307     wxWebViewZoom level = wxWEBVIEW_ZOOM_MEDIUM;
308     float zoomFactor = 1.0;
309 
310     if (m_impl->m_zoomType == wxWEBVIEW_ZOOM_TYPE_LAYOUT)
311     {
312         zoomFactor = (float)GetIEOpticalZoomFactor();
313         zoomFactor /= 100;
314     }
315     else if (m_impl->m_zoomType == wxWEBVIEW_ZOOM_TYPE_TEXT)
316     {
317         level = GetIETextZoom();
318         switch(level)
319         {
320             case wxWEBVIEW_ZOOM_TINY:
321                 zoomFactor = 0.6f;
322                 break;
323             case wxWEBVIEW_ZOOM_SMALL:
324                 zoomFactor = 0.8f;
325                 break;
326             case wxWEBVIEW_ZOOM_MEDIUM:
327                 zoomFactor = 1.0f;
328                 break;
329             case wxWEBVIEW_ZOOM_LARGE:
330                 zoomFactor = 1.3f;
331                 break;
332             case wxWEBVIEW_ZOOM_LARGEST:
333                 zoomFactor = 1.6f;
334                 break;
335             default:
336                 wxFAIL;
337         }
338     }
339 
340     return zoomFactor;
341 }
342 
SetZoom(wxWebViewZoom zoom)343 void wxWebViewIE::SetZoom(wxWebViewZoom zoom)
344 {
345     switch( m_impl->m_zoomType )
346     {
347         case wxWEBVIEW_ZOOM_TYPE_LAYOUT:
348             SetIEOpticalZoom(zoom);
349             break;
350         case wxWEBVIEW_ZOOM_TYPE_TEXT:
351             SetIETextZoom(zoom);
352             break;
353         default:
354             wxFAIL;
355     }
356 }
357 
SetZoomFactor(float zoom)358 void wxWebViewIE::SetZoomFactor(float zoom)
359 {
360     wxWebViewZoom level = wxWEBVIEW_ZOOM_MEDIUM;
361 
362     if (m_impl->m_zoomType == wxWEBVIEW_ZOOM_TYPE_LAYOUT)
363     {
364         SetIEOpticalZoomFactor(zoom * 100);
365     }
366     else if (m_impl->m_zoomType == wxWEBVIEW_ZOOM_TYPE_TEXT)
367     {
368         //We make a somewhat arbitray map here, taken from values used by webkit
369         if (zoom <= 65)
370         {
371             level = wxWEBVIEW_ZOOM_TINY;
372         }
373         else if (zoom > 65 && zoom <= 90)
374         {
375             level = wxWEBVIEW_ZOOM_SMALL;
376         }
377         else if (zoom > 90 && zoom <= 115)
378         {
379             level = wxWEBVIEW_ZOOM_MEDIUM;
380         }
381         else if (zoom > 115 && zoom <= 145)
382         {
383             level = wxWEBVIEW_ZOOM_LARGE;
384         }
385         else
386         {
387             level = wxWEBVIEW_ZOOM_LARGEST;
388         }
389         SetIETextZoom(level);
390     }
391 }
392 
SetIETextZoom(wxWebViewZoom level)393 void wxWebViewIE::SetIETextZoom(wxWebViewZoom level)
394 {
395     //We do not use OLECMDID_OPTICAL_GETZOOMRANGE as the docs say the range
396     //is 0 to 4 so the check is unnecessary, these match exactly with the
397     //enum values
398     VARIANT zoomVariant;
399     VariantInit (&zoomVariant);
400     V_VT(&zoomVariant) = VT_I4;
401     V_I4(&zoomVariant) = level;
402 
403 #if wxDEBUG_LEVEL
404     HRESULT result =
405 #endif
406             m_impl->m_webBrowser->ExecWB(OLECMDID_ZOOM,
407                                          OLECMDEXECOPT_DONTPROMPTUSER,
408                                          &zoomVariant, NULL);
409     wxASSERT(result == S_OK);
410 }
411 
GetIETextZoom() const412 wxWebViewZoom wxWebViewIE::GetIETextZoom() const
413 {
414     VARIANT zoomVariant;
415     VariantInit (&zoomVariant);
416     V_VT(&zoomVariant) = VT_I4;
417 
418 #if wxDEBUG_LEVEL
419     HRESULT result =
420 #endif
421             m_impl->m_webBrowser->ExecWB(OLECMDID_ZOOM,
422                                          OLECMDEXECOPT_DONTPROMPTUSER,
423                                          NULL, &zoomVariant);
424     wxASSERT(result == S_OK);
425 
426     //We can safely cast here as we know that the range matches our enum
427     return static_cast<wxWebViewZoom>(V_I4(&zoomVariant));
428 }
429 
SetIEOpticalZoom(wxWebViewZoom level)430 void wxWebViewIE::SetIEOpticalZoom(wxWebViewZoom level)
431 {
432     int zoom = 100;
433 
434     //We make a somewhat arbitray map here, taken from values used by webkit
435     switch(level)
436     {
437         case wxWEBVIEW_ZOOM_TINY:
438             zoom = 60;
439             break;
440         case wxWEBVIEW_ZOOM_SMALL:
441             zoom = 80;
442             break;
443         case wxWEBVIEW_ZOOM_MEDIUM:
444             zoom = 100;
445             break;
446         case wxWEBVIEW_ZOOM_LARGE:
447             zoom = 130;
448             break;
449         case wxWEBVIEW_ZOOM_LARGEST:
450             zoom = 160;
451             break;
452         default:
453             wxFAIL;
454     }
455     SetIEOpticalZoomFactor(zoom);
456 }
457 
SetIEOpticalZoomFactor(int zoom)458 void wxWebViewIE::SetIEOpticalZoomFactor(int zoom)
459 {
460     //We do not use OLECMDID_OPTICAL_GETZOOMRANGE as the docs say the range
461     //is 10 to 1000 so the check is unnecessary
462     VARIANT zoomVariant;
463     VariantInit (&zoomVariant);
464     V_VT(&zoomVariant) = VT_I4;
465     V_I4(&zoomVariant) = zoom;
466 
467 #if wxDEBUG_LEVEL
468     HRESULT result =
469 #endif
470             m_impl->m_webBrowser->ExecWB((OLECMDID)63 /*OLECMDID_OPTICAL_ZOOM*/,
471                                          OLECMDEXECOPT_DODEFAULT,
472                                          &zoomVariant,
473                                          NULL);
474     wxASSERT(result == S_OK);
475 }
476 
GetIEOpticalZoom() const477 wxWebViewZoom wxWebViewIE::GetIEOpticalZoom() const
478 {
479     const int zoom = GetIEOpticalZoomFactor();
480 
481     //We make a somewhat arbitray map here, taken from values used by webkit
482     if (zoom <= 65)
483     {
484         return wxWEBVIEW_ZOOM_TINY;
485     }
486     else if (zoom > 65 && zoom <= 90)
487     {
488         return wxWEBVIEW_ZOOM_SMALL;
489     }
490     else if (zoom > 90 && zoom <= 115)
491     {
492         return wxWEBVIEW_ZOOM_MEDIUM;
493     }
494     else if (zoom > 115 && zoom <= 145)
495     {
496         return wxWEBVIEW_ZOOM_LARGE;
497     }
498     else /*if (zoom > 145) */ //Using else removes a compiler warning
499     {
500         return wxWEBVIEW_ZOOM_LARGEST;
501     }
502 }
503 
GetIEOpticalZoomFactor() const504 int wxWebViewIE::GetIEOpticalZoomFactor() const
505 {
506     VARIANT zoomVariant;
507     VariantInit (&zoomVariant);
508     V_VT(&zoomVariant) = VT_I4;
509 
510 #if wxDEBUG_LEVEL
511     HRESULT result =
512 #endif
513             m_impl->m_webBrowser->ExecWB((OLECMDID)63 /*OLECMDID_OPTICAL_ZOOM*/,
514                                          OLECMDEXECOPT_DODEFAULT, NULL,
515                                          &zoomVariant);
516     wxASSERT(result == S_OK);
517 
518     const int zoom = V_I4(&zoomVariant);
519 
520     return zoom;
521 }
522 
SetZoomType(wxWebViewZoomType type)523 void wxWebViewIE::SetZoomType(wxWebViewZoomType type)
524 {
525     m_impl->m_zoomType = type;
526 }
527 
GetZoomType() const528 wxWebViewZoomType wxWebViewIE::GetZoomType() const
529 {
530     return m_impl->m_zoomType;
531 }
532 
CanSetZoomType(wxWebViewZoomType type) const533 bool wxWebViewIE::CanSetZoomType(wxWebViewZoomType type) const
534 {
535     //IE 6 and below only support text zoom, so check the registry to see what
536     //version we actually have
537     wxRegKey key(wxRegKey::HKLM, "Software\\Microsoft\\Internet Explorer");
538     wxString value;
539     key.QueryValue("Version", value);
540 
541     long version = wxAtoi(value.Left(1));
542     if(version <= 6 && type == wxWEBVIEW_ZOOM_TYPE_LAYOUT)
543         return false;
544     else
545         return true;
546 }
547 
Print()548 void wxWebViewIE::Print()
549 {
550     m_impl->m_webBrowser->ExecWB(OLECMDID_PRINTPREVIEW,
551                                  OLECMDEXECOPT_DODEFAULT, NULL, NULL);
552 }
553 
CanGoBack() const554 bool wxWebViewIE::CanGoBack() const
555 {
556     if(m_impl->m_historyEnabled)
557         return m_impl->m_historyPosition > 0;
558     else
559         return false;
560 }
561 
CanGoForward() const562 bool wxWebViewIE::CanGoForward() const
563 {
564     if(m_impl->m_historyEnabled)
565         return m_impl->m_historyPosition !=
566                static_cast<int>(m_impl->m_historyList.size()) - 1;
567     else
568         return false;
569 }
570 
LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem> item)571 void wxWebViewIE::LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem> item)
572 {
573     int pos = -1;
574     for(unsigned int i = 0; i < m_impl->m_historyList.size(); i++)
575     {
576         //We compare the actual pointers to find the correct item
577         if(m_impl->m_historyList[i].get() == item.get())
578             pos = i;
579     }
580     wxASSERT_MSG(pos != static_cast<int>(m_impl->m_historyList.size()),
581                  "invalid history item");
582     m_impl->m_historyLoadingFromList = true;
583     LoadURL(item->GetUrl());
584     m_impl->m_historyPosition = pos;
585 }
586 
GetBackwardHistory()587 wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewIE::GetBackwardHistory()
588 {
589     wxVector<wxSharedPtr<wxWebViewHistoryItem> > backhist;
590     //As we don't have std::copy or an iterator constructor in the wxwidgets
591     //native vector we construct it by hand
592     for(int i = 0; i < m_impl->m_historyPosition; i++)
593     {
594         backhist.push_back(m_impl->m_historyList[i]);
595     }
596     return backhist;
597 }
598 
GetForwardHistory()599 wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewIE::GetForwardHistory()
600 {
601     wxVector<wxSharedPtr<wxWebViewHistoryItem> > forwardhist;
602     //As we don't have std::copy or an iterator constructor in the wxwidgets
603     //native vector we construct it by hand
604     for(int i = m_impl->m_historyPosition + 1; i < static_cast<int>(m_impl->m_historyList.size()); i++)
605     {
606         forwardhist.push_back(m_impl->m_historyList[i]);
607     }
608     return forwardhist;
609 }
610 
GoBack()611 void wxWebViewIE::GoBack()
612 {
613     LoadHistoryItem(m_impl->m_historyList[m_impl->m_historyPosition - 1]);
614 }
615 
GoForward()616 void wxWebViewIE::GoForward()
617 {
618     LoadHistoryItem(m_impl->m_historyList[m_impl->m_historyPosition + 1]);
619 }
620 
Stop()621 void wxWebViewIE::Stop()
622 {
623     m_impl->m_ie.CallMethod("Stop");
624 }
625 
ClearHistory()626 void wxWebViewIE::ClearHistory()
627 {
628     m_impl->m_historyList.clear();
629     m_impl->m_historyPosition = -1;
630 }
631 
EnableHistory(bool enable)632 void wxWebViewIE::EnableHistory(bool enable)
633 {
634     m_impl->m_historyEnabled = enable;
635     m_impl->m_historyList.clear();
636     m_impl->m_historyPosition = -1;
637 }
638 
Reload(wxWebViewReloadFlags flags)639 void wxWebViewIE::Reload(wxWebViewReloadFlags flags)
640 {
641     VARIANTARG level;
642     VariantInit(&level);
643     V_VT(&level) = VT_I2;
644 
645     switch(flags)
646     {
647         case wxWEBVIEW_RELOAD_DEFAULT:
648             V_I2(&level) = REFRESH_NORMAL;
649             break;
650         case wxWEBVIEW_RELOAD_NO_CACHE:
651             V_I2(&level) = REFRESH_COMPLETELY;
652             break;
653         default:
654             wxFAIL_MSG("Unexpected reload type");
655     }
656 
657     m_impl->m_webBrowser->Refresh2(&level);
658 }
659 
IsOfflineMode()660 bool wxWebViewIE::IsOfflineMode()
661 {
662     wxVariant out = m_impl->m_ie.GetProperty("Offline");
663 
664     wxASSERT(out.GetType() == "bool");
665 
666     return out.GetBool();
667 }
668 
SetOfflineMode(bool offline)669 void wxWebViewIE::SetOfflineMode(bool offline)
670 {
671 #if wxDEBUG_LEVEL
672     const HRESULT success =
673 #endif
674             m_impl->m_ie.PutProperty("Offline", (offline ?
675                                                  VARIANT_TRUE :
676                                                  VARIANT_FALSE));
677     wxASSERT(SUCCEEDED(success));
678 }
679 
IsBusy() const680 bool wxWebViewIE::IsBusy() const
681 {
682     if (m_impl->m_isBusy) return true;
683 
684     wxVariant out = m_impl->m_ie.GetProperty("Busy");
685 
686     wxASSERT(out.GetType() == "bool");
687 
688     return out.GetBool();
689 }
690 
GetCurrentURL() const691 wxString wxWebViewIE::GetCurrentURL() const
692 {
693     wxVariant out = m_impl->m_ie.GetProperty("LocationURL");
694 
695     wxASSERT(out.GetType() == "string");
696     return out.GetString();
697 }
698 
GetCurrentTitle() const699 wxString wxWebViewIE::GetCurrentTitle() const
700 {
701     wxCOMPtr<IHTMLDocument2> document(m_impl->GetDocument());
702 
703     wxString s;
704     if(document)
705     {
706         wxBasicString title;
707         if ( document->get_nameProp(title.ByRef()) == S_OK )
708             s = title;
709     }
710 
711     return s;
712 }
713 
CanCut() const714 bool wxWebViewIE::CanCut() const
715 {
716     return m_impl->CanExecCommand("Cut");
717 }
718 
CanCopy() const719 bool wxWebViewIE::CanCopy() const
720 {
721     return m_impl->CanExecCommand("Copy");
722 }
723 
CanPaste() const724 bool wxWebViewIE::CanPaste() const
725 {
726     return m_impl->CanExecCommand("Paste");
727 }
728 
Cut()729 void wxWebViewIE::Cut()
730 {
731     m_impl->ExecCommand("Cut");
732 }
733 
Copy()734 void wxWebViewIE::Copy()
735 {
736     m_impl->ExecCommand("Copy");
737 }
738 
Paste()739 void wxWebViewIE::Paste()
740 {
741     m_impl->ExecCommand("Paste");
742 }
743 
CanUndo() const744 bool wxWebViewIE::CanUndo() const
745 {
746     return m_impl->CanExecCommand("Undo");
747 }
748 
CanRedo() const749 bool wxWebViewIE::CanRedo() const
750 {
751     return m_impl->CanExecCommand("Redo");
752 }
753 
Undo()754 void wxWebViewIE::Undo()
755 {
756     m_impl->ExecCommand("Undo");
757 }
758 
Redo()759 void wxWebViewIE::Redo()
760 {
761     m_impl->ExecCommand("Redo");
762 }
763 
Find(const wxString & text,int flags)764 long wxWebViewIE::Find(const wxString& text, int flags)
765 {
766     return m_impl->Find(text, flags);
767 }
768 
Find(const wxString & text,int flags)769 long wxWebViewIEImpl::Find(const wxString& text, int flags)
770 {
771     //If the text is empty then we clear.
772     if(text.IsEmpty())
773     {
774         m_webview->ClearSelection();
775         if(m_findFlags & wxWEBVIEW_FIND_HIGHLIGHT_RESULT)
776         {
777             FindInternal(m_findText, (m_findFlags &~ wxWEBVIEW_FIND_HIGHLIGHT_RESULT), wxWEBVIEW_FIND_REMOVE_HIGHLIGHT);
778         }
779         FindClear();
780         return wxNOT_FOUND;
781     }
782     //Have we done this search before?
783     if(m_findText == text)
784     {
785         //Just do a highlight?
786         if((flags & wxWEBVIEW_FIND_HIGHLIGHT_RESULT) != (m_findFlags & wxWEBVIEW_FIND_HIGHLIGHT_RESULT))
787         {
788             m_findFlags = flags;
789             if(!m_findPointers.empty())
790             {
791                 FindInternal(m_findText, m_findFlags, ((flags & wxWEBVIEW_FIND_HIGHLIGHT_RESULT) == 0 ? wxWEBVIEW_FIND_REMOVE_HIGHLIGHT : 0));
792             }
793             return m_findPosition;
794         }
795         else if(((m_findFlags & wxWEBVIEW_FIND_ENTIRE_WORD) == (flags & wxWEBVIEW_FIND_ENTIRE_WORD)) && ((m_findFlags & wxWEBVIEW_FIND_MATCH_CASE) == (flags&wxWEBVIEW_FIND_MATCH_CASE)))
796         {
797             m_findFlags = flags;
798             return FindNext(((flags & wxWEBVIEW_FIND_BACKWARDS) ? -1 : 1));
799         }
800     }
801     //Remove old highlight if any.
802     if(m_findFlags & wxWEBVIEW_FIND_HIGHLIGHT_RESULT)
803     {
804         FindInternal(m_findText, (m_findFlags &~ wxWEBVIEW_FIND_HIGHLIGHT_RESULT), wxWEBVIEW_FIND_REMOVE_HIGHLIGHT);
805     }
806     //Reset find variables.
807     FindClear();
808     m_webview->ClearSelection();
809     m_findText = text;
810     m_findFlags = flags;
811     //find the text and return wxNOT_FOUND if there are no matches.
812     FindInternal(text, flags, wxWEBVIEW_FIND_ADD_POINTERS);
813     if(m_findPointers.empty())
814         return wxNOT_FOUND;
815 
816     // Or their number if there are.
817     return m_findPointers.size();
818 }
819 
SetEditable(bool enable)820 void wxWebViewIE::SetEditable(bool enable)
821 {
822     wxCOMPtr<IHTMLDocument2> document(m_impl->GetDocument());
823 
824     if(document)
825     {
826         if( enable )
827             document->put_designMode(wxBasicString("On"));
828         else
829             document->put_designMode(wxBasicString("Off"));
830 
831     }
832 }
833 
IsEditable() const834 bool wxWebViewIE::IsEditable() const
835 {
836     wxCOMPtr<IHTMLDocument2> document(m_impl->GetDocument());
837 
838     if(document)
839     {
840         wxBasicString mode;
841         if ( document->get_designMode(mode.ByRef()) == S_OK )
842         {
843             if ( wxString(mode) == "On" )
844                 return true;
845         }
846     }
847     return false;
848 }
849 
SelectAll()850 void wxWebViewIE::SelectAll()
851 {
852     m_impl->ExecCommand("SelectAll");
853 }
854 
HasSelection() const855 bool wxWebViewIE::HasSelection() const
856 {
857     wxCOMPtr<IHTMLDocument2> document(m_impl->GetDocument());
858 
859     if(document)
860     {
861         wxCOMPtr<IHTMLSelectionObject> selection;
862         wxString sel;
863         HRESULT hr = document->get_selection(&selection);
864         if(SUCCEEDED(hr))
865         {
866             wxBasicString type;
867             if ( selection->get_type(type.ByRef()) == S_OK )
868                 sel = type;
869         }
870         return sel != "None";
871     }
872     else
873     {
874         return false;
875     }
876 }
877 
DeleteSelection()878 void wxWebViewIE::DeleteSelection()
879 {
880     m_impl->ExecCommand("Delete");
881 }
882 
GetSelectedText() const883 wxString wxWebViewIE::GetSelectedText() const
884 {
885     wxCOMPtr<IHTMLDocument2> document(m_impl->GetDocument());
886 
887     if(document)
888     {
889         wxCOMPtr<IHTMLSelectionObject> selection;
890         wxString selected;
891         HRESULT hr = document->get_selection(&selection);
892         if(SUCCEEDED(hr))
893         {
894             wxCOMPtr<IDispatch> disrange;
895             hr = selection->createRange(&disrange);
896             if(SUCCEEDED(hr))
897             {
898                 wxCOMPtr<IHTMLTxtRange> range;
899                 hr = disrange->QueryInterface(IID_IHTMLTxtRange, (void**)&range);
900                 if(SUCCEEDED(hr))
901                 {
902                     wxBasicString text;
903                     if ( range->get_text(text.ByRef()) == S_OK )
904                         selected = text;
905                 }
906             }
907         }
908         return selected;
909     }
910     else
911     {
912         return "";
913     }
914 }
915 
GetSelectedSource() const916 wxString wxWebViewIE::GetSelectedSource() const
917 {
918     wxCOMPtr<IHTMLDocument2> document(m_impl->GetDocument());
919 
920     if(document)
921     {
922         wxCOMPtr<IHTMLSelectionObject> selection;
923         wxString selected;
924         HRESULT hr = document->get_selection(&selection);
925         if(SUCCEEDED(hr))
926         {
927             wxCOMPtr<IDispatch> disrange;
928             hr = selection->createRange(&disrange);
929             if(SUCCEEDED(hr))
930             {
931                 wxCOMPtr<IHTMLTxtRange> range;
932                 hr = disrange->QueryInterface(IID_IHTMLTxtRange, (void**)&range);
933                 if(SUCCEEDED(hr))
934                 {
935                     wxBasicString text;
936                     if ( range->get_htmlText(text.ByRef()) == S_OK )
937                         selected = text;
938                 }
939             }
940         }
941         return selected;
942     }
943     else
944     {
945         return "";
946     }
947 }
948 
ClearSelection()949 void wxWebViewIE::ClearSelection()
950 {
951     wxCOMPtr<IHTMLDocument2> document(m_impl->GetDocument());
952 
953     if(document)
954     {
955         wxCOMPtr<IHTMLSelectionObject> selection;
956         wxString selected;
957         HRESULT hr = document->get_selection(&selection);
958         if(SUCCEEDED(hr))
959         {
960             selection->empty();
961         }
962     }
963 }
964 
GetPageText() const965 wxString wxWebViewIE::GetPageText() const
966 {
967     wxCOMPtr<IHTMLDocument2> document(m_impl->GetDocument());
968 
969     if(document)
970     {
971         wxString text;
972         wxCOMPtr<IHTMLElement> body;
973         HRESULT hr = document->get_body(&body);
974         if(SUCCEEDED(hr))
975         {
976             wxBasicString out;
977             if ( body->get_innerText(out.ByRef()) == S_OK )
978                 text = out;
979         }
980         return text;
981     }
982     else
983     {
984         return "";
985     }
986 }
987 
MSWSetEmulationLevel(wxWebViewIE_EmulationLevel level)988 bool wxWebViewIE::MSWSetEmulationLevel(wxWebViewIE_EmulationLevel level)
989 {
990     // Registry key where emulation level for programs are set
991     static const wxChar* IE_EMULATION_KEY =
992         wxT("SOFTWARE\\Microsoft\\Internet Explorer\\Main")
993         wxT("\\FeatureControl\\FEATURE_BROWSER_EMULATION");
994 
995     wxRegKey key(wxRegKey::HKCU, IE_EMULATION_KEY);
996     if ( !key.Exists() )
997     {
998         wxLogWarning(_("Failed to find web view emulation level in the registry"));
999         return false;
1000     }
1001 
1002     const wxString programName = wxGetFullModuleName().AfterLast('\\');
1003     if ( level != wxWEBVIEWIE_EMU_DEFAULT )
1004     {
1005         if ( !key.SetValue(programName, level) )
1006         {
1007             wxLogWarning(_("Failed to set web view to modern emulation level"));
1008             return false;
1009         }
1010     }
1011     else
1012     {
1013         if ( !key.DeleteValue(programName) )
1014         {
1015             wxLogWarning(_("Failed to reset web view to standard emulation level"));
1016             return false;
1017         }
1018     }
1019 
1020     return true;
1021 }
1022 
1023 static
CallEval(const wxString & code,wxAutomationObject & scriptAO,wxVariant * varResult)1024 bool CallEval(const wxString& code,
1025               wxAutomationObject& scriptAO,
1026               wxVariant* varResult)
1027 {
1028     wxVariant varCode(code);
1029     return scriptAO.Invoke("eval", DISPATCH_METHOD, *varResult, 1, &varCode);
1030 }
1031 
RunScript(const wxString & javascript,wxString * output) const1032 bool wxWebViewIE::RunScript(const wxString& javascript, wxString* output) const
1033 {
1034     wxCOMPtr<IHTMLDocument2> document(m_impl->GetDocument());
1035     if ( !document )
1036     {
1037         wxLogWarning(_("Can't run JavaScript script without a valid HTML document"));
1038         return false;
1039     }
1040 
1041     IDispatch* scriptDispatch = NULL;
1042     if ( FAILED(document->get_Script(&scriptDispatch)) )
1043     {
1044         wxLogWarning(_("Can't get the JavaScript object"));
1045         return false;
1046     }
1047 
1048     wxJSScriptWrapper wrapJS(javascript, &m_runScriptCount);
1049 
1050     wxAutomationObject scriptAO(scriptDispatch);
1051     wxVariant varResult;
1052 
1053     wxString err;
1054     if ( !CallEval(wrapJS.GetWrappedCode(), scriptAO, &varResult) )
1055     {
1056         err = _("failed to evaluate");
1057     }
1058     else if ( varResult.IsType("bool") && varResult.GetBool() )
1059     {
1060         if ( output != NULL )
1061         {
1062             if ( CallEval(wrapJS.GetOutputCode(), scriptAO, &varResult) )
1063                 *output = varResult.MakeString();
1064             else
1065                 err = _("failed to retrieve execution result");
1066         }
1067 
1068         CallEval(wrapJS.GetCleanUpCode(), scriptAO, &varResult);
1069     }
1070     else // result available but not the expected "true"
1071     {
1072         err = varResult.MakeString();
1073     }
1074 
1075     if ( !err.empty() )
1076     {
1077         wxLogWarning(_("Error running JavaScript: %s"), varResult.MakeString());
1078         return false;
1079     }
1080 
1081     return true;
1082 }
1083 
RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)1084 void wxWebViewIE::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
1085 {
1086     wxDynamicLibrary urlMon(wxT("urlmon.dll"));
1087     if(urlMon.HasSymbol(wxT("CoInternetGetSession")))
1088     {
1089         typedef HRESULT (WINAPI *CoInternetGetSession_t)(DWORD, wxIInternetSession**, DWORD);
1090         wxDYNLIB_FUNCTION(CoInternetGetSession_t, CoInternetGetSession, urlMon);
1091 
1092         ClassFactory* cf = new ClassFactory(handler);
1093         wxIInternetSession* session;
1094         HRESULT res = (*pfnCoInternetGetSession)(0, &session, 0);
1095         if(FAILED(res))
1096         {
1097             wxFAIL_MSG("Could not retrieve internet session");
1098         }
1099 
1100         HRESULT hr = session->RegisterNameSpace(cf, CLSID_FileProtocol,
1101                                                 handler->GetName().wc_str(),
1102                                                 0, NULL, 0);
1103         if(FAILED(hr))
1104         {
1105             wxFAIL_MSG("Could not register protocol");
1106         }
1107         m_impl->m_factories.push_back(cf);
1108     }
1109     else
1110     {
1111         wxFAIL_MSG("urlmon does not contain CoInternetGetSession");
1112     }
1113 }
1114 
GetNativeBackend() const1115 void* wxWebViewIE::GetNativeBackend() const
1116 {
1117     return m_impl->m_webBrowser;
1118 }
1119 
CanExecCommand(wxString command) const1120 bool wxWebViewIEImpl::CanExecCommand(wxString command) const
1121 {
1122     wxCOMPtr<IHTMLDocument2> document(GetDocument());
1123 
1124     if(document)
1125     {
1126         VARIANT_BOOL enabled;
1127 
1128         document->queryCommandEnabled(wxBasicString(command), &enabled);
1129 
1130         return (enabled == VARIANT_TRUE);
1131     }
1132     else
1133     {
1134         return false;
1135     }
1136 
1137 }
1138 
ExecCommand(wxString command)1139 void wxWebViewIEImpl::ExecCommand(wxString command)
1140 {
1141     wxCOMPtr<IHTMLDocument2> document(GetDocument());
1142 
1143     if(document)
1144     {
1145         document->execCommand(wxBasicString(command), VARIANT_FALSE, VARIANT(), NULL);
1146     }
1147 }
1148 
GetDocument() const1149 wxCOMPtr<IHTMLDocument2> wxWebViewIEImpl::GetDocument() const
1150 {
1151     wxCOMPtr<IDispatch> dispatch;
1152     wxCOMPtr<IHTMLDocument2> document;
1153     HRESULT result = m_webBrowser->get_Document(&dispatch);
1154     if(dispatch && SUCCEEDED(result))
1155     {
1156         //document is set to null automatically if the interface isn't supported
1157         dispatch->QueryInterface(IID_IHTMLDocument2, (void**)&document);
1158     }
1159     return document;
1160 }
1161 
IsElementVisible(wxCOMPtr<IHTMLElement> elm)1162 bool wxWebViewIEImpl::IsElementVisible(wxCOMPtr<IHTMLElement> elm)
1163 {
1164     wxCOMPtr<IHTMLElement> elm1 = elm;
1165     bool is_visible = true;
1166     //This method is not perfect but it does discover most of the hidden elements.
1167     //so if a better solution is found, then please do improve.
1168     while(elm1)
1169     {
1170         wxCOMPtr<wxIHTMLElement2> elm2;
1171         if(SUCCEEDED(elm1->QueryInterface(wxIID_IHTMLElement2, (void**) &elm2)))
1172         {
1173             wxCOMPtr<wxIHTMLCurrentStyle> style;
1174             if(SUCCEEDED(elm2->get_currentStyle(&style)))
1175             {
1176                 wxBasicString display_bstr;
1177                 wxBasicString visibility_bstr;
1178 
1179                 //Check if the object has the style display:none.
1180                 if((style->get_display(display_bstr.ByRef()) != S_OK) ||
1181                     wxString(display_bstr).IsSameAs(wxS("none"), false))
1182                 {
1183                     is_visible = false;
1184                 }
1185                 //Check if the object has the style visibility:hidden.
1186                 if((is_visible && (style->get_visibility(visibility_bstr.ByRef()) != S_OK)) ||
1187                     wxString(visibility_bstr).IsSameAs(wxS("hidden"), false))
1188                 {
1189                     is_visible = false;
1190                 }
1191                 style->Release();
1192             }
1193             elm2->Release();
1194         }
1195 
1196         //Lets check the object's parent element.
1197         IHTMLElement* parent;
1198         if(is_visible && SUCCEEDED(elm1->get_parentElement(&parent)))
1199         {
1200             elm1 = parent;
1201         }
1202         else
1203         {
1204             elm1->Release();
1205             break;
1206         }
1207     }
1208     return is_visible;
1209 }
1210 
FindInternal(const wxString & text,int flags,int internal_flag)1211 void wxWebViewIEImpl::FindInternal(const wxString& text, int flags, int internal_flag)
1212 {
1213     long find_flag = 0;
1214     wxCOMPtr<wxIMarkupServices> pIMS;
1215     wxCOMPtr<IHTMLDocument2> document = GetDocument();
1216 
1217     //This function does the acutal work.
1218     if(document && SUCCEEDED(document->QueryInterface(wxIID_IMarkupServices, (void **)&pIMS)))
1219     {
1220         wxCOMPtr<wxIMarkupContainer> pIMC;
1221         if(SUCCEEDED(document->QueryInterface(wxIID_IMarkupContainer, (void **)&pIMC)))
1222         {
1223             wxCOMPtr<wxIMarkupPointer> ptrBegin, ptrEnd;
1224             wxBasicString attr_bstr(wxS("style=\"background-color:#ffff00\""));
1225             wxBasicString text_bstr(text);
1226 
1227             pIMS->CreateMarkupPointer(&ptrBegin);
1228             pIMS->CreateMarkupPointer(&ptrEnd);
1229 
1230             ptrBegin->SetGravity(wxPOINTER_GRAVITY_Right);
1231             ptrBegin->MoveToContainer(pIMC, TRUE);
1232             //Create the find flag from the wx one.
1233             if(flags & wxWEBVIEW_FIND_ENTIRE_WORD)
1234             {
1235                 find_flag |= wxFINDTEXT_WHOLEWORD;
1236             }
1237             if(flags & wxWEBVIEW_FIND_MATCH_CASE)
1238             {
1239                 find_flag |= wxFINDTEXT_MATCHCASE;
1240             }
1241 
1242             //A little speed-up to avoid to re-alloc in the positions vector.
1243             if(text.Len() < 3 && m_findPointers.capacity() < 500)
1244             {
1245                m_findPointers.reserve(text.Len() == 1 ? 1000 : 500);
1246             }
1247 
1248             while(ptrBegin->FindText(text_bstr, find_flag, ptrEnd, NULL) == S_OK)
1249             {
1250                 wxCOMPtr<IHTMLElement> elm;
1251                 if(ptrBegin->CurrentScope(&elm) == S_OK)
1252                 {
1253                     if(IsElementVisible(elm))
1254                     {
1255                         //Highlight the word if the flag was set.
1256                         if(flags & wxWEBVIEW_FIND_HIGHLIGHT_RESULT)
1257                         {
1258                             IHTMLElement* pFontEl;
1259                             pIMS->CreateElement(wxTAGID_FONT, attr_bstr, &pFontEl);
1260                             pIMS->InsertElement(pFontEl, ptrBegin, ptrEnd);
1261                         }
1262                         if(internal_flag & wxWEBVIEW_FIND_REMOVE_HIGHLIGHT)
1263                         {
1264                             IHTMLElement* pFontEl;
1265                             ptrBegin->CurrentScope(&pFontEl);
1266                             pIMS->RemoveElement(pFontEl);
1267                             pFontEl->Release();
1268                         }
1269                         if(internal_flag & wxWEBVIEW_FIND_ADD_POINTERS)
1270                         {
1271                             wxIMarkupPointer *cptrBegin, *cptrEnd;
1272                             pIMS->CreateMarkupPointer(&cptrBegin);
1273                             pIMS->CreateMarkupPointer(&cptrEnd);
1274                             cptrBegin->MoveToPointer(ptrBegin);
1275                             cptrEnd->MoveToPointer(ptrEnd);
1276                             m_findPointers.push_back(wxFindPointers(cptrBegin,cptrEnd));
1277                         }
1278                     }
1279                 }
1280                 ptrBegin->MoveToPointer(ptrEnd);
1281             }
1282         }
1283     }
1284 }
1285 
FindNext(int direction)1286 long wxWebViewIEImpl::FindNext(int direction)
1287 {
1288     //Don't bother if we have no pointers set.
1289     if(m_findPointers.empty())
1290     {
1291         return wxNOT_FOUND;
1292     }
1293     //Manage the find position and do some checks.
1294     if(direction > 0)
1295     {
1296         m_findPosition++;
1297     }
1298     else
1299     {
1300         m_findPosition--;
1301     }
1302 
1303     if(m_findPosition >= (signed)m_findPointers.size())
1304     {
1305         if(m_findFlags & wxWEBVIEW_FIND_WRAP)
1306         {
1307             m_findPosition = 0;
1308         }
1309         else
1310         {
1311             m_findPosition--;
1312             return wxNOT_FOUND;
1313         }
1314     }
1315     else if(m_findPosition < 0)
1316     {
1317         if(m_findFlags & wxWEBVIEW_FIND_WRAP)
1318         {
1319             m_findPosition = m_findPointers.size()-1;
1320         }
1321         else
1322         {
1323             m_findPosition++;
1324             return wxNOT_FOUND;
1325         }
1326     }
1327 
1328     wxCOMPtr<IHTMLDocument2> document = GetDocument();
1329     wxCOMPtr<IHTMLElement> body_element;
1330 
1331     long ret = -1;
1332     //Now try to create a range from the body.
1333     if(document && SUCCEEDED(document->get_body(&body_element)))
1334     {
1335         wxCOMPtr<IHTMLBodyElement> body;
1336         if(SUCCEEDED(body_element->QueryInterface(IID_IHTMLBodyElement,(void**)&body)))
1337         {
1338             wxCOMPtr<wxIHTMLTxtRange> range;
1339             if(SUCCEEDED(body->createTextRange((IHTMLTxtRange**)(&range))))
1340             {
1341                 wxCOMPtr<wxIMarkupServices> pIMS;
1342                 //So far so good, now we try to position our find pointers.
1343                 if(SUCCEEDED(document->QueryInterface(wxIID_IMarkupServices,(void **)&pIMS)))
1344                 {
1345                     wxIMarkupPointer *begin = m_findPointers[m_findPosition].begin, *end = m_findPointers[m_findPosition].end;
1346                     if(pIMS->MoveRangeToPointers(begin,end,range) == S_OK && range->select() == S_OK)
1347                     {
1348                         ret = m_findPosition;
1349                     }
1350                 }
1351             }
1352         }
1353     }
1354     return ret;
1355 }
1356 
FindClear()1357 void wxWebViewIEImpl::FindClear()
1358 {
1359     //Reset find variables.
1360     m_findText.Empty();
1361     m_findFlags = wxWEBVIEW_FIND_DEFAULT;
1362     m_findPosition = -1;
1363 
1364     //The m_findPointers contains pointers for the found text.
1365     //Since it uses ref counting we call release on the pointers first
1366     //before we remove them from the vector. In other words do not just
1367     //remove elements from m_findPointers without calling release first
1368     //or you will get a memory leak.
1369     size_t count = m_findPointers.size();
1370     for(size_t i = 0; i < count; i++)
1371     {
1372         m_findPointers[i].begin->Release();
1373         m_findPointers[i].end->Release();
1374     }
1375     m_findPointers.clear();
1376 }
1377 
EnableControlFeature(long flag,bool enable)1378 bool wxWebViewIEImpl::EnableControlFeature(long flag, bool enable)
1379 {
1380 #if wxUSE_DYNLIB_CLASS
1381 
1382     wxDynamicLibrary urlMon(wxT("urlmon.dll"));
1383     if( urlMon.IsLoaded() &&
1384         urlMon.HasSymbol("CoInternetSetFeatureEnabled") &&
1385         urlMon.HasSymbol("CoInternetIsFeatureEnabled"))
1386     {
1387         typedef HRESULT (WINAPI *CoInternetSetFeatureEnabled_t)(DWORD, DWORD, BOOL);
1388         typedef HRESULT (WINAPI *CoInternetIsFeatureEnabled_t)(DWORD, DWORD);
1389 
1390         wxDYNLIB_FUNCTION(CoInternetSetFeatureEnabled_t, CoInternetSetFeatureEnabled, urlMon);
1391         wxDYNLIB_FUNCTION(CoInternetIsFeatureEnabled_t, CoInternetIsFeatureEnabled, urlMon);
1392 
1393         HRESULT hr = (*pfnCoInternetIsFeatureEnabled)(flag,
1394                                                       0x2 /* SET_FEATURE_ON_PROCESS */);
1395         if((hr == S_OK && enable) || (hr == S_FALSE && !enable))
1396             return true;
1397 
1398         hr = (*pfnCoInternetSetFeatureEnabled)(flag,
1399                                                0x2/* SET_FEATURE_ON_PROCESS */,
1400                                                (enable ? TRUE : FALSE));
1401         if ( FAILED(hr) )
1402         {
1403             wxLogApiError(wxT("CoInternetSetFeatureEnabled"), hr);
1404             return false;
1405         }
1406         return true;
1407     }
1408     return false;
1409 #else
1410     wxUnusedVar(flag);
1411     wxUnusedVar(enable);
1412     return false;
1413 #endif // wxUSE_DYNLIB_CLASS/!wxUSE_DYNLIB_CLASS
1414 }
1415 
onActiveXEvent(wxActiveXEvent & evt)1416 void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
1417 {
1418     if (m_impl->m_webBrowser == NULL) return;
1419 
1420     switch (evt.GetDispatchId())
1421     {
1422         case DISPID_BEFORENAVIGATE2:
1423         {
1424             m_impl->m_isBusy = true;
1425 
1426             wxString url = evt[1].GetString();
1427             wxString target = evt[3].GetString();
1428 
1429             wxWebViewEvent event(wxEVT_WEBVIEW_NAVIGATING,
1430                                  GetId(), url, target);
1431 
1432             //skip empty javascript events.
1433             if(url == "javascript:\"\"" && target.IsEmpty())
1434             {
1435                 event.Veto();
1436             }
1437             else
1438             {
1439                 event.SetEventObject(this);
1440                 HandleWindowEvent(event);
1441             }
1442 
1443             if (!event.IsAllowed())
1444             {
1445                 wxActiveXEventNativeMSW* nativeParams =
1446                     evt.GetNativeParameters();
1447                 *V_BOOLREF(&nativeParams->pDispParams->rgvarg[0]) = VARIANT_TRUE;
1448             }
1449 
1450             // at this point, either the navigation event has been cancelled
1451             // and we're not busy, either it was accepted and IWebBrowser2's
1452             // Busy property will be true; so we don't need our override
1453             // flag anymore.
1454             m_impl->m_isBusy = false;
1455 
1456             break;
1457         }
1458 
1459         case DISPID_NAVIGATECOMPLETE2:
1460         {
1461             wxString url = evt[1].GetString();
1462             // TODO: set target parameter if possible
1463             wxString target;
1464             wxWebViewEvent event(wxEVT_WEBVIEW_NAVIGATED,
1465                                  GetId(), url, target);
1466             event.SetEventObject(this);
1467             HandleWindowEvent(event);
1468             break;
1469         }
1470 
1471         case DISPID_PROGRESSCHANGE:
1472         {
1473             // download progress
1474             break;
1475         }
1476 
1477         case DISPID_DOCUMENTCOMPLETE:
1478         {
1479             //Only send a complete even if we are actually finished, this brings
1480             //the event in to line with webkit
1481             READYSTATE rs;
1482             m_impl->m_webBrowser->get_ReadyState( &rs );
1483             if(rs != READYSTATE_COMPLETE)
1484                 break;
1485 
1486             wxString url = evt[1].GetString();
1487 
1488             //As we are complete we also add to the history list, but not if the
1489             //page is not the main page, ie it is a subframe
1490             //We also have to check if we are loading a file:// url, if so we
1491             //need to change the comparison as ie passes back a different style
1492             //of url
1493             if(m_impl->m_historyEnabled && !m_impl->m_historyLoadingFromList &&
1494               (url == GetCurrentURL() ||
1495               (GetCurrentURL().substr(0, 4) == "file" &&
1496                wxFileName::URLToFileName(GetCurrentURL()).GetFullPath() == url)))
1497             {
1498                 //If we are not at the end of the list, then erase everything
1499                 //between us and the end before adding the new page
1500                 if(m_impl->m_historyPosition != static_cast<int>(m_impl->m_historyList.size()) - 1)
1501                 {
1502                     m_impl->m_historyList.erase(m_impl->m_historyList.begin() + m_impl->m_historyPosition + 1,
1503                                                 m_impl->m_historyList.end());
1504                 }
1505                 wxSharedPtr<wxWebViewHistoryItem> item(new wxWebViewHistoryItem(url, GetCurrentTitle()));
1506                 m_impl->m_historyList.push_back(item);
1507                 m_impl->m_historyPosition++;
1508             }
1509             //Reset as we are done now
1510             m_impl->m_historyLoadingFromList = false;
1511             //Reset the find values.
1512             m_impl->FindClear();
1513             // TODO: set target parameter if possible
1514             wxString target;
1515             wxWebViewEvent event(wxEVT_WEBVIEW_LOADED, GetId(),
1516                                  url, target);
1517             event.SetEventObject(this);
1518             HandleWindowEvent(event);
1519             break;
1520         }
1521 
1522         case DISPID_STATUSTEXTCHANGE:
1523         {
1524             break;
1525         }
1526 
1527         case DISPID_TITLECHANGE:
1528         {
1529             wxString title = evt[0].GetString();
1530 
1531             wxWebViewEvent event(wxEVT_WEBVIEW_TITLE_CHANGED,
1532                                  GetId(), GetCurrentURL(), "");
1533             event.SetString(title);
1534             event.SetEventObject(this);
1535             HandleWindowEvent(event);
1536             break;
1537         }
1538 
1539         case DISPID_NAVIGATEERROR:
1540         {
1541             wxWebViewEvent event(wxEVT_WEBVIEW_ERROR, GetId(),
1542                                  evt[1].GetString(), evt[2].GetString());
1543             event.SetEventObject(this);
1544 
1545             switch (evt[3].GetLong())
1546             {
1547                 // 400 Error codes
1548                 WX_ERROR_CASE(HTTP_STATUS_BAD_REQUEST, wxWEBVIEW_NAV_ERR_REQUEST)
1549                 WX_ERROR_CASE(HTTP_STATUS_DENIED, wxWEBVIEW_NAV_ERR_AUTH)
1550                 WX_ERROR_CASE(HTTP_STATUS_PAYMENT_REQ, wxWEBVIEW_NAV_ERR_OTHER)
1551                 WX_ERROR_CASE(HTTP_STATUS_FORBIDDEN, wxWEBVIEW_NAV_ERR_AUTH)
1552                 WX_ERROR_CASE(HTTP_STATUS_NOT_FOUND, wxWEBVIEW_NAV_ERR_NOT_FOUND)
1553                 WX_ERROR_CASE(HTTP_STATUS_BAD_METHOD, wxWEBVIEW_NAV_ERR_REQUEST)
1554                 WX_ERROR_CASE(HTTP_STATUS_NONE_ACCEPTABLE, wxWEBVIEW_NAV_ERR_OTHER)
1555                 WX_ERROR_CASE(HTTP_STATUS_PROXY_AUTH_REQ, wxWEBVIEW_NAV_ERR_AUTH)
1556                 WX_ERROR_CASE(HTTP_STATUS_REQUEST_TIMEOUT, wxWEBVIEW_NAV_ERR_CONNECTION)
1557                 WX_ERROR_CASE(HTTP_STATUS_CONFLICT, wxWEBVIEW_NAV_ERR_REQUEST)
1558                 WX_ERROR_CASE(HTTP_STATUS_GONE, wxWEBVIEW_NAV_ERR_NOT_FOUND)
1559                 WX_ERROR_CASE(HTTP_STATUS_LENGTH_REQUIRED, wxWEBVIEW_NAV_ERR_REQUEST)
1560                 WX_ERROR_CASE(HTTP_STATUS_PRECOND_FAILED, wxWEBVIEW_NAV_ERR_REQUEST)
1561                 WX_ERROR_CASE(HTTP_STATUS_REQUEST_TOO_LARGE, wxWEBVIEW_NAV_ERR_REQUEST)
1562                 WX_ERROR_CASE(HTTP_STATUS_URI_TOO_LONG, wxWEBVIEW_NAV_ERR_REQUEST)
1563                 WX_ERROR_CASE(HTTP_STATUS_UNSUPPORTED_MEDIA, wxWEBVIEW_NAV_ERR_REQUEST)
1564                 WX_ERROR_CASE(HTTP_STATUS_RETRY_WITH, wxWEBVIEW_NAV_ERR_OTHER)
1565 
1566                 // 500 - Error codes
1567                 WX_ERROR_CASE(HTTP_STATUS_SERVER_ERROR, wxWEBVIEW_NAV_ERR_CONNECTION)
1568                 WX_ERROR_CASE(HTTP_STATUS_NOT_SUPPORTED, wxWEBVIEW_NAV_ERR_CONNECTION)
1569                 WX_ERROR_CASE(HTTP_STATUS_BAD_GATEWAY, wxWEBVIEW_NAV_ERR_CONNECTION)
1570                 WX_ERROR_CASE(HTTP_STATUS_SERVICE_UNAVAIL, wxWEBVIEW_NAV_ERR_CONNECTION)
1571                 WX_ERROR_CASE(HTTP_STATUS_GATEWAY_TIMEOUT, wxWEBVIEW_NAV_ERR_CONNECTION)
1572                 WX_ERROR_CASE(HTTP_STATUS_VERSION_NOT_SUP, wxWEBVIEW_NAV_ERR_REQUEST)
1573 
1574                 // URL Moniker error codes
1575                 WX_ERROR_CASE(INET_E_INVALID_URL, wxWEBVIEW_NAV_ERR_REQUEST)
1576                 WX_ERROR_CASE(INET_E_NO_SESSION, wxWEBVIEW_NAV_ERR_CONNECTION)
1577                 WX_ERROR_CASE(INET_E_CANNOT_CONNECT, wxWEBVIEW_NAV_ERR_CONNECTION)
1578                 WX_ERROR_CASE(INET_E_RESOURCE_NOT_FOUND, wxWEBVIEW_NAV_ERR_NOT_FOUND)
1579                 WX_ERROR_CASE(INET_E_OBJECT_NOT_FOUND, wxWEBVIEW_NAV_ERR_NOT_FOUND)
1580                 WX_ERROR_CASE(INET_E_DATA_NOT_AVAILABLE, wxWEBVIEW_NAV_ERR_NOT_FOUND)
1581                 WX_ERROR_CASE(INET_E_DOWNLOAD_FAILURE, wxWEBVIEW_NAV_ERR_CONNECTION)
1582                 WX_ERROR_CASE(INET_E_AUTHENTICATION_REQUIRED, wxWEBVIEW_NAV_ERR_AUTH)
1583                 WX_ERROR_CASE(INET_E_NO_VALID_MEDIA, wxWEBVIEW_NAV_ERR_REQUEST)
1584                 WX_ERROR_CASE(INET_E_CONNECTION_TIMEOUT, wxWEBVIEW_NAV_ERR_CONNECTION)
1585                 WX_ERROR_CASE(INET_E_INVALID_REQUEST, wxWEBVIEW_NAV_ERR_REQUEST)
1586                 WX_ERROR_CASE(INET_E_UNKNOWN_PROTOCOL, wxWEBVIEW_NAV_ERR_REQUEST)
1587                 WX_ERROR_CASE(INET_E_SECURITY_PROBLEM, wxWEBVIEW_NAV_ERR_SECURITY)
1588                 WX_ERROR_CASE(INET_E_CANNOT_LOAD_DATA, wxWEBVIEW_NAV_ERR_OTHER)
1589                 WX_ERROR_CASE(INET_E_REDIRECT_FAILED, wxWEBVIEW_NAV_ERR_OTHER)
1590                 WX_ERROR_CASE(INET_E_REDIRECT_TO_DIR, wxWEBVIEW_NAV_ERR_REQUEST)
1591                 WX_ERROR_CASE(INET_E_CANNOT_LOCK_REQUEST, wxWEBVIEW_NAV_ERR_OTHER)
1592                 WX_ERROR_CASE(INET_E_USE_EXTEND_BINDING, wxWEBVIEW_NAV_ERR_OTHER)
1593                 WX_ERROR_CASE(INET_E_TERMINATED_BIND, wxWEBVIEW_NAV_ERR_OTHER)
1594                 WX_ERROR_CASE(INET_E_INVALID_CERTIFICATE, wxWEBVIEW_NAV_ERR_CERTIFICATE)
1595                 WX_ERROR_CASE(INET_E_CODE_DOWNLOAD_DECLINED, wxWEBVIEW_NAV_ERR_USER_CANCELLED)
1596                 WX_ERROR_CASE(INET_E_RESULT_DISPATCHED, wxWEBVIEW_NAV_ERR_OTHER)
1597                 WX_ERROR_CASE(INET_E_CANNOT_REPLACE_SFP_FILE, wxWEBVIEW_NAV_ERR_SECURITY)
1598                 WX_ERROR_CASE(INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY, wxWEBVIEW_NAV_ERR_SECURITY)
1599                 WX_ERROR_CASE(INET_E_CODE_INSTALL_SUPPRESSED, wxWEBVIEW_NAV_ERR_SECURITY)
1600             }
1601             HandleWindowEvent(event);
1602             break;
1603         }
1604         case DISPID_NEWWINDOW3:
1605         {
1606             wxString url = evt[4].GetString();
1607             long flags = evt[2].GetLong();
1608 
1609             wxWebViewNavigationActionFlags navFlags = wxWEBVIEW_NAV_ACTION_OTHER;
1610 
1611             if(flags & wxNWMF_USERINITED || flags & wxNWMF_USERREQUESTED)
1612                 navFlags = wxWEBVIEW_NAV_ACTION_USER;
1613 
1614             wxWebViewEvent event(wxEVT_WEBVIEW_NEWWINDOW,
1615                                  GetId(), url, wxEmptyString, navFlags);
1616             event.SetEventObject(this);
1617             HandleWindowEvent(event);
1618 
1619             //We always cancel this event otherwise an Internet Exporer window
1620             //is opened for the url
1621             wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters();
1622             *V_BOOLREF(&nativeParams->pDispParams->rgvarg[3]) = VARIANT_TRUE;
1623             break;
1624         }
1625     }
1626 
1627     evt.Skip();
1628 }
1629 
VirtualProtocol(wxSharedPtr<wxWebViewHandler> handler)1630 VirtualProtocol::VirtualProtocol(wxSharedPtr<wxWebViewHandler> handler)
1631 {
1632     m_file = NULL;
1633     m_handler = handler;
1634 }
1635 
QueryInterface(REFIID riid,void ** ppv)1636 STDMETHODIMP VirtualProtocol::QueryInterface(REFIID riid, void **ppv)
1637 {
1638     wxLogQueryInterface(wxT("VirtualProtocol"), riid);
1639 
1640     if(riid == IID_IUnknown)
1641     {
1642         wxIInternetProtocolRoot *InternetProtocolRoot = this;
1643         IUnknown *Unknown = InternetProtocolRoot;
1644         *ppv = Unknown;
1645         AddRef();
1646         return S_OK;
1647     }
1648     if(riid == wxIID_IInternetProtocolRoot)
1649     {
1650         wxIInternetProtocolRoot *InternetProtocolRoot = this;
1651         *ppv = InternetProtocolRoot;
1652         AddRef();
1653         return S_OK;
1654     }
1655     if(riid == wxIID_IInternetProtocol)
1656     {
1657         wxIInternetProtocol *InternetProtocol = this;
1658         *ppv = InternetProtocol;
1659         AddRef();
1660         return S_OK;
1661     }
1662     if(riid == wxIID_IInternetProtocolInfo)
1663     {
1664         wxIInternetProtocolInfo *InternetProtocolInfo = this;
1665         *ppv = InternetProtocolInfo;
1666         AddRef();
1667         return S_OK;
1668     }
1669 
1670     *ppv = NULL;
1671     return (HRESULT) E_NOINTERFACE;
1672 }
1673 
STDMETHODIMP_(ULONG)1674 STDMETHODIMP_(ULONG) VirtualProtocol::AddRef()
1675 {
1676     wxLogAddRef(wxT("VirtualProtocol"), m_cRef);
1677     return ++m_cRef;
1678 }
1679 
STDMETHODIMP_(ULONG)1680 STDMETHODIMP_(ULONG) VirtualProtocol::Release()
1681 {
1682     wxLogRelease(wxT("VirtualProtocol"), m_cRef);
1683     if( --m_cRef == wxAutoULong(0))
1684     {
1685         delete this;
1686         return 0;
1687     }
1688     else
1689         return m_cRef;
1690 }
1691 
Start(LPCWSTR szUrl,wxIInternetProtocolSink * pOIProtSink,wxIInternetBindInfo * pOIBindInfo,DWORD grfPI,HANDLE_PTR dwReserved)1692 HRESULT STDMETHODCALLTYPE VirtualProtocol::Start(LPCWSTR szUrl, wxIInternetProtocolSink *pOIProtSink,
1693                                wxIInternetBindInfo *pOIBindInfo, DWORD grfPI,
1694                                HANDLE_PTR dwReserved)
1695 {
1696     wxUnusedVar(szUrl);
1697     wxUnusedVar(pOIBindInfo);
1698     wxUnusedVar(grfPI);
1699     wxUnusedVar(dwReserved);
1700     m_protocolSink = pOIProtSink;
1701 
1702     //We get the file itself from the protocol handler
1703     m_file = m_handler->GetFile(szUrl);
1704 
1705 
1706     if(!m_file)
1707         return INET_E_RESOURCE_NOT_FOUND;
1708 
1709     //We return the stream length for current and total size as we can always
1710     //read the whole file from the stream
1711     wxFileOffset length = m_file->GetStream()->GetLength();
1712     m_protocolSink->ReportData(wxBSCF_FIRSTDATANOTIFICATION |
1713                                wxBSCF_DATAFULLYAVAILABLE |
1714                                wxBSCF_LASTDATANOTIFICATION,
1715                                length, length);
1716     return S_OK;
1717 }
1718 
Read(void * pv,ULONG cb,ULONG * pcbRead)1719 HRESULT STDMETHODCALLTYPE VirtualProtocol::Read(void *pv, ULONG cb, ULONG *pcbRead)
1720 {
1721     //If the file is null we return false to indicte it is finished
1722     if(!m_file)
1723         return S_FALSE;
1724 
1725     wxStreamError err = m_file->GetStream()->Read(pv, cb).GetLastError();
1726     *pcbRead = m_file->GetStream()->LastRead();
1727 
1728     if(err == wxSTREAM_NO_ERROR)
1729     {
1730         if(*pcbRead < cb)
1731         {
1732             wxDELETE(m_file);
1733             m_protocolSink->ReportResult(S_OK, 0, NULL);
1734         }
1735         //As we are not eof there is more data
1736         return S_OK;
1737     }
1738     else if(err == wxSTREAM_EOF)
1739     {
1740         wxDELETE(m_file);
1741         m_protocolSink->ReportResult(S_OK, 0, NULL);
1742         //We are eof and so finished
1743         return S_OK;
1744     }
1745     else if(err ==  wxSTREAM_READ_ERROR)
1746     {
1747         wxDELETE(m_file);
1748         return INET_E_DOWNLOAD_FAILURE;
1749     }
1750     else
1751     {
1752         //Dummy return to suppress a compiler warning
1753         wxFAIL;
1754         return INET_E_DOWNLOAD_FAILURE;
1755     }
1756 }
1757 
CombineUrl(LPCWSTR pwzBaseUrl,LPCWSTR pwzRelativeUrl,DWORD dwCombineFlags,LPWSTR pwzResult,DWORD cchResult,DWORD * pcchResult,DWORD dwReserved)1758 HRESULT STDMETHODCALLTYPE VirtualProtocol::CombineUrl(
1759         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl,
1760         DWORD dwCombineFlags, LPWSTR pwzResult,
1761         DWORD cchResult, DWORD *pcchResult,
1762         DWORD dwReserved)
1763 {
1764     wxUnusedVar(pwzBaseUrl);
1765     wxUnusedVar(pwzRelativeUrl);
1766     wxUnusedVar(dwCombineFlags);
1767     wxUnusedVar(pwzResult);
1768     wxUnusedVar(cchResult);
1769     wxUnusedVar(pcchResult);
1770     wxUnusedVar(dwReserved);
1771 
1772     return INET_E_DEFAULT_ACTION;
1773 }
1774 
ParseUrl(LPCWSTR pwzUrl,wxPARSEACTION ParseAction,DWORD dwParseFlags,LPWSTR pwzResult,DWORD cchResult,DWORD * pcchResult,DWORD dwReserved)1775 HRESULT STDMETHODCALLTYPE VirtualProtocol::ParseUrl(
1776         LPCWSTR pwzUrl, wxPARSEACTION ParseAction,
1777         DWORD dwParseFlags, LPWSTR pwzResult,
1778         DWORD cchResult, DWORD *pcchResult,
1779         DWORD dwReserved)
1780 {
1781     wxUnusedVar(pwzUrl);
1782     wxUnusedVar(dwParseFlags);
1783     wxUnusedVar(dwReserved);
1784 
1785     const size_t secLen = m_handler->GetSecurityURL().length();
1786     if ( secLen > 0 )
1787     {
1788         switch ( ParseAction )
1789         {
1790             case wxPARSE_SECURITY_URL:
1791             case wxPARSE_SECURITY_DOMAIN:
1792             {
1793                 if ( cchResult < secLen )
1794                     return S_FALSE;
1795                 wcscpy(pwzResult, m_handler->GetSecurityURL().wc_str());
1796                 *pcchResult = secLen;
1797                 return S_OK;
1798             }
1799         }
1800     }
1801 
1802     return INET_E_DEFAULT_ACTION;
1803 }
1804 
CompareUrl(LPCWSTR pwzUrl1,LPCWSTR pwzUrl2,DWORD dwCompareFlags)1805 HRESULT STDMETHODCALLTYPE VirtualProtocol::CompareUrl(
1806         LPCWSTR pwzUrl1,
1807         LPCWSTR pwzUrl2,
1808         DWORD dwCompareFlags)
1809 {
1810     wxUnusedVar(pwzUrl1);
1811     wxUnusedVar(pwzUrl2);
1812     wxUnusedVar(dwCompareFlags);
1813 
1814     return INET_E_DEFAULT_ACTION;
1815 }
1816 
QueryInfo(LPCWSTR pwzUrl,wxQUERYOPTION OueryOption,DWORD dwQueryFlags,LPVOID pBuffer,DWORD cbBuffer,DWORD * pcbBuf,DWORD dwReserved)1817 HRESULT STDMETHODCALLTYPE VirtualProtocol::QueryInfo(
1818         LPCWSTR pwzUrl, wxQUERYOPTION OueryOption,
1819         DWORD dwQueryFlags, LPVOID pBuffer,
1820         DWORD cbBuffer, DWORD *pcbBuf,
1821         DWORD dwReserved)
1822 {
1823     wxUnusedVar(pwzUrl);
1824     wxUnusedVar(OueryOption);
1825     wxUnusedVar(dwQueryFlags);
1826     wxUnusedVar(pBuffer);
1827     wxUnusedVar(cbBuffer);
1828     wxUnusedVar(pcbBuf);
1829     wxUnusedVar(dwReserved);
1830 
1831     return INET_E_DEFAULT_ACTION;
1832 }
1833 
1834 BEGIN_IID_TABLE(ClassFactory)
1835     ADD_IID(Unknown)
1836     ADD_IID(ClassFactory)
1837 END_IID_TABLE;
1838 
IMPLEMENT_IUNKNOWN_METHODS(ClassFactory)1839 IMPLEMENT_IUNKNOWN_METHODS(ClassFactory)
1840 
1841 HRESULT STDMETHODCALLTYPE ClassFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid,
1842                                      void ** ppvObject)
1843 {
1844     if (pUnkOuter)
1845         return CLASS_E_NOAGGREGATION;
1846     VirtualProtocol* vp = new VirtualProtocol(m_handler);
1847     vp->AddRef();
1848     HRESULT hr = vp->QueryInterface(riid, ppvObject);
1849     vp->Release();
1850     return hr;
1851 
1852 }
1853 
LockServer(BOOL fLock)1854 STDMETHODIMP ClassFactory::LockServer(BOOL fLock)
1855 {
1856     wxUnusedVar(fLock);
1857     return S_OK;
1858 }
1859 
wxIEContainer(wxWindow * parent,REFIID iid,IUnknown * pUnk,DocHostUIHandler * uiHandler)1860 wxIEContainer::wxIEContainer(wxWindow *parent, REFIID iid, IUnknown *pUnk,
1861                              DocHostUIHandler* uiHandler) :
1862     wxActiveXContainer(parent,iid,pUnk)
1863 {
1864     m_uiHandler = uiHandler;
1865 }
1866 
~wxIEContainer()1867 wxIEContainer::~wxIEContainer()
1868 {
1869 }
1870 
QueryClientSiteInterface(REFIID iid,void ** _interface,const char * & desc)1871 bool wxIEContainer::QueryClientSiteInterface(REFIID iid, void **_interface,
1872                                              const char *&desc)
1873 {
1874     if (m_uiHandler && IsEqualIID(iid, wxIID_IDocHostUIHandler))
1875     {
1876         *_interface = (IUnknown *) (wxIDocHostUIHandler *) m_uiHandler;
1877         desc = "IDocHostUIHandler";
1878         return true;
1879     }
1880     return false;
1881 }
1882 
ShowContextMenu(DWORD dwID,POINT * ppt,IUnknown * pcmdtReserved,IDispatch * pdispReserved)1883 HRESULT wxSTDCALL DocHostUIHandler::ShowContextMenu(DWORD dwID, POINT *ppt,
1884                                           IUnknown *pcmdtReserved,
1885                                           IDispatch *pdispReserved)
1886 {
1887     wxUnusedVar(dwID);
1888     wxUnusedVar(ppt);
1889     wxUnusedVar(pcmdtReserved);
1890     wxUnusedVar(pdispReserved);
1891     if(m_browser->IsContextMenuEnabled())
1892         return E_NOTIMPL;
1893     else
1894         return S_OK;
1895 }
1896 
GetHostInfo(DOCHOSTUIINFO * pInfo)1897 HRESULT wxSTDCALL DocHostUIHandler::GetHostInfo(DOCHOSTUIINFO *pInfo)
1898 {
1899     // Don't show 3d border and enable themes and also enable sending redirect
1900     // notifications as otherwise we wouldn't get wxEVT_WEBVIEW_NAVIGATING when
1901     // redirected.
1902     pInfo->dwFlags |= DOCHOSTUIFLAG_NO3DBORDER |
1903                       DOCHOSTUIFLAG_THEME |
1904                       DOCHOSTUIFLAG_ENABLE_REDIRECT_NOTIFICATION |
1905                       DOCHOSTUIFLAG_DPI_AWARE;
1906     return S_OK;
1907 }
1908 
ShowUI(DWORD dwID,IOleInPlaceActiveObject * pActiveObject,IOleCommandTarget * pCommandTarget,IOleInPlaceFrame * pFrame,IOleInPlaceUIWindow * pDoc)1909 HRESULT wxSTDCALL DocHostUIHandler::ShowUI(DWORD dwID,
1910                                  IOleInPlaceActiveObject *pActiveObject,
1911                                  IOleCommandTarget *pCommandTarget,
1912                                  IOleInPlaceFrame *pFrame,
1913                                  IOleInPlaceUIWindow *pDoc)
1914 {
1915     wxUnusedVar(dwID);
1916     wxUnusedVar(pActiveObject);
1917     wxUnusedVar(pCommandTarget);
1918     wxUnusedVar(pFrame);
1919     wxUnusedVar(pDoc);
1920     return S_FALSE;
1921 }
1922 
HideUI(void)1923 HRESULT wxSTDCALL DocHostUIHandler::HideUI(void)
1924 {
1925     return E_NOTIMPL;
1926 }
1927 
UpdateUI(void)1928 HRESULT wxSTDCALL DocHostUIHandler::UpdateUI(void)
1929 {
1930     return E_NOTIMPL;
1931 }
1932 
EnableModeless(BOOL fEnable)1933 HRESULT wxSTDCALL DocHostUIHandler::EnableModeless(BOOL fEnable)
1934 {
1935     wxUnusedVar(fEnable);
1936     return E_NOTIMPL;
1937 }
1938 
OnDocWindowActivate(BOOL fActivate)1939 HRESULT wxSTDCALL DocHostUIHandler::OnDocWindowActivate(BOOL fActivate)
1940 {
1941     wxUnusedVar(fActivate);
1942     return E_NOTIMPL;
1943 }
1944 
OnFrameWindowActivate(BOOL fActivate)1945 HRESULT wxSTDCALL DocHostUIHandler::OnFrameWindowActivate(BOOL fActivate)
1946 {
1947     wxUnusedVar(fActivate);
1948     return E_NOTIMPL;
1949 }
1950 
ResizeBorder(LPCRECT prcBorder,IOleInPlaceUIWindow * pUIWindow,BOOL fFrameWindow)1951 HRESULT wxSTDCALL DocHostUIHandler::ResizeBorder(LPCRECT prcBorder,
1952                                        IOleInPlaceUIWindow *pUIWindow,
1953                                        BOOL fFrameWindow)
1954 {
1955     wxUnusedVar(prcBorder);
1956     wxUnusedVar(pUIWindow);
1957     wxUnusedVar(fFrameWindow);
1958     return E_NOTIMPL;
1959 }
1960 
TranslateAccelerator(LPMSG lpMsg,const GUID * pguidCmdGroup,DWORD nCmdID)1961 HRESULT wxSTDCALL DocHostUIHandler::TranslateAccelerator(LPMSG lpMsg,
1962                                                const GUID *pguidCmdGroup,
1963                                                DWORD nCmdID)
1964 {
1965     if(lpMsg && lpMsg->message == WM_KEYDOWN)
1966     {
1967         // check control is down but that it isn't right-alt which is mapped to
1968         // alt + ctrl
1969         if(GetKeyState(VK_CONTROL) & 0x8000 &&
1970          !(GetKeyState(VK_MENU) & 0x8000))
1971         {
1972             //skip the accelerators used by the control
1973             switch(lpMsg->wParam)
1974             {
1975                 case 'F':
1976                 case 'L':
1977                 case 'N':
1978                 case 'O':
1979                 case 'P':
1980                     return S_OK;
1981             }
1982         }
1983         //skip F5
1984         if(lpMsg->wParam == VK_F5)
1985         {
1986             return S_OK;
1987         }
1988     }
1989 
1990     wxUnusedVar(pguidCmdGroup);
1991     wxUnusedVar(nCmdID);
1992     return E_NOTIMPL;
1993 }
1994 
GetOptionKeyPath(LPOLESTR * pchKey,DWORD dw)1995 HRESULT wxSTDCALL DocHostUIHandler::GetOptionKeyPath(LPOLESTR *pchKey,DWORD dw)
1996 {
1997     wxUnusedVar(pchKey);
1998     wxUnusedVar(dw);
1999     return E_NOTIMPL;
2000 }
2001 
GetDropTarget(IDropTarget * pDropTarget,IDropTarget ** ppDropTarget)2002 HRESULT wxSTDCALL DocHostUIHandler::GetDropTarget(IDropTarget *pDropTarget,
2003                                         IDropTarget **ppDropTarget)
2004 {
2005     wxUnusedVar(pDropTarget);
2006     wxUnusedVar(ppDropTarget);
2007     return E_NOTIMPL;
2008 }
2009 
GetExternal(IDispatch ** ppDispatch)2010 HRESULT wxSTDCALL DocHostUIHandler::GetExternal(IDispatch **ppDispatch)
2011 {
2012     wxUnusedVar(ppDispatch);
2013     return E_NOTIMPL;
2014 }
2015 
TranslateUrl(DWORD dwTranslate,OLECHAR * pchURLIn,OLECHAR ** ppchURLOut)2016 HRESULT wxSTDCALL DocHostUIHandler::TranslateUrl(DWORD dwTranslate,
2017                                        OLECHAR *pchURLIn,
2018                                        OLECHAR **ppchURLOut)
2019 {
2020     wxUnusedVar(dwTranslate);
2021     wxUnusedVar(pchURLIn);
2022     wxUnusedVar(ppchURLOut);
2023     return E_NOTIMPL;
2024 }
2025 
FilterDataObject(IDataObject * pDO,IDataObject ** ppDORet)2026 HRESULT wxSTDCALL DocHostUIHandler::FilterDataObject(IDataObject *pDO, IDataObject **ppDORet)
2027 {
2028     wxUnusedVar(pDO);
2029     wxUnusedVar(ppDORet);
2030     return E_NOTIMPL;
2031 }
2032 
2033 BEGIN_IID_TABLE(DocHostUIHandler)
2034     ADD_IID(Unknown)
2035     ADD_RAW_IID(wxIID_IDocHostUIHandler)
2036 END_IID_TABLE;
2037 
2038 IMPLEMENT_IUNKNOWN_METHODS(DocHostUIHandler)
2039 
2040 #endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE
2041