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.

274 lines
8.2KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 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. END_JUCE_NAMESPACE
  19. #define DownloadClickDetector MakeObjCClassName(DownloadClickDetector)
  20. @interface DownloadClickDetector : NSObject
  21. {
  22. juce::WebBrowserComponent* ownerComponent;
  23. }
  24. - (DownloadClickDetector*) initWithWebBrowserOwner: (juce::WebBrowserComponent*) ownerComponent;
  25. - (void) webView: (WebView*) webView decidePolicyForNavigationAction: (NSDictionary*) actionInformation
  26. request: (NSURLRequest*) request
  27. frame: (WebFrame*) frame
  28. decisionListener: (id<WebPolicyDecisionListener>) listener;
  29. @end
  30. //==============================================================================
  31. @implementation DownloadClickDetector
  32. - (DownloadClickDetector*) initWithWebBrowserOwner: (juce::WebBrowserComponent*) ownerComponent_
  33. {
  34. [super init];
  35. ownerComponent = ownerComponent_;
  36. return self;
  37. }
  38. - (void) webView: (WebView*) sender decidePolicyForNavigationAction: (NSDictionary*) actionInformation
  39. request: (NSURLRequest*) request
  40. frame: (WebFrame*) frame
  41. decisionListener: (id <WebPolicyDecisionListener>) listener
  42. {
  43. (void) sender;
  44. (void) request;
  45. (void) frame;
  46. NSURL* url = [actionInformation valueForKey: nsStringLiteral ("WebActionOriginalURLKey")];
  47. if (ownerComponent->pageAboutToLoad (nsStringToJuce ([url absoluteString])))
  48. [listener use];
  49. else
  50. [listener ignore];
  51. }
  52. @end
  53. BEGIN_JUCE_NAMESPACE
  54. //==============================================================================
  55. class WebBrowserComponentInternal : public NSViewComponent
  56. {
  57. public:
  58. WebBrowserComponentInternal (WebBrowserComponent* owner)
  59. {
  60. webView = [[WebView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
  61. frameName: nsEmptyString()
  62. groupName: nsEmptyString()];
  63. setView (webView);
  64. clickListener = [[DownloadClickDetector alloc] initWithWebBrowserOwner: owner];
  65. [webView setPolicyDelegate: clickListener];
  66. }
  67. ~WebBrowserComponentInternal()
  68. {
  69. [webView setPolicyDelegate: nil];
  70. [clickListener release];
  71. setView (nil);
  72. }
  73. void goToURL (const String& url,
  74. const StringArray* headers,
  75. const MemoryBlock* postData)
  76. {
  77. NSMutableURLRequest* r
  78. = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: juceStringToNS (url)]
  79. cachePolicy: NSURLRequestUseProtocolCachePolicy
  80. timeoutInterval: 30.0];
  81. if (postData != nullptr && postData->getSize() > 0)
  82. {
  83. [r setHTTPMethod: nsStringLiteral ("POST")];
  84. [r setHTTPBody: [NSData dataWithBytes: postData->getData()
  85. length: postData->getSize()]];
  86. }
  87. if (headers != nullptr)
  88. {
  89. for (int i = 0; i < headers->size(); ++i)
  90. {
  91. const String headerName ((*headers)[i].upToFirstOccurrenceOf (":", false, false).trim());
  92. const String headerValue ((*headers)[i].fromFirstOccurrenceOf (":", false, false).trim());
  93. [r setValue: juceStringToNS (headerValue)
  94. forHTTPHeaderField: juceStringToNS (headerName)];
  95. }
  96. }
  97. stop();
  98. [[webView mainFrame] loadRequest: r];
  99. }
  100. void goBack()
  101. {
  102. [webView goBack];
  103. }
  104. void goForward()
  105. {
  106. [webView goForward];
  107. }
  108. void stop()
  109. {
  110. [webView stopLoading: nil];
  111. }
  112. void refresh()
  113. {
  114. [webView reload: nil];
  115. }
  116. void mouseMove (const MouseEvent&)
  117. {
  118. // WebKit doesn't capture mouse-moves itself, so it seems the only way to make
  119. // them work is to push them via this non-public method..
  120. if ([webView respondsToSelector: @selector (_updateMouseoverWithFakeEvent)])
  121. [webView performSelector: @selector (_updateMouseoverWithFakeEvent)];
  122. }
  123. private:
  124. WebView* webView;
  125. DownloadClickDetector* clickListener;
  126. };
  127. //==============================================================================
  128. WebBrowserComponent::WebBrowserComponent (const bool unloadPageWhenBrowserIsHidden_)
  129. : browser (nullptr),
  130. blankPageShown (false),
  131. unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_)
  132. {
  133. setOpaque (true);
  134. addAndMakeVisible (browser = new WebBrowserComponentInternal (this));
  135. }
  136. WebBrowserComponent::~WebBrowserComponent()
  137. {
  138. deleteAndZero (browser);
  139. }
  140. //==============================================================================
  141. void WebBrowserComponent::goToURL (const String& url,
  142. const StringArray* headers,
  143. const MemoryBlock* postData)
  144. {
  145. lastURL = url;
  146. lastHeaders.clear();
  147. if (headers != nullptr)
  148. lastHeaders = *headers;
  149. lastPostData.setSize (0);
  150. if (postData != nullptr)
  151. lastPostData = *postData;
  152. blankPageShown = false;
  153. browser->goToURL (url, headers, postData);
  154. }
  155. void WebBrowserComponent::stop()
  156. {
  157. browser->stop();
  158. }
  159. void WebBrowserComponent::goBack()
  160. {
  161. lastURL = String::empty;
  162. blankPageShown = false;
  163. browser->goBack();
  164. }
  165. void WebBrowserComponent::goForward()
  166. {
  167. lastURL = String::empty;
  168. browser->goForward();
  169. }
  170. void WebBrowserComponent::refresh()
  171. {
  172. browser->refresh();
  173. }
  174. //==============================================================================
  175. void WebBrowserComponent::paint (Graphics&)
  176. {
  177. }
  178. void WebBrowserComponent::checkWindowAssociation()
  179. {
  180. if (isShowing())
  181. {
  182. if (blankPageShown)
  183. goBack();
  184. }
  185. else
  186. {
  187. if (unloadPageWhenBrowserIsHidden && ! blankPageShown)
  188. {
  189. // when the component becomes invisible, some stuff like flash
  190. // carries on playing audio, so we need to force it onto a blank
  191. // page to avoid this, (and send it back when it's made visible again).
  192. blankPageShown = true;
  193. browser->goToURL ("about:blank", 0, 0);
  194. }
  195. }
  196. }
  197. void WebBrowserComponent::reloadLastURL()
  198. {
  199. if (lastURL.isNotEmpty())
  200. {
  201. goToURL (lastURL, &lastHeaders, &lastPostData);
  202. lastURL = String::empty;
  203. }
  204. }
  205. void WebBrowserComponent::parentHierarchyChanged()
  206. {
  207. checkWindowAssociation();
  208. }
  209. void WebBrowserComponent::resized()
  210. {
  211. browser->setSize (getWidth(), getHeight());
  212. }
  213. void WebBrowserComponent::visibilityChanged()
  214. {
  215. checkWindowAssociation();
  216. }
  217. bool WebBrowserComponent::pageAboutToLoad (const String&)
  218. {
  219. return true;
  220. }