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
3 // found in the LICENSE file.
5 #include "mojo/services/html_viewer/weburlloader_impl.h"
8 #include "base/logging.h"
9 #include "base/strings/string_util.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "mojo/common/common_type_converters.h"
12 #include "mojo/services/html_viewer/blink_url_request_type_converters.h"
13 #include "mojo/services/public/interfaces/network/network_service.mojom.h"
14 #include "net/base/net_errors.h"
15 #include "third_party/WebKit/public/platform/WebURLError.h"
16 #include "third_party/WebKit/public/platform/WebURLLoadTiming.h"
17 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
18 #include "third_party/WebKit/public/platform/WebURLResponse.h"
23 static blink::WebURLResponse::HTTPVersion
StatusLineToHTTPVersion(
24 const String
& status_line
) {
25 if (status_line
.is_null())
26 return blink::WebURLResponse::HTTP_0_9
;
28 if (StartsWithASCII(status_line
, "HTTP/1.0", true))
29 return blink::WebURLResponse::HTTP_1_0
;
31 if (StartsWithASCII(status_line
, "HTTP/1.1", true))
32 return blink::WebURLResponse::HTTP_1_1
;
34 return blink::WebURLResponse::Unknown
;
37 blink::WebURLResponse
ToWebURLResponse(const URLResponsePtr
& url_response
) {
38 blink::WebURLResponse result
;
40 result
.setURL(GURL(url_response
->url
));
41 result
.setMIMEType(blink::WebString::fromUTF8(url_response
->mime_type
));
42 result
.setTextEncodingName(blink::WebString::fromUTF8(url_response
->charset
));
43 result
.setHTTPVersion(StatusLineToHTTPVersion(url_response
->status_line
));
44 result
.setHTTPStatusCode(url_response
->status_code
);
46 // TODO(darin): Initialize timing properly.
47 blink::WebURLLoadTiming timing
;
49 result
.setLoadTiming(timing
);
51 for (size_t i
= 0; i
< url_response
->headers
.size(); ++i
) {
52 const std::string
& header_line
= url_response
->headers
[i
];
53 size_t first_colon
= header_line
.find(":");
55 if (first_colon
== std::string::npos
|| first_colon
== 0)
59 TrimWhitespaceASCII(header_line
.substr(first_colon
+ 1),
62 result
.setHTTPHeaderField(
63 blink::WebString::fromUTF8(header_line
.substr(0, first_colon
)),
64 blink::WebString::fromUTF8(value
));
72 WebURLRequestExtraData::WebURLRequestExtraData() {
75 WebURLRequestExtraData::~WebURLRequestExtraData() {
78 WebURLLoaderImpl::WebURLLoaderImpl(NetworkService
* network_service
)
81 network_service
->CreateURLLoader(GetProxy(&url_loader_
));
84 WebURLLoaderImpl::~WebURLLoaderImpl() {
87 void WebURLLoaderImpl::loadSynchronously(
88 const blink::WebURLRequest
& request
,
89 blink::WebURLResponse
& response
,
90 blink::WebURLError
& error
,
91 blink::WebData
& data
) {
95 void WebURLLoaderImpl::loadAsynchronously(const blink::WebURLRequest
& request
,
96 blink::WebURLLoaderClient
* client
) {
100 URLRequestPtr url_request
= URLRequest::From(request
);
101 url_request
->auto_follow_redirects
= false;
103 if (request
.extraData()) {
104 WebURLRequestExtraData
* extra_data
=
105 static_cast<WebURLRequestExtraData
*>(request
.extraData());
106 base::ThreadTaskRunnerHandle::Get()->PostTask(
108 base::Bind(&WebURLLoaderImpl::OnReceivedResponse
,
109 weak_factory_
.GetWeakPtr(),
110 base::Passed(&extra_data
->synthetic_response
)));
112 url_loader_
->Start(url_request
.Pass(),
113 base::Bind(&WebURLLoaderImpl::OnReceivedResponse
,
114 weak_factory_
.GetWeakPtr()));
118 void WebURLLoaderImpl::cancel() {
120 response_body_stream_
.reset();
122 URLResponsePtr
failed_response(URLResponse::New());
123 failed_response
->url
= String::From(url_
);
124 failed_response
->error
= NetworkError::New();
125 failed_response
->error
->code
= net::ERR_ABORTED
;
127 base::ThreadTaskRunnerHandle::Get()->PostTask(
129 base::Bind(&WebURLLoaderImpl::OnReceivedResponse
,
130 weak_factory_
.GetWeakPtr(),
131 base::Passed(&failed_response
)));
134 void WebURLLoaderImpl::setDefersLoading(bool defers_loading
) {
138 void WebURLLoaderImpl::OnReceivedResponse(URLResponsePtr url_response
) {
139 url_
= GURL(url_response
->url
);
141 if (url_response
->error
) {
142 OnReceivedError(url_response
.Pass());
143 } else if (url_response
->redirect_url
) {
144 OnReceivedRedirect(url_response
.Pass());
146 base::WeakPtr
<WebURLLoaderImpl
> self(weak_factory_
.GetWeakPtr());
147 client_
->didReceiveResponse(this, ToWebURLResponse(url_response
));
149 // We may have been deleted during didReceiveResponse.
153 // Start streaming data
154 response_body_stream_
= url_response
->body
.Pass();
159 void WebURLLoaderImpl::OnReceivedError(URLResponsePtr url_response
) {
160 blink::WebURLError web_error
;
161 web_error
.domain
= blink::WebString::fromUTF8(net::kErrorDomain
);
162 web_error
.reason
= url_response
->error
->code
;
163 web_error
.unreachableURL
= GURL(url_response
->url
);
164 web_error
.staleCopyInCache
= false;
165 web_error
.isCancellation
=
166 url_response
->error
->code
== net::ERR_ABORTED
? true : false;
168 client_
->didFail(this, web_error
);
171 void WebURLLoaderImpl::OnReceivedRedirect(URLResponsePtr url_response
) {
172 blink::WebURLRequest new_request
;
173 new_request
.initialize();
174 new_request
.setURL(GURL(url_response
->redirect_url
));
175 new_request
.setHTTPMethod(
176 blink::WebString::fromUTF8(url_response
->redirect_method
));
178 client_
->willSendRequest(this, new_request
, ToWebURLResponse(url_response
));
179 // TODO(darin): Check if new_request was rejected.
181 url_loader_
->FollowRedirect(
182 base::Bind(&WebURLLoaderImpl::OnReceivedResponse
,
183 weak_factory_
.GetWeakPtr()));
186 void WebURLLoaderImpl::ReadMore() {
189 MojoResult rv
= BeginReadDataRaw(response_body_stream_
.get(),
192 MOJO_READ_DATA_FLAG_NONE
);
193 if (rv
== MOJO_RESULT_OK
) {
194 client_
->didReceiveData(this, static_cast<const char*>(buf
), buf_size
, -1);
195 EndReadDataRaw(response_body_stream_
.get(), buf_size
);
197 } else if (rv
== MOJO_RESULT_SHOULD_WAIT
) {
199 } else if (rv
== MOJO_RESULT_FAILED_PRECONDITION
) {
200 // We reached end-of-file.
201 double finish_time
= base::Time::Now().ToDoubleT();
202 client_
->didFinishLoading(
205 blink::WebURLLoaderClient::kUnknownEncodedDataLength
);
207 // TODO(darin): Oops!
211 void WebURLLoaderImpl::WaitToReadMore() {
212 handle_watcher_
.Start(
213 response_body_stream_
.get(),
214 MOJO_HANDLE_SIGNAL_READABLE
,
215 MOJO_DEADLINE_INDEFINITE
,
216 base::Bind(&WebURLLoaderImpl::OnResponseBodyStreamReady
,
217 weak_factory_
.GetWeakPtr()));
220 void WebURLLoaderImpl::OnResponseBodyStreamReady(MojoResult result
) {