]> git.saurik.com Git - wxWidgets.git/blame - src/msw/webview_ie.cpp
Hide the infobar in the sample if we start navigating to another page.
[wxWidgets.git] / src / msw / webview_ie.cpp
CommitLineData
61b98a2d 1/////////////////////////////////////////////////////////////////////////////
8290e3cd 2// Name: src/msw/webview_ie.cpp
61b98a2d
SL
3// Purpose: wxMSW wxWebViewIE class implementation for web view component
4// Author: Marianne Gagnon
5// Id: $Id$
153530af 6// Copyright: (c) 2010 Marianne Gagnon, 2011 Steven Lamerton
61b98a2d
SL
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
384b8d9f
SL
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
13#if defined(__BORLANDC__)
14 #pragma hdrstop
15#endif
16
8290e3cd 17#include "wx/msw/webview_ie.h"
61b98a2d 18
66f2aa61 19#if wxUSE_WEBVIEW_IE
61b98a2d
SL
20
21#include <olectl.h>
22#include <oleidl.h>
23#include <exdispid.h>
24#include <exdisp.h>
25#include <mshtml.h>
cd4e4673 26#include "wx/msw/registry.h"
1d7d04d7 27#include "wx/msw/missing.h"
7d3f6b4d
SL
28#include "wx/filesys.h"
29
aa35b9ca
SL
30//We link to urlmon as it is required for CoInternetGetSession
31#pragma comment(lib, "urlmon")
32
61b98a2d 33BEGIN_EVENT_TABLE(wxWebViewIE, wxControl)
97ad1425
SL
34 EVT_ACTIVEX(wxID_ANY, wxWebViewIE::onActiveXEvent)
35 EVT_ERASE_BACKGROUND(wxWebViewIE::onEraseBg)
61b98a2d
SL
36END_EVENT_TABLE()
37
38bool wxWebViewIE::Create(wxWindow* parent,
39 wxWindowID id,
40 const wxString& url,
41 const wxPoint& pos,
42 const wxSize& size,
43 long style,
44 const wxString& name)
45{
46 if (!wxControl::Create(parent, id, pos, size, style,
47 wxDefaultValidator, name))
48 {
49 return false;
50 }
51
52 m_webBrowser = NULL;
61b98a2d 53 m_isBusy = false;
74af0b13
SL
54 m_historyLoadingFromList = false;
55 m_historyEnabled = true;
56 m_historyPosition = -1;
c5f417cb 57 m_zoomType = wxWEB_VIEW_ZOOM_TYPE_TEXT;
61b98a2d
SL
58
59 if (::CoCreateInstance(CLSID_WebBrowser, NULL,
60 CLSCTX_INPROC_SERVER, // CLSCTX_INPROC,
61 IID_IWebBrowser2 , (void**)&m_webBrowser) != 0)
62 {
63 wxLogError("Failed to initialize IE, CoCreateInstance returned an error");
64 return false;
65 }
66
67 m_ie.SetDispatchPtr(m_webBrowser); // wxAutomationObject will release itself
68
69 m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
70 m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
61b98a2d
SL
71
72 m_container = new wxActiveXContainer(this, IID_IWebBrowser2, m_webBrowser);
73
74 SetBackgroundStyle(wxBG_STYLE_PAINT);
75 SetDoubleBuffered(true);
9ef101cd 76 LoadUrl(url);
61b98a2d
SL
77 return true;
78}
79
80
81void wxWebViewIE::LoadUrl(const wxString& url)
82{
7fbc727b 83 m_ie.CallMethod("Navigate", (BSTR) url.wc_str(), NULL, NULL, NULL, NULL);
61b98a2d
SL
84}
85
442262d4 86void wxWebViewIE::SetPage(const wxString& html, const wxString& baseUrl)
61b98a2d 87{
61b98a2d
SL
88 BSTR bstr = SysAllocString(html.wc_str());
89
90 // Creates a new one-dimensional array
91 SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1);
92 if (psaStrings != NULL)
93 {
94 VARIANT *param;
442262d4 95
61b98a2d
SL
96 HRESULT hr = SafeArrayAccessData(psaStrings, (LPVOID*)&param);
97 param->vt = VT_BSTR;
98 param->bstrVal = bstr;
61b98a2d 99 hr = SafeArrayUnaccessData(psaStrings);
442262d4 100
617227c3 101 IHTMLDocument2* document = GetDocument();
61b98a2d 102 document->write(psaStrings);
442262d4 103 document->Release();
61b98a2d
SL
104
105 // SafeArrayDestroy calls SysFreeString for each BSTR
106 SafeArrayDestroy(psaStrings);
442262d4
SL
107
108 //We send the events when we are done to mimic webkit
109 //Navigated event
110 wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED,
111 GetId(), baseUrl, "", false);
112 event.SetEventObject(this);
113 HandleWindowEvent(event);
114
115 //Document complete event
116 event.SetEventType(wxEVT_COMMAND_WEB_VIEW_LOADED);
117 event.SetEventObject(this);
118 HandleWindowEvent(event);
61b98a2d
SL
119 }
120 else
121 {
122 wxLogError("wxWebViewIE::SetPage() : psaStrings is NULL");
123 }
124
125}
126
127wxString wxWebViewIE::GetPageSource()
128{
617227c3 129 IHTMLDocument2* document = GetDocument();
61b98a2d
SL
130 IHTMLElement *bodyTag = NULL;
131 IHTMLElement *htmlTag = NULL;
423adfde 132 wxString source;
7fbc727b
SL
133 HRESULT hr = document->get_body(&bodyTag);
134 if(SUCCEEDED(hr))
135 {
136 hr = bodyTag->get_parentElement(&htmlTag);
137 if(SUCCEEDED(hr))
138 {
423adfde 139 BSTR bstr;
7fbc727b 140 htmlTag->get_outerHTML(&bstr);
423adfde 141 source = wxString(bstr);
7fbc727b
SL
142 htmlTag->Release();
143 }
144 bodyTag->Release();
145 }
61b98a2d
SL
146
147 document->Release();
423adfde 148 return source;
61b98a2d
SL
149}
150
61b98a2d
SL
151wxWebViewZoom wxWebViewIE::GetZoom()
152{
c5f417cb
SL
153 if(m_zoomType == wxWEB_VIEW_ZOOM_TYPE_LAYOUT)
154 return GetIEOpticalZoom();
155 else if(m_zoomType == wxWEB_VIEW_ZOOM_TYPE_TEXT)
156 return GetIETextZoom();
157 else
158 wxFAIL;
423adfde
SL
159
160 //Dummy return to stop compiler warnings
161 return wxWEB_VIEW_ZOOM_MEDIUM;
1d7d04d7 162
61b98a2d 163}
c5f417cb 164
61b98a2d
SL
165void wxWebViewIE::SetZoom(wxWebViewZoom zoom)
166{
c5f417cb
SL
167 if(m_zoomType == wxWEB_VIEW_ZOOM_TYPE_LAYOUT)
168 SetIEOpticalZoom(zoom);
169 else if(m_zoomType == wxWEB_VIEW_ZOOM_TYPE_TEXT)
170 SetIETextZoom(zoom);
171 else
172 wxFAIL;
61b98a2d
SL
173}
174
c5f417cb 175void wxWebViewIE::SetIETextZoom(wxWebViewZoom level)
61b98a2d 176{
1d7d04d7 177 //We do not use OLECMDID_OPTICAL_GETZOOMRANGE as the docs say the range
c5f417cb
SL
178 //is 0 to 4 so the check is unnecessary, these match exactly with the
179 //enum values
61b98a2d
SL
180 VARIANT zoomVariant;
181 VariantInit (&zoomVariant);
182 V_VT(&zoomVariant) = VT_I4;
183 V_I4(&zoomVariant) = level;
184
185 HRESULT result = m_webBrowser->ExecWB(OLECMDID_ZOOM,
186 OLECMDEXECOPT_DONTPROMPTUSER,
187 &zoomVariant, NULL);
c5f417cb 188 wxASSERT(result == S_OK);
61b98a2d
SL
189}
190
c5f417cb 191wxWebViewZoom wxWebViewIE::GetIETextZoom()
61b98a2d
SL
192{
193 VARIANT zoomVariant;
194 VariantInit (&zoomVariant);
195 V_VT(&zoomVariant) = VT_I4;
61b98a2d
SL
196
197 HRESULT result = m_webBrowser->ExecWB(OLECMDID_ZOOM,
198 OLECMDEXECOPT_DONTPROMPTUSER,
199 NULL, &zoomVariant);
c5f417cb 200 wxASSERT(result == S_OK);
61b98a2d 201
c5f417cb
SL
202 //We can safely cast here as we know that the range matches our enum
203 return static_cast<wxWebViewZoom>(V_I4(&zoomVariant));
61b98a2d
SL
204}
205
c5f417cb 206void wxWebViewIE::SetIEOpticalZoom(wxWebViewZoom level)
61b98a2d 207{
1d7d04d7 208 //We do not use OLECMDID_OPTICAL_GETZOOMRANGE as the docs say the range
c5f417cb 209 //is 10 to 1000 so the check is unnecessary
61b98a2d
SL
210 VARIANT zoomVariant;
211 VariantInit (&zoomVariant);
212 V_VT(&zoomVariant) = VT_I4;
c5f417cb
SL
213
214 //We make a somewhat arbitray map here, taken from values used by webkit
215 switch(level)
216 {
217 case wxWEB_VIEW_ZOOM_TINY:
218 V_I4(&zoomVariant) = 60;
219 break;
220 case wxWEB_VIEW_ZOOM_SMALL:
221 V_I4(&zoomVariant) = 80;
222 break;
223 case wxWEB_VIEW_ZOOM_MEDIUM:
224 V_I4(&zoomVariant) = 100;
225 break;
226 case wxWEB_VIEW_ZOOM_LARGE:
227 V_I4(&zoomVariant) = 130;
228 break;
229 case wxWEB_VIEW_ZOOM_LARGEST:
230 V_I4(&zoomVariant) = 160;
231 break;
232 default:
233 wxFAIL;
234 }
61b98a2d
SL
235
236 HRESULT result = m_webBrowser->ExecWB((OLECMDID)OLECMDID_OPTICAL_ZOOM,
237 OLECMDEXECOPT_DODEFAULT,
238 &zoomVariant,
239 NULL);
c5f417cb 240 wxASSERT(result == S_OK);
61b98a2d
SL
241}
242
c5f417cb 243wxWebViewZoom wxWebViewIE::GetIEOpticalZoom()
61b98a2d 244{
61b98a2d
SL
245 VARIANT zoomVariant;
246 VariantInit (&zoomVariant);
247 V_VT(&zoomVariant) = VT_I4;
61b98a2d
SL
248
249 HRESULT result = m_webBrowser->ExecWB((OLECMDID)OLECMDID_OPTICAL_ZOOM,
250 OLECMDEXECOPT_DODEFAULT, NULL,
251 &zoomVariant);
c5f417cb 252 wxASSERT(result == S_OK);
61b98a2d
SL
253
254 const int zoom = V_I4(&zoomVariant);
61b98a2d 255
c5f417cb
SL
256 //We make a somewhat arbitray map here, taken from values used by webkit
257 if (zoom <= 65)
258 {
259 return wxWEB_VIEW_ZOOM_TINY;
260 }
261 else if (zoom > 65 && zoom <= 90)
262 {
263 return wxWEB_VIEW_ZOOM_SMALL;
264 }
265 else if (zoom > 90 && zoom <= 115)
266 {
267 return wxWEB_VIEW_ZOOM_MEDIUM;
268 }
269 else if (zoom > 115 && zoom <= 145)
270 {
271 return wxWEB_VIEW_ZOOM_LARGE;
272 }
423adfde 273 else /*if (zoom > 145) */ //Using else removes a compiler warning
c5f417cb
SL
274 {
275 return wxWEB_VIEW_ZOOM_LARGEST;
276 }
61b98a2d
SL
277}
278
c5f417cb 279void wxWebViewIE::SetZoomType(wxWebViewZoomType type)
61b98a2d 280{
c5f417cb 281 m_zoomType = type;
61b98a2d
SL
282}
283
284wxWebViewZoomType wxWebViewIE::GetZoomType() const
285{
c5f417cb 286 return m_zoomType;
61b98a2d
SL
287}
288
cd4e4673 289bool wxWebViewIE::CanSetZoomType(wxWebViewZoomType type) const
61b98a2d 290{
cd4e4673
SL
291 //IE 6 and below only support text zoom, so check the registry to see what
292 //version we actually have
293 wxRegKey key(wxRegKey::HKLM, "Software\\Microsoft\\Internet Explorer");
294 wxString value;
295 key.QueryValue("Version", value);
296
297 long version = wxAtoi(value.Left(1));
298 if(version <= 6 && type == wxWEB_VIEW_ZOOM_TYPE_LAYOUT)
299 return false;
300 else
301 return true;
61b98a2d
SL
302}
303
304void wxWebViewIE::Print()
305{
306 m_webBrowser->ExecWB(OLECMDID_PRINTPREVIEW,
307 OLECMDEXECOPT_DODEFAULT, NULL, NULL);
308}
309
74af0b13 310bool wxWebViewIE::CanGoBack()
61b98a2d 311{
74af0b13
SL
312 if(m_historyEnabled)
313 return m_historyPosition > 0;
314 else
315 return false;
316}
61b98a2d 317
74af0b13
SL
318bool wxWebViewIE::CanGoForward()
319{
320 if(m_historyEnabled)
22ca10fa 321 return m_historyPosition != static_cast<int>(m_historyList.size()) - 1;
74af0b13
SL
322 else
323 return false;
61b98a2d
SL
324}
325
3e7968c2 326void wxWebViewIE::LoadHistoryItem(wxSharedPtr<wxWebHistoryItem> item)
61b98a2d 327{
74af0b13
SL
328 int pos = -1;
329 for(unsigned int i = 0; i < m_historyList.size(); i++)
330 {
3e7968c2
SL
331 //We compare the actual pointers to find the correct item
332 if(m_historyList[i].get() == item.get())
74af0b13
SL
333 pos = i;
334 }
1d7d04d7 335 wxASSERT_MSG(pos != static_cast<int>(m_historyList.size()),
22ca10fa 336 "invalid history item");
74af0b13
SL
337 m_historyLoadingFromList = true;
338 LoadUrl(item->GetUrl());
339 m_historyPosition = pos;
340}
61b98a2d 341
5cbda74b
SL
342wxVector<wxSharedPtr<wxWebHistoryItem> > wxWebViewIE::GetBackwardHistory()
343{
344 wxVector<wxSharedPtr<wxWebHistoryItem> > backhist;
345 //As we don't have std::copy or an iterator constructor in the wxwidgets
346 //native vector we construct it by hand
347 for(int i = 0; i < m_historyPosition; i++)
348 {
349 backhist.push_back(m_historyList[i]);
350 }
351 return backhist;
352}
353
354wxVector<wxSharedPtr<wxWebHistoryItem> > wxWebViewIE::GetForwardHistory()
355{
356 wxVector<wxSharedPtr<wxWebHistoryItem> > forwardhist;
357 //As we don't have std::copy or an iterator constructor in the wxwidgets
358 //native vector we construct it by hand
22ca10fa 359 for(int i = m_historyPosition + 1; i < static_cast<int>(m_historyList.size()); i++)
5cbda74b
SL
360 {
361 forwardhist.push_back(m_historyList[i]);
362 }
363 return forwardhist;
364}
365
74af0b13
SL
366void wxWebViewIE::GoBack()
367{
3e7968c2 368 LoadHistoryItem(m_historyList[m_historyPosition - 1]);
74af0b13
SL
369}
370
371void wxWebViewIE::GoForward()
372{
3e7968c2 373 LoadHistoryItem(m_historyList[m_historyPosition + 1]);
61b98a2d
SL
374}
375
376void wxWebViewIE::Stop()
377{
7fbc727b 378 m_ie.CallMethod("Stop");
61b98a2d
SL
379}
380
74af0b13
SL
381void wxWebViewIE::ClearHistory()
382{
383 m_historyList.clear();
384 m_historyPosition = -1;
385}
386
387void wxWebViewIE::EnableHistory(bool enable)
388{
389 m_historyEnabled = enable;
390 m_historyList.clear();
391 m_historyPosition = -1;
392}
61b98a2d
SL
393
394void wxWebViewIE::Reload(wxWebViewReloadFlags flags)
395{
7aa18fc7
SL
396 VARIANTARG level;
397 VariantInit(&level);
398 V_VT(&level) = VT_I2;
61b98a2d 399
7aa18fc7 400 switch(flags)
61b98a2d 401 {
7aa18fc7
SL
402 case wxWEB_VIEW_RELOAD_DEFAULT:
403 V_I2(&level) = REFRESH_NORMAL;
404 break;
405 case wxWEB_VIEW_RELOAD_NO_CACHE:
406 V_I2(&level) = REFRESH_COMPLETELY;
407 break;
408 default:
409 wxFAIL_MSG("Unexpected reload type");
61b98a2d
SL
410 }
411
7aa18fc7 412 m_webBrowser->Refresh2(&level);
61b98a2d
SL
413}
414
415bool wxWebViewIE::IsOfflineMode()
416{
417 wxVariant out = m_ie.GetProperty("Offline");
418
419 wxASSERT(out.GetType() == "bool");
420
421 return out.GetBool();
422}
423
424void wxWebViewIE::SetOfflineMode(bool offline)
425{
426 // FIXME: the wxWidgets docs do not really document what the return
427 // parameter of PutProperty is
428 const bool success = m_ie.PutProperty("Offline", (offline ?
429 VARIANT_TRUE :
430 VARIANT_FALSE));
431 wxASSERT(success);
432}
433
434bool wxWebViewIE::IsBusy()
435{
436 if (m_isBusy) return true;
437
438 wxVariant out = m_ie.GetProperty("Busy");
439
440 wxASSERT(out.GetType() == "bool");
441
442 return out.GetBool();
443}
444
445wxString wxWebViewIE::GetCurrentURL()
446{
447 wxVariant out = m_ie.GetProperty("LocationURL");
448
449 wxASSERT(out.GetType() == "string");
450 return out.GetString();
451}
452
453wxString wxWebViewIE::GetCurrentTitle()
454{
617227c3 455 IHTMLDocument2* document = GetDocument();
977c5320 456 BSTR title;
7fbc727b 457
977c5320 458 document->get_nameProp(&title);
7fbc727b 459 document->Release();
977c5320 460 return wxString(title);
61b98a2d
SL
461}
462
4681a3ea
SL
463bool wxWebViewIE::CanCut()
464{
465 return CanExecCommand("Cut");
466}
467
468bool wxWebViewIE::CanCopy()
469{
470 return CanExecCommand("Copy");
471}
472bool wxWebViewIE::CanPaste()
473{
474 return CanExecCommand("Paste");
475}
476
477void wxWebViewIE::Cut()
478{
479 ExecCommand("Cut");
480}
481
482void wxWebViewIE::Copy()
483{
484 ExecCommand("Copy");
485}
486
487void wxWebViewIE::Paste()
488{
489 ExecCommand("Paste");
490}
491
97e49559
SL
492bool wxWebViewIE::CanUndo()
493{
494 return CanExecCommand("Undo");
495}
496bool wxWebViewIE::CanRedo()
497{
498 return CanExecCommand("Redo");
499}
500
501void wxWebViewIE::Undo()
502{
503 ExecCommand("Undo");
504}
505
506void wxWebViewIE::Redo()
507{
508 ExecCommand("Redo");
509}
510
c7cbe308
SL
511void wxWebViewIE::SetEditable(bool enable)
512{
513 IHTMLDocument2* document = GetDocument();
514 if( enable )
515 document->put_designMode(SysAllocString(L"On"));
516 else
517 document->put_designMode(SysAllocString(L"Off"));
7fbc727b
SL
518
519 document->Release();
c7cbe308
SL
520}
521
522bool wxWebViewIE::IsEditable()
523{
524 IHTMLDocument2* document = GetDocument();
525 BSTR mode;
526 document->get_designMode(&mode);
423adfde 527 document->Release();
c7cbe308
SL
528 if(wxString(mode) == "On")
529 return true;
530 else
531 return false;
532}
533
63a65070
SL
534void wxWebViewIE::SelectAll()
535{
536 ExecCommand("SelectAll");
537}
538
539bool wxWebViewIE::HasSelection()
540{
541 IHTMLDocument2* document = GetDocument();
542 IHTMLSelectionObject* selection;
423adfde 543 wxString sel;
7fbc727b
SL
544 HRESULT hr = document->get_selection(&selection);
545 if(SUCCEEDED(hr))
546 {
423adfde 547 BSTR type;
7fbc727b 548 selection->get_type(&type);
423adfde 549 sel = wxString(type);
7fbc727b
SL
550 selection->Release();
551 }
552 document->Release();
423adfde 553 return sel != "None";
63a65070
SL
554}
555
556void wxWebViewIE::DeleteSelection()
557{
558 ExecCommand("Delete");
559}
560
c9355a3d
SL
561wxString wxWebViewIE::GetSelectedText()
562{
563 IHTMLDocument2* document = GetDocument();
564 IHTMLSelectionObject* selection;
565 wxString selected;
566 HRESULT hr = document->get_selection(&selection);
567 if(SUCCEEDED(hr))
568 {
569 IDispatch* disrange;
570 hr = selection->createRange(&disrange);
571 if(SUCCEEDED(hr))
572 {
573 IHTMLTxtRange* range;
574 hr = disrange->QueryInterface(IID_IHTMLTxtRange, (void**)&range);
575 if(SUCCEEDED(hr))
576 {
577 BSTR text;
578 range->get_text(&text);
579 selected = wxString(text);
580 range->Release();
581 }
582 disrange->Release();
583 }
584 selection->Release();
585 }
586 document->Release();
587 return selected;
588}
589
97ba4d81 590wxString wxWebViewIE::GetSelectedSource()
0fe8a1b6
SL
591{
592 IHTMLDocument2* document = GetDocument();
593 IHTMLSelectionObject* selection;
594 wxString selected;
595 HRESULT hr = document->get_selection(&selection);
596 if(SUCCEEDED(hr))
597 {
598 IDispatch* disrange;
599 hr = selection->createRange(&disrange);
600 if(SUCCEEDED(hr))
601 {
602 IHTMLTxtRange* range;
603 hr = disrange->QueryInterface(IID_IHTMLTxtRange, (void**)&range);
604 if(SUCCEEDED(hr))
605 {
606 BSTR text;
607 range->get_htmlText(&text);
608 selected = wxString(text);
609 range->Release();
610 }
611 disrange->Release();
612 }
613 selection->Release();
614 }
615 document->Release();
616 return selected;
617}
618
41933aa5
SL
619void wxWebViewIE::ClearSelection()
620{
621 IHTMLDocument2* document = GetDocument();
622 IHTMLSelectionObject* selection;
623 wxString selected;
624 HRESULT hr = document->get_selection(&selection);
625 if(SUCCEEDED(hr))
626 {
627 selection->empty();
628 selection->Release();
629 }
630 document->Release();
631}
632
241b769f
SL
633wxString wxWebViewIE::GetPageText()
634{
635 IHTMLDocument2* document = GetDocument();
423adfde 636 wxString text;
241b769f
SL
637 IHTMLElement* body;
638 HRESULT hr = document->get_body(&body);
639 if(SUCCEEDED(hr))
640 {
423adfde 641 BSTR out;
241b769f 642 body->get_innerText(&out);
423adfde 643 text = wxString(out);
241b769f
SL
644 body->Release();
645 }
646 document->Release();
423adfde 647 return text;
241b769f
SL
648}
649
c9ccc09c
SL
650void wxWebViewIE::RunScript(const wxString& javascript)
651{
652 IHTMLDocument2* document = GetDocument();
653 IHTMLWindow2* window;
654 wxString language = "javascript";
655 HRESULT hr = document->get_parentWindow(&window);
656 if(SUCCEEDED(hr))
657 {
658 VARIANT level;
659 VariantInit(&level);
660 V_VT(&level) = VT_EMPTY;
661 window->execScript(SysAllocString(javascript), SysAllocString(language), &level);
662 }
663 document->Release();
664}
665
9e3d4a32 666void wxWebViewIE::RegisterHandler(wxWebHandler* handler)
29365629
SL
667{
668 ClassFactory* cf = new ClassFactory(handler);
669 IInternetSession* session;
670 if(FAILED(CoInternetGetSession(0, &session, 0)))
671 {
672 wxFAIL_MSG("Could not retrive internet session");
673 }
674
9e3d4a32 675 HRESULT hr = session->RegisterNameSpace(cf, CLSID_FileProtocol, handler->GetName(), 0, NULL, 0);
29365629
SL
676 if(FAILED(hr))
677 {
678 wxFAIL_MSG("Could not register protocol");
679 }
680}
681
4681a3ea
SL
682bool wxWebViewIE::CanExecCommand(wxString command)
683{
617227c3 684 IHTMLDocument2* document = GetDocument();
4681a3ea 685 VARIANT_BOOL enabled;
7fbc727b 686
4681a3ea 687 document->queryCommandEnabled(SysAllocString(command.wc_str()), &enabled);
7fbc727b 688 document->Release();
4681a3ea
SL
689
690 return (enabled == VARIANT_TRUE);
691}
692
693void wxWebViewIE::ExecCommand(wxString command)
694{
617227c3
SL
695 IHTMLDocument2* document = GetDocument();
696 document->execCommand(SysAllocString(command.wc_str()), VARIANT_FALSE, VARIANT(), NULL);
7fbc727b 697 document->Release();
617227c3 698}
4681a3ea 699
617227c3
SL
700IHTMLDocument2* wxWebViewIE::GetDocument()
701{
702 wxVariant variant = m_ie.GetProperty("Document");
703 IHTMLDocument2* document = (IHTMLDocument2*)variant.GetVoidPtr();
4681a3ea 704
617227c3
SL
705 wxASSERT(document);
706
707 return document;
4681a3ea
SL
708}
709
61b98a2d
SL
710void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
711{
712 if (m_webBrowser == NULL) return;
713
714 switch (evt.GetDispatchId())
715 {
716 case DISPID_BEFORENAVIGATE2:
717 {
718 m_isBusy = true;
719
720 wxString url = evt[1].GetString();
721 wxString target = evt[3].GetString();
722
723 wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING,
724 GetId(), url, target, true);
725 event.SetEventObject(this);
726 HandleWindowEvent(event);
727
728 if (event.IsVetoed())
729 {
730 wxActiveXEventNativeMSW* nativeParams =
731 evt.GetNativeParameters();
732 *V_BOOLREF(&nativeParams->pDispParams->rgvarg[0]) = VARIANT_TRUE;
733 }
734
735 // at this point, either the navigation event has been cancelled
736 // and we're not busy, either it was accepted and IWebBrowser2's
737 // Busy property will be true; so we don't need our override
738 // flag anymore.
739 m_isBusy = false;
740
741 break;
742 }
743
744 case DISPID_NAVIGATECOMPLETE2:
745 {
746 wxString url = evt[1].GetString();
747 // TODO: set target parameter if possible
748 wxString target = wxEmptyString;
749 wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED,
750 GetId(), url, target, false);
751 event.SetEventObject(this);
752 HandleWindowEvent(event);
753 break;
754 }
755
756 case DISPID_PROGRESSCHANGE:
757 {
758 // download progress
759 break;
760 }
761
762 case DISPID_DOCUMENTCOMPLETE:
763 {
3ee442ff
SL
764 //Only send a complete even if we are actually finished, this brings
765 //the event in to line with webkit
766 READYSTATE rs;
767 m_webBrowser->get_ReadyState( &rs );
768 if(rs != READYSTATE_COMPLETE)
769 break;
770
61b98a2d 771 wxString url = evt[1].GetString();
113e0a92
SL
772
773 //As we are complete we also add to the history list, but not if the
774 //page is not the main page, ie it is a subframe
775 if(m_historyEnabled && !m_historyLoadingFromList && url == GetCurrentURL())
74af0b13
SL
776 {
777 //If we are not at the end of the list, then erase everything
778 //between us and the end before adding the new page
22ca10fa 779 if(m_historyPosition != static_cast<int>(m_historyList.size()) - 1)
74af0b13
SL
780 {
781 m_historyList.erase(m_historyList.begin() + m_historyPosition + 1,
782 m_historyList.end());
783 }
784 wxSharedPtr<wxWebHistoryItem> item(new wxWebHistoryItem(url, GetCurrentTitle()));
785 m_historyList.push_back(item);
786 m_historyPosition++;
787 }
788 //Reset as we are done now
789 m_historyLoadingFromList = false;
61b98a2d
SL
790 // TODO: set target parameter if possible
791 wxString target = wxEmptyString;
792 wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(),
793 url, target, false);
794 event.SetEventObject(this);
795 HandleWindowEvent(event);
796 break;
797 }
798
799 case DISPID_STATUSTEXTCHANGE:
800 {
801 break;
802 }
803
804 case DISPID_TITLECHANGE:
805 {
153530af
SL
806 wxString title = evt[0].GetString();
807
808 wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED,
809 GetId(), GetCurrentURL(), wxEmptyString, true);
810 event.SetString(title);
811 event.SetEventObject(this);
812 HandleWindowEvent(event);
61b98a2d
SL
813 break;
814 }
815
816 case DISPID_NAVIGATEERROR:
817 {
818 wxWebNavigationError errorType = wxWEB_NAV_ERR_OTHER;
819 wxString errorCode = "?";
820 switch (evt[3].GetLong())
821 {
822 case INET_E_INVALID_URL: // (0x800C0002L or -2146697214)
823 errorCode = "INET_E_INVALID_URL";
824 errorType = wxWEB_NAV_ERR_REQUEST;
825 break;
826 case INET_E_NO_SESSION: // (0x800C0003L or -2146697213)
827 errorCode = "INET_E_NO_SESSION";
828 errorType = wxWEB_NAV_ERR_CONNECTION;
829 break;
830 case INET_E_CANNOT_CONNECT: // (0x800C0004L or -2146697212)
831 errorCode = "INET_E_CANNOT_CONNECT";
832 errorType = wxWEB_NAV_ERR_CONNECTION;
833 break;
834 case INET_E_RESOURCE_NOT_FOUND: // (0x800C0005L or -2146697211)
835 errorCode = "INET_E_RESOURCE_NOT_FOUND";
836 errorType = wxWEB_NAV_ERR_NOT_FOUND;
837 break;
838 case INET_E_OBJECT_NOT_FOUND: // (0x800C0006L or -2146697210)
839 errorCode = "INET_E_OBJECT_NOT_FOUND";
840 errorType = wxWEB_NAV_ERR_NOT_FOUND;
841 break;
842 case INET_E_DATA_NOT_AVAILABLE: // (0x800C0007L or -2146697209)
843 errorCode = "INET_E_DATA_NOT_AVAILABLE";
844 errorType = wxWEB_NAV_ERR_NOT_FOUND;
845 break;
846 case INET_E_DOWNLOAD_FAILURE: // (0x800C0008L or -2146697208)
847 errorCode = "INET_E_DOWNLOAD_FAILURE";
848 errorType = wxWEB_NAV_ERR_CONNECTION;
849 break;
850 case INET_E_AUTHENTICATION_REQUIRED: // (0x800C0009L or -2146697207)
851 errorCode = "INET_E_AUTHENTICATION_REQUIRED";
852 errorType = wxWEB_NAV_ERR_AUTH;
853 break;
854 case INET_E_NO_VALID_MEDIA: // (0x800C000AL or -2146697206)
855 errorCode = "INET_E_NO_VALID_MEDIA";
856 errorType = wxWEB_NAV_ERR_REQUEST;
857 break;
858 case INET_E_CONNECTION_TIMEOUT: // (0x800C000BL or -2146697205)
859 errorCode = "INET_E_CONNECTION_TIMEOUT";
860 errorType = wxWEB_NAV_ERR_CONNECTION;
861 break;
862 case INET_E_INVALID_REQUEST: // (0x800C000CL or -2146697204)
863 errorCode = "INET_E_INVALID_REQUEST";
864 errorType = wxWEB_NAV_ERR_REQUEST;
865 break;
866 case INET_E_UNKNOWN_PROTOCOL: // (0x800C000DL or -2146697203)
867 errorCode = "INET_E_UNKNOWN_PROTOCOL";
868 errorType = wxWEB_NAV_ERR_REQUEST;
869 break;
870 case INET_E_SECURITY_PROBLEM: // (0x800C000EL or -2146697202)
871 errorCode = "INET_E_SECURITY_PROBLEM";
872 errorType = wxWEB_NAV_ERR_SECURITY;
873 break;
874 case INET_E_CANNOT_LOAD_DATA: // (0x800C000FL or -2146697201)
875 errorCode = "INET_E_CANNOT_LOAD_DATA";
876 errorType = wxWEB_NAV_ERR_OTHER;
877 break;
878 case INET_E_CANNOT_INSTANTIATE_OBJECT:
879 // CoCreateInstance will return an error code if this happens,
880 // we'll handle this above.
881 return;
882 break;
883 case INET_E_REDIRECT_FAILED: // (0x800C0014L or -2146697196)
884 errorCode = "INET_E_REDIRECT_FAILED";
885 errorType = wxWEB_NAV_ERR_OTHER;
886 break;
887 case INET_E_REDIRECT_TO_DIR: // (0x800C0015L or -2146697195)
888 errorCode = "INET_E_REDIRECT_TO_DIR";
889 errorType = wxWEB_NAV_ERR_REQUEST;
890 break;
891 case INET_E_CANNOT_LOCK_REQUEST: // (0x800C0016L or -2146697194)
892 errorCode = "INET_E_CANNOT_LOCK_REQUEST";
893 errorType = wxWEB_NAV_ERR_OTHER;
894 break;
895 case INET_E_USE_EXTEND_BINDING: // (0x800C0017L or -2146697193)
896 errorCode = "INET_E_USE_EXTEND_BINDING";
897 errorType = wxWEB_NAV_ERR_OTHER;
898 break;
899 case INET_E_TERMINATED_BIND: // (0x800C0018L or -2146697192)
900 errorCode = "INET_E_TERMINATED_BIND";
901 errorType = wxWEB_NAV_ERR_OTHER;
902 break;
903 case INET_E_INVALID_CERTIFICATE: // (0x800C0019L or -2146697191)
904 errorCode = "INET_E_INVALID_CERTIFICATE";
905 errorType = wxWEB_NAV_ERR_CERTIFICATE;
906 break;
907 case INET_E_CODE_DOWNLOAD_DECLINED: // (0x800C0100L or -2146696960)
908 errorCode = "INET_E_CODE_DOWNLOAD_DECLINED";
909 errorType = wxWEB_NAV_ERR_USER_CANCELLED;
910 break;
911 case INET_E_RESULT_DISPATCHED: // (0x800C0200L or -2146696704)
912 // cancel request cancelled...
913 errorCode = "INET_E_RESULT_DISPATCHED";
914 errorType = wxWEB_NAV_ERR_OTHER;
915 break;
916 case INET_E_CANNOT_REPLACE_SFP_FILE: // (0x800C0300L or -2146696448)
917 errorCode = "INET_E_CANNOT_REPLACE_SFP_FILE";
918 errorType = wxWEB_NAV_ERR_SECURITY;
919 break;
920 case INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY:
921 errorCode = "INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY";
922 errorType = wxWEB_NAV_ERR_SECURITY;
923 break;
924 case INET_E_CODE_INSTALL_SUPPRESSED:
925 errorCode = "INET_E_CODE_INSTALL_SUPPRESSED";
926 errorType = wxWEB_NAV_ERR_SECURITY;
927 break;
928 }
929
930 wxString url = evt[1].GetString();
931 wxString target = evt[2].GetString();
932 wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR, GetId(),
933 url, target, false);
934 event.SetEventObject(this);
935 event.SetInt(errorType);
936 event.SetString(errorCode);
937 HandleWindowEvent(event);
938 break;
939 }
853b6cd0 940 case DISPID_NEWWINDOW3:
61b98a2d 941 {
853b6cd0
SL
942 wxString url = evt[4].GetString();
943
944 wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW,
945 GetId(), url, wxEmptyString, true);
946 event.SetEventObject(this);
947 HandleWindowEvent(event);
948
d676fb21
SL
949 //We always cancel this event otherwise an Internet Exporer window
950 //is opened for the url
951 wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters();
952 *V_BOOLREF(&nativeParams->pDispParams->rgvarg[3]) = VARIANT_TRUE;
be19c556
SL
953 break;
954 }
61b98a2d
SL
955 }
956
957 evt.Skip();
958}
959
9e3d4a32 960VirtualProtocol::VirtualProtocol(wxWebHandler *handler)
7d3f6b4d
SL
961{
962 m_refCount = 0;
963 m_file = NULL;
29365629 964 m_handler = handler;
7d3f6b4d
SL
965}
966
967VirtualProtocol::~VirtualProtocol()
968{
7d3f6b4d
SL
969}
970
971ULONG VirtualProtocol::AddRef()
972{
973 m_refCount++;
974 return m_refCount;
975}
976
977HRESULT VirtualProtocol::QueryInterface(REFIID riid, void **ppvObject)
978{
29365629
SL
979 if(riid == IID_IUnknown || riid == IID_IInternetProtocolRoot ||
980 riid == IID_IInternetProtocol)
7d3f6b4d 981 {
666f73c4
SL
982 *ppvObject = (IInternetProtocol*)this;
983 AddRef();
984 return S_OK;
985 }
986 else if(riid == IID_IInternetProtocolInfo)
987 {
988 *ppvObject = (IInternetProtocolInfo*)this;
7d3f6b4d
SL
989 AddRef();
990 return S_OK;
991 }
992 else
993 {
994 *ppvObject = NULL;
995 return E_POINTER;
996 }
997}
998
999ULONG VirtualProtocol::Release()
1000{
1001 m_refCount--;
1002 if (m_refCount > 0)
1003 {
1004 return m_refCount;
1005 }
1006 else
1007 {
1008 delete this;
1009 return 0;
1010 }
1011}
1012
1013HRESULT VirtualProtocol::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink,
0995b9dc
SL
1014 IInternetBindInfo *pOIBindInfo, DWORD grfPI,
1015 HANDLE_PTR dwReserved)
7d3f6b4d 1016{
0995b9dc
SL
1017 wxUnusedVar(szUrl);
1018 wxUnusedVar(pOIBindInfo);
1019 wxUnusedVar(grfPI);
1020 wxUnusedVar(dwReserved);
7d3f6b4d 1021 m_protocolSink = pOIProtSink;
29365629
SL
1022
1023 //We get the file itself from the protocol handler
1024 m_file = m_handler->GetFile(szUrl);
1025
7d3f6b4d
SL
1026
1027 if(!m_file)
1028 return INET_E_RESOURCE_NOT_FOUND;
1029
1030 //We return the stream length for current and total size as we can always
1031 //read the whole file from the stream
666f73c4 1032 wxFileOffset length = m_file->GetStream()->GetLength();
7d3f6b4d
SL
1033 m_protocolSink->ReportData(BSCF_FIRSTDATANOTIFICATION |
1034 BSCF_DATAFULLYAVAILABLE |
1035 BSCF_LASTDATANOTIFICATION,
666f73c4 1036 length, length);
7d3f6b4d
SL
1037 return S_OK;
1038}
1039
1040HRESULT VirtualProtocol::Read(void *pv, ULONG cb, ULONG *pcbRead)
1041{
1042 //If the file is null we return false to indicte it is finished
1043 if(!m_file)
1044 return S_FALSE;
1045
1046 wxStreamError err = m_file->GetStream()->Read(pv, cb).GetLastError();
1047 *pcbRead = m_file->GetStream()->LastRead();
1048
1049 if(err == wxSTREAM_NO_ERROR)
1050 {
1051 if(*pcbRead < cb)
1052 {
1053 wxDELETE(m_file);
1054 m_protocolSink->ReportResult(S_OK, 0, NULL);
1055 }
1056 //As we are not eof there is more data
1057 return S_OK;
1058 }
1059 else if(err == wxSTREAM_EOF)
1060 {
1061 wxDELETE(m_file);
1062 m_protocolSink->ReportResult(S_OK, 0, NULL);
1063 //We are eof and so finished
1064 return S_OK;
1065 }
1066 else if(err == wxSTREAM_READ_ERROR)
1067 {
1068 wxDELETE(m_file);
1069 return INET_E_DOWNLOAD_FAILURE;
1070 }
0995b9dc
SL
1071 else
1072 {
1073 //Dummy return to surpress a compiler warning
1074 wxFAIL;
1075 return INET_E_DOWNLOAD_FAILURE;
1076 }
7d3f6b4d
SL
1077}
1078
666f73c4 1079HRESULT VirtualProtocol::CombineUrl(LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl,
b7d74e9c
SL
1080 DWORD WXUNUSED(dwCombineFlags),
1081 LPWSTR pwzResult,
666f73c4 1082 DWORD cchResult, DWORD *pcchResult,
b7d74e9c 1083 DWORD WXUNUSED(dwReserved))
666f73c4 1084{
b7d74e9c 1085
e1efca65 1086 wxString newuri = m_handler->CombineURIs(pwzBaseUrl, pwzRelativeUrl);
b7d74e9c 1087 //Check the buffer we are given can hold the new url
e1efca65
SL
1088 if(wxStrlen(newuri) > cchResult)
1089 return S_FALSE;
1090
1091 wxStrcpy(pwzResult, newuri.c_str());
1092 *pcchResult = wxStrlen(newuri);
1093 return S_OK;
666f73c4
SL
1094}
1095
b7d74e9c
SL
1096HRESULT VirtualProtocol::ParseUrl(LPCWSTR pwzUrl,
1097 PARSEACTION WXUNUSED(ParseAction),
1098 DWORD WXUNUSED(dwParseFlags),
1099 LPWSTR pwzResult,
666f73c4 1100 DWORD cchResult, DWORD *pcchResult,
b7d74e9c 1101 DWORD WXUNUSED(dwReserved))
666f73c4 1102{
b7d74e9c
SL
1103 //Check the buffer we are given can hold the new url
1104 if(wxStrlen(pwzUrl) > cchResult)
1105 return S_FALSE;
1106
e1efca65
SL
1107 wxStrcpy(pwzResult, pwzUrl);
1108 *pcchResult = wxStrlen(pwzResult);
29365629 1109 return S_OK;
666f73c4
SL
1110}
1111
b7d74e9c
SL
1112HRESULT VirtualProtocol::QueryInfo(LPCWSTR WXUNUSED(pwzUrl),
1113 QUERYOPTION WXUNUSED(OueryOption),
1114 DWORD WXUNUSED(dwQueryFlags),
1115 LPVOID WXUNUSED(pBuffer),
1116 DWORD WXUNUSED(cbBuffer),
1117 DWORD* WXUNUSED(pcbBuf),
1118 DWORD WXUNUSED(dwReserved))
666f73c4
SL
1119{
1120 return INET_E_DEFAULT_ACTION;
1121}
1122
7d3f6b4d
SL
1123HRESULT ClassFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid,
1124 void ** ppvObject)
1125{
1126 if (pUnkOuter)
1127 return CLASS_E_NOAGGREGATION;
29365629 1128 VirtualProtocol* vp = new VirtualProtocol(m_handler);
7d3f6b4d
SL
1129 vp->AddRef();
1130 HRESULT hr = vp->QueryInterface(riid, ppvObject);
1131 vp->Release();
1132 return hr;
1133
1134}
1135
1136STDMETHODIMP ClassFactory::LockServer(BOOL fLock)
1137{
0995b9dc
SL
1138 wxUnusedVar(fLock);
1139 return S_OK;
7d3f6b4d
SL
1140}
1141
1142ULONG ClassFactory::AddRef(void)
1143{
1144 m_refCount++;
1145 return m_refCount;
1146}
1147
1148HRESULT ClassFactory::QueryInterface(REFIID riid, void **ppvObject)
1149{
1150 if ((riid == IID_IUnknown) || (riid == IID_IClassFactory))
1151 {
1152 *ppvObject = this;
1153 AddRef();
1154 return S_OK;
1155 }
1156 else
1157 {
1158 *ppvObject = NULL;
1159 return E_POINTER;
1160 }
1161
1162}
1163
1164ULONG ClassFactory::Release(void)
1165{
1166 m_refCount--;
1167 if (m_refCount > 0)
1168 {
1169 return m_refCount;
1170 }
1171 else
1172 {
1173 delete this;
1174 return 0;
1175 }
1176
1177}
1178
61b98a2d 1179#endif