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.

326 lines
10.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 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. handler->Release();
  55. }
  56. }
  57. }
  58. void goToURL (const String& url,
  59. const StringArray* headers,
  60. const MemoryBlock* postData)
  61. {
  62. if (browser != 0)
  63. {
  64. LPSAFEARRAY sa = 0;
  65. VARIANT flags, frame, postDataVar, headersVar; // (_variant_t isn't available in all compilers)
  66. VariantInit (&flags);
  67. VariantInit (&frame);
  68. VariantInit (&postDataVar);
  69. VariantInit (&headersVar);
  70. if (headers != 0)
  71. {
  72. V_VT (&headersVar) = VT_BSTR;
  73. V_BSTR (&headersVar) = SysAllocString ((const OLECHAR*) headers->joinIntoString ("\r\n"));
  74. }
  75. if (postData != 0 && postData->getSize() > 0)
  76. {
  77. LPSAFEARRAY sa = SafeArrayCreateVector (VT_UI1, 0, postData->getSize());
  78. if (sa != 0)
  79. {
  80. void* data = 0;
  81. SafeArrayAccessData (sa, &data);
  82. jassert (data != 0);
  83. if (data != 0)
  84. {
  85. postData->copyTo (data, 0, postData->getSize());
  86. SafeArrayUnaccessData (sa);
  87. VARIANT postDataVar2;
  88. VariantInit (&postDataVar2);
  89. V_VT (&postDataVar2) = VT_ARRAY | VT_UI1;
  90. V_ARRAY (&postDataVar2) = sa;
  91. postDataVar = postDataVar2;
  92. }
  93. }
  94. }
  95. browser->Navigate ((BSTR) (const OLECHAR*) url,
  96. &flags, &frame,
  97. &postDataVar, &headersVar);
  98. if (sa != 0)
  99. SafeArrayDestroy (sa);
  100. VariantClear (&flags);
  101. VariantClear (&frame);
  102. VariantClear (&postDataVar);
  103. VariantClear (&headersVar);
  104. }
  105. }
  106. //==============================================================================
  107. IWebBrowser2* browser;
  108. private:
  109. IConnectionPoint* connectionPoint;
  110. DWORD adviseCookie;
  111. //==============================================================================
  112. class EventHandler : public ComBaseClassHelper <IDispatch>,
  113. public ComponentMovementWatcher
  114. {
  115. public:
  116. EventHandler (WebBrowserComponent& owner_)
  117. : ComponentMovementWatcher (&owner_),
  118. owner (owner_)
  119. {
  120. }
  121. //==============================================================================
  122. HRESULT __stdcall GetTypeInfoCount (UINT*) { return E_NOTIMPL; }
  123. HRESULT __stdcall GetTypeInfo (UINT, LCID, ITypeInfo**) { return E_NOTIMPL; }
  124. HRESULT __stdcall GetIDsOfNames (REFIID, LPOLESTR*, UINT, LCID, DISPID*) { return E_NOTIMPL; }
  125. HRESULT __stdcall Invoke (DISPID dispIdMember, REFIID /*riid*/, LCID /*lcid*/, WORD /*wFlags*/, DISPPARAMS* pDispParams,
  126. VARIANT* /*pVarResult*/, EXCEPINFO* /*pExcepInfo*/, UINT* /*puArgErr*/)
  127. {
  128. if (dispIdMember == DISPID_BEFORENAVIGATE2)
  129. {
  130. VARIANT* const vurl = pDispParams->rgvarg[5].pvarVal;
  131. String url;
  132. if ((vurl->vt & VT_BYREF) != 0)
  133. url = *vurl->pbstrVal;
  134. else
  135. url = vurl->bstrVal;
  136. *pDispParams->rgvarg->pboolVal
  137. = owner.pageAboutToLoad (url) ? VARIANT_FALSE
  138. : VARIANT_TRUE;
  139. return S_OK;
  140. }
  141. return E_NOTIMPL;
  142. }
  143. void componentMovedOrResized (bool, bool ) {}
  144. void componentPeerChanged() {}
  145. void componentVisibilityChanged() { owner.visibilityChanged(); }
  146. //==============================================================================
  147. private:
  148. WebBrowserComponent& owner;
  149. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EventHandler);
  150. };
  151. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebBrowserComponentInternal);
  152. };
  153. //==============================================================================
  154. WebBrowserComponent::WebBrowserComponent (const bool unloadPageWhenBrowserIsHidden_)
  155. : browser (0),
  156. blankPageShown (false),
  157. unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_)
  158. {
  159. setOpaque (true);
  160. addAndMakeVisible (browser = new WebBrowserComponentInternal());
  161. }
  162. WebBrowserComponent::~WebBrowserComponent()
  163. {
  164. delete browser;
  165. }
  166. //==============================================================================
  167. void WebBrowserComponent::goToURL (const String& url,
  168. const StringArray* headers,
  169. const MemoryBlock* postData)
  170. {
  171. lastURL = url;
  172. lastHeaders.clear();
  173. if (headers != 0)
  174. lastHeaders = *headers;
  175. lastPostData.setSize (0);
  176. if (postData != 0)
  177. lastPostData = *postData;
  178. blankPageShown = false;
  179. browser->goToURL (url, headers, postData);
  180. }
  181. void WebBrowserComponent::stop()
  182. {
  183. if (browser->browser != 0)
  184. browser->browser->Stop();
  185. }
  186. void WebBrowserComponent::goBack()
  187. {
  188. lastURL = String::empty;
  189. blankPageShown = false;
  190. if (browser->browser != 0)
  191. browser->browser->GoBack();
  192. }
  193. void WebBrowserComponent::goForward()
  194. {
  195. lastURL = String::empty;
  196. if (browser->browser != 0)
  197. browser->browser->GoForward();
  198. }
  199. void WebBrowserComponent::refresh()
  200. {
  201. if (browser->browser != 0)
  202. browser->browser->Refresh();
  203. }
  204. //==============================================================================
  205. void WebBrowserComponent::paint (Graphics& g)
  206. {
  207. if (browser->browser == 0)
  208. g.fillAll (Colours::white);
  209. }
  210. void WebBrowserComponent::checkWindowAssociation()
  211. {
  212. if (isShowing())
  213. {
  214. if (browser->browser == 0 && getPeer() != 0)
  215. {
  216. browser->createBrowser();
  217. reloadLastURL();
  218. }
  219. else
  220. {
  221. if (blankPageShown)
  222. goBack();
  223. }
  224. }
  225. else
  226. {
  227. if (browser != 0 && unloadPageWhenBrowserIsHidden && ! blankPageShown)
  228. {
  229. // when the component becomes invisible, some stuff like flash
  230. // carries on playing audio, so we need to force it onto a blank
  231. // page to avoid this..
  232. blankPageShown = true;
  233. browser->goToURL ("about:blank", 0, 0);
  234. }
  235. }
  236. }
  237. void WebBrowserComponent::reloadLastURL()
  238. {
  239. if (lastURL.isNotEmpty())
  240. {
  241. goToURL (lastURL, &lastHeaders, &lastPostData);
  242. lastURL = String::empty;
  243. }
  244. }
  245. void WebBrowserComponent::parentHierarchyChanged()
  246. {
  247. checkWindowAssociation();
  248. }
  249. void WebBrowserComponent::resized()
  250. {
  251. browser->setSize (getWidth(), getHeight());
  252. }
  253. void WebBrowserComponent::visibilityChanged()
  254. {
  255. checkWindowAssociation();
  256. }
  257. bool WebBrowserComponent::pageAboutToLoad (const String&)
  258. {
  259. return true;
  260. }
  261. #endif