49536c62332134d6a3d1b08dabed8431f26bbb59
[WebKit-https.git] / Source / WebKit / UIProcess / Cocoa / LegacyCustomProtocolManagerClient.mm
1 /*
2  * Copyright (C) 2012-2017 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 "LegacyCustomProtocolManagerClient.h"
28
29 #import "DataReference.h"
30 #import "LegacyCustomProtocolManagerProxy.h"
31 #import <WebCore/ResourceError.h>
32 #import <WebCore/ResourceRequest.h>
33 #import <WebCore/ResourceResponse.h>
34
35 using namespace WebCore;
36 using namespace WebKit;
37
38 @interface WKCustomProtocolLoader : NSObject <NSURLConnectionDelegate> {
39 @private
40     LegacyCustomProtocolManagerProxy* _customProtocolManagerProxy;
41     uint64_t _customProtocolID;
42     NSURLCacheStoragePolicy _storagePolicy;
43     NSURLConnection *_urlConnection;
44 }
45 - (id)initWithLegacyCustomProtocolManagerProxy:(LegacyCustomProtocolManagerProxy*)customProtocolManagerProxy customProtocolID:(uint64_t)customProtocolID request:(NSURLRequest *)request;
46 - (void)customProtocolManagerProxyDestroyed;
47 @end
48
49 @implementation WKCustomProtocolLoader
50
51 - (id)initWithLegacyCustomProtocolManagerProxy:(LegacyCustomProtocolManagerProxy*)customProtocolManagerProxy customProtocolID:(uint64_t)customProtocolID request:(NSURLRequest *)request
52 {
53     self = [super init];
54     if (!self)
55         return nil;
56
57     ASSERT(customProtocolManagerProxy);
58     ASSERT(request);
59     _customProtocolManagerProxy = customProtocolManagerProxy;
60     _customProtocolID = customProtocolID;
61     _storagePolicy = NSURLCacheStorageNotAllowed;
62 #pragma clang diagnostic push
63 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
64     _urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
65     [_urlConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
66     [_urlConnection start];
67 #pragma clang diagnostic pop
68
69     return self;
70 }
71
72 - (void)dealloc
73 {
74     [_urlConnection cancel];
75     [_urlConnection release];
76     [super dealloc];
77 }
78
79 - (void)customProtocolManagerProxyDestroyed
80 {
81     ASSERT(_customProtocolManagerProxy);
82     _customProtocolManagerProxy = nullptr;
83     [_urlConnection cancel];
84 }
85
86 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
87 {
88     ResourceError coreError(error);
89     _customProtocolManagerProxy->didFailWithError(_customProtocolID, coreError);
90     _customProtocolManagerProxy->stopLoading(_customProtocolID);
91 }
92
93 - (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
94 {
95     ASSERT(_storagePolicy == NSURLCacheStorageNotAllowed);
96     _storagePolicy = [cachedResponse storagePolicy];
97     return cachedResponse;
98 }
99
100 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
101 {
102     ResourceResponse coreResponse(response);
103     _customProtocolManagerProxy->didReceiveResponse(_customProtocolID, coreResponse, _storagePolicy);
104 }
105
106 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
107 {
108     IPC::DataReference coreData(static_cast<const uint8_t*>([data bytes]), [data length]);
109     _customProtocolManagerProxy->didLoadData(_customProtocolID, coreData);
110 }
111
112 - (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
113 {
114     if (redirectResponse) {
115         _customProtocolManagerProxy->wasRedirectedToRequest(_customProtocolID, request, redirectResponse);
116         return nil;
117     }
118     return request;
119 }
120
121 - (void)connectionDidFinishLoading:(NSURLConnection *)connection
122 {
123     _customProtocolManagerProxy->didFinishLoading(_customProtocolID);
124     _customProtocolManagerProxy->stopLoading(_customProtocolID);
125 }
126
127 @end
128
129 namespace WebKit {
130
131 void LegacyCustomProtocolManagerClient::startLoading(LegacyCustomProtocolManagerProxy& manager, uint64_t customProtocolID, const ResourceRequest& coreRequest)
132 {
133     NSURLRequest *request = coreRequest.nsURLRequest(DoNotUpdateHTTPBody);
134     if (!request)
135         return;
136
137     WKCustomProtocolLoader *loader = [[WKCustomProtocolLoader alloc] initWithLegacyCustomProtocolManagerProxy:&manager customProtocolID:customProtocolID request:request];
138     ASSERT(loader);
139     ASSERT(!m_loaderMap.contains(customProtocolID));
140     m_loaderMap.add(customProtocolID, loader);
141     [loader release];
142 }
143
144 void LegacyCustomProtocolManagerClient::stopLoading(LegacyCustomProtocolManagerProxy&, uint64_t customProtocolID)
145 {
146     m_loaderMap.remove(customProtocolID);
147 }
148
149 void LegacyCustomProtocolManagerClient::invalidate(LegacyCustomProtocolManagerProxy&)
150 {
151     while (!m_loaderMap.isEmpty()) {
152         auto loader = m_loaderMap.take(m_loaderMap.begin()->key);
153         ASSERT(loader);
154         [loader customProtocolManagerProxyDestroyed];
155     }
156 }
157
158 } // namespace WebKit