OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "sky/viewer/platform/weburlloader_impl.h" | |
6 | |
7 #include "base/bind.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/network/public/interfaces/network_service.mojom.h" | |
13 #include "sky/engine/public/platform/WebURLError.h" | |
14 #include "sky/engine/public/platform/WebURLLoadTiming.h" | |
15 #include "sky/engine/public/platform/WebURLLoaderClient.h" | |
16 #include "sky/engine/public/platform/WebURLResponse.h" | |
17 #include "sky/viewer/converters/url_request_types.h" | |
18 #include "sky/viewer/platform/net_constants.h" | |
19 | |
20 namespace sky { | |
21 namespace { | |
22 | |
23 static blink::WebURLResponse::HTTPVersion StatusLineToHTTPVersion( | |
24 const mojo::String& status_line) { | |
25 if (status_line.is_null()) | |
26 return blink::WebURLResponse::HTTP_0_9; | |
27 | |
28 if (StartsWithASCII(status_line, "HTTP/1.0", true)) | |
29 return blink::WebURLResponse::HTTP_1_0; | |
30 | |
31 if (StartsWithASCII(status_line, "HTTP/1.1", true)) | |
32 return blink::WebURLResponse::HTTP_1_1; | |
33 | |
34 return blink::WebURLResponse::Unknown; | |
35 } | |
36 | |
37 blink::WebURLResponse ToWebURLResponse(const mojo::URLResponsePtr& url_response)
{ | |
38 blink::WebURLResponse result; | |
39 result.initialize(); | |
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); | |
45 | |
46 // TODO(darin): Initialize timing properly. | |
47 blink::WebURLLoadTiming timing; | |
48 timing.initialize(); | |
49 result.setLoadTiming(timing); | |
50 | |
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(":"); | |
54 | |
55 if (first_colon == std::string::npos || first_colon == 0) | |
56 continue; | |
57 | |
58 std::string value; | |
59 TrimWhitespaceASCII(header_line.substr(first_colon + 1), | |
60 base::TRIM_LEADING, | |
61 &value); | |
62 result.setHTTPHeaderField( | |
63 blink::WebString::fromUTF8(header_line.substr(0, first_colon)), | |
64 blink::WebString::fromUTF8(value)); | |
65 } | |
66 | |
67 return result; | |
68 } | |
69 | |
70 } // namespace | |
71 | |
72 WebURLLoaderImpl::WebURLLoaderImpl(mojo::NetworkService* network_service) | |
73 : client_(NULL), | |
74 weak_factory_(this) { | |
75 network_service->CreateURLLoader(GetProxy(&url_loader_)); | |
76 } | |
77 | |
78 WebURLLoaderImpl::~WebURLLoaderImpl() { | |
79 } | |
80 | |
81 void WebURLLoaderImpl::loadAsynchronously(const blink::WebURLRequest& request, | |
82 blink::WebURLLoaderClient* client) { | |
83 client_ = client; | |
84 url_ = request.url(); | |
85 | |
86 mojo::URLRequestPtr url_request = mojo::URLRequest::From(request); | |
87 url_request->auto_follow_redirects = false; | |
88 url_loader_->Start(url_request.Pass(), | |
89 base::Bind(&WebURLLoaderImpl::OnReceivedResponse, | |
90 weak_factory_.GetWeakPtr())); | |
91 } | |
92 | |
93 void WebURLLoaderImpl::cancel() { | |
94 url_loader_.reset(); | |
95 response_body_stream_.reset(); | |
96 | |
97 mojo::URLResponsePtr failed_response(mojo::URLResponse::New()); | |
98 failed_response->url = mojo::String::From(url_); | |
99 failed_response->error = mojo::NetworkError::New(); | |
100 failed_response->error->code = kNetErrorAborted; | |
101 | |
102 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
103 FROM_HERE, | |
104 base::Bind(&WebURLLoaderImpl::OnReceivedResponse, | |
105 weak_factory_.GetWeakPtr(), | |
106 base::Passed(&failed_response))); | |
107 } | |
108 | |
109 void WebURLLoaderImpl::OnReceivedResponse(mojo::URLResponsePtr url_response) { | |
110 url_ = GURL(url_response->url); | |
111 | |
112 if (url_response->error) { | |
113 OnReceivedError(url_response.Pass()); | |
114 } else if (url_response->redirect_url) { | |
115 OnReceivedRedirect(url_response.Pass()); | |
116 } else { | |
117 base::WeakPtr<WebURLLoaderImpl> self(weak_factory_.GetWeakPtr()); | |
118 client_->didReceiveResponse(this, ToWebURLResponse(url_response)); | |
119 | |
120 // We may have been deleted during didReceiveResponse. | |
121 if (!self) | |
122 return; | |
123 | |
124 // Start streaming data | |
125 response_body_stream_ = url_response->body.Pass(); | |
126 ReadMore(); | |
127 } | |
128 } | |
129 | |
130 void WebURLLoaderImpl::OnReceivedError(mojo::URLResponsePtr url_response) { | |
131 blink::WebURLError web_error; | |
132 web_error.domain = blink::WebString::fromUTF8(kNetErrorDomain); | |
133 web_error.reason = url_response->error->code; | |
134 web_error.unreachableURL = GURL(url_response->url); | |
135 web_error.staleCopyInCache = false; | |
136 web_error.isCancellation = | |
137 url_response->error->code == kNetErrorAborted ? true : false; | |
138 | |
139 client_->didFail(this, web_error); | |
140 } | |
141 | |
142 void WebURLLoaderImpl::OnReceivedRedirect(mojo::URLResponsePtr url_response) { | |
143 blink::WebURLRequest new_request; | |
144 new_request.initialize(); | |
145 new_request.setURL(GURL(url_response->redirect_url)); | |
146 new_request.setHTTPMethod( | |
147 blink::WebString::fromUTF8(url_response->redirect_method)); | |
148 | |
149 client_->willSendRequest(this, new_request, ToWebURLResponse(url_response)); | |
150 // TODO(darin): Check if new_request was rejected. | |
151 | |
152 url_loader_->FollowRedirect( | |
153 base::Bind(&WebURLLoaderImpl::OnReceivedResponse, | |
154 weak_factory_.GetWeakPtr())); | |
155 } | |
156 | |
157 void WebURLLoaderImpl::ReadMore() { | |
158 const void* buf; | |
159 uint32_t buf_size; | |
160 MojoResult rv = mojo::BeginReadDataRaw(response_body_stream_.get(), | |
161 &buf, | |
162 &buf_size, | |
163 MOJO_READ_DATA_FLAG_NONE); | |
164 if (rv == MOJO_RESULT_OK) { | |
165 client_->didReceiveData(this, static_cast<const char*>(buf), buf_size, -1); | |
166 EndReadDataRaw(response_body_stream_.get(), buf_size); | |
167 WaitToReadMore(); | |
168 } else if (rv == MOJO_RESULT_SHOULD_WAIT) { | |
169 WaitToReadMore(); | |
170 } else if (rv == MOJO_RESULT_FAILED_PRECONDITION) { | |
171 // We reached end-of-file. | |
172 double finish_time = base::Time::Now().ToDoubleT(); | |
173 client_->didFinishLoading( | |
174 this, | |
175 finish_time, | |
176 blink::WebURLLoaderClient::kUnknownEncodedDataLength); | |
177 } else { | |
178 // TODO(darin): Oops! | |
179 } | |
180 } | |
181 | |
182 void WebURLLoaderImpl::WaitToReadMore() { | |
183 handle_watcher_.Start( | |
184 response_body_stream_.get(), | |
185 MOJO_HANDLE_SIGNAL_READABLE, | |
186 MOJO_DEADLINE_INDEFINITE, | |
187 base::Bind(&WebURLLoaderImpl::OnResponseBodyStreamReady, | |
188 weak_factory_.GetWeakPtr())); | |
189 } | |
190 | |
191 void WebURLLoaderImpl::OnResponseBodyStreamReady(MojoResult result) { | |
192 ReadMore(); | |
193 } | |
194 | |
195 } // namespace sky | |
OLD | NEW |