| @@ -554,9 +554,9 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) | |||
| }; | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost) | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options) | |||
| { | |||
| return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost); | |||
| return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options); | |||
| } | |||
| //============================================================================== | |||
| @@ -648,9 +648,9 @@ public: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) | |||
| }; | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost) | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options) | |||
| { | |||
| return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost); | |||
| return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options); | |||
| } | |||
| } // namespace juce | |||
| @@ -607,9 +607,9 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) | |||
| }; | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost) | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options) | |||
| { | |||
| return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost); | |||
| return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options); | |||
| } | |||
| #endif | |||
| @@ -412,10 +412,8 @@ struct BackgroundDownloadTask : public URL::DownloadTask | |||
| { | |||
| BackgroundDownloadTask (const URL& urlToUse, | |||
| const File& targetLocationToUse, | |||
| String extraHeadersToUse, | |||
| URL::DownloadTask::Listener* listenerToUse, | |||
| bool shouldUsePostRequest) | |||
| : listener (listenerToUse), | |||
| const URL::DownloadTaskOptions& options) | |||
| : listener (options.listener), | |||
| uniqueIdentifier (String (urlToUse.toString (true).hashCode64()) + String (Random().nextInt64())) | |||
| { | |||
| targetLocation = targetLocationToUse; | |||
| @@ -429,11 +427,11 @@ struct BackgroundDownloadTask : public URL::DownloadTask | |||
| auto nsUrl = [NSURL URLWithString: juceStringToNS (urlToUse.toString (true))]; | |||
| NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL: nsUrl]; | |||
| if (shouldUsePostRequest) | |||
| if (options.usePost) | |||
| [request setHTTPMethod: @"POST"]; | |||
| StringArray headerLines; | |||
| headerLines.addLines (extraHeadersToUse); | |||
| headerLines.addLines (options.extraHeaders); | |||
| headerLines.removeEmptyStrings (true); | |||
| for (int i = 0; i < headerLines.size(); ++i) | |||
| @@ -445,10 +443,14 @@ struct BackgroundDownloadTask : public URL::DownloadTask | |||
| [request addValue: juceStringToNS (value) forHTTPHeaderField: juceStringToNS (key)]; | |||
| } | |||
| session = | |||
| [NSURLSession sessionWithConfiguration: [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: juceStringToNS (uniqueIdentifier)] | |||
| delegate: delegate | |||
| delegateQueue: nullptr]; | |||
| auto* configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: juceStringToNS (uniqueIdentifier)]; | |||
| if (options.sharedContainer.isNotEmpty()) | |||
| [configuration setSharedContainerIdentifier: juceStringToNS (options.sharedContainer)]; | |||
| session = [NSURLSession sessionWithConfiguration: configuration | |||
| delegate: delegate | |||
| delegateQueue: nullptr]; | |||
| if (session != nullptr) | |||
| downloadTask = [session downloadTaskWithRequest:request]; | |||
| @@ -648,9 +650,9 @@ struct BackgroundDownloadTask : public URL::DownloadTask | |||
| HashMap<String, BackgroundDownloadTask*, DefaultHashFunctions, CriticalSection> BackgroundDownloadTask::activeSessions; | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool usePostRequest) | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options) | |||
| { | |||
| std::unique_ptr<BackgroundDownloadTask> downloadTask (new BackgroundDownloadTask (*this, targetLocation, extraHeaders, listener, usePostRequest)); | |||
| auto downloadTask = std::make_unique<BackgroundDownloadTask> (*this, targetLocation, options); | |||
| if (downloadTask->initOK() && downloadTask->connect()) | |||
| return downloadTask; | |||
| @@ -663,9 +665,9 @@ void URL::DownloadTask::juce_iosURLSessionNotify (const String& identifier) | |||
| BackgroundDownloadTask::invokeNotify (identifier); | |||
| } | |||
| #else | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool usePost) | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options) | |||
| { | |||
| return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, usePost); | |||
| return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options); | |||
| } | |||
| #endif | |||
| @@ -929,9 +931,9 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (URLConnectionState) | |||
| }; | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost) | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options) | |||
| { | |||
| return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost); | |||
| return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options); | |||
| } | |||
| JUCE_END_IGNORE_WARNINGS_GCC_LIKE | |||
| @@ -650,9 +650,9 @@ bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& targetEmailA | |||
| return mapiSendMail (0, 0, &message, MAPI_DIALOG | MAPI_LOGON_UI, 0) == SUCCESS_SUCCESS; | |||
| } | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost) | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options) | |||
| { | |||
| return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost); | |||
| return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options); | |||
| } | |||
| } // namespace juce | |||
| @@ -106,29 +106,26 @@ struct FallbackDownloadTask : public URL::DownloadTask, | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FallbackDownloadTask) | |||
| }; | |||
| void URL::DownloadTask::Listener::progress (DownloadTask*, int64, int64) {} | |||
| URL::DownloadTask::Listener::~Listener() {} | |||
| void URL::DownloadTaskListener::progress (DownloadTask*, int64, int64) {} | |||
| //============================================================================== | |||
| std::unique_ptr<URL::DownloadTask> URL::DownloadTask::createFallbackDownloader (const URL& urlToUse, | |||
| const File& targetFileToUse, | |||
| const String& extraHeadersToUse, | |||
| Listener* listenerToUse, | |||
| bool usePostRequest) | |||
| const DownloadTaskOptions& options) | |||
| { | |||
| const size_t bufferSize = 0x8000; | |||
| targetFileToUse.deleteFile(); | |||
| if (auto outputStream = targetFileToUse.createOutputStream (bufferSize)) | |||
| { | |||
| auto stream = std::make_unique<WebInputStream> (urlToUse, usePostRequest); | |||
| stream->withExtraHeaders (extraHeadersToUse); | |||
| auto stream = std::make_unique<WebInputStream> (urlToUse, options.usePost); | |||
| stream->withExtraHeaders (options.extraHeaders); | |||
| if (stream->connect (nullptr)) | |||
| return std::make_unique<FallbackDownloadTask> (std::move (outputStream), | |||
| bufferSize, | |||
| std::move (stream), | |||
| listenerToUse); | |||
| options.listener); | |||
| } | |||
| return nullptr; | |||
| @@ -1005,4 +1002,15 @@ std::unique_ptr<InputStream> URL::createInputStream (bool usePostCommand, | |||
| .withHttpRequestCmd (httpRequestCmd)); | |||
| } | |||
| std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, | |||
| String extraHeaders, | |||
| DownloadTask::Listener* listener, | |||
| bool usePostCommand) | |||
| { | |||
| auto options = DownloadTaskOptions().withExtraHeaders (std::move (extraHeaders)) | |||
| .withListener (listener) | |||
| .withUsePost (usePostCommand); | |||
| return downloadToFile (targetLocation, std::move (options)); | |||
| } | |||
| } // namespace juce | |||
| @@ -428,29 +428,72 @@ public: | |||
| std::unique_ptr<OutputStream> createOutputStream() const; | |||
| //============================================================================== | |||
| /** Represents a download task. | |||
| class DownloadTask; | |||
| Returned by downloadToFile() to allow querying and controlling the download task. | |||
| /** Used to receive callbacks for download progress. */ | |||
| struct JUCE_API DownloadTaskListener | |||
| { | |||
| virtual ~DownloadTaskListener() = default; | |||
| /** Called when the download has finished. Be aware that this callback may | |||
| come on an arbitrary thread. | |||
| */ | |||
| virtual void finished (DownloadTask* task, bool success) = 0; | |||
| /** Called periodically by the OS to indicate download progress. | |||
| Beware that this callback may come on an arbitrary thread. | |||
| */ | |||
| virtual void progress (DownloadTask* task, int64 bytesDownloaded, int64 totalLength); | |||
| }; | |||
| /** Holds options that will can be specified when starting a new download | |||
| with downloadToFile(). | |||
| */ | |||
| class JUCE_API DownloadTask | |||
| class DownloadTaskOptions | |||
| { | |||
| public: | |||
| /** Used to receive callbacks for download progress. */ | |||
| struct JUCE_API Listener | |||
| { | |||
| virtual ~Listener(); | |||
| String extraHeaders; | |||
| String sharedContainer; | |||
| DownloadTaskListener* listener = nullptr; | |||
| bool usePost = false; | |||
| /** Specifies headers to add to the request. */ | |||
| auto withExtraHeaders (String value) const { return with (&DownloadTaskOptions::extraHeaders, std::move (value)); } | |||
| /** On iOS, specifies the container where the downloaded file will be stored. | |||
| If you initiate a download task from inside an app extension on iOS, | |||
| you must supply this option. | |||
| This is currently unused on other platforms. | |||
| */ | |||
| auto withSharedContainer (String value) const { return with (&DownloadTaskOptions::sharedContainer, std::move (value)); } | |||
| /** Called when the download has finished. Be aware that this callback may | |||
| come on an arbitrary thread. | |||
| */ | |||
| virtual void finished (URL::DownloadTask* task, bool success) = 0; | |||
| /** Specifies an observer for the download task. */ | |||
| auto withListener (DownloadTaskListener* value) const { return with (&DownloadTaskOptions::listener, std::move (value)); } | |||
| /** Called periodically by the OS to indicate download progress. | |||
| /** Specifies whether a post command should be used. */ | |||
| auto withUsePost (bool value) const { return with (&DownloadTaskOptions::usePost, value); } | |||
| Beware that this callback may come on an arbitrary thread. | |||
| */ | |||
| virtual void progress (URL::DownloadTask* task, int64 bytesDownloaded, int64 totalLength); | |||
| }; | |||
| private: | |||
| template <typename Member, typename Value> | |||
| DownloadTaskOptions with (Member&& member, Value&& value) const | |||
| { | |||
| auto copy = *this; | |||
| copy.*member = std::forward<Value> (value); | |||
| return copy; | |||
| } | |||
| }; | |||
| /** Represents a download task. | |||
| Returned by downloadToFile() to allow querying and controlling the download task. | |||
| */ | |||
| class JUCE_API DownloadTask | |||
| { | |||
| public: | |||
| using Listener = DownloadTaskListener; | |||
| /** Releases the resources of the download task, unregisters the listener | |||
| and cancels the download if necessary. | |||
| @@ -493,7 +536,7 @@ public: | |||
| private: | |||
| friend class URL; | |||
| static std::unique_ptr<DownloadTask> createFallbackDownloader (const URL&, const File&, const String&, Listener*, bool); | |||
| static std::unique_ptr<DownloadTask> createFallbackDownloader (const URL&, const File&, const DownloadTaskOptions&); | |||
| public: | |||
| #if JUCE_IOS | |||
| @@ -505,6 +548,13 @@ public: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DownloadTask) | |||
| }; | |||
| /** This function is replaced by a new overload accepting a DownloadTaskOptions argument. */ | |||
| [[deprecated ("Use the overload with a DownloadTaskOptions argument instead")]] | |||
| std::unique_ptr<DownloadTask> downloadToFile (const File& targetLocation, | |||
| String extraHeaders = String(), | |||
| DownloadTaskListener* listener = nullptr, | |||
| bool usePostCommand = false); | |||
| /** Download the URL to a file. | |||
| This method attempts to download the URL to a given file location. | |||
| @@ -515,9 +565,7 @@ public: | |||
| network re-connections and continuing your download while your app is suspended. | |||
| */ | |||
| std::unique_ptr<DownloadTask> downloadToFile (const File& targetLocation, | |||
| String extraHeaders = String(), | |||
| DownloadTask::Listener* listener = nullptr, | |||
| bool usePostCommand = false); | |||
| const DownloadTaskOptions& options); | |||
| //============================================================================== | |||
| /** Tries to download the entire contents of this URL into a binary data block. | |||