]> git.saurik.com Git - wxWidgets.git/blame - src/msw/webview_ie.cpp
Another Chinese translations update from Jiawei Huang.
[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
9d2f31db 19#if wxUSE_WEBVIEW && 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 28#include "wx/filesys.h"
e924e848 29#include "wx/dynlib.h"
7d3f6b4d 30
cddf4541
SL
31wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewIE, wxWebView);
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);
4d0dddc7 76 LoadURL(url);
61b98a2d
SL
77 return true;
78}
79
39498710
SL
80wxWebViewIE::~wxWebViewIE()
81{
82 for(unsigned int i = 0; i < m_factories.size(); i++)
83 {
84 m_factories[i]->Release();
85 }
86}
61b98a2d 87
4d0dddc7 88void wxWebViewIE::LoadURL(const wxString& url)
61b98a2d 89{
e8d243a9 90 m_ie.CallMethod("Navigate", wxConvertStringToOle(url));
61b98a2d
SL
91}
92
442262d4 93void wxWebViewIE::SetPage(const wxString& html, const wxString& baseUrl)
61b98a2d 94{
61b98a2d
SL
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;
442262d4 102
61b98a2d
SL
103 HRESULT hr = SafeArrayAccessData(psaStrings, (LPVOID*)&param);
104 param->vt = VT_BSTR;
105 param->bstrVal = bstr;
61b98a2d 106 hr = SafeArrayUnaccessData(psaStrings);
442262d4 107
617227c3 108 IHTMLDocument2* document = GetDocument();
61b98a2d 109 document->write(psaStrings);
442262d4 110 document->Release();
61b98a2d
SL
111
112 // SafeArrayDestroy calls SysFreeString for each BSTR
113 SafeArrayDestroy(psaStrings);
442262d4
SL
114
115 //We send the events when we are done to mimic webkit
116 //Navigated event
04fa04d8 117 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED,
3225a4b8 118 GetId(), baseUrl, "");
442262d4
SL
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);
61b98a2d
SL
126 }
127 else
128 {
129 wxLogError("wxWebViewIE::SetPage() : psaStrings is NULL");
130 }
131
132}
133
e669ddde 134wxString wxWebViewIE::GetPageSource() const
61b98a2d 135{
617227c3 136 IHTMLDocument2* document = GetDocument();
61b98a2d
SL
137 IHTMLElement *bodyTag = NULL;
138 IHTMLElement *htmlTag = NULL;
423adfde 139 wxString source;
7fbc727b
SL
140 HRESULT hr = document->get_body(&bodyTag);
141 if(SUCCEEDED(hr))
142 {
143 hr = bodyTag->get_parentElement(&htmlTag);
144 if(SUCCEEDED(hr))
145 {
423adfde 146 BSTR bstr;
7fbc727b 147 htmlTag->get_outerHTML(&bstr);
423adfde 148 source = wxString(bstr);
7fbc727b
SL
149 htmlTag->Release();
150 }
151 bodyTag->Release();
152 }
61b98a2d
SL
153
154 document->Release();
423adfde 155 return source;
61b98a2d
SL
156}
157
e669ddde 158wxWebViewZoom wxWebViewIE::GetZoom() const
61b98a2d 159{
8acbf08b
SL
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 }
423adfde
SL
169
170 //Dummy return to stop compiler warnings
171 return wxWEB_VIEW_ZOOM_MEDIUM;
1d7d04d7 172
61b98a2d 173}
c5f417cb 174
61b98a2d
SL
175void wxWebViewIE::SetZoom(wxWebViewZoom zoom)
176{
8acbf08b
SL
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 }
61b98a2d
SL
188}
189
c5f417cb 190void wxWebViewIE::SetIETextZoom(wxWebViewZoom level)
61b98a2d 191{
1d7d04d7 192 //We do not use OLECMDID_OPTICAL_GETZOOMRANGE as the docs say the range
c5f417cb
SL
193 //is 0 to 4 so the check is unnecessary, these match exactly with the
194 //enum values
61b98a2d
SL
195 VARIANT zoomVariant;
196 VariantInit (&zoomVariant);
197 V_VT(&zoomVariant) = VT_I4;
198 V_I4(&zoomVariant) = level;
199
8acbf08b
SL
200#if wxDEBUG_LEVEL
201 HRESULT result =
202#endif
203 m_webBrowser->ExecWB(OLECMDID_ZOOM,
204 OLECMDEXECOPT_DONTPROMPTUSER,
205 &zoomVariant, NULL);
c5f417cb 206 wxASSERT(result == S_OK);
61b98a2d
SL
207}
208
e669ddde 209wxWebViewZoom wxWebViewIE::GetIETextZoom() const
61b98a2d
SL
210{
211 VARIANT zoomVariant;
212 VariantInit (&zoomVariant);
213 V_VT(&zoomVariant) = VT_I4;
61b98a2d 214
8acbf08b
SL
215#if wxDEBUG_LEVEL
216 HRESULT result =
217#endif
218 m_webBrowser->ExecWB(OLECMDID_ZOOM,
219 OLECMDEXECOPT_DONTPROMPTUSER,
220 NULL, &zoomVariant);
c5f417cb 221 wxASSERT(result == S_OK);
61b98a2d 222
c5f417cb
SL
223 //We can safely cast here as we know that the range matches our enum
224 return static_cast<wxWebViewZoom>(V_I4(&zoomVariant));
61b98a2d
SL
225}
226
c5f417cb 227void wxWebViewIE::SetIEOpticalZoom(wxWebViewZoom level)
61b98a2d 228{
1d7d04d7 229 //We do not use OLECMDID_OPTICAL_GETZOOMRANGE as the docs say the range
c5f417cb 230 //is 10 to 1000 so the check is unnecessary
61b98a2d
SL
231 VARIANT zoomVariant;
232 VariantInit (&zoomVariant);
233 V_VT(&zoomVariant) = VT_I4;
c5f417cb
SL
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 }
61b98a2d 256
8acbf08b
SL
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);
c5f417cb 264 wxASSERT(result == S_OK);
61b98a2d
SL
265}
266
e669ddde 267wxWebViewZoom wxWebViewIE::GetIEOpticalZoom() const
61b98a2d 268{
61b98a2d
SL
269 VARIANT zoomVariant;
270 VariantInit (&zoomVariant);
271 V_VT(&zoomVariant) = VT_I4;
61b98a2d 272
8acbf08b
SL
273#if wxDEBUG_LEVEL
274 HRESULT result =
275#endif
276 m_webBrowser->ExecWB((OLECMDID)63 /*OLECMDID_OPTICAL_ZOOM*/,
277 OLECMDEXECOPT_DODEFAULT, NULL,
278 &zoomVariant);
c5f417cb 279 wxASSERT(result == S_OK);
61b98a2d
SL
280
281 const int zoom = V_I4(&zoomVariant);
61b98a2d 282
c5f417cb
SL
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 }
423adfde 300 else /*if (zoom > 145) */ //Using else removes a compiler warning
c5f417cb
SL
301 {
302 return wxWEB_VIEW_ZOOM_LARGEST;
303 }
61b98a2d
SL
304}
305
c5f417cb 306void wxWebViewIE::SetZoomType(wxWebViewZoomType type)
61b98a2d 307{
c5f417cb 308 m_zoomType = type;
61b98a2d
SL
309}
310
311wxWebViewZoomType wxWebViewIE::GetZoomType() const
312{
c5f417cb 313 return m_zoomType;
61b98a2d
SL
314}
315
cd4e4673 316bool wxWebViewIE::CanSetZoomType(wxWebViewZoomType type) const
61b98a2d 317{
cd4e4673
SL
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;
61b98a2d
SL
329}
330
331void wxWebViewIE::Print()
332{
333 m_webBrowser->ExecWB(OLECMDID_PRINTPREVIEW,
334 OLECMDEXECOPT_DODEFAULT, NULL, NULL);
335}
336
e669ddde 337bool wxWebViewIE::CanGoBack() const
61b98a2d 338{
74af0b13
SL
339 if(m_historyEnabled)
340 return m_historyPosition > 0;
341 else
342 return false;
343}
61b98a2d 344
e669ddde 345bool wxWebViewIE::CanGoForward() const
74af0b13
SL
346{
347 if(m_historyEnabled)
22ca10fa 348 return m_historyPosition != static_cast<int>(m_historyList.size()) - 1;
74af0b13
SL
349 else
350 return false;
61b98a2d
SL
351}
352
c13d6ac1 353void wxWebViewIE::LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem> item)
61b98a2d 354{
74af0b13
SL
355 int pos = -1;
356 for(unsigned int i = 0; i < m_historyList.size(); i++)
357 {
3e7968c2
SL
358 //We compare the actual pointers to find the correct item
359 if(m_historyList[i].get() == item.get())
74af0b13
SL
360 pos = i;
361 }
1d7d04d7 362 wxASSERT_MSG(pos != static_cast<int>(m_historyList.size()),
22ca10fa 363 "invalid history item");
74af0b13 364 m_historyLoadingFromList = true;
4d0dddc7 365 LoadURL(item->GetUrl());
74af0b13
SL
366 m_historyPosition = pos;
367}
61b98a2d 368
c13d6ac1 369wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewIE::GetBackwardHistory()
5cbda74b 370{
c13d6ac1 371 wxVector<wxSharedPtr<wxWebViewHistoryItem> > backhist;
5cbda74b
SL
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
c13d6ac1 381wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewIE::GetForwardHistory()
5cbda74b 382{
c13d6ac1 383 wxVector<wxSharedPtr<wxWebViewHistoryItem> > forwardhist;
5cbda74b
SL
384 //As we don't have std::copy or an iterator constructor in the wxwidgets
385 //native vector we construct it by hand
22ca10fa 386 for(int i = m_historyPosition + 1; i < static_cast<int>(m_historyList.size()); i++)
5cbda74b
SL
387 {
388 forwardhist.push_back(m_historyList[i]);
389 }
390 return forwardhist;
391}
392
74af0b13
SL
393void wxWebViewIE::GoBack()
394{
3e7968c2 395 LoadHistoryItem(m_historyList[m_historyPosition - 1]);
74af0b13
SL
396}
397
398void wxWebViewIE::GoForward()
399{
3e7968c2 400 LoadHistoryItem(m_historyList[m_historyPosition + 1]);
61b98a2d
SL
401}
402
403void wxWebViewIE::Stop()
404{
7fbc727b 405 m_ie.CallMethod("Stop");
61b98a2d
SL
406}
407
74af0b13
SL
408void wxWebViewIE::ClearHistory()
409{
410 m_historyList.clear();
411 m_historyPosition = -1;
412}
413
414void wxWebViewIE::EnableHistory(bool enable)
415{
416 m_historyEnabled = enable;
417 m_historyList.clear();
418 m_historyPosition = -1;
419}
61b98a2d
SL
420
421void wxWebViewIE::Reload(wxWebViewReloadFlags flags)
422{
7aa18fc7
SL
423 VARIANTARG level;
424 VariantInit(&level);
425 V_VT(&level) = VT_I2;
61b98a2d 426
7aa18fc7 427 switch(flags)
61b98a2d 428 {
7aa18fc7
SL
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");
61b98a2d
SL
437 }
438
7aa18fc7 439 m_webBrowser->Refresh2(&level);
61b98a2d
SL
440}
441
442bool wxWebViewIE::IsOfflineMode()
443{
444 wxVariant out = m_ie.GetProperty("Offline");
445
446 wxASSERT(out.GetType() == "bool");
447
448 return out.GetBool();
449}
450
451void wxWebViewIE::SetOfflineMode(bool offline)
452{
453 // FIXME: the wxWidgets docs do not really document what the return
454 // parameter of PutProperty is
8acbf08b
SL
455#if wxDEBUG_LEVEL
456 const bool success =
457#endif
458 m_ie.PutProperty("Offline", (offline ?
459 VARIANT_TRUE :
460 VARIANT_FALSE));
61b98a2d
SL
461 wxASSERT(success);
462}
463
e669ddde
SL
464bool wxWebViewIE::IsBusy() const
465{
61b98a2d
SL
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
e669ddde 475wxString wxWebViewIE::GetCurrentURL() const
61b98a2d
SL
476{
477 wxVariant out = m_ie.GetProperty("LocationURL");
478
479 wxASSERT(out.GetType() == "string");
480 return out.GetString();
481}
482
e669ddde 483wxString wxWebViewIE::GetCurrentTitle() const
61b98a2d 484{
617227c3 485 IHTMLDocument2* document = GetDocument();
977c5320 486 BSTR title;
7fbc727b 487
977c5320 488 document->get_nameProp(&title);
7fbc727b 489 document->Release();
977c5320 490 return wxString(title);
61b98a2d
SL
491}
492
e669ddde 493bool wxWebViewIE::CanCut() const
4681a3ea
SL
494{
495 return CanExecCommand("Cut");
496}
497
e669ddde 498bool wxWebViewIE::CanCopy() const
4681a3ea
SL
499{
500 return CanExecCommand("Copy");
501}
e669ddde 502bool wxWebViewIE::CanPaste() const
4681a3ea
SL
503{
504 return CanExecCommand("Paste");
505}
506
507void wxWebViewIE::Cut()
508{
509 ExecCommand("Cut");
510}
511
512void wxWebViewIE::Copy()
513{
514 ExecCommand("Copy");
515}
516
517void wxWebViewIE::Paste()
518{
519 ExecCommand("Paste");
520}
521
e669ddde 522bool wxWebViewIE::CanUndo() const
97e49559
SL
523{
524 return CanExecCommand("Undo");
525}
e669ddde 526bool wxWebViewIE::CanRedo() const
97e49559
SL
527{
528 return CanExecCommand("Redo");
529}
530
531void wxWebViewIE::Undo()
532{
533 ExecCommand("Undo");
534}
535
536void wxWebViewIE::Redo()
537{
538 ExecCommand("Redo");
539}
540
c7cbe308
SL
541void 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"));
7fbc727b
SL
548
549 document->Release();
c7cbe308
SL
550}
551
e669ddde 552bool wxWebViewIE::IsEditable() const
c7cbe308
SL
553{
554 IHTMLDocument2* document = GetDocument();
555 BSTR mode;
556 document->get_designMode(&mode);
423adfde 557 document->Release();
c7cbe308
SL
558 if(wxString(mode) == "On")
559 return true;
560 else
561 return false;
562}
563
63a65070
SL
564void wxWebViewIE::SelectAll()
565{
566 ExecCommand("SelectAll");
567}
568
e669ddde 569bool wxWebViewIE::HasSelection() const
63a65070
SL
570{
571 IHTMLDocument2* document = GetDocument();
572 IHTMLSelectionObject* selection;
423adfde 573 wxString sel;
7fbc727b
SL
574 HRESULT hr = document->get_selection(&selection);
575 if(SUCCEEDED(hr))
576 {
423adfde 577 BSTR type;
7fbc727b 578 selection->get_type(&type);
423adfde 579 sel = wxString(type);
7fbc727b
SL
580 selection->Release();
581 }
582 document->Release();
423adfde 583 return sel != "None";
63a65070
SL
584}
585
586void wxWebViewIE::DeleteSelection()
587{
588 ExecCommand("Delete");
589}
590
e669ddde 591wxString wxWebViewIE::GetSelectedText() const
c9355a3d
SL
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
e669ddde 620wxString wxWebViewIE::GetSelectedSource() const
0fe8a1b6
SL
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
41933aa5
SL
649void 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
e669ddde 663wxString wxWebViewIE::GetPageText() const
241b769f
SL
664{
665 IHTMLDocument2* document = GetDocument();
423adfde 666 wxString text;
241b769f
SL
667 IHTMLElement* body;
668 HRESULT hr = document->get_body(&body);
669 if(SUCCEEDED(hr))
670 {
423adfde 671 BSTR out;
241b769f 672 body->get_innerText(&out);
423adfde 673 text = wxString(out);
241b769f
SL
674 body->Release();
675 }
676 document->Release();
423adfde 677 return text;
241b769f
SL
678}
679
c9ccc09c
SL
680void 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
7d8d6163 696void wxWebViewIE::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
29365629 697{
e924e848
SL
698 wxDynamicLibrary urlMon(wxT("urlmon.dll"));
699 if(urlMon.HasSymbol(wxT("CoInternetGetSession")))
29365629 700 {
e924e848
SL
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 }
29365629 711
e924e848
SL
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 }
39498710 717 m_factories.push_back(cf);
e924e848
SL
718 }
719 else
29365629 720 {
e924e848 721 wxFAIL_MSG("urlmon does not contain CoInternetGetSession");
29365629
SL
722 }
723}
724
e669ddde 725bool wxWebViewIE::CanExecCommand(wxString command) const
4681a3ea 726{
617227c3 727 IHTMLDocument2* document = GetDocument();
4681a3ea 728 VARIANT_BOOL enabled;
7fbc727b 729
4681a3ea 730 document->queryCommandEnabled(SysAllocString(command.wc_str()), &enabled);
7fbc727b 731 document->Release();
4681a3ea
SL
732
733 return (enabled == VARIANT_TRUE);
734}
735
736void wxWebViewIE::ExecCommand(wxString command)
737{
617227c3
SL
738 IHTMLDocument2* document = GetDocument();
739 document->execCommand(SysAllocString(command.wc_str()), VARIANT_FALSE, VARIANT(), NULL);
7fbc727b 740 document->Release();
617227c3 741}
4681a3ea 742
e669ddde 743IHTMLDocument2* wxWebViewIE::GetDocument() const
617227c3
SL
744{
745 wxVariant variant = m_ie.GetProperty("Document");
746 IHTMLDocument2* document = (IHTMLDocument2*)variant.GetVoidPtr();
4681a3ea 747
617227c3
SL
748 wxASSERT(document);
749
750 return document;
4681a3ea
SL
751}
752
61b98a2d
SL
753void 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
04fa04d8 766 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING,
3225a4b8 767 GetId(), url, target);
e11b9a6b
SL
768
769 //skip empty javascript events.
770 if(url == "javascript:\"\"" && target.IsEmpty())
771 {
772 event.Veto();
773 }
774 else
775 {
776 event.SetEventObject(this);
777 HandleWindowEvent(event);
778 }
61b98a2d 779
3225a4b8 780 if (!event.IsAllowed())
61b98a2d
SL
781 {
782 wxActiveXEventNativeMSW* nativeParams =
783 evt.GetNativeParameters();
784 *V_BOOLREF(&nativeParams->pDispParams->rgvarg[0]) = VARIANT_TRUE;
785 }
786
787 // at this point, either the navigation event has been cancelled
788 // and we're not busy, either it was accepted and IWebBrowser2's
789 // Busy property will be true; so we don't need our override
790 // flag anymore.
791 m_isBusy = false;
792
793 break;
794 }
795
796 case DISPID_NAVIGATECOMPLETE2:
797 {
798 wxString url = evt[1].GetString();
799 // TODO: set target parameter if possible
800 wxString target = wxEmptyString;
04fa04d8 801 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED,
3225a4b8 802 GetId(), url, target);
61b98a2d
SL
803 event.SetEventObject(this);
804 HandleWindowEvent(event);
805 break;
806 }
807
808 case DISPID_PROGRESSCHANGE:
809 {
810 // download progress
811 break;
812 }
813
814 case DISPID_DOCUMENTCOMPLETE:
815 {
3ee442ff
SL
816 //Only send a complete even if we are actually finished, this brings
817 //the event in to line with webkit
818 READYSTATE rs;
819 m_webBrowser->get_ReadyState( &rs );
820 if(rs != READYSTATE_COMPLETE)
821 break;
822
61b98a2d 823 wxString url = evt[1].GetString();
113e0a92
SL
824
825 //As we are complete we also add to the history list, but not if the
826 //page is not the main page, ie it is a subframe
f239a200
SL
827 //We also have to check if we are loading a file:// url, if so we
828 //need to change the comparison as ie passes back a different style
829 //of url
830 if(m_historyEnabled && !m_historyLoadingFromList &&
831 (url == GetCurrentURL() ||
832 (GetCurrentURL().substr(0, 4) == "file" &&
833 wxFileSystem::URLToFileName(GetCurrentURL()).GetFullPath() == url)))
74af0b13
SL
834 {
835 //If we are not at the end of the list, then erase everything
836 //between us and the end before adding the new page
22ca10fa 837 if(m_historyPosition != static_cast<int>(m_historyList.size()) - 1)
74af0b13
SL
838 {
839 m_historyList.erase(m_historyList.begin() + m_historyPosition + 1,
840 m_historyList.end());
841 }
c13d6ac1 842 wxSharedPtr<wxWebViewHistoryItem> item(new wxWebViewHistoryItem(url, GetCurrentTitle()));
74af0b13
SL
843 m_historyList.push_back(item);
844 m_historyPosition++;
845 }
846 //Reset as we are done now
847 m_historyLoadingFromList = false;
61b98a2d
SL
848 // TODO: set target parameter if possible
849 wxString target = wxEmptyString;
04fa04d8 850 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(),
3225a4b8 851 url, target);
61b98a2d
SL
852 event.SetEventObject(this);
853 HandleWindowEvent(event);
854 break;
855 }
856
857 case DISPID_STATUSTEXTCHANGE:
858 {
859 break;
860 }
861
862 case DISPID_TITLECHANGE:
863 {
153530af
SL
864 wxString title = evt[0].GetString();
865
04fa04d8 866 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED,
3225a4b8 867 GetId(), GetCurrentURL(), "");
153530af
SL
868 event.SetString(title);
869 event.SetEventObject(this);
870 HandleWindowEvent(event);
61b98a2d
SL
871 break;
872 }
873
874 case DISPID_NAVIGATEERROR:
875 {
04fa04d8 876 wxWebViewNavigationError errorType = wxWEB_NAV_ERR_OTHER;
61b98a2d
SL
877 wxString errorCode = "?";
878 switch (evt[3].GetLong())
879 {
880 case INET_E_INVALID_URL: // (0x800C0002L or -2146697214)
881 errorCode = "INET_E_INVALID_URL";
882 errorType = wxWEB_NAV_ERR_REQUEST;
883 break;
884 case INET_E_NO_SESSION: // (0x800C0003L or -2146697213)
885 errorCode = "INET_E_NO_SESSION";
886 errorType = wxWEB_NAV_ERR_CONNECTION;
887 break;
888 case INET_E_CANNOT_CONNECT: // (0x800C0004L or -2146697212)
889 errorCode = "INET_E_CANNOT_CONNECT";
890 errorType = wxWEB_NAV_ERR_CONNECTION;
891 break;
892 case INET_E_RESOURCE_NOT_FOUND: // (0x800C0005L or -2146697211)
893 errorCode = "INET_E_RESOURCE_NOT_FOUND";
894 errorType = wxWEB_NAV_ERR_NOT_FOUND;
895 break;
896 case INET_E_OBJECT_NOT_FOUND: // (0x800C0006L or -2146697210)
897 errorCode = "INET_E_OBJECT_NOT_FOUND";
898 errorType = wxWEB_NAV_ERR_NOT_FOUND;
899 break;
900 case INET_E_DATA_NOT_AVAILABLE: // (0x800C0007L or -2146697209)
901 errorCode = "INET_E_DATA_NOT_AVAILABLE";
902 errorType = wxWEB_NAV_ERR_NOT_FOUND;
903 break;
904 case INET_E_DOWNLOAD_FAILURE: // (0x800C0008L or -2146697208)
905 errorCode = "INET_E_DOWNLOAD_FAILURE";
906 errorType = wxWEB_NAV_ERR_CONNECTION;
907 break;
908 case INET_E_AUTHENTICATION_REQUIRED: // (0x800C0009L or -2146697207)
909 errorCode = "INET_E_AUTHENTICATION_REQUIRED";
910 errorType = wxWEB_NAV_ERR_AUTH;
911 break;
912 case INET_E_NO_VALID_MEDIA: // (0x800C000AL or -2146697206)
913 errorCode = "INET_E_NO_VALID_MEDIA";
914 errorType = wxWEB_NAV_ERR_REQUEST;
915 break;
916 case INET_E_CONNECTION_TIMEOUT: // (0x800C000BL or -2146697205)
917 errorCode = "INET_E_CONNECTION_TIMEOUT";
918 errorType = wxWEB_NAV_ERR_CONNECTION;
919 break;
920 case INET_E_INVALID_REQUEST: // (0x800C000CL or -2146697204)
921 errorCode = "INET_E_INVALID_REQUEST";
922 errorType = wxWEB_NAV_ERR_REQUEST;
923 break;
924 case INET_E_UNKNOWN_PROTOCOL: // (0x800C000DL or -2146697203)
925 errorCode = "INET_E_UNKNOWN_PROTOCOL";
926 errorType = wxWEB_NAV_ERR_REQUEST;
927 break;
928 case INET_E_SECURITY_PROBLEM: // (0x800C000EL or -2146697202)
929 errorCode = "INET_E_SECURITY_PROBLEM";
930 errorType = wxWEB_NAV_ERR_SECURITY;
931 break;
932 case INET_E_CANNOT_LOAD_DATA: // (0x800C000FL or -2146697201)
933 errorCode = "INET_E_CANNOT_LOAD_DATA";
934 errorType = wxWEB_NAV_ERR_OTHER;
935 break;
936 case INET_E_CANNOT_INSTANTIATE_OBJECT:
937 // CoCreateInstance will return an error code if this happens,
938 // we'll handle this above.
939 return;
940 break;
941 case INET_E_REDIRECT_FAILED: // (0x800C0014L or -2146697196)
942 errorCode = "INET_E_REDIRECT_FAILED";
943 errorType = wxWEB_NAV_ERR_OTHER;
944 break;
945 case INET_E_REDIRECT_TO_DIR: // (0x800C0015L or -2146697195)
946 errorCode = "INET_E_REDIRECT_TO_DIR";
947 errorType = wxWEB_NAV_ERR_REQUEST;
948 break;
949 case INET_E_CANNOT_LOCK_REQUEST: // (0x800C0016L or -2146697194)
950 errorCode = "INET_E_CANNOT_LOCK_REQUEST";
951 errorType = wxWEB_NAV_ERR_OTHER;
952 break;
953 case INET_E_USE_EXTEND_BINDING: // (0x800C0017L or -2146697193)
954 errorCode = "INET_E_USE_EXTEND_BINDING";
955 errorType = wxWEB_NAV_ERR_OTHER;
956 break;
957 case INET_E_TERMINATED_BIND: // (0x800C0018L or -2146697192)
958 errorCode = "INET_E_TERMINATED_BIND";
959 errorType = wxWEB_NAV_ERR_OTHER;
960 break;
961 case INET_E_INVALID_CERTIFICATE: // (0x800C0019L or -2146697191)
962 errorCode = "INET_E_INVALID_CERTIFICATE";
963 errorType = wxWEB_NAV_ERR_CERTIFICATE;
964 break;
965 case INET_E_CODE_DOWNLOAD_DECLINED: // (0x800C0100L or -2146696960)
966 errorCode = "INET_E_CODE_DOWNLOAD_DECLINED";
967 errorType = wxWEB_NAV_ERR_USER_CANCELLED;
968 break;
969 case INET_E_RESULT_DISPATCHED: // (0x800C0200L or -2146696704)
970 // cancel request cancelled...
971 errorCode = "INET_E_RESULT_DISPATCHED";
972 errorType = wxWEB_NAV_ERR_OTHER;
973 break;
974 case INET_E_CANNOT_REPLACE_SFP_FILE: // (0x800C0300L or -2146696448)
975 errorCode = "INET_E_CANNOT_REPLACE_SFP_FILE";
976 errorType = wxWEB_NAV_ERR_SECURITY;
977 break;
978 case INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY:
979 errorCode = "INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY";
980 errorType = wxWEB_NAV_ERR_SECURITY;
981 break;
982 case INET_E_CODE_INSTALL_SUPPRESSED:
983 errorCode = "INET_E_CODE_INSTALL_SUPPRESSED";
984 errorType = wxWEB_NAV_ERR_SECURITY;
985 break;
986 }
987
988 wxString url = evt[1].GetString();
989 wxString target = evt[2].GetString();
04fa04d8 990 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR, GetId(),
3225a4b8 991 url, target);
61b98a2d
SL
992 event.SetEventObject(this);
993 event.SetInt(errorType);
994 event.SetString(errorCode);
995 HandleWindowEvent(event);
996 break;
997 }
853b6cd0 998 case DISPID_NEWWINDOW3:
61b98a2d 999 {
853b6cd0
SL
1000 wxString url = evt[4].GetString();
1001
04fa04d8 1002 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW,
3225a4b8 1003 GetId(), url, wxEmptyString);
853b6cd0
SL
1004 event.SetEventObject(this);
1005 HandleWindowEvent(event);
1006
d676fb21
SL
1007 //We always cancel this event otherwise an Internet Exporer window
1008 //is opened for the url
1009 wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters();
1010 *V_BOOLREF(&nativeParams->pDispParams->rgvarg[3]) = VARIANT_TRUE;
be19c556
SL
1011 break;
1012 }
61b98a2d
SL
1013 }
1014
1015 evt.Skip();
1016}
1017
7d8d6163 1018VirtualProtocol::VirtualProtocol(wxSharedPtr<wxWebViewHandler> handler)
7d3f6b4d
SL
1019{
1020 m_refCount = 0;
1021 m_file = NULL;
29365629 1022 m_handler = handler;
7d3f6b4d
SL
1023}
1024
1025VirtualProtocol::~VirtualProtocol()
1026{
7d3f6b4d
SL
1027}
1028
1029ULONG VirtualProtocol::AddRef()
1030{
1031 m_refCount++;
1032 return m_refCount;
1033}
1034
1035HRESULT VirtualProtocol::QueryInterface(REFIID riid, void **ppvObject)
1036{
29365629
SL
1037 if(riid == IID_IUnknown || riid == IID_IInternetProtocolRoot ||
1038 riid == IID_IInternetProtocol)
7d3f6b4d 1039 {
666f73c4
SL
1040 *ppvObject = (IInternetProtocol*)this;
1041 AddRef();
1042 return S_OK;
1043 }
7d3f6b4d
SL
1044 else
1045 {
1046 *ppvObject = NULL;
1047 return E_POINTER;
1048 }
1049}
1050
1051ULONG VirtualProtocol::Release()
1052{
1053 m_refCount--;
1054 if (m_refCount > 0)
1055 {
1056 return m_refCount;
1057 }
1058 else
1059 {
1060 delete this;
1061 return 0;
1062 }
1063}
1064
1065HRESULT VirtualProtocol::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink,
0995b9dc
SL
1066 IInternetBindInfo *pOIBindInfo, DWORD grfPI,
1067 HANDLE_PTR dwReserved)
7d3f6b4d 1068{
0995b9dc
SL
1069 wxUnusedVar(szUrl);
1070 wxUnusedVar(pOIBindInfo);
1071 wxUnusedVar(grfPI);
1072 wxUnusedVar(dwReserved);
7d3f6b4d 1073 m_protocolSink = pOIProtSink;
29365629
SL
1074
1075 //We get the file itself from the protocol handler
1076 m_file = m_handler->GetFile(szUrl);
1077
7d3f6b4d
SL
1078
1079 if(!m_file)
1080 return INET_E_RESOURCE_NOT_FOUND;
1081
1082 //We return the stream length for current and total size as we can always
1083 //read the whole file from the stream
666f73c4 1084 wxFileOffset length = m_file->GetStream()->GetLength();
7d3f6b4d
SL
1085 m_protocolSink->ReportData(BSCF_FIRSTDATANOTIFICATION |
1086 BSCF_DATAFULLYAVAILABLE |
1087 BSCF_LASTDATANOTIFICATION,
666f73c4 1088 length, length);
7d3f6b4d
SL
1089 return S_OK;
1090}
1091
1092HRESULT VirtualProtocol::Read(void *pv, ULONG cb, ULONG *pcbRead)
1093{
1094 //If the file is null we return false to indicte it is finished
1095 if(!m_file)
1096 return S_FALSE;
1097
1098 wxStreamError err = m_file->GetStream()->Read(pv, cb).GetLastError();
1099 *pcbRead = m_file->GetStream()->LastRead();
1100
1101 if(err == wxSTREAM_NO_ERROR)
1102 {
1103 if(*pcbRead < cb)
1104 {
1105 wxDELETE(m_file);
1106 m_protocolSink->ReportResult(S_OK, 0, NULL);
1107 }
1108 //As we are not eof there is more data
1109 return S_OK;
1110 }
1111 else if(err == wxSTREAM_EOF)
1112 {
1113 wxDELETE(m_file);
1114 m_protocolSink->ReportResult(S_OK, 0, NULL);
1115 //We are eof and so finished
1116 return S_OK;
1117 }
1118 else if(err == wxSTREAM_READ_ERROR)
1119 {
1120 wxDELETE(m_file);
1121 return INET_E_DOWNLOAD_FAILURE;
1122 }
0995b9dc
SL
1123 else
1124 {
1125 //Dummy return to surpress a compiler warning
1126 wxFAIL;
1127 return INET_E_DOWNLOAD_FAILURE;
1128 }
7d3f6b4d
SL
1129}
1130
1131HRESULT ClassFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid,
1132 void ** ppvObject)
1133{
1134 if (pUnkOuter)
1135 return CLASS_E_NOAGGREGATION;
29365629 1136 VirtualProtocol* vp = new VirtualProtocol(m_handler);
7d3f6b4d
SL
1137 vp->AddRef();
1138 HRESULT hr = vp->QueryInterface(riid, ppvObject);
1139 vp->Release();
1140 return hr;
1141
1142}
1143
1144STDMETHODIMP ClassFactory::LockServer(BOOL fLock)
1145{
0995b9dc
SL
1146 wxUnusedVar(fLock);
1147 return S_OK;
7d3f6b4d
SL
1148}
1149
1150ULONG ClassFactory::AddRef(void)
1151{
1152 m_refCount++;
1153 return m_refCount;
1154}
1155
1156HRESULT ClassFactory::QueryInterface(REFIID riid, void **ppvObject)
1157{
1158 if ((riid == IID_IUnknown) || (riid == IID_IClassFactory))
1159 {
1160 *ppvObject = this;
1161 AddRef();
1162 return S_OK;
1163 }
1164 else
1165 {
1166 *ppvObject = NULL;
1167 return E_POINTER;
1168 }
1169
1170}
1171
1172ULONG ClassFactory::Release(void)
1173{
1174 m_refCount--;
1175 if (m_refCount > 0)
1176 {
1177 return m_refCount;
1178 }
1179 else
1180 {
1181 delete this;
1182 return 0;
1183 }
1184
1185}
1186
9d2f31db 1187#endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE