Move URL from WebCore to WTF
[WebKit-https.git] / Source / WebKit / NetworkProcess / Downloads / DownloadManager.cpp
1 /*
2  * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "DownloadManager.h"
28
29 #include "Download.h"
30 #include "NetworkBlobRegistry.h"
31 #include "NetworkLoad.h"
32 #include "NetworkSession.h"
33 #include "PendingDownload.h"
34 #include "SessionTracker.h"
35 #include <WebCore/NotImplemented.h>
36 #include <pal/SessionID.h>
37 #include <wtf/StdLibExtras.h>
38
39 namespace WebKit {
40 using namespace WebCore;
41
42 DownloadManager::DownloadManager(Client& client)
43     : m_client(client)
44 {
45 }
46
47 void DownloadManager::startDownload(NetworkConnectionToWebProcess* connection, PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedName)
48 {
49     auto* networkSession = SessionTracker::networkSession(sessionID);
50     if (!networkSession)
51         return;
52
53     NetworkLoadParameters parameters;
54     parameters.sessionID = sessionID;
55     parameters.request = request;
56     parameters.clientCredentialPolicy = ClientCredentialPolicy::MayAskClientForCredentials;
57     if (request.url().protocolIsBlob() && connection)
58         parameters.blobFileReferences = NetworkBlobRegistry::singleton().filesInBlob(*connection, request.url());
59     parameters.storedCredentialsPolicy = sessionID.isEphemeral() ? StoredCredentialsPolicy::DoNotUse : StoredCredentialsPolicy::Use;
60
61     m_pendingDownloads.add(downloadID, std::make_unique<PendingDownload>(WTFMove(parameters), downloadID, *networkSession, suggestedName));
62 }
63
64 void DownloadManager::dataTaskBecameDownloadTask(DownloadID downloadID, std::unique_ptr<Download>&& download)
65 {
66     ASSERT(m_pendingDownloads.contains(downloadID));
67     if (auto pendingDownload = m_pendingDownloads.take(downloadID)) {
68 #if PLATFORM(COCOA)
69         pendingDownload->didBecomeDownload(download);
70 #endif
71     }
72     ASSERT(!m_downloads.contains(downloadID));
73     m_downloadsAfterDestinationDecided.remove(downloadID);
74     m_downloads.add(downloadID, WTFMove(download));
75 }
76
77 void DownloadManager::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
78 {
79     auto* pendingDownload = m_pendingDownloads.get(downloadID);
80     ASSERT(pendingDownload);
81     if (pendingDownload)
82         pendingDownload->continueWillSendRequest(WTFMove(request));
83 }
84
85 void DownloadManager::willDecidePendingDownloadDestination(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler)
86 {
87     auto downloadID = networkDataTask.pendingDownloadID();
88     auto addResult = m_downloadsWaitingForDestination.set(downloadID, std::make_pair<RefPtr<NetworkDataTask>, ResponseCompletionHandler>(&networkDataTask, WTFMove(completionHandler)));
89     ASSERT_UNUSED(addResult, addResult.isNewEntry);
90 }
91
92 void DownloadManager::convertNetworkLoadToDownload(DownloadID downloadID, std::unique_ptr<NetworkLoad>&& networkLoad, ResponseCompletionHandler&& completionHandler, Vector<RefPtr<WebCore::BlobDataFileReference>>&& blobFileReferences, const ResourceRequest& request, const ResourceResponse& response)
93 {
94     ASSERT(!m_pendingDownloads.contains(downloadID));
95     m_pendingDownloads.add(downloadID, std::make_unique<PendingDownload>(WTFMove(networkLoad), WTFMove(completionHandler), downloadID, request, response));
96 }
97
98 void DownloadManager::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
99 {
100     if (m_downloadsWaitingForDestination.contains(downloadID)) {
101         auto pair = m_downloadsWaitingForDestination.take(downloadID);
102         auto networkDataTask = WTFMove(pair.first);
103         auto completionHandler = WTFMove(pair.second);
104         ASSERT(networkDataTask);
105         ASSERT(completionHandler);
106         ASSERT(m_pendingDownloads.contains(downloadID));
107
108         networkDataTask->setPendingDownloadLocation(destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
109         completionHandler(PolicyAction::Download);
110         if (networkDataTask->state() == NetworkDataTask::State::Canceling || networkDataTask->state() == NetworkDataTask::State::Completed)
111             return;
112
113         if (m_downloads.contains(downloadID)) {
114             // The completion handler already called dataTaskBecameDownloadTask().
115             return;
116         }
117
118         ASSERT(!m_downloadsAfterDestinationDecided.contains(downloadID));
119         m_downloadsAfterDestinationDecided.set(downloadID, networkDataTask);
120     }
121 }
122
123 void DownloadManager::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, SandboxExtension::Handle&& sandboxExtensionHandle)
124 {
125 #if !PLATFORM(COCOA)
126     notImplemented();
127 #else
128     auto download = std::make_unique<Download>(*this, downloadID, nullptr, sessionID);
129
130     download->resume(resumeData, path, WTFMove(sandboxExtensionHandle));
131     ASSERT(!m_downloads.contains(downloadID));
132     m_downloads.add(downloadID, WTFMove(download));
133 #endif
134 }
135
136 void DownloadManager::cancelDownload(DownloadID downloadID)
137 {
138     if (Download* download = m_downloads.get(downloadID)) {
139         ASSERT(!m_downloadsWaitingForDestination.contains(downloadID));
140         ASSERT(!m_pendingDownloads.contains(downloadID));
141         download->cancel();
142         return;
143     }
144     auto pendingDownload = m_pendingDownloads.take(downloadID);
145     if (m_downloadsWaitingForDestination.contains(downloadID)) {
146         auto pair = m_downloadsWaitingForDestination.take(downloadID);
147         auto networkDataTask = WTFMove(pair.first);
148         auto completionHandler = WTFMove(pair.second);
149         ASSERT(networkDataTask);
150         ASSERT(completionHandler);
151
152         networkDataTask->cancel();
153         completionHandler(PolicyAction::Ignore);
154         m_client.pendingDownloadCanceled(downloadID);
155         return;
156     }
157
158     if (pendingDownload)
159         pendingDownload->cancel();
160 }
161
162 #if PLATFORM(COCOA)
163 void DownloadManager::publishDownloadProgress(DownloadID downloadID, const URL& url, SandboxExtension::Handle&& sandboxExtensionHandle)
164 {
165     if (auto* download = m_downloads.get(downloadID))
166         download->publishProgress(url, WTFMove(sandboxExtensionHandle));
167     else if (auto* pendingDownload = m_pendingDownloads.get(downloadID))
168         pendingDownload->publishProgress(url, WTFMove(sandboxExtensionHandle));
169 }
170 #endif // PLATFORM(COCOA)
171
172 void DownloadManager::downloadFinished(Download* download)
173 {
174     ASSERT(m_downloads.contains(download->downloadID()));
175     m_downloads.remove(download->downloadID());
176 }
177
178 void DownloadManager::didCreateDownload()
179 {
180     m_client.didCreateDownload();
181 }
182
183 void DownloadManager::didDestroyDownload()
184 {
185     m_client.didDestroyDownload();
186 }
187
188 IPC::Connection* DownloadManager::downloadProxyConnection()
189 {
190     return m_client.downloadProxyConnection();
191 }
192
193 AuthenticationManager& DownloadManager::downloadsAuthenticationManager()
194 {
195     return m_client.downloadsAuthenticationManager();
196 }
197
198 } // namespace WebKit