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