[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[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 "NetworkConnectionToWebProcess.h"
31 #include "NetworkLoad.h"
32 #include "NetworkSession.h"
33 #include "PendingDownload.h"
34 #include <WebCore/NotImplemented.h>
35 #include <pal/SessionID.h>
36 #include <wtf/StdLibExtras.h>
37
38 namespace WebKit {
39 using namespace WebCore;
40
41 DownloadManager::DownloadManager(Client& client)
42     : m_client(client)
43 {
44 }
45
46 void DownloadManager::startDownload(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedName)
47 {
48     auto* networkSession = client().networkSession(sessionID);
49     if (!networkSession)
50         return;
51
52     NetworkLoadParameters parameters { sessionID };
53     parameters.request = request;
54     parameters.clientCredentialPolicy = ClientCredentialPolicy::MayAskClientForCredentials;
55     if (request.url().protocolIsBlob())
56         parameters.blobFileReferences = client().networkSession(sessionID)->blobRegistry().filesInBlob(request.url());
57     parameters.storedCredentialsPolicy = sessionID.isEphemeral() ? StoredCredentialsPolicy::DoNotUse : StoredCredentialsPolicy::Use;
58
59     m_pendingDownloads.add(downloadID, makeUnique<PendingDownload>(m_client.parentProcessConnectionForDownloads(), WTFMove(parameters), downloadID, *networkSession, &client().networkSession(sessionID)->blobRegistry(), suggestedName));
60 }
61
62 void DownloadManager::dataTaskBecameDownloadTask(DownloadID downloadID, std::unique_ptr<Download>&& download)
63 {
64     ASSERT(m_pendingDownloads.contains(downloadID));
65     if (auto pendingDownload = m_pendingDownloads.take(downloadID)) {
66 #if PLATFORM(COCOA)
67         pendingDownload->didBecomeDownload(download);
68 #endif
69     }
70     ASSERT(!m_downloads.contains(downloadID));
71     m_downloadsAfterDestinationDecided.remove(downloadID);
72     m_downloads.add(downloadID, WTFMove(download));
73 }
74
75 void DownloadManager::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
76 {
77     auto* pendingDownload = m_pendingDownloads.get(downloadID);
78     ASSERT(pendingDownload);
79     if (pendingDownload)
80         pendingDownload->continueWillSendRequest(WTFMove(request));
81 }
82
83 void DownloadManager::willDecidePendingDownloadDestination(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler)
84 {
85     auto downloadID = networkDataTask.pendingDownloadID();
86     auto addResult = m_downloadsWaitingForDestination.set(downloadID, std::make_pair<RefPtr<NetworkDataTask>, ResponseCompletionHandler>(&networkDataTask, WTFMove(completionHandler)));
87     ASSERT_UNUSED(addResult, addResult.isNewEntry);
88 }
89
90 void DownloadManager::convertNetworkLoadToDownload(DownloadID downloadID, std::unique_ptr<NetworkLoad>&& networkLoad, ResponseCompletionHandler&& completionHandler, Vector<RefPtr<WebCore::BlobDataFileReference>>&& blobFileReferences, const ResourceRequest& request, const ResourceResponse& response)
91 {
92     ASSERT(!m_pendingDownloads.contains(downloadID));
93     m_pendingDownloads.add(downloadID, makeUnique<PendingDownload>(m_client.parentProcessConnectionForDownloads(), WTFMove(networkLoad), WTFMove(completionHandler), downloadID, request, response));
94 }
95
96 void DownloadManager::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
97 {
98     if (m_downloadsWaitingForDestination.contains(downloadID)) {
99         auto pair = m_downloadsWaitingForDestination.take(downloadID);
100         auto networkDataTask = WTFMove(pair.first);
101         auto completionHandler = WTFMove(pair.second);
102         ASSERT(networkDataTask);
103         ASSERT(completionHandler);
104         ASSERT(m_pendingDownloads.contains(downloadID));
105
106         networkDataTask->setPendingDownloadLocation(destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
107         completionHandler(PolicyAction::Download);
108         if (networkDataTask->state() == NetworkDataTask::State::Canceling || networkDataTask->state() == NetworkDataTask::State::Completed)
109             return;
110
111         if (m_downloads.contains(downloadID)) {
112             // The completion handler already called dataTaskBecameDownloadTask().
113             return;
114         }
115
116         ASSERT(!m_downloadsAfterDestinationDecided.contains(downloadID));
117         m_downloadsAfterDestinationDecided.set(downloadID, networkDataTask);
118     }
119 }
120
121 void DownloadManager::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, SandboxExtension::Handle&& sandboxExtensionHandle)
122 {
123 #if !PLATFORM(COCOA)
124     notImplemented();
125 #else
126     auto download = makeUnique<Download>(*this, downloadID, nullptr, sessionID);
127
128     download->resume(resumeData, path, WTFMove(sandboxExtensionHandle));
129     ASSERT(!m_downloads.contains(downloadID));
130     m_downloads.add(downloadID, WTFMove(download));
131 #endif
132 }
133
134 void DownloadManager::cancelDownload(DownloadID downloadID)
135 {
136     if (Download* download = m_downloads.get(downloadID)) {
137         ASSERT(!m_downloadsWaitingForDestination.contains(downloadID));
138         ASSERT(!m_pendingDownloads.contains(downloadID));
139         download->cancel();
140         return;
141     }
142     auto pendingDownload = m_pendingDownloads.take(downloadID);
143     if (m_downloadsWaitingForDestination.contains(downloadID)) {
144         auto pair = m_downloadsWaitingForDestination.take(downloadID);
145         auto networkDataTask = WTFMove(pair.first);
146         auto completionHandler = WTFMove(pair.second);
147         ASSERT(networkDataTask);
148         ASSERT(completionHandler);
149
150         networkDataTask->cancel();
151         completionHandler(PolicyAction::Ignore);
152         m_client.pendingDownloadCanceled(downloadID);
153         return;
154     }
155
156     if (pendingDownload)
157         pendingDownload->cancel();
158 }
159
160 #if PLATFORM(COCOA)
161 void DownloadManager::publishDownloadProgress(DownloadID downloadID, const URL& url, SandboxExtension::Handle&& sandboxExtensionHandle)
162 {
163     if (auto* download = m_downloads.get(downloadID))
164         download->publishProgress(url, WTFMove(sandboxExtensionHandle));
165     else if (auto* pendingDownload = m_pendingDownloads.get(downloadID))
166         pendingDownload->publishProgress(url, WTFMove(sandboxExtensionHandle));
167 }
168 #endif // PLATFORM(COCOA)
169
170 void DownloadManager::downloadFinished(Download& download)
171 {
172     ASSERT(m_downloads.contains(download.downloadID()));
173     m_downloads.remove(download.downloadID());
174 }
175
176 void DownloadManager::didCreateDownload()
177 {
178     m_client.didCreateDownload();
179 }
180
181 void DownloadManager::didDestroyDownload()
182 {
183     m_client.didDestroyDownload();
184 }
185
186 IPC::Connection* DownloadManager::downloadProxyConnection()
187 {
188     return m_client.downloadProxyConnection();
189 }
190
191 AuthenticationManager& DownloadManager::downloadsAuthenticationManager()
192 {
193     return m_client.downloadsAuthenticationManager();
194 }
195
196 void DownloadManager::applicationDidEnterBackground()
197 {
198     for (auto& download : m_downloads.values())
199         download->applicationDidEnterBackground();
200 }
201
202 void DownloadManager::applicationWillEnterForeground()
203 {
204     for (auto& download : m_downloads.values())
205         download->applicationWillEnterForeground();
206 }
207
208 } // namespace WebKit