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