The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

363 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. //==============================================================================
  24. #ifdef _MSC_VER
  25. #pragma warning (disable: 4514)
  26. #pragma warning (push)
  27. #endif
  28. #include "win32_headers.h"
  29. #include <comutil.h>
  30. #include <Exdisp.h>
  31. #include <exdispid.h>
  32. #ifdef _MSC_VER
  33. #pragma warning (pop)
  34. #pragma warning (disable: 4312 4244)
  35. #endif
  36. #include "../../../src/juce_core/basics/juce_StandardHeader.h"
  37. BEGIN_JUCE_NAMESPACE
  38. #include "../../../src/juce_appframework/gui/components/special/juce_WebBrowserComponent.h"
  39. #include "../../../src/juce_appframework/gui/components/special/juce_ActiveXControlComponent.h"
  40. //==============================================================================
  41. class WebBrowserComponentInternal : public ActiveXControlComponent
  42. {
  43. public:
  44. //==============================================================================
  45. WebBrowserComponentInternal()
  46. : browser (0),
  47. connectionPoint (0),
  48. adviseCookie (0)
  49. {
  50. }
  51. ~WebBrowserComponentInternal()
  52. {
  53. if (connectionPoint != 0)
  54. connectionPoint->Unadvise (adviseCookie);
  55. if (browser != 0)
  56. browser->Release();
  57. }
  58. void createBrowser()
  59. {
  60. createControl (&CLSID_WebBrowser);
  61. browser = (IWebBrowser2*) queryInterface (&IID_IWebBrowser2);
  62. IConnectionPointContainer* connectionPointContainer = (IConnectionPointContainer*) queryInterface (&IID_IConnectionPointContainer);
  63. if (connectionPointContainer != 0)
  64. {
  65. connectionPointContainer->FindConnectionPoint (DIID_DWebBrowserEvents2,
  66. &connectionPoint);
  67. if (connectionPoint != 0)
  68. {
  69. WebBrowserComponent* const owner = dynamic_cast <WebBrowserComponent*> (getParentComponent());
  70. jassert (owner != 0);
  71. EventHandler* handler = new EventHandler (owner);
  72. connectionPoint->Advise (handler, &adviseCookie);
  73. }
  74. }
  75. }
  76. void goToURL (const String& url,
  77. const StringArray* headers,
  78. const MemoryBlock* postData)
  79. {
  80. if (browser != 0)
  81. {
  82. LPSAFEARRAY sa = 0;
  83. _variant_t flags, frame, postDataVar, headersVar;
  84. if (headers != 0)
  85. headersVar = (const tchar*) headers->joinIntoString ("\r\n");
  86. if (postData != 0 && postData->getSize() > 0)
  87. {
  88. LPSAFEARRAY sa = SafeArrayCreateVector (VT_UI1, 0, postData->getSize());
  89. if (sa != 0)
  90. {
  91. void* data = 0;
  92. SafeArrayAccessData (sa, &data);
  93. jassert (data != 0);
  94. if (data != 0)
  95. {
  96. postData->copyTo (data, 0, postData->getSize());
  97. SafeArrayUnaccessData (sa);
  98. VARIANT postDataVar2;
  99. VariantInit (&postDataVar2);
  100. V_VT (&postDataVar2) = VT_ARRAY | VT_UI1;
  101. V_ARRAY (&postDataVar2) = sa;
  102. postDataVar = postDataVar2;
  103. }
  104. }
  105. }
  106. browser->Navigate ((BSTR) (const OLECHAR*) url,
  107. &flags, &frame,
  108. &postDataVar, &headersVar);
  109. if (sa != 0)
  110. SafeArrayDestroy (sa);
  111. }
  112. }
  113. //==============================================================================
  114. IWebBrowser2* browser;
  115. //==============================================================================
  116. juce_UseDebuggingNewOperator
  117. private:
  118. IConnectionPoint* connectionPoint;
  119. DWORD adviseCookie;
  120. //==============================================================================
  121. class EventHandler : public IDispatch
  122. {
  123. public:
  124. EventHandler (WebBrowserComponent* owner_)
  125. : owner (owner_),
  126. refCount (0)
  127. {
  128. }
  129. ~EventHandler()
  130. {
  131. }
  132. //==============================================================================
  133. HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
  134. {
  135. if (id == IID_IUnknown || id == IID_IDispatch || id == DIID_DWebBrowserEvents2)
  136. {
  137. AddRef();
  138. *result = this;
  139. return S_OK;
  140. }
  141. *result = 0;
  142. return E_NOINTERFACE;
  143. }
  144. ULONG __stdcall AddRef() { return ++refCount; }
  145. ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; }
  146. HRESULT __stdcall GetTypeInfoCount (UINT __RPC_FAR*) { return E_NOTIMPL; }
  147. HRESULT __stdcall GetTypeInfo (UINT, LCID, ITypeInfo __RPC_FAR *__RPC_FAR*) { return E_NOTIMPL; }
  148. HRESULT __stdcall GetIDsOfNames (REFIID, LPOLESTR __RPC_FAR*, UINT, LCID, DISPID __RPC_FAR*) { return E_NOTIMPL; }
  149. HRESULT __stdcall Invoke (DISPID dispIdMember, REFIID /*riid*/, LCID /*lcid*/,
  150. WORD /*wFlags*/, DISPPARAMS __RPC_FAR* pDispParams,
  151. VARIANT __RPC_FAR* /*pVarResult*/, EXCEPINFO __RPC_FAR* /*pExcepInfo*/,
  152. UINT __RPC_FAR* /*puArgErr*/)
  153. {
  154. switch (dispIdMember)
  155. {
  156. case DISPID_BEFORENAVIGATE2:
  157. {
  158. VARIANT* const vurl = pDispParams->rgvarg[5].pvarVal;
  159. String url;
  160. if ((vurl->vt & VT_BYREF) != 0)
  161. url = *vurl->pbstrVal;
  162. else
  163. url = vurl->bstrVal;
  164. *pDispParams->rgvarg->pboolVal
  165. = owner->pageAboutToLoad (url) ? VARIANT_FALSE
  166. : VARIANT_TRUE;
  167. return S_OK;
  168. }
  169. default:
  170. break;
  171. }
  172. return E_NOTIMPL;
  173. }
  174. //==============================================================================
  175. juce_UseDebuggingNewOperator
  176. private:
  177. WebBrowserComponent* const owner;
  178. int refCount;
  179. EventHandler (const EventHandler&);
  180. const EventHandler& operator= (const EventHandler&);
  181. };
  182. };
  183. //==============================================================================
  184. WebBrowserComponent::WebBrowserComponent()
  185. : browser (0),
  186. blankPageShown (false)
  187. {
  188. setOpaque (true);
  189. addAndMakeVisible (browser = new WebBrowserComponentInternal());
  190. }
  191. WebBrowserComponent::~WebBrowserComponent()
  192. {
  193. delete browser;
  194. }
  195. //==============================================================================
  196. void WebBrowserComponent::goToURL (const String& url,
  197. const StringArray* headers,
  198. const MemoryBlock* postData)
  199. {
  200. lastURL = url;
  201. lastHeaders.clear();
  202. if (headers != 0)
  203. lastHeaders = *headers;
  204. lastPostData.setSize (0);
  205. if (postData != 0)
  206. lastPostData = *postData;
  207. blankPageShown = false;
  208. browser->goToURL (url, headers, postData);
  209. }
  210. void WebBrowserComponent::stop()
  211. {
  212. if (browser->browser != 0)
  213. browser->browser->Stop();
  214. }
  215. void WebBrowserComponent::goBack()
  216. {
  217. lastURL = String::empty;
  218. blankPageShown = false;
  219. if (browser->browser != 0)
  220. browser->browser->GoBack();
  221. }
  222. void WebBrowserComponent::goForward()
  223. {
  224. lastURL = String::empty;
  225. if (browser->browser != 0)
  226. browser->browser->GoForward();
  227. }
  228. //==============================================================================
  229. void WebBrowserComponent::paint (Graphics& g)
  230. {
  231. if (browser->browser == 0)
  232. g.fillAll (Colours::white);
  233. }
  234. void WebBrowserComponent::checkWindowAssociation()
  235. {
  236. if (isShowing())
  237. {
  238. if (blankPageShown)
  239. goBack();
  240. if (browser->browser == 0 && getPeer() != 0)
  241. {
  242. browser->createBrowser();
  243. reloadLastURL();
  244. }
  245. }
  246. else
  247. {
  248. if (browser != 0 && ! blankPageShown)
  249. {
  250. // when the component becomes invisible, some stuff like flash
  251. // carries on playing audio, so we need to force it onto a blank
  252. // page to avoid this..
  253. blankPageShown = true;
  254. browser->goToURL ("about:blank", 0, 0);
  255. }
  256. }
  257. }
  258. void WebBrowserComponent::reloadLastURL()
  259. {
  260. if (lastURL.isNotEmpty())
  261. {
  262. goToURL (lastURL, &lastHeaders, &lastPostData);
  263. lastURL = String::empty;
  264. }
  265. }
  266. void WebBrowserComponent::parentHierarchyChanged()
  267. {
  268. checkWindowAssociation();
  269. }
  270. void WebBrowserComponent::moved()
  271. {
  272. }
  273. void WebBrowserComponent::resized()
  274. {
  275. browser->setSize (getWidth(), getHeight());
  276. }
  277. void WebBrowserComponent::visibilityChanged()
  278. {
  279. checkWindowAssociation();
  280. }
  281. bool WebBrowserComponent::pageAboutToLoad (const String&)
  282. {
  283. return true;
  284. }
  285. END_JUCE_NAMESPACE