1 | /* |
2 | * Copyright (C) 2006 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 | * |
8 | * 1. Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. |
10 | * 2. Redistributions in binary form must reproduce the above copyright |
11 | * notice, this list of conditions and the following disclaimer in the |
12 | * documentation and/or other materials provided with the distribution. |
13 | * 3. Neither the name of Apple Inc. ("Apple") nor the names of |
14 | * its contributors may be used to endorse or promote products derived |
15 | * from this software without specific prior written permission. |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
18 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
20 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
28 | |
29 | #include "config.h" |
30 | #include "NetscapePlugInStreamLoader.h" |
31 | |
32 | #include "DocumentLoader.h" |
33 | #include "FrameLoader.h" |
34 | #include "FrameLoaderClient.h" |
35 | #include <wtf/CompletionHandler.h> |
36 | #include <wtf/Ref.h> |
37 | |
38 | #if ENABLE(CONTENT_EXTENSIONS) |
39 | #include "ResourceLoadInfo.h" |
40 | #endif |
41 | |
42 | namespace WebCore { |
43 | |
44 | // FIXME: Skip Content Security Policy check when associated plugin element is in a user agent shadow tree. |
45 | // See <https://bugs.webkit.org/show_bug.cgi?id=146663>. |
46 | NetscapePlugInStreamLoader::NetscapePlugInStreamLoader(Frame& frame, NetscapePlugInStreamLoaderClient& client) |
47 | : ResourceLoader(frame, ResourceLoaderOptions( |
48 | SendCallbackPolicy::SendCallbacks, |
49 | ContentSniffingPolicy::SniffContent, |
50 | DataBufferingPolicy::DoNotBufferData, |
51 | StoredCredentialsPolicy::Use, |
52 | ClientCredentialPolicy::MayAskClientForCredentials, |
53 | FetchOptions::Credentials::Include, |
54 | SecurityCheckPolicy::SkipSecurityCheck, |
55 | FetchOptions::Mode::NoCors, |
56 | CertificateInfoPolicy::DoNotIncludeCertificateInfo, |
57 | ContentSecurityPolicyImposition::DoPolicyCheck, |
58 | DefersLoadingPolicy::AllowDefersLoading, |
59 | CachingPolicy::AllowCaching)) |
60 | , m_client(&client) |
61 | { |
62 | #if ENABLE(CONTENT_EXTENSIONS) |
63 | m_resourceType = ContentExtensions::ResourceType::PlugInStream; |
64 | #endif |
65 | } |
66 | |
67 | NetscapePlugInStreamLoader::~NetscapePlugInStreamLoader() = default; |
68 | |
69 | void NetscapePlugInStreamLoader::create(Frame& frame, NetscapePlugInStreamLoaderClient& client, ResourceRequest&& request, CompletionHandler<void(RefPtr<NetscapePlugInStreamLoader>&&)>&& completionHandler) |
70 | { |
71 | auto loader(adoptRef(*new NetscapePlugInStreamLoader(frame, client))); |
72 | loader->init(WTFMove(request), [loader = loader.copyRef(), completionHandler = WTFMove(completionHandler)] (bool initialized) mutable { |
73 | if (!initialized) |
74 | return completionHandler(nullptr); |
75 | completionHandler(WTFMove(loader)); |
76 | }); |
77 | } |
78 | |
79 | bool NetscapePlugInStreamLoader::isDone() const |
80 | { |
81 | return !m_client; |
82 | } |
83 | |
84 | void NetscapePlugInStreamLoader::releaseResources() |
85 | { |
86 | m_client = nullptr; |
87 | ResourceLoader::releaseResources(); |
88 | } |
89 | |
90 | void NetscapePlugInStreamLoader::init(ResourceRequest&& request, CompletionHandler<void(bool)>&& completionHandler) |
91 | { |
92 | ResourceLoader::init(WTFMove(request), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (bool success) mutable { |
93 | if (!success) |
94 | return completionHandler(false); |
95 | ASSERT(!reachedTerminalState()); |
96 | m_documentLoader->addPlugInStreamLoader(*this); |
97 | m_isInitialized = true; |
98 | completionHandler(true); |
99 | }); |
100 | } |
101 | |
102 | void NetscapePlugInStreamLoader::willSendRequest(ResourceRequest&& request, const ResourceResponse& redirectResponse, CompletionHandler<void(ResourceRequest&&)>&& callback) |
103 | { |
104 | m_client->willSendRequest(this, WTFMove(request), redirectResponse, [protectedThis = makeRef(*this), redirectResponse, callback = WTFMove(callback)] (ResourceRequest&& request) mutable { |
105 | if (!request.isNull()) |
106 | protectedThis->willSendRequestInternal(WTFMove(request), redirectResponse, WTFMove(callback)); |
107 | else |
108 | callback({ }); |
109 | }); |
110 | } |
111 | |
112 | void NetscapePlugInStreamLoader::didReceiveResponse(const ResourceResponse& response, CompletionHandler<void()>&& policyCompletionHandler) |
113 | { |
114 | Ref<NetscapePlugInStreamLoader> protectedThis(*this); |
115 | CompletionHandlerCallingScope completionHandlerCaller(WTFMove(policyCompletionHandler)); |
116 | |
117 | m_client->didReceiveResponse(this, response); |
118 | |
119 | // Don't continue if the stream is cancelled |
120 | if (!m_client) |
121 | return; |
122 | |
123 | ResourceLoader::didReceiveResponse(response, [this, protectedThis = WTFMove(protectedThis), response, completionHandlerCaller = WTFMove(completionHandlerCaller)]() mutable { |
124 | // Don't continue if the stream is cancelled |
125 | if (!m_client) |
126 | return; |
127 | |
128 | if (!response.isHTTP()) |
129 | return; |
130 | |
131 | if (m_client->wantsAllStreams()) |
132 | return; |
133 | |
134 | // Status code can be null when serving from a Web archive. |
135 | if (response.httpStatusCode() && (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400)) |
136 | cancel(frameLoader()->client().fileDoesNotExistError(response)); |
137 | }); |
138 | } |
139 | |
140 | void NetscapePlugInStreamLoader::didReceiveData(const char* data, unsigned length, long long encodedDataLength, DataPayloadType dataPayloadType) |
141 | { |
142 | didReceiveDataOrBuffer(data, length, nullptr, encodedDataLength, dataPayloadType); |
143 | } |
144 | |
145 | void NetscapePlugInStreamLoader::didReceiveBuffer(Ref<SharedBuffer>&& buffer, long long encodedDataLength, DataPayloadType dataPayloadType) |
146 | { |
147 | didReceiveDataOrBuffer(nullptr, 0, WTFMove(buffer), encodedDataLength, dataPayloadType); |
148 | } |
149 | |
150 | void NetscapePlugInStreamLoader::didReceiveDataOrBuffer(const char* data, int length, RefPtr<SharedBuffer>&& buffer, long long encodedDataLength, DataPayloadType dataPayloadType) |
151 | { |
152 | Ref<NetscapePlugInStreamLoader> protectedThis(*this); |
153 | |
154 | m_client->didReceiveData(this, buffer ? buffer->data() : data, buffer ? buffer->size() : length); |
155 | |
156 | ResourceLoader::didReceiveDataOrBuffer(data, length, WTFMove(buffer), encodedDataLength, dataPayloadType); |
157 | } |
158 | |
159 | void NetscapePlugInStreamLoader::didFinishLoading(const NetworkLoadMetrics& networkLoadMetrics) |
160 | { |
161 | Ref<NetscapePlugInStreamLoader> protectedThis(*this); |
162 | |
163 | notifyDone(); |
164 | |
165 | m_client->didFinishLoading(this); |
166 | ResourceLoader::didFinishLoading(networkLoadMetrics); |
167 | } |
168 | |
169 | void NetscapePlugInStreamLoader::didFail(const ResourceError& error) |
170 | { |
171 | Ref<NetscapePlugInStreamLoader> protectedThis(*this); |
172 | |
173 | notifyDone(); |
174 | |
175 | m_client->didFail(this, error); |
176 | ResourceLoader::didFail(error); |
177 | } |
178 | |
179 | void NetscapePlugInStreamLoader::willCancel(const ResourceError& error) |
180 | { |
181 | m_client->didFail(this, error); |
182 | } |
183 | |
184 | void NetscapePlugInStreamLoader::didCancel(const ResourceError&) |
185 | { |
186 | notifyDone(); |
187 | } |
188 | |
189 | void NetscapePlugInStreamLoader::notifyDone() |
190 | { |
191 | if (!m_isInitialized) |
192 | return; |
193 | |
194 | m_documentLoader->removePlugInStreamLoader(*this); |
195 | } |
196 | |
197 | |
198 | } |
199 | |