1 | /* |
2 | * Copyright (C) 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 "NetworkDataTask.h" |
28 | |
29 | #include "NetworkDataTaskBlob.h" |
30 | #include "NetworkLoadParameters.h" |
31 | #include "NetworkSession.h" |
32 | #include <WebCore/ResourceError.h> |
33 | #include <WebCore/ResourceResponse.h> |
34 | #include <wtf/RunLoop.h> |
35 | |
36 | #if PLATFORM(COCOA) |
37 | #include "NetworkDataTaskCocoa.h" |
38 | #endif |
39 | #if USE(SOUP) |
40 | #include "NetworkDataTaskSoup.h" |
41 | #endif |
42 | #if USE(CURL) |
43 | #include "NetworkDataTaskCurl.h" |
44 | #endif |
45 | |
46 | namespace WebKit { |
47 | using namespace WebCore; |
48 | |
49 | Ref<NetworkDataTask> NetworkDataTask::create(NetworkSession& session, NetworkDataTaskClient& client, const NetworkLoadParameters& parameters) |
50 | { |
51 | ASSERT(!parameters.request.url().protocolIsBlob()); |
52 | #if PLATFORM(COCOA) |
53 | return NetworkDataTaskCocoa::create(session, client, parameters.request, parameters.webFrameID, parameters.webPageID, parameters.storedCredentialsPolicy, parameters.contentSniffingPolicy, parameters.contentEncodingSniffingPolicy, parameters.shouldClearReferrerOnHTTPSToHTTPRedirect, parameters.shouldPreconnectOnly, parameters.isMainFrameNavigation, parameters.isMainResourceNavigationForAnyFrame, parameters.networkActivityTracker); |
54 | #endif |
55 | #if USE(SOUP) |
56 | return NetworkDataTaskSoup::create(session, client, parameters.request, parameters.storedCredentialsPolicy, parameters.contentSniffingPolicy, parameters.contentEncodingSniffingPolicy, parameters.shouldClearReferrerOnHTTPSToHTTPRedirect, parameters.isMainFrameNavigation); |
57 | #endif |
58 | #if USE(CURL) |
59 | return NetworkDataTaskCurl::create(session, client, parameters.request, parameters.storedCredentialsPolicy, parameters.contentSniffingPolicy, parameters.contentEncodingSniffingPolicy, parameters.shouldClearReferrerOnHTTPSToHTTPRedirect, parameters.isMainFrameNavigation); |
60 | #endif |
61 | } |
62 | |
63 | NetworkDataTask::NetworkDataTask(NetworkSession& session, NetworkDataTaskClient& client, const ResourceRequest& requestWithCredentials, StoredCredentialsPolicy storedCredentialsPolicy, bool shouldClearReferrerOnHTTPSToHTTPRedirect, bool dataTaskIsForMainFrameNavigation) |
64 | : m_failureTimer(*this, &NetworkDataTask::failureTimerFired) |
65 | , m_session(session) |
66 | , m_client(&client) |
67 | , m_partition(requestWithCredentials.cachePartition()) |
68 | , m_storedCredentialsPolicy(storedCredentialsPolicy) |
69 | , m_lastHTTPMethod(requestWithCredentials.httpMethod()) |
70 | , m_firstRequest(requestWithCredentials) |
71 | , m_shouldClearReferrerOnHTTPSToHTTPRedirect(shouldClearReferrerOnHTTPSToHTTPRedirect) |
72 | , m_dataTaskIsForMainFrameNavigation(dataTaskIsForMainFrameNavigation) |
73 | { |
74 | ASSERT(RunLoop::isMain()); |
75 | |
76 | if (!requestWithCredentials.url().isValid()) { |
77 | scheduleFailure(InvalidURLFailure); |
78 | return; |
79 | } |
80 | |
81 | if (!portAllowed(requestWithCredentials.url())) { |
82 | scheduleFailure(BlockedFailure); |
83 | return; |
84 | } |
85 | } |
86 | |
87 | NetworkDataTask::~NetworkDataTask() |
88 | { |
89 | ASSERT(RunLoop::isMain()); |
90 | ASSERT(!m_client); |
91 | } |
92 | |
93 | void NetworkDataTask::scheduleFailure(FailureType type) |
94 | { |
95 | ASSERT(type != NoFailure); |
96 | m_scheduledFailureType = type; |
97 | m_failureTimer.startOneShot(0_s); |
98 | } |
99 | |
100 | void NetworkDataTask::didReceiveResponse(ResourceResponse&& response, ResponseCompletionHandler&& completionHandler) |
101 | { |
102 | ASSERT(m_client); |
103 | if (response.isHTTP09()) { |
104 | auto url = response.url(); |
105 | Optional<uint16_t> port = url.port(); |
106 | if (port && !WTF::isDefaultPortForProtocol(port.value(), url.protocol())) { |
107 | completionHandler(PolicyAction::Ignore); |
108 | cancel(); |
109 | m_client->didCompleteWithError({ String(), 0, url, "Cancelled load from '" + url.stringCenterEllipsizedToLength() + "' because it is using HTTP/0.9." }); |
110 | return; |
111 | } |
112 | } |
113 | m_client->didReceiveResponse(WTFMove(response), WTFMove(completionHandler)); |
114 | } |
115 | |
116 | bool NetworkDataTask::() const |
117 | { |
118 | return m_client ? m_client->shouldCaptureExtraNetworkLoadMetrics() : false; |
119 | } |
120 | |
121 | void NetworkDataTask::failureTimerFired() |
122 | { |
123 | RefPtr<NetworkDataTask> protectedThis(this); |
124 | |
125 | switch (m_scheduledFailureType) { |
126 | case BlockedFailure: |
127 | m_scheduledFailureType = NoFailure; |
128 | if (m_client) |
129 | m_client->wasBlocked(); |
130 | return; |
131 | case InvalidURLFailure: |
132 | m_scheduledFailureType = NoFailure; |
133 | if (m_client) |
134 | m_client->cannotShowURL(); |
135 | return; |
136 | case RestrictedURLFailure: |
137 | m_scheduledFailureType = NoFailure; |
138 | if (m_client) |
139 | m_client->wasBlockedByRestrictions(); |
140 | return; |
141 | case NoFailure: |
142 | ASSERT_NOT_REACHED(); |
143 | break; |
144 | } |
145 | ASSERT_NOT_REACHED(); |
146 | } |
147 | |
148 | String NetworkDataTask::description() const |
149 | { |
150 | return emptyString(); |
151 | } |
152 | |
153 | } // namespace WebKit |
154 | |