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. |
| 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 |