1 | /* |
2 | * Copyright (C) 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 | #include "config.h" |
27 | #include "WebURLSchemeTaskProxy.h" |
28 | |
29 | #include "URLSchemeTaskParameters.h" |
30 | #include "WebCoreArgumentCoders.h" |
31 | #include "WebPage.h" |
32 | #include "WebPageProxyMessages.h" |
33 | #include "WebURLSchemeHandlerProxy.h" |
34 | #include <WebCore/NetworkLoadMetrics.h> |
35 | #include <WebCore/ResourceError.h> |
36 | #include <WebCore/ResourceLoader.h> |
37 | #include <wtf/CompletionHandler.h> |
38 | |
39 | namespace WebKit { |
40 | using namespace WebCore; |
41 | |
42 | WebURLSchemeTaskProxy::WebURLSchemeTaskProxy(WebURLSchemeHandlerProxy& handler, ResourceLoader& loader) |
43 | : m_urlSchemeHandler(handler) |
44 | , m_coreLoader(&loader) |
45 | , m_request(loader.request()) |
46 | , m_identifier(loader.identifier()) |
47 | { |
48 | } |
49 | |
50 | void WebURLSchemeTaskProxy::startLoading() |
51 | { |
52 | ASSERT(m_coreLoader); |
53 | m_urlSchemeHandler.page().send(Messages::WebPageProxy::StartURLSchemeTask({m_urlSchemeHandler.identifier(), m_coreLoader->identifier(), m_request})); |
54 | } |
55 | |
56 | void WebURLSchemeTaskProxy::stopLoading() |
57 | { |
58 | ASSERT(m_coreLoader); |
59 | m_urlSchemeHandler.page().send(Messages::WebPageProxy::StopURLSchemeTask(m_urlSchemeHandler.identifier(), m_coreLoader->identifier())); |
60 | m_coreLoader = nullptr; |
61 | |
62 | // This line will result in this being deleted. |
63 | m_urlSchemeHandler.taskDidStopLoading(*this); |
64 | } |
65 | |
66 | void WebURLSchemeTaskProxy::didPerformRedirection(WebCore::ResourceResponse&& redirectResponse, WebCore::ResourceRequest&& request) |
67 | { |
68 | if (!hasLoader()) |
69 | return; |
70 | |
71 | auto completionHandler = [this, protectedThis = makeRef(*this), originalRequest = request] (ResourceRequest&& request) { |
72 | m_waitingForCompletionHandler = false; |
73 | // We do not inform the UIProcess of WebKit's new request with the given suggested request. |
74 | // We do want to know if WebKit would have generated a request that differs from the suggested request, though. |
75 | if (request.url() != originalRequest.url()) |
76 | WTFLogAlways("Redirected scheme task would have been sent to a different URL." ); |
77 | |
78 | processNextPendingTask(); |
79 | }; |
80 | |
81 | if (m_waitingForCompletionHandler) { |
82 | WTFLogAlways("Received redirect during previous redirect processing, queuing it." ); |
83 | queueTask([this, protectedThis = makeRef(*this), redirectResponse = WTFMove(redirectResponse), request = WTFMove(request)]() mutable { |
84 | didPerformRedirection(WTFMove(redirectResponse), WTFMove(request)); |
85 | }); |
86 | return; |
87 | } |
88 | m_waitingForCompletionHandler = true; |
89 | |
90 | m_coreLoader->willSendRequest(WTFMove(request), redirectResponse, WTFMove(completionHandler)); |
91 | } |
92 | |
93 | void WebURLSchemeTaskProxy::didReceiveResponse(const ResourceResponse& response) |
94 | { |
95 | if (m_waitingForCompletionHandler) { |
96 | WTFLogAlways("Received response during redirect processing, queuing it." ); |
97 | queueTask([this, protectedThis = makeRef(*this), response] { |
98 | didReceiveResponse(response); |
99 | }); |
100 | return; |
101 | } |
102 | |
103 | if (!hasLoader()) |
104 | return; |
105 | |
106 | m_waitingForCompletionHandler = true; |
107 | m_coreLoader->didReceiveResponse(response, [this, protectedThis = makeRef(*this)] { |
108 | m_waitingForCompletionHandler = false; |
109 | processNextPendingTask(); |
110 | }); |
111 | } |
112 | |
113 | void WebURLSchemeTaskProxy::didReceiveData(size_t size, const uint8_t* data) |
114 | { |
115 | if (!hasLoader()) |
116 | return; |
117 | |
118 | if (m_waitingForCompletionHandler) { |
119 | WTFLogAlways("Received data during response processing, queuing it." ); |
120 | Vector<uint8_t> dataVector; |
121 | dataVector.append(data, size); |
122 | queueTask([this, protectedThis = makeRef(*this), dataVector = WTFMove(dataVector)] { |
123 | didReceiveData(dataVector.size(), dataVector.data()); |
124 | }); |
125 | return; |
126 | } |
127 | |
128 | m_coreLoader->didReceiveData(reinterpret_cast<const char*>(data), size, 0, DataPayloadType::DataPayloadBytes); |
129 | processNextPendingTask(); |
130 | } |
131 | |
132 | void WebURLSchemeTaskProxy::didComplete(const ResourceError& error) |
133 | { |
134 | if (!hasLoader()) |
135 | return; |
136 | |
137 | if (m_waitingForCompletionHandler) { |
138 | queueTask([this, protectedThis = makeRef(*this), error] { |
139 | didComplete(error); |
140 | }); |
141 | return; |
142 | } |
143 | |
144 | if (error.isNull()) |
145 | m_coreLoader->didFinishLoading(NetworkLoadMetrics()); |
146 | else |
147 | m_coreLoader->didFail(error); |
148 | |
149 | m_coreLoader = nullptr; |
150 | } |
151 | |
152 | bool WebURLSchemeTaskProxy::hasLoader() |
153 | { |
154 | if (m_coreLoader && m_coreLoader->reachedTerminalState()) |
155 | m_coreLoader = nullptr; |
156 | |
157 | return m_coreLoader; |
158 | } |
159 | |
160 | void WebURLSchemeTaskProxy::processNextPendingTask() |
161 | { |
162 | if (!m_queuedTasks.isEmpty()) |
163 | m_queuedTasks.takeFirst()(); |
164 | } |
165 | |
166 | } // namespace WebKit |
167 | |