OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "modules/fetch/FetchManager.h" | 6 #include "modules/fetch/FetchManager.h" |
7 | 7 |
8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
9 #include "bindings/core/v8/ScriptPromiseResolver.h" | 9 #include "bindings/core/v8/ScriptPromiseResolver.h" |
10 #include "bindings/core/v8/ScriptState.h" | 10 #include "bindings/core/v8/ScriptState.h" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 #include "modules/fetch/ResponseInit.h" | 30 #include "modules/fetch/ResponseInit.h" |
31 #include "platform/network/ResourceError.h" | 31 #include "platform/network/ResourceError.h" |
32 #include "platform/network/ResourceRequest.h" | 32 #include "platform/network/ResourceRequest.h" |
33 #include "platform/network/ResourceResponse.h" | 33 #include "platform/network/ResourceResponse.h" |
34 #include "platform/weborigin/SecurityOrigin.h" | 34 #include "platform/weborigin/SecurityOrigin.h" |
35 #include "public/platform/WebURLRequest.h" | 35 #include "public/platform/WebURLRequest.h" |
36 #include "wtf/HashSet.h" | 36 #include "wtf/HashSet.h" |
37 | 37 |
38 namespace blink { | 38 namespace blink { |
39 | 39 |
40 namespace { | |
41 | |
42 bool IsRedirectStatusCode(int statusCode) | |
43 { | |
44 return (statusCode == 301 || statusCode == 302 || statusCode == 303 || statu sCode == 307 || statusCode == 308); | |
45 } | |
46 | |
47 } // namespace | |
48 | |
49 class FetchManager::Loader final : public NoBaseWillBeGarbageCollectedFinalized< FetchManager::Loader>, public ThreadableLoaderClient, public ContextLifecycleObs erver { | 40 class FetchManager::Loader final : public NoBaseWillBeGarbageCollectedFinalized< FetchManager::Loader>, public ThreadableLoaderClient, public ContextLifecycleObs erver { |
50 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(FetchManager::Loader); | 41 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(FetchManager::Loader); |
51 public: | 42 public: |
52 static PassOwnPtrWillBeRawPtr<Loader> create(ExecutionContext* executionCont ext, FetchManager* fetchManager, ScriptPromiseResolver* resolver, FetchRequestDa ta* request) | 43 static PassOwnPtrWillBeRawPtr<Loader> create(ExecutionContext* executionCont ext, FetchManager* fetchManager, ScriptPromiseResolver* resolver, FetchRequestDa ta* request) |
53 { | 44 { |
54 return adoptPtrWillBeNoop(new Loader(executionContext, fetchManager, res olver, request)); | 45 return adoptPtrWillBeNoop(new Loader(executionContext, fetchManager, res olver, request)); |
55 } | 46 } |
56 | 47 |
57 ~Loader() override; | 48 ~Loader() override; |
58 DECLARE_VIRTUAL_TRACE(); | 49 DECLARE_VIRTUAL_TRACE(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
104 DEFINE_TRACE(FetchManager::Loader) | 95 DEFINE_TRACE(FetchManager::Loader) |
105 { | 96 { |
106 visitor->trace(m_fetchManager); | 97 visitor->trace(m_fetchManager); |
107 visitor->trace(m_resolver); | 98 visitor->trace(m_resolver); |
108 visitor->trace(m_request); | 99 visitor->trace(m_request); |
109 ContextLifecycleObserver::trace(visitor); | 100 ContextLifecycleObserver::trace(visitor); |
110 } | 101 } |
111 | 102 |
112 void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo nse& response, PassOwnPtr<WebDataConsumerHandle> handle) | 103 void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo nse& response, PassOwnPtr<WebDataConsumerHandle> handle) |
113 { | 104 { |
114 ASSERT(handle); | |
115 | |
116 m_responseHttpStatusCode = response.httpStatusCode(); | 105 m_responseHttpStatusCode = response.httpStatusCode(); |
yhirano
2015/08/18 07:56:49
Please keep the assertion.
horo
2015/08/19 07:36:12
Done.
| |
117 | 106 |
118 // Recompute the tainting if the request was redirected to a different | 107 // Recompute the tainting if the request was redirected to a different |
119 // origin. | 108 // origin. |
120 if (!SecurityOrigin::create(response.url())->isSameSchemeHostPort(m_request- >origin().get())) { | 109 if (!SecurityOrigin::create(response.url())->isSameSchemeHostPort(m_request- >origin().get())) { |
121 switch (m_request->mode()) { | 110 switch (m_request->mode()) { |
122 case WebURLRequest::FetchRequestModeSameOrigin: | 111 case WebURLRequest::FetchRequestModeSameOrigin: |
123 ASSERT_NOT_REACHED(); | 112 ASSERT_NOT_REACHED(); |
124 break; | 113 break; |
125 case WebURLRequest::FetchRequestModeNoCORS: | 114 case WebURLRequest::FetchRequestModeNoCORS: |
126 m_request->setResponseTainting(FetchRequestData::OpaqueTainting); | 115 m_request->setResponseTainting(FetchRequestData::OpaqueTainting); |
127 break; | 116 break; |
128 case WebURLRequest::FetchRequestModeCORS: | 117 case WebURLRequest::FetchRequestModeCORS: |
129 case WebURLRequest::FetchRequestModeCORSWithForcedPreflight: | 118 case WebURLRequest::FetchRequestModeCORSWithForcedPreflight: |
130 m_request->setResponseTainting(FetchRequestData::CORSTainting); | 119 m_request->setResponseTainting(FetchRequestData::CORSTainting); |
131 break; | 120 break; |
132 } | 121 } |
133 } | 122 } |
134 FetchResponseData* responseData = FetchResponseData::createWithBuffer(new Bo dyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(handle))); | 123 |
124 bool isRedirectResponse = false; | |
125 FetchResponseData* responseData = nullptr; | |
126 if (!handle) { | |
127 ASSERT(m_request->redirect() == WebURLRequest::FetchRedirectModeManual); | |
128 isRedirectResponse = true; | |
129 responseData = FetchResponseData::create(); | |
130 } else { | |
131 responseData = FetchResponseData::createWithBuffer(new BodyStreamBuffer( createFetchDataConsumerHandleFromWebHandle(handle))); | |
132 } | |
135 responseData->setStatus(response.httpStatusCode()); | 133 responseData->setStatus(response.httpStatusCode()); |
136 responseData->setStatusMessage(response.httpStatusText()); | 134 responseData->setStatusMessage(response.httpStatusText()); |
137 for (auto& it : response.httpHeaderFields()) | 135 for (auto& it : response.httpHeaderFields()) |
138 responseData->headerList()->append(it.key, it.value); | 136 responseData->headerList()->append(it.key, it.value); |
139 responseData->setURL(response.url()); | 137 responseData->setURL(response.url()); |
140 responseData->setMIMEType(response.mimeType()); | 138 responseData->setMIMEType(response.mimeType()); |
141 | 139 |
142 FetchResponseData* taintedResponse = nullptr; | 140 FetchResponseData* taintedResponse = nullptr; |
143 | 141 |
144 if (IsRedirectStatusCode(m_responseHttpStatusCode)) { | 142 if (isRedirectResponse) { |
145 Vector<String> locations; | 143 taintedResponse = responseData->createOpaqueRedirectFilteredResponse(); |
146 responseData->headerList()->getAll("location", locations); | 144 } else { |
147 if (locations.size() > 1) { | |
148 performNetworkError("Multiple Location header."); | |
149 return; | |
150 } | |
151 if (locations.size() == 1) { | |
152 KURL locationURL(m_request->url(), locations[0]); | |
153 if (!locationURL.isValid()) { | |
154 performNetworkError("Invalid Location header."); | |
155 return; | |
156 } | |
157 ASSERT(m_request->redirect() == WebURLRequest::FetchRedirectModeManu al); | |
158 taintedResponse = responseData->createOpaqueRedirectFilteredResponse (); | |
159 } | |
160 // When the location header doesn't exist, we don't treat the response | |
161 // as a redirect response, and execute tainting. | |
162 } | |
163 if (!taintedResponse) { | |
164 switch (m_request->tainting()) { | 145 switch (m_request->tainting()) { |
165 case FetchRequestData::BasicTainting: | 146 case FetchRequestData::BasicTainting: |
166 taintedResponse = responseData->createBasicFilteredResponse(); | 147 taintedResponse = responseData->createBasicFilteredResponse(); |
167 break; | 148 break; |
168 case FetchRequestData::CORSTainting: | 149 case FetchRequestData::CORSTainting: |
169 taintedResponse = responseData->createCORSFilteredResponse(); | 150 taintedResponse = responseData->createCORSFilteredResponse(); |
170 break; | 151 break; |
171 case FetchRequestData::OpaqueTainting: | 152 case FetchRequestData::OpaqueTainting: |
172 taintedResponse = responseData->createOpaqueFilteredResponse(); | 153 taintedResponse = responseData->createOpaqueFilteredResponse(); |
173 break; | 154 break; |
174 } | 155 } |
175 } | 156 } |
176 Response* r = Response::create(m_resolver->executionContext(), taintedRespon se); | 157 Response* r = Response::create(m_resolver->executionContext(), taintedRespon se); |
177 r->headers()->setGuard(Headers::ImmutableGuard); | 158 r->headers()->setGuard(Headers::ImmutableGuard); |
178 m_resolver->resolve(r); | 159 m_resolver->resolve(r); |
179 m_resolver.clear(); | 160 m_resolver.clear(); |
161 | |
162 if (isRedirectResponse) { | |
163 // There is no need to read the body of redirect response because there | |
164 // is no way to read the body of opaque-redirect filtered response's | |
165 // internal response. | |
166 // TODO(horo): If we support any API which expose the internal body, we | |
167 // will have to read the body. And also HTTPCache changes will be needed | |
168 // because it doesn't store the body of redirect responses. | |
169 notifyFinished(); | |
170 } | |
180 } | 171 } |
181 | 172 |
182 void FetchManager::Loader::didFinishLoading(unsigned long, double) | 173 void FetchManager::Loader::didFinishLoading(unsigned long, double) |
183 { | 174 { |
184 ASSERT(!m_failed); | 175 ASSERT(!m_failed); |
185 m_finished = true; | 176 m_finished = true; |
186 | 177 |
187 if (document() && document()->frame() && document()->frame()->page() | 178 if (document() && document()->frame() && document()->frame()->page() |
188 && m_responseHttpStatusCode >= 200 && m_responseHttpStatusCode < 300) { | 179 && m_responseHttpStatusCode >= 200 && m_responseHttpStatusCode < 300) { |
189 document()->frame()->page()->chromeClient().ajaxSucceeded(document()->fr ame()); | 180 document()->frame()->page()->chromeClient().ajaxSucceeded(document()->fr ame()); |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
488 | 479 |
489 DEFINE_TRACE(FetchManager) | 480 DEFINE_TRACE(FetchManager) |
490 { | 481 { |
491 #if ENABLE(OILPAN) | 482 #if ENABLE(OILPAN) |
492 visitor->trace(m_executionContext); | 483 visitor->trace(m_executionContext); |
493 visitor->trace(m_loaders); | 484 visitor->trace(m_loaders); |
494 #endif | 485 #endif |
495 } | 486 } |
496 | 487 |
497 } // namespace blink | 488 } // namespace blink |
OLD | NEW |