2 ==============================================================================
\r
4 This file is part of the JUCE library.
\r
5 Copyright (c) 2022 - Raw Material Software Limited
\r
7 JUCE is an open source library subject to commercial or open-source
\r
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
\r
11 Agreement and JUCE Privacy Policy.
\r
13 End User License Agreement: www.juce.com/juce-7-licence
\r
14 Privacy Policy: www.juce.com/juce-privacy-policy
\r
16 Or: You may also use this code under the terms of the GPL v3 (see
\r
17 www.gnu.org/licenses).
\r
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
\r
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
\r
23 ==============================================================================
\r
29 #if JUCE_MAC && defined (MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
\r
30 #define WKWEBVIEW_OPENPANEL_SUPPORTED 1
\r
33 static NSURL* appendParametersToFileURL (const URL& url, NSURL* fileUrl)
\r
35 if (@available (macOS 10.10, *))
\r
37 const auto parameterNames = url.getParameterNames();
\r
38 const auto parameterValues = url.getParameterValues();
\r
40 jassert (parameterNames.size() == parameterValues.size());
\r
42 if (parameterNames.isEmpty())
\r
45 NSUniquePtr<NSURLComponents> components ([[NSURLComponents alloc] initWithURL: fileUrl resolvingAgainstBaseURL: NO]);
\r
46 NSUniquePtr<NSMutableArray> queryItems ([[NSMutableArray alloc] init]);
\r
48 for (int i = 0; i < parameterNames.size(); ++i)
\r
49 [queryItems.get() addObject: [NSURLQueryItem queryItemWithName: juceStringToNS (parameterNames[i])
\r
50 value: juceStringToNS (parameterValues[i])]];
\r
52 [components.get() setQueryItems: queryItems.get()];
\r
54 return [components.get() URL];
\r
57 const auto queryString = url.getQueryString();
\r
59 if (queryString.isNotEmpty())
\r
60 if (NSString* fileUrlString = [fileUrl absoluteString])
\r
61 return [NSURL URLWithString: [fileUrlString stringByAppendingString: juceStringToNS (queryString)]];
\r
66 static NSMutableURLRequest* getRequestForURL (const String& url, const StringArray* headers, const MemoryBlock* postData)
\r
68 NSString* urlString = juceStringToNS (url);
\r
70 if (@available (macOS 10.9, *))
\r
72 urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters: [NSCharacterSet URLQueryAllowedCharacterSet]];
\r
76 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
\r
77 urlString = [urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
\r
78 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
\r
81 if (NSURL* nsURL = [NSURL URLWithString: urlString])
\r
83 NSMutableURLRequest* r
\r
84 = [NSMutableURLRequest requestWithURL: nsURL
\r
85 cachePolicy: NSURLRequestUseProtocolCachePolicy
\r
86 timeoutInterval: 30.0];
\r
88 if (postData != nullptr && postData->getSize() > 0)
\r
90 [r setHTTPMethod: nsStringLiteral ("POST")];
\r
91 [r setHTTPBody: [NSData dataWithBytes: postData->getData()
\r
92 length: postData->getSize()]];
\r
95 if (headers != nullptr)
\r
97 for (int i = 0; i < headers->size(); ++i)
\r
99 auto headerName = (*headers)[i].upToFirstOccurrenceOf (":", false, false).trim();
\r
100 auto headerValue = (*headers)[i].fromFirstOccurrenceOf (":", false, false).trim();
\r
102 [r setValue: juceStringToNS (headerValue)
\r
103 forHTTPHeaderField: juceStringToNS (headerName)];
\r
114 template <class WebViewClass>
\r
115 struct WebViewKeyEquivalentResponder : public ObjCClass<WebViewClass>
\r
117 WebViewKeyEquivalentResponder()
\r
118 : ObjCClass<WebViewClass> ("WebViewKeyEquivalentResponder_")
\r
120 ObjCClass<WebViewClass>::addMethod (@selector (performKeyEquivalent:), performKeyEquivalent);
\r
121 ObjCClass<WebViewClass>::registerClass();
\r
125 static BOOL performKeyEquivalent (id self, SEL selector, NSEvent* event)
\r
127 const auto isCommandDown = [event]
\r
129 const auto modifierFlags = [event modifierFlags];
\r
131 #if defined (MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
\r
132 if (@available (macOS 10.12, *))
\r
133 return (modifierFlags & NSEventModifierFlagDeviceIndependentFlagsMask) == NSEventModifierFlagCommand;
\r
136 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
\r
137 return (modifierFlags & NSDeviceIndependentModifierFlagsMask) == NSCommandKeyMask;
\r
138 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
\r
143 auto sendAction = [&] (SEL actionSelector) -> BOOL
\r
145 return [NSApp sendAction: actionSelector
\r
146 to: [[self window] firstResponder]
\r
150 if ([[event charactersIgnoringModifiers] isEqualToString: @"x"]) return sendAction (@selector (cut:));
\r
151 if ([[event charactersIgnoringModifiers] isEqualToString: @"c"]) return sendAction (@selector (copy:));
\r
152 if ([[event charactersIgnoringModifiers] isEqualToString: @"v"]) return sendAction (@selector (paste:));
\r
153 if ([[event charactersIgnoringModifiers] isEqualToString: @"a"]) return sendAction (@selector (selectAll:));
\r
156 return ObjCClass<WebViewClass>::template sendSuperclassMessage<BOOL> (self, selector, event);
\r
160 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
\r
161 struct DownloadClickDetectorClass : public ObjCClass<NSObject>
\r
163 DownloadClickDetectorClass() : ObjCClass<NSObject> ("JUCEWebClickDetector_")
\r
165 addIvar<WebBrowserComponent*> ("owner");
\r
167 addMethod (@selector (webView:decidePolicyForNavigationAction:request:frame:decisionListener:), decidePolicyForNavigationAction);
\r
168 addMethod (@selector (webView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener:), decidePolicyForNewWindowAction);
\r
169 addMethod (@selector (webView:didFinishLoadForFrame:), didFinishLoadForFrame);
\r
170 addMethod (@selector (webView:didFailLoadWithError:forFrame:), didFailLoadWithError);
\r
171 addMethod (@selector (webView:didFailProvisionalLoadWithError:forFrame:), didFailLoadWithError);
\r
172 addMethod (@selector (webView:willCloseFrame:), willCloseFrame);
\r
173 addMethod (@selector (webView:runOpenPanelForFileButtonWithResultListener:allowMultipleFiles:), runOpenPanel);
\r
178 static void setOwner (id self, WebBrowserComponent* owner) { object_setInstanceVariable (self, "owner", owner); }
\r
179 static WebBrowserComponent* getOwner (id self) { return getIvar<WebBrowserComponent*> (self, "owner"); }
\r
182 static String getOriginalURL (NSDictionary* actionInformation)
\r
184 if (NSURL* url = [actionInformation valueForKey: nsStringLiteral ("WebActionOriginalURLKey")])
\r
185 return nsStringToJuce ([url absoluteString]);
\r
190 static void decidePolicyForNavigationAction (id self, SEL, WebView*, NSDictionary* actionInformation,
\r
191 NSURLRequest*, WebFrame*, id<WebPolicyDecisionListener> listener)
\r
193 if (getOwner (self)->pageAboutToLoad (getOriginalURL (actionInformation)))
\r
199 static void decidePolicyForNewWindowAction (id self, SEL, WebView*, NSDictionary* actionInformation,
\r
200 NSURLRequest*, NSString*, id<WebPolicyDecisionListener> listener)
\r
202 getOwner (self)->newWindowAttemptingToLoad (getOriginalURL (actionInformation));
\r
206 static void didFinishLoadForFrame (id self, SEL, WebView* sender, WebFrame* frame)
\r
208 if ([frame isEqual: [sender mainFrame]])
\r
210 NSURL* url = [[[frame dataSource] request] URL];
\r
211 getOwner (self)->pageFinishedLoading (nsStringToJuce ([url absoluteString]));
\r
215 static void didFailLoadWithError (id self, SEL, WebView* sender, NSError* error, WebFrame* frame)
\r
217 if ([frame isEqual: [sender mainFrame]] && error != nullptr && [error code] != NSURLErrorCancelled)
\r
219 auto errorString = nsStringToJuce ([error localizedDescription]);
\r
220 bool proceedToErrorPage = getOwner (self)->pageLoadHadNetworkError (errorString);
\r
222 // WebKit doesn't have an internal error page, so make a really simple one ourselves
\r
223 if (proceedToErrorPage)
\r
224 getOwner (self)->goToURL ("data:text/plain;charset=UTF-8," + errorString);
\r
228 static void willCloseFrame (id self, SEL, WebView*, WebFrame*)
\r
230 getOwner (self)->windowCloseRequest();
\r
233 static void runOpenPanel (id, SEL, WebView*, id<WebOpenPanelResultListener> resultListener, BOOL allowMultipleFiles)
\r
235 struct DeletedFileChooserWrapper : private DeletedAtShutdown
\r
237 DeletedFileChooserWrapper (std::unique_ptr<FileChooser> fc, id<WebOpenPanelResultListener> rl)
\r
238 : chooser (std::move (fc)), listener (rl)
\r
240 [listener.get() retain];
\r
243 std::unique_ptr<FileChooser> chooser;
\r
244 ObjCObjectHandle<id<WebOpenPanelResultListener>> listener;
\r
247 auto chooser = std::make_unique<FileChooser> (TRANS("Select the file you want to upload..."),
\r
248 File::getSpecialLocation (File::userHomeDirectory), "*");
\r
249 auto* wrapper = new DeletedFileChooserWrapper (std::move (chooser), resultListener);
\r
251 auto flags = FileBrowserComponent::openMode | FileBrowserComponent::canSelectFiles
\r
252 | (allowMultipleFiles ? FileBrowserComponent::canSelectMultipleItems : 0);
\r
254 wrapper->chooser->launchAsync (flags, [wrapper] (const FileChooser&)
\r
256 for (auto& f : wrapper->chooser->getResults())
\r
257 [wrapper->listener.get() chooseFilename: juceStringToNS (f.getFullPathName())];
\r
263 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
\r
266 struct API_AVAILABLE (macos (10.10)) WebViewDelegateClass : public ObjCClass<NSObject>
\r
268 WebViewDelegateClass() : ObjCClass<NSObject> ("JUCEWebViewDelegate_")
\r
270 addIvar<WebBrowserComponent*> ("owner");
\r
272 addMethod (@selector (webView:decidePolicyForNavigationAction:decisionHandler:), decidePolicyForNavigationAction);
\r
273 addMethod (@selector (webView:didFinishNavigation:), didFinishNavigation);
\r
274 addMethod (@selector (webView:didFailNavigation:withError:), didFailNavigation);
\r
275 addMethod (@selector (webView:didFailProvisionalNavigation:withError:), didFailProvisionalNavigation);
\r
276 addMethod (@selector (webViewDidClose:), webViewDidClose);
\r
277 addMethod (@selector (webView:createWebViewWithConfiguration:forNavigationAction:
\r
278 windowFeatures:), createWebView);
\r
280 #if WKWEBVIEW_OPENPANEL_SUPPORTED
\r
281 if (@available (macOS 10.12, *))
\r
282 addMethod (@selector (webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:), runOpenPanel);
\r
288 static void setOwner (id self, WebBrowserComponent* owner) { object_setInstanceVariable (self, "owner", owner); }
\r
289 static WebBrowserComponent* getOwner (id self) { return getIvar<WebBrowserComponent*> (self, "owner"); }
\r
292 static void decidePolicyForNavigationAction (id self, SEL, WKWebView*, WKNavigationAction* navigationAction,
\r
293 void (^decisionHandler)(WKNavigationActionPolicy))
\r
295 if (getOwner (self)->pageAboutToLoad (nsStringToJuce ([[[navigationAction request] URL] absoluteString])))
\r
296 decisionHandler (WKNavigationActionPolicyAllow);
\r
298 decisionHandler (WKNavigationActionPolicyCancel);
\r
301 static void didFinishNavigation (id self, SEL, WKWebView* webview, WKNavigation*)
\r
303 getOwner (self)->pageFinishedLoading (nsStringToJuce ([[webview URL] absoluteString]));
\r
306 static void displayError (WebBrowserComponent* owner, NSError* error)
\r
308 if ([error code] != NSURLErrorCancelled)
\r
310 auto errorString = nsStringToJuce ([error localizedDescription]);
\r
311 bool proceedToErrorPage = owner->pageLoadHadNetworkError (errorString);
\r
313 // WKWebView doesn't have an internal error page, so make a really simple one ourselves
\r
314 if (proceedToErrorPage)
\r
315 owner->goToURL ("data:text/plain;charset=UTF-8," + errorString);
\r
319 static void didFailNavigation (id self, SEL, WKWebView*, WKNavigation*, NSError* error)
\r
321 displayError (getOwner (self), error);
\r
324 static void didFailProvisionalNavigation (id self, SEL, WKWebView*, WKNavigation*, NSError* error)
\r
326 displayError (getOwner (self), error);
\r
329 static void webViewDidClose (id self, SEL, WKWebView*)
\r
331 getOwner (self)->windowCloseRequest();
\r
334 static WKWebView* createWebView (id self, SEL, WKWebView*, WKWebViewConfiguration*,
\r
335 WKNavigationAction* navigationAction, WKWindowFeatures*)
\r
337 getOwner (self)->newWindowAttemptingToLoad (nsStringToJuce ([[[navigationAction request] URL] absoluteString]));
\r
341 #if WKWEBVIEW_OPENPANEL_SUPPORTED
\r
342 API_AVAILABLE (macos (10.12))
\r
343 static void runOpenPanel (id, SEL, WKWebView*, WKOpenPanelParameters* parameters, WKFrameInfo*,
\r
344 void (^completionHandler)(NSArray<NSURL*>*))
\r
346 using CompletionHandlerType = decltype (completionHandler);
\r
348 class DeletedFileChooserWrapper : private DeletedAtShutdown
\r
351 DeletedFileChooserWrapper (std::unique_ptr<FileChooser> fc, CompletionHandlerType h)
\r
352 : chooser (std::move (fc)), handler (h)
\r
354 [handler.get() retain];
\r
357 ~DeletedFileChooserWrapper()
\r
359 callHandler (nullptr);
\r
362 void callHandler (NSArray<NSURL*>* urls)
\r
367 handler.get() (urls);
\r
368 handlerCalled = true;
\r
371 std::unique_ptr<FileChooser> chooser;
\r
374 ObjCObjectHandle<CompletionHandlerType> handler;
\r
375 bool handlerCalled = false;
\r
378 auto chooser = std::make_unique<FileChooser> (TRANS("Select the file you want to upload..."),
\r
379 File::getSpecialLocation (File::userHomeDirectory), "*");
\r
380 auto* wrapper = new DeletedFileChooserWrapper (std::move (chooser), completionHandler);
\r
382 auto flags = FileBrowserComponent::openMode | FileBrowserComponent::canSelectFiles
\r
383 | ([parameters allowsMultipleSelection] ? FileBrowserComponent::canSelectMultipleItems : 0);
\r
385 #if (defined (MAC_OS_X_VERSION_10_14) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14)
\r
386 if (@available (macOS 10.14, *))
\r
388 if ([parameters allowsDirectories])
\r
389 flags |= FileBrowserComponent::canSelectDirectories;
\r
393 wrapper->chooser->launchAsync (flags, [wrapper] (const FileChooser&)
\r
395 auto results = wrapper->chooser->getResults();
\r
396 auto urls = [NSMutableArray arrayWithCapacity: (NSUInteger) results.size()];
\r
398 for (auto& f : results)
\r
399 [urls addObject: [NSURL fileURLWithPath: juceStringToNS (f.getFullPathName())]];
\r
401 wrapper->callHandler (urls);
\r
408 //==============================================================================
\r
411 virtual ~WebViewBase() = default;
\r
413 virtual void goToURL (const String&, const StringArray*, const MemoryBlock*) = 0;
\r
414 virtual void goBack() = 0;
\r
415 virtual void goForward() = 0;
\r
416 virtual void stop() = 0;
\r
417 virtual void refresh() = 0;
\r
419 virtual id getWebView() = 0;
\r
423 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
\r
424 class WebViewImpl : public WebViewBase
\r
427 WebViewImpl (WebBrowserComponent* owner)
\r
429 static WebViewKeyEquivalentResponder<WebView> webviewClass;
\r
431 webView.reset ([webviewClass.createInstance() initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
\r
432 frameName: nsEmptyString()
\r
433 groupName: nsEmptyString()]);
\r
435 static DownloadClickDetectorClass cls;
\r
436 clickListener.reset ([cls.createInstance() init]);
\r
437 DownloadClickDetectorClass::setOwner (clickListener.get(), owner);
\r
439 [webView.get() setPolicyDelegate: clickListener.get()];
\r
440 [webView.get() setFrameLoadDelegate: clickListener.get()];
\r
441 [webView.get() setUIDelegate: clickListener.get()];
\r
444 ~WebViewImpl() override
\r
446 [webView.get() setPolicyDelegate: nil];
\r
447 [webView.get() setFrameLoadDelegate: nil];
\r
448 [webView.get() setUIDelegate: nil];
\r
451 void goToURL (const String& url,
\r
452 const StringArray* headers,
\r
453 const MemoryBlock* postData) override
\r
455 if (url.trimStart().startsWithIgnoreCase ("javascript:"))
\r
457 [webView.get() stringByEvaluatingJavaScriptFromString: juceStringToNS (url.fromFirstOccurrenceOf (":", false, false))];
\r
463 auto getRequest = [&]() -> NSMutableURLRequest*
\r
465 if (url.trimStart().startsWithIgnoreCase ("file:"))
\r
467 auto file = URL (url).getLocalFile();
\r
469 if (NSURL* nsUrl = [NSURL fileURLWithPath: juceStringToNS (file.getFullPathName())])
\r
470 return [NSMutableURLRequest requestWithURL: appendParametersToFileURL (url, nsUrl)
\r
471 cachePolicy: NSURLRequestUseProtocolCachePolicy
\r
472 timeoutInterval: 30.0];
\r
477 return getRequestForURL (url, headers, postData);
\r
480 if (NSMutableURLRequest* request = getRequest())
\r
481 [[webView.get() mainFrame] loadRequest: request];
\r
484 void goBack() override { [webView.get() goBack]; }
\r
485 void goForward() override { [webView.get() goForward]; }
\r
487 void stop() override { [webView.get() stopLoading: nil]; }
\r
488 void refresh() override { [webView.get() reload: nil]; }
\r
490 id getWebView() override { return webView.get(); }
\r
492 void mouseMove (const MouseEvent&)
\r
494 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")
\r
495 // WebKit doesn't capture mouse-moves itself, so it seems the only way to make
\r
496 // them work is to push them via this non-public method..
\r
497 if ([webView.get() respondsToSelector: @selector (_updateMouseoverWithFakeEvent)])
\r
498 [webView.get() performSelector: @selector (_updateMouseoverWithFakeEvent)];
\r
499 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
\r
503 ObjCObjectHandle<WebView*> webView;
\r
504 ObjCObjectHandle<id> clickListener;
\r
506 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
\r
509 class API_AVAILABLE (macos (10.11)) WKWebViewImpl : public WebViewBase
\r
512 WKWebViewImpl (WebBrowserComponent* owner)
\r
515 static WebViewKeyEquivalentResponder<WKWebView> webviewClass;
\r
517 webView.reset ([webviewClass.createInstance() initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)]);
\r
519 webView.reset ([[WKWebView alloc] initWithFrame: CGRectMake (0, 0, 100.0f, 100.0f)]);
\r
522 static WebViewDelegateClass cls;
\r
523 webViewDelegate.reset ([cls.createInstance() init]);
\r
524 WebViewDelegateClass::setOwner (webViewDelegate.get(), owner);
\r
526 [webView.get() setNavigationDelegate: webViewDelegate.get()];
\r
527 [webView.get() setUIDelegate: webViewDelegate.get()];
\r
530 ~WKWebViewImpl() override
\r
532 [webView.get() setNavigationDelegate: nil];
\r
533 [webView.get() setUIDelegate: nil];
\r
536 void goToURL (const String& url,
\r
537 const StringArray* headers,
\r
538 const MemoryBlock* postData) override
\r
540 auto trimmed = url.trimStart();
\r
542 if (trimmed.startsWithIgnoreCase ("javascript:"))
\r
544 [webView.get() evaluateJavaScript: juceStringToNS (url.fromFirstOccurrenceOf (":", false, false))
\r
545 completionHandler: nil];
\r
552 if (trimmed.startsWithIgnoreCase ("file:"))
\r
554 auto file = URL (url).getLocalFile();
\r
556 if (NSURL* nsUrl = [NSURL fileURLWithPath: juceStringToNS (file.getFullPathName())])
\r
557 [webView.get() loadFileURL: appendParametersToFileURL (url, nsUrl) allowingReadAccessToURL: nsUrl];
\r
559 else if (NSMutableURLRequest* request = getRequestForURL (url, headers, postData))
\r
561 [webView.get() loadRequest: request];
\r
565 void goBack() override { [webView.get() goBack]; }
\r
566 void goForward() override { [webView.get() goForward]; }
\r
568 void stop() override { [webView.get() stopLoading]; }
\r
569 void refresh() override { [webView.get() reload]; }
\r
571 id getWebView() override { return webView.get(); }
\r
574 ObjCObjectHandle<WKWebView*> webView;
\r
575 ObjCObjectHandle<id> webViewDelegate;
\r
578 //==============================================================================
\r
579 class WebBrowserComponent::Pimpl
\r
581 : public NSViewComponent
\r
583 : public UIViewComponent
\r
587 Pimpl (WebBrowserComponent* owner)
\r
589 if (@available (macOS 10.11, *))
\r
590 webView = std::make_unique<WKWebViewImpl> (owner);
\r
593 webView = std::make_unique<WebViewImpl> (owner);
\r
596 setView (webView->getWebView());
\r
605 void goToURL (const String& url,
\r
606 const StringArray* headers,
\r
607 const MemoryBlock* postData)
\r
609 webView->goToURL (url, headers, postData);
\r
612 void goBack() { webView->goBack(); }
\r
613 void goForward() { webView->goForward(); }
\r
615 void stop() { webView->stop(); }
\r
616 void refresh() { webView->refresh(); }
\r
619 std::unique_ptr<WebViewBase> webView;
\r
622 //==============================================================================
\r
623 WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)
\r
624 : unloadPageWhenHidden (unloadWhenHidden)
\r
627 browser.reset (new Pimpl (this));
\r
628 addAndMakeVisible (browser.get());
\r
631 WebBrowserComponent::~WebBrowserComponent() = default;
\r
633 //==============================================================================
\r
634 void WebBrowserComponent::goToURL (const String& url,
\r
635 const StringArray* headers,
\r
636 const MemoryBlock* postData)
\r
640 if (headers != nullptr)
\r
641 lastHeaders = *headers;
\r
643 lastHeaders.clear();
\r
645 if (postData != nullptr)
\r
646 lastPostData = *postData;
\r
648 lastPostData.reset();
\r
650 blankPageShown = false;
\r
652 browser->goToURL (url, headers, postData);
\r
655 void WebBrowserComponent::stop()
\r
660 void WebBrowserComponent::goBack()
\r
663 blankPageShown = false;
\r
667 void WebBrowserComponent::goForward()
\r
670 browser->goForward();
\r
673 void WebBrowserComponent::refresh()
\r
675 browser->refresh();
\r
678 //==============================================================================
\r
679 void WebBrowserComponent::paint (Graphics&)
\r
683 void WebBrowserComponent::checkWindowAssociation()
\r
689 if (blankPageShown)
\r
694 if (unloadPageWhenHidden && ! blankPageShown)
\r
696 // when the component becomes invisible, some stuff like flash
\r
697 // carries on playing audio, so we need to force it onto a blank
\r
698 // page to avoid this, (and send it back when it's made visible again).
\r
700 blankPageShown = true;
\r
701 browser->goToURL ("about:blank", nullptr, nullptr);
\r
706 void WebBrowserComponent::reloadLastURL()
\r
708 if (lastURL.isNotEmpty())
\r
710 goToURL (lastURL, &lastHeaders, &lastPostData);
\r
715 void WebBrowserComponent::parentHierarchyChanged()
\r
717 checkWindowAssociation();
\r
720 void WebBrowserComponent::resized()
\r
722 browser->setSize (getWidth(), getHeight());
\r
725 void WebBrowserComponent::visibilityChanged()
\r
727 checkWindowAssociation();
\r
730 void WebBrowserComponent::focusGained (FocusChangeType)
\r
734 void WebBrowserComponent::clearCookies()
\r
736 NSHTTPCookieStorage* storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
\r
738 if (NSArray* cookies = [storage cookies])
\r
740 const NSUInteger n = [cookies count];
\r
742 for (NSUInteger i = 0; i < n; ++i)
\r
743 [storage deleteCookie: [cookies objectAtIndex: i]];
\r
746 [[NSUserDefaults standardUserDefaults] synchronize];
\r
749 } // namespace juce
\r