d30e4792ea2e9f4a3698f97e187e7796fd244a82
[WebKit-https.git] / Source / WebKit / NetworkProcess / Downloads / cocoa / DownloadCocoa.mm
1 /*
2  * Copyright (C) 2015 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 #import "config.h"
27 #import "Download.h"
28
29 #import "DataReference.h"
30 #import "NetworkSessionCocoa.h"
31 #import "SessionTracker.h"
32 #import "WKDownloadProgress.h"
33 #import <pal/spi/cf/CFNetworkSPI.h>
34 #import <pal/spi/cocoa/NSProgressSPI.h>
35
36 namespace WebKit {
37
38 void Download::resume(const IPC::DataReference& resumeData, const String& path, SandboxExtension::Handle&& sandboxExtensionHandle)
39 {
40     m_sandboxExtension = SandboxExtension::create(WTFMove(sandboxExtensionHandle));
41     if (m_sandboxExtension)
42         m_sandboxExtension->consume();
43
44     auto* networkSession = SessionTracker::networkSession(m_sessionID);
45     if (!networkSession) {
46         WTFLogAlways("Could not find network session with given session ID");
47         return;
48     }
49     auto& cocoaSession = static_cast<NetworkSessionCocoa&>(*networkSession);
50     auto nsData = adoptNS([[NSData alloc] initWithBytes:resumeData.data() length:resumeData.size()]);
51
52     // FIXME: This is a temporary workaround for <rdar://problem/34745171>.
53 #if (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400)
54     static NSSet<Class> *plistClasses = nil;
55     static dispatch_once_t onceToken;
56
57     dispatch_once(&onceToken, ^{
58         plistClasses = [[NSSet setWithObjects:[NSDictionary class], [NSArray class], [NSString class], [NSNumber class], [NSData class], [NSURL class], [NSURLRequest class], nil] retain];
59     });
60     auto unarchiver = adoptNS([[NSKeyedUnarchiver alloc] initForReadingFromData:nsData.get() error:nil]);
61     [unarchiver setDecodingFailurePolicy:NSDecodingFailurePolicyRaiseException];
62     auto dictionary = retainPtr([unarchiver decodeObjectOfClasses:plistClasses forKey:@"NSKeyedArchiveRootObjectKey"]);
63     [unarchiver finishDecoding];
64     [dictionary setObject:static_cast<NSString*>(path) forKey:@"NSURLSessionResumeInfoLocalPath"];
65     auto encoder = adoptNS([[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]);
66     [encoder encodeObject:dictionary.get() forKey:@"NSKeyedArchiveRootObjectKey"];
67     NSData *updatedData = [encoder encodedData];
68 #else
69     NSMutableDictionary *dictionary = [NSPropertyListSerialization propertyListWithData:nsData.get() options:NSPropertyListMutableContainersAndLeaves format:0 error:nullptr];
70     [dictionary setObject:static_cast<NSString*>(path) forKey:@"NSURLSessionResumeInfoLocalPath"];
71     NSData *updatedData = [NSPropertyListSerialization dataWithPropertyList:dictionary format:NSPropertyListXMLFormat_v1_0 options:0 error:nullptr];
72 #endif
73
74     m_downloadTask = cocoaSession.downloadTaskWithResumeData(updatedData);
75     cocoaSession.addDownloadID(m_downloadTask.get().taskIdentifier, m_downloadID);
76     m_downloadTask.get()._pathToDownloadTaskFile = path;
77
78     [m_downloadTask resume];
79 }
80     
81 void Download::platformCancelNetworkLoad()
82 {
83     ASSERT(m_downloadTask);
84     [m_downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
85         if (resumeData && resumeData.bytes && resumeData.length)
86             didCancel(IPC::DataReference(reinterpret_cast<const uint8_t*>(resumeData.bytes), resumeData.length));
87         else
88             didCancel({ });
89     }];
90 }
91
92 void Download::platformDestroyDownload()
93 {
94     if (m_progress)
95 #if USE(NSPROGRESS_PUBLISHING_SPI)
96         [m_progress _unpublish];
97 #else
98         [m_progress unpublish];
99 #endif
100 }
101
102 void Download::publishProgress(const URL& url, SandboxExtension::Handle&& sandboxExtensionHandle)
103 {
104 #if WK_API_ENABLED
105     ASSERT(!m_progress);
106     ASSERT(url.isValid());
107
108     auto sandboxExtension = SandboxExtension::create(WTFMove(sandboxExtensionHandle));
109
110     ASSERT(sandboxExtension);
111
112     m_progress = adoptNS([[WKDownloadProgress alloc] initWithDownloadTask:m_downloadTask.get() download:this URL:(NSURL *)url sandboxExtension:sandboxExtension]);
113 #if USE(NSPROGRESS_PUBLISHING_SPI)
114     [m_progress _publish];
115 #else
116     [m_progress publish];
117 #endif
118 #else
119     UNUSED_PARAM(url);
120     UNUSED_PARAM(sandboxExtensionHandle);
121 #endif // not WK_API_ENABLED
122 }
123
124 }