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/network/public/interfaces/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"
20 using mojo::URLResponsePtr
;
22 namespace html_viewer
{
25 blink::WebURLResponse::HTTPVersion
StatusLineToHTTPVersion(
26 const mojo::String
& status_line
) {
27 if (status_line
.is_null())
28 return blink::WebURLResponse::HTTP_0_9
;
30 if (StartsWithASCII(status_line
, "HTTP/1.0", true))
31 return blink::WebURLResponse::HTTP_1_0
;
33 if (StartsWithASCII(status_line
, "HTTP/1.1", true))
34 return blink::WebURLResponse::HTTP_1_1
;
36 return blink::WebURLResponse::Unknown
;
39 blink::WebURLResponse
ToWebURLResponse(const URLResponsePtr
& url_response
) {
40 blink::WebURLResponse result
;
42 result
.setURL(GURL(url_response
->url
));
43 result
.setMIMEType(blink::WebString::fromUTF8(url_response
->mime_type
));
44 result
.setTextEncodingName(blink::WebString::fromUTF8(url_response
->charset
));
45 result
.setHTTPVersion(StatusLineToHTTPVersion(url_response
->status_line
));
46 result
.setHTTPStatusCode(url_response
->status_code
);
48 // TODO(darin): Initialize timing properly.
49 blink::WebURLLoadTiming timing
;
51 result
.setLoadTiming(timing
);
53 for (size_t i
= 0; i
< url_response
->headers
.size(); ++i
) {
54 const std::string
& header_line
= url_response
->headers
[i
];
55 size_t first_colon
= header_line
.find(":");
57 if (first_colon
== std::string::npos
|| first_colon
== 0)
61 TrimWhitespaceASCII(header_line
.substr(first_colon
+ 1),
64 result
.setHTTPHeaderField(
65 blink::WebString::fromUTF8(header_line
.substr(0, first_colon
)),
66 blink::WebString::fromUTF8(value
));
74 WebURLRequestExtraData::WebURLRequestExtraData() {
77 WebURLRequestExtraData::~WebURLRequestExtraData() {
80 WebURLLoaderImpl::WebURLLoaderImpl(mojo::NetworkService
* network_service
)
81 : client_(NULL
), weak_factory_(this) {
82 network_service
->CreateURLLoader(GetProxy(&url_loader_
));
85 WebURLLoaderImpl::~WebURLLoaderImpl() {
88 void WebURLLoaderImpl::loadSynchronously(
89 const blink::WebURLRequest
& request
,
90 blink::WebURLResponse
& response
,
91 blink::WebURLError
& error
,
92 blink::WebData
& data
) {
96 void WebURLLoaderImpl::loadAsynchronously(const blink::WebURLRequest
& request
,
97 blink::WebURLLoaderClient
* client
) {
101 mojo::URLRequestPtr url_request
= mojo::URLRequest::From(request
);
102 url_request
->auto_follow_redirects
= false;
104 if (request
.extraData()) {
105 WebURLRequestExtraData
* extra_data
=
106 static_cast<WebURLRequestExtraData
*>(request
.extraData());
107 base::ThreadTaskRunnerHandle::Get()->PostTask(
109 base::Bind(&WebURLLoaderImpl::OnReceivedResponse
,
110 weak_factory_
.GetWeakPtr(),
111 base::Passed(&extra_data
->synthetic_response
)));
113 url_loader_
->Start(url_request
.Pass(),
114 base::Bind(&WebURLLoaderImpl::OnReceivedResponse
,
115 weak_factory_
.GetWeakPtr()));
119 void WebURLLoaderImpl::cancel() {
121 response_body_stream_
.reset();
123 URLResponsePtr
failed_response(mojo::URLResponse::New());
124 failed_response
->url
= mojo::String::From(url_
);
125 failed_response
->error
= mojo::NetworkError::New();
126 failed_response
->error
->code
= net::ERR_ABORTED
;
128 base::ThreadTaskRunnerHandle::Get()->PostTask(
130 base::Bind(&WebURLLoaderImpl::OnReceivedResponse
,
131 weak_factory_
.GetWeakPtr(),
132 base::Passed(&failed_response
)));
135 void WebURLLoaderImpl::setDefersLoading(bool defers_loading
) {
139 void WebURLLoaderImpl::OnReceivedResponse(URLResponsePtr url_response
) {
140 url_
= GURL(url_response
->url
);
142 if (url_response
->error
) {
143 OnReceivedError(url_response
.Pass());
144 } else if (url_response
->redirect_url
) {
145 OnReceivedRedirect(url_response
.Pass());
147 base::WeakPtr
<WebURLLoaderImpl
> self(weak_factory_
.GetWeakPtr());
148 client_
->didReceiveResponse(this, ToWebURLResponse(url_response
));
150 // We may have been deleted during didReceiveResponse.
154 // Start streaming data
155 response_body_stream_
= url_response
->body
.Pass();
160 void WebURLLoaderImpl::OnReceivedError(URLResponsePtr url_response
) {
161 blink::WebURLError web_error
;
162 web_error
.domain
= blink::WebString::fromUTF8(net::kErrorDomain
);
163 web_error
.reason
= url_response
->error
->code
;
164 web_error
.unreachableURL
= GURL(url_response
->url
);
165 web_error
.staleCopyInCache
= false;
166 web_error
.isCancellation
=
167 url_response
->error
->code
== net::ERR_ABORTED
? true : false;
169 client_
->didFail(this, web_error
);
172 void WebURLLoaderImpl::OnReceivedRedirect(URLResponsePtr url_response
) {
173 blink::WebURLRequest new_request
;
174 new_request
.initialize();
175 new_request
.setURL(GURL(url_response
->redirect_url
));
176 new_request
.setHTTPMethod(
177 blink::WebString::fromUTF8(url_response
->redirect_method
));
179 client_
->willSendRequest(this, new_request
, ToWebURLResponse(url_response
));
180 // TODO(darin): Check if new_request was rejected.
182 url_loader_
->FollowRedirect(
183 base::Bind(&WebURLLoaderImpl::OnReceivedResponse
,
184 weak_factory_
.GetWeakPtr()));
187 void WebURLLoaderImpl::ReadMore() {
190 MojoResult rv
= BeginReadDataRaw(response_body_stream_
.get(),
193 MOJO_READ_DATA_FLAG_NONE
);
194 if (rv
== MOJO_RESULT_OK
) {
195 client_
->didReceiveData(this, static_cast<const char*>(buf
), buf_size
, -1);
196 EndReadDataRaw(response_body_stream_
.get(), buf_size
);
198 } else if (rv
== MOJO_RESULT_SHOULD_WAIT
) {
200 } else if (rv
== MOJO_RESULT_FAILED_PRECONDITION
) {
201 // We reached end-of-file.
202 double finish_time
= base::Time::Now().ToDoubleT();
203 client_
->didFinishLoading(
206 blink::WebURLLoaderClient::kUnknownEncodedDataLength
);
208 // TODO(darin): Oops!
212 void WebURLLoaderImpl::WaitToReadMore() {
213 handle_watcher_
.Start(
214 response_body_stream_
.get(),
215 MOJO_HANDLE_SIGNAL_READABLE
,
216 MOJO_DEADLINE_INDEFINITE
,
217 base::Bind(&WebURLLoaderImpl::OnResponseBodyStreamReady
,
218 weak_factory_
.GetWeakPtr()));
221 void WebURLLoaderImpl::OnResponseBodyStreamReady(MojoResult result
) {
225 } // namespace html_viewer