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.

365 lines
11KB

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