1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00
JUCE/modules/juce_gui_extra/native/juce_mac_WebBrowserComponent.mm
2011-08-13 21:13:50 +01:00

273 lines
8.2 KiB
Text

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
END_JUCE_NAMESPACE
#define DownloadClickDetector MakeObjCClassName(DownloadClickDetector)
@interface DownloadClickDetector : NSObject
{
juce::WebBrowserComponent* ownerComponent;
}
- (DownloadClickDetector*) initWithWebBrowserOwner: (juce::WebBrowserComponent*) ownerComponent;
- (void) webView: (WebView*) webView decidePolicyForNavigationAction: (NSDictionary*) actionInformation
request: (NSURLRequest*) request
frame: (WebFrame*) frame
decisionListener: (id<WebPolicyDecisionListener>) listener;
@end
//==============================================================================
@implementation DownloadClickDetector
- (DownloadClickDetector*) initWithWebBrowserOwner: (juce::WebBrowserComponent*) ownerComponent_
{
[super init];
ownerComponent = ownerComponent_;
return self;
}
- (void) webView: (WebView*) sender decidePolicyForNavigationAction: (NSDictionary*) actionInformation
request: (NSURLRequest*) request
frame: (WebFrame*) frame
decisionListener: (id <WebPolicyDecisionListener>) listener
{
(void) sender;
(void) request;
(void) frame;
NSURL* url = [actionInformation valueForKey: nsStringLiteral ("WebActionOriginalURLKey")];
if (ownerComponent->pageAboutToLoad (nsStringToJuce ([url absoluteString])))
[listener use];
else
[listener ignore];
}
@end
BEGIN_JUCE_NAMESPACE
//==============================================================================
class WebBrowserComponentInternal : public NSViewComponent
{
public:
WebBrowserComponentInternal (WebBrowserComponent* owner)
{
webView = [[WebView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
frameName: nsEmptyString()
groupName: nsEmptyString()];
setView (webView);
clickListener = [[DownloadClickDetector alloc] initWithWebBrowserOwner: owner];
[webView setPolicyDelegate: clickListener];
}
~WebBrowserComponentInternal()
{
[webView setPolicyDelegate: nil];
[clickListener release];
setView (nil);
}
void goToURL (const String& url,
const StringArray* headers,
const MemoryBlock* postData)
{
NSMutableURLRequest* r
= [NSMutableURLRequest requestWithURL: [NSURL URLWithString: juceStringToNS (url)]
cachePolicy: NSURLRequestUseProtocolCachePolicy
timeoutInterval: 30.0];
if (postData != nullptr && postData->getSize() > 0)
{
[r setHTTPMethod: nsStringLiteral ("POST")];
[r setHTTPBody: [NSData dataWithBytes: postData->getData()
length: postData->getSize()]];
}
if (headers != nullptr)
{
for (int i = 0; i < headers->size(); ++i)
{
const String headerName ((*headers)[i].upToFirstOccurrenceOf (":", false, false).trim());
const String headerValue ((*headers)[i].fromFirstOccurrenceOf (":", false, false).trim());
[r setValue: juceStringToNS (headerValue)
forHTTPHeaderField: juceStringToNS (headerName)];
}
}
stop();
[[webView mainFrame] loadRequest: r];
}
void goBack()
{
[webView goBack];
}
void goForward()
{
[webView goForward];
}
void stop()
{
[webView stopLoading: nil];
}
void refresh()
{
[webView reload: nil];
}
void mouseMove (const MouseEvent&)
{
// WebKit doesn't capture mouse-moves itself, so it seems the only way to make
// them work is to push them via this non-public method..
if ([webView respondsToSelector: @selector (_updateMouseoverWithFakeEvent)])
[webView performSelector: @selector (_updateMouseoverWithFakeEvent)];
}
private:
WebView* webView;
DownloadClickDetector* clickListener;
};
//==============================================================================
WebBrowserComponent::WebBrowserComponent (const bool unloadPageWhenBrowserIsHidden_)
: browser (nullptr),
blankPageShown (false),
unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_)
{
setOpaque (true);
addAndMakeVisible (browser = new WebBrowserComponentInternal (this));
}
WebBrowserComponent::~WebBrowserComponent()
{
deleteAndZero (browser);
}
//==============================================================================
void WebBrowserComponent::goToURL (const String& url,
const StringArray* headers,
const MemoryBlock* postData)
{
lastURL = url;
lastHeaders.clear();
if (headers != nullptr)
lastHeaders = *headers;
lastPostData.setSize (0);
if (postData != nullptr)
lastPostData = *postData;
blankPageShown = false;
browser->goToURL (url, headers, postData);
}
void WebBrowserComponent::stop()
{
browser->stop();
}
void WebBrowserComponent::goBack()
{
lastURL = String::empty;
blankPageShown = false;
browser->goBack();
}
void WebBrowserComponent::goForward()
{
lastURL = String::empty;
browser->goForward();
}
void WebBrowserComponent::refresh()
{
browser->refresh();
}
//==============================================================================
void WebBrowserComponent::paint (Graphics&)
{
}
void WebBrowserComponent::checkWindowAssociation()
{
if (isShowing())
{
if (blankPageShown)
goBack();
}
else
{
if (unloadPageWhenBrowserIsHidden && ! blankPageShown)
{
// when the component becomes invisible, some stuff like flash
// carries on playing audio, so we need to force it onto a blank
// page to avoid this, (and send it back when it's made visible again).
blankPageShown = true;
browser->goToURL ("about:blank", 0, 0);
}
}
}
void WebBrowserComponent::reloadLastURL()
{
if (lastURL.isNotEmpty())
{
goToURL (lastURL, &lastHeaders, &lastPostData);
lastURL = String::empty;
}
}
void WebBrowserComponent::parentHierarchyChanged()
{
checkWindowAssociation();
}
void WebBrowserComponent::resized()
{
browser->setSize (getWidth(), getHeight());
}
void WebBrowserComponent::visibilityChanged()
{
checkWindowAssociation();
}
bool WebBrowserComponent::pageAboutToLoad (const String&)
{
return true;
}