OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 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 "content/browser/service_worker/service_worker_controllee_url_loader_fa ctory.h" | |
6 | |
7 #include "content/common/service_worker/service_worker_utils.h" | |
8 #include "content/public/browser/browser_thread.h" | |
9 #include "mojo/public/cpp/system/data_pipe.h" | |
10 #include "net/base/io_buffer.h" | |
11 #include "storage/browser/blob/blob_data_handle.h" | |
12 #include "storage/browser/blob/blob_storage_context.h" | |
13 | |
14 namespace content { | |
15 | |
16 void ServiceWorkerControlleeURLLoaderFactory::CreateLoaderAndStart( | |
17 mojom::URLLoaderAssociatedRequest request, | |
18 int32_t routing_id, | |
19 int32_t request_id, | |
20 uint32_t options, | |
21 const ResourceRequest& url_request, | |
22 mojom::URLLoaderClientPtr client) { | |
23 LOG(ERROR) << "URL: " << url_request.url; | |
24 request_ = std::move(request); | |
25 url_request_ = std::move(url_request); | |
26 client_ = std::move(client); | |
27 // TODO(scottmg): This factory currently only handles one request due to the | |
28 // way it's hooked up for navigation and with ServiceWorkerStorage. It should | |
29 // probably delegate all its work to a URLLoaderImpl that's created here, but | |
30 // that's not done yet to keep things a bit simpler for now. | |
kinuko
2017/05/09 14:45:25
Maybe the main work should be done by URLLoader im
scottmg
2017/05/09 22:14:10
Yeah, agreed. It just adds even more boilerplate,
| |
31 } | |
32 | |
33 ServiceWorkerControlleeURLLoaderFactory:: | |
34 ~ServiceWorkerControlleeURLLoaderFactory() {} | |
35 | |
36 void ServiceWorkerControlleeURLLoaderFactory::SyncLoad( | |
37 int32_t routing_id, | |
38 int32_t request_id, | |
39 const ResourceRequest& request, | |
40 SyncLoadCallback callback) { | |
41 NOTREACHED(); | |
42 } | |
43 | |
44 void ServiceWorkerControlleeURLLoaderFactory::FallbackToNetwork() { | |
45 DCHECK_EQ(ResponseType::kNotDetermined, response_type_); | |
46 response_type_ = ResponseType::kFallbackToNetwork; | |
47 StartRequest(); | |
48 } | |
49 | |
50 bool ServiceWorkerControlleeURLLoaderFactory::ShouldFallbackToNetwork() { | |
51 return response_type_ == ResponseType::kFallbackToNetwork; | |
52 } | |
53 | |
54 ui::PageTransition | |
55 ServiceWorkerControlleeURLLoaderFactory::GetPageTransition() { | |
56 NOTIMPLEMENTED() << __FUNCTION__; | |
57 return ui::PAGE_TRANSITION_LINK; | |
58 } | |
59 | |
60 size_t ServiceWorkerControlleeURLLoaderFactory::GetURLChainSize() { | |
61 NOTIMPLEMENTED() << __FUNCTION__; | |
62 return 0; | |
63 } | |
64 | |
65 void ServiceWorkerControlleeURLLoaderFactory::ForwardToServiceWorker() { | |
66 DCHECK_EQ(ResponseType::kNotDetermined, response_type_); | |
67 response_type_ = ResponseType::kForwardToServiceWorker; | |
68 StartRequest(); | |
69 } | |
70 | |
71 void ServiceWorkerControlleeURLLoaderFactory::FallbackToNetworkOrRenderer() { | |
72 NOTIMPLEMENTED() << __FUNCTION__; | |
73 } | |
74 | |
75 void ServiceWorkerControlleeURLLoaderFactory::FailToNetworkOrRenderer() { | |
76 NOTIMPLEMENTED() << __FUNCTION__; | |
77 } | |
78 | |
79 void ServiceWorkerControlleeURLLoaderFactory::FailDueToLostController() { | |
80 NOTIMPLEMENTED() << __FUNCTION__; | |
81 } | |
82 | |
83 bool ServiceWorkerControlleeURLLoaderFactory::WasCanceled() const { | |
84 NOTIMPLEMENTED() << __FUNCTION__; | |
85 return false; | |
86 } | |
87 | |
88 std::unique_ptr<ServiceWorkerFetchRequest> | |
89 ServiceWorkerControlleeURLLoaderFactory::CreateFetchRequest() { | |
90 std::string blob_uuid; | |
91 uint64_t blob_size = 0; | |
92 #if 0 // TODO(scottmg): | |
93 if (HasRequestBody()) | |
94 CreateRequestBodyBlob(&blob_uuid, &blob_size); | |
95 #endif | |
96 std::unique_ptr<ServiceWorkerFetchRequest> request( | |
97 new ServiceWorkerFetchRequest()); | |
98 request->mode = request_mode_; | |
99 request->is_main_resource_load = | |
100 ServiceWorkerUtils::IsMainResourceType(resource_type_); | |
101 request->request_context_type = request_context_type_; | |
102 request->frame_type = frame_type_; | |
103 request->url = url_request_.url; | |
104 request->method = url_request_.method; | |
105 #if 0 // TODO(scottmg): | |
106 const net::HttpRequestHeaders& headers = request_->extra_request_headers(); | |
107 for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();) { | |
108 if (ServiceWorkerContext::IsExcludedHeaderNameForFetchEvent(it.name())) | |
109 continue; | |
110 request->headers[it.name()] = it.value(); | |
111 } | |
112 #endif | |
113 request->blob_uuid = blob_uuid; | |
114 request->blob_size = blob_size; | |
115 request->credentials_mode = credentials_mode_; | |
116 request->redirect_mode = redirect_mode_; | |
117 request->client_id = client_id_; | |
118 #if 0 // TODO(scottmg): | |
119 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); | |
120 if (info) { | |
121 request->is_reload = ui::PageTransitionCoreTypeIs( | |
122 info->GetPageTransition(), ui::PAGE_TRANSITION_RELOAD); | |
123 request->referrer = | |
124 Referrer(GURL(request_->referrer()), info->GetReferrerPolicy()); | |
125 } else { | |
126 CHECK( | |
127 request_->referrer_policy() == | |
128 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE); | |
129 request->referrer = | |
130 Referrer(GURL(request_->referrer()), blink::kWebReferrerPolicyDefault); | |
131 } | |
132 #endif | |
133 request->fetch_type = fetch_type_; | |
134 return request; | |
135 } | |
136 | |
137 void ServiceWorkerControlleeURLLoaderFactory::StartRequest() { | |
138 if (response_type_ == ResponseType::kFallbackToNetwork) { | |
139 // Need to restart the request, and send it through the network. | |
140 BrowserThread::PostTask( | |
141 BrowserThread::UI, FROM_HERE, | |
142 base::Bind(network_fallback_callback_, | |
143 base::Passed(std::move( | |
144 base::MakeUnique<ResourceRequest>(url_request_))))); | |
145 return; | |
146 } | |
147 if (response_type_ != ResponseType::kForwardToServiceWorker) { | |
148 NOTIMPLEMENTED() << " Unexpected response type!"; | |
149 return; | |
150 } | |
151 DCHECK(!fetch_dispatcher_); | |
152 ServiceWorkerMetrics::URLRequestJobResult result = | |
153 ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_DELEGATE; | |
154 ServiceWorkerVersion* active_worker = | |
155 delegate_->GetServiceWorkerVersion(&result); | |
156 fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher( | |
157 CreateFetchRequest(), active_worker, resource_type_, timeout_, | |
158 net::NetLogWithSource() /* TODO(scottmg): net log */, | |
159 base::Bind(&ServiceWorkerControlleeURLLoaderFactory::DidPrepareFetchEvent, | |
160 weak_factory_.GetWeakPtr(), active_worker), | |
161 base::Bind( | |
162 &ServiceWorkerControlleeURLLoaderFactory::DidDispatchFetchEvent, | |
163 weak_factory_.GetWeakPtr()))); | |
164 fetch_dispatcher_->Run(); | |
165 } | |
166 | |
167 void ServiceWorkerControlleeURLLoaderFactory::DidPrepareFetchEvent( | |
168 scoped_refptr<ServiceWorkerVersion> version) {} | |
169 | |
170 void ServiceWorkerControlleeURLLoaderFactory::DidDispatchFetchEvent( | |
171 ServiceWorkerStatusCode status, | |
172 ServiceWorkerFetchEventResult fetch_result, | |
173 const ServiceWorkerResponse& response, | |
174 blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream, | |
175 const scoped_refptr<ServiceWorkerVersion>& version) { | |
176 ResourceResponseHead head; | |
177 // TODO(scottmg): More stuff copied over. | |
178 head.headers = new net::HttpResponseHeaders(""); | |
179 for (const auto& kv : response.headers) | |
180 head.headers->AddHeader(kv.first + ": " + kv.second); | |
181 head.url_list_via_service_worker = response.url_list; | |
182 head.mime_type = "text/html"; // TODO(scottmg): No idea where to get this. | |
183 head.was_fetched_via_service_worker = true; | |
184 head.cors_exposed_header_names = response.cors_exposed_header_names; | |
185 client_->OnReceiveResponse(head, base::nullopt /* TODO(scottmg): ssl info */, | |
186 mojom::DownloadedTempFilePtr()); | |
187 | |
188 // Ideally, we would always get a data pipe fom SWFetchDispatcher and use this | |
189 // case. See: | |
190 // https://docs.google.com/a/google.com/document/d/1_ROmusFvd8ATwIZa29-P6Ls5yy Ljfld0KvKchVfA84Y/edit?usp=drive_web | |
191 if (!body_as_stream.is_null() && body_as_stream->stream.is_valid()) { | |
192 client_->OnStartLoadingResponseBody(std::move(body_as_stream->stream)); | |
193 } else { | |
194 // TODO(scottmg): This is temporary hacky to load the blob right here and | |
195 // turn it into a data pipe to respond with, until we are always able to | |
196 // take the above path. | |
197 if (!response.blob_uuid.empty() && blob_storage_context_) { | |
198 std::unique_ptr<storage::BlobDataHandle> blob_data_handle = | |
199 blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid); | |
200 blob_reader_ = blob_data_handle->CreateReader( | |
201 nullptr /* file system context */, | |
202 BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE).get()); | |
203 CHECK(storage::BlobReader::Status::DONE == | |
204 blob_reader_->CalculateSize(net::CompletionCallback())); | |
205 blob_reader_->SetReadRange(0, blob_reader_->total_size()); | |
206 scoped_refptr<net::IOBuffer> buffer( | |
207 new net::IOBuffer(static_cast<size_t>(blob_reader_->total_size()))); | |
208 | |
209 int bytes_read; | |
210 blob_reader_->Read( | |
211 buffer.get(), blob_reader_->total_size(), &bytes_read, | |
212 base::Bind(&ServiceWorkerControlleeURLLoaderFactory::AfterRead, | |
213 weak_factory_.GetWeakPtr(), buffer)); | |
214 } | |
215 } | |
216 } | |
217 | |
218 void ServiceWorkerControlleeURLLoaderFactory::AfterRead( | |
219 scoped_refptr<net::IOBuffer> buffer, | |
220 int bytes) { | |
221 uint32_t bytes_written = static_cast<uint32_t>(bytes); | |
222 mojo::WriteDataRaw(data_pipe_.producer_handle.get(), buffer->data(), | |
223 &bytes_written, MOJO_WRITE_DATA_FLAG_NONE); | |
224 client_->OnStartLoadingResponseBody(std::move(data_pipe_.consumer_handle)); | |
225 } | |
226 | |
227 } // namespace content | |
OLD | NEW |