| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading | 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading |
| 6 | 6 |
| 7 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 7 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
| 8 | 8 |
| 9 #include <stddef.h> | 9 #include <stddef.h> |
| 10 | 10 |
| (...skipping 1137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 net::HttpRequestHeaders headers; | 1148 net::HttpRequestHeaders headers; |
| 1149 headers.AddHeadersFromString(request_data.headers); | 1149 headers.AddHeadersFromString(request_data.headers); |
| 1150 | 1150 |
| 1151 if (is_shutdown_ || | 1151 if (is_shutdown_ || |
| 1152 !ShouldServiceRequest(child_id, request_data, headers, requester_info, | 1152 !ShouldServiceRequest(child_id, request_data, headers, requester_info, |
| 1153 resource_context)) { | 1153 resource_context)) { |
| 1154 AbortRequestBeforeItStarts(requester_info->filter(), sync_result_handler, | 1154 AbortRequestBeforeItStarts(requester_info->filter(), sync_result_handler, |
| 1155 request_id, std::move(url_loader_client)); | 1155 request_id, std::move(url_loader_client)); |
| 1156 return; | 1156 return; |
| 1157 } | 1157 } |
| 1158 // Check if we have a registered interceptor for the headers passed in. If | |
| 1159 // yes then we need to mark the current request as pending and wait for the | |
| 1160 // interceptor to invoke the callback with a status code indicating whether | |
| 1161 // the request needs to be aborted or continued. | |
| 1162 for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();) { | |
| 1163 HeaderInterceptorMap::iterator index = | |
| 1164 http_header_interceptor_map_.find(it.name()); | |
| 1165 if (index != http_header_interceptor_map_.end()) { | |
| 1166 HeaderInterceptorInfo& interceptor_info = index->second; | |
| 1167 | 1158 |
| 1168 bool call_interceptor = true; | 1159 if (!is_navigation_stream_request) { |
| 1169 if (!interceptor_info.starts_with.empty()) { | 1160 // Check if we have a registered interceptor for the headers passed in. If |
| 1170 call_interceptor = | 1161 // yes then we need to mark the current request as pending and wait for the |
| 1171 base::StartsWith(it.value(), interceptor_info.starts_with, | 1162 // interceptor to invoke the callback with a status code indicating whether |
| 1172 base::CompareCase::INSENSITIVE_ASCII); | 1163 // the request needs to be aborted or continued. |
| 1173 } | 1164 for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();) { |
| 1174 if (call_interceptor) { | 1165 HeaderInterceptorMap::iterator index = |
| 1175 interceptor_info.interceptor.Run( | 1166 http_header_interceptor_map_.find(it.name()); |
| 1176 it.name(), it.value(), child_id, resource_context, | 1167 if (index != http_header_interceptor_map_.end()) { |
| 1177 base::Bind(&ResourceDispatcherHostImpl::ContinuePendingBeginRequest, | 1168 HeaderInterceptorInfo& interceptor_info = index->second; |
| 1178 base::Unretained(this), requester_info, request_id, | 1169 |
| 1179 request_data, sync_result_handler, route_id, headers, | 1170 bool call_interceptor = true; |
| 1180 base::Passed(std::move(mojo_request)), | 1171 if (!interceptor_info.starts_with.empty()) { |
| 1181 base::Passed(std::move(url_loader_client)))); | 1172 call_interceptor = |
| 1182 return; | 1173 base::StartsWith(it.value(), interceptor_info.starts_with, |
| 1174 base::CompareCase::INSENSITIVE_ASCII); |
| 1175 } |
| 1176 if (call_interceptor) { |
| 1177 interceptor_info.interceptor.Run( |
| 1178 it.name(), it.value(), child_id, resource_context, |
| 1179 base::Bind( |
| 1180 &ResourceDispatcherHostImpl::ContinuePendingBeginRequest, |
| 1181 base::Unretained(this), requester_info, request_id, |
| 1182 request_data, sync_result_handler, route_id, headers, |
| 1183 base::Passed(std::move(mojo_request)), |
| 1184 base::Passed(std::move(url_loader_client)))); |
| 1185 return; |
| 1186 } |
| 1183 } | 1187 } |
| 1184 } | 1188 } |
| 1185 } | 1189 } |
| 1186 ContinuePendingBeginRequest( | 1190 ContinuePendingBeginRequest( |
| 1187 requester_info, request_id, request_data, sync_result_handler, route_id, | 1191 requester_info, request_id, request_data, sync_result_handler, route_id, |
| 1188 headers, std::move(mojo_request), std::move(url_loader_client), | 1192 headers, std::move(mojo_request), std::move(url_loader_client), |
| 1189 HeaderInterceptorResult::CONTINUE); | 1193 HeaderInterceptorResult::CONTINUE); |
| 1190 } | 1194 } |
| 1191 | 1195 |
| 1192 void ResourceDispatcherHostImpl::ContinuePendingBeginRequest( | 1196 void ResourceDispatcherHostImpl::ContinuePendingBeginRequest( |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1207 // in a non-content error code is not safe, but future header interceptors | 1211 // in a non-content error code is not safe, but future header interceptors |
| 1208 // might say to kill for reasons other than illegal origins. | 1212 // might say to kill for reasons other than illegal origins. |
| 1209 bad_message::ReceivedBadMessage(requester_info->filter(), | 1213 bad_message::ReceivedBadMessage(requester_info->filter(), |
| 1210 bad_message::RDH_ILLEGAL_ORIGIN); | 1214 bad_message::RDH_ILLEGAL_ORIGIN); |
| 1211 } | 1215 } |
| 1212 AbortRequestBeforeItStarts(requester_info->filter(), sync_result_handler, | 1216 AbortRequestBeforeItStarts(requester_info->filter(), sync_result_handler, |
| 1213 request_id, std::move(url_loader_client)); | 1217 request_id, std::move(url_loader_client)); |
| 1214 return; | 1218 return; |
| 1215 } | 1219 } |
| 1216 int child_id = requester_info->child_id(); | 1220 int child_id = requester_info->child_id(); |
| 1217 | 1221 storage::BlobStorageContext* blob_context = nullptr; |
| 1222 bool allow_download = false; |
| 1223 bool do_not_prompt_for_login = false; |
| 1224 bool report_raw_headers = false; |
| 1225 bool is_sync_load = !!sync_result_handler; |
| 1226 int load_flags = BuildLoadFlagsForRequest(request_data, is_sync_load); |
| 1218 bool is_navigation_stream_request = | 1227 bool is_navigation_stream_request = |
| 1219 IsBrowserSideNavigationEnabled() && | 1228 IsBrowserSideNavigationEnabled() && |
| 1220 IsResourceTypeFrame(request_data.resource_type); | 1229 IsResourceTypeFrame(request_data.resource_type); |
| 1221 | 1230 |
| 1222 ResourceContext* resource_context = NULL; | 1231 ResourceContext* resource_context = NULL; |
| 1223 net::URLRequestContext* request_context = NULL; | 1232 net::URLRequestContext* request_context = NULL; |
| 1224 requester_info->GetContexts(request_data.resource_type, &resource_context, | 1233 requester_info->GetContexts(request_data.resource_type, &resource_context, |
| 1225 &request_context); | 1234 &request_context); |
| 1226 | 1235 |
| 1227 // Allow the observer to block/handle the request. | 1236 // Allow the observer to block/handle the request. |
| 1228 if (delegate_ && !delegate_->ShouldBeginRequest(request_data.method, | 1237 if (delegate_ && !delegate_->ShouldBeginRequest(request_data.method, |
| 1229 request_data.url, | 1238 request_data.url, |
| 1230 request_data.resource_type, | 1239 request_data.resource_type, |
| 1231 resource_context)) { | 1240 resource_context)) { |
| 1232 AbortRequestBeforeItStarts(requester_info->filter(), sync_result_handler, | 1241 AbortRequestBeforeItStarts(requester_info->filter(), sync_result_handler, |
| 1233 request_id, std::move(url_loader_client)); | 1242 request_id, std::move(url_loader_client)); |
| 1234 return; | 1243 return; |
| 1235 } | 1244 } |
| 1236 | 1245 |
| 1237 // Construct the request. | 1246 // Construct the request. |
| 1238 std::unique_ptr<net::URLRequest> new_request = request_context->CreateRequest( | 1247 std::unique_ptr<net::URLRequest> new_request = request_context->CreateRequest( |
| 1239 is_navigation_stream_request ? request_data.resource_body_stream_url | 1248 is_navigation_stream_request ? request_data.resource_body_stream_url |
| 1240 : request_data.url, | 1249 : request_data.url, |
| 1241 request_data.priority, nullptr, kTrafficAnnotation); | 1250 request_data.priority, nullptr, kTrafficAnnotation); |
| 1242 | 1251 |
| 1243 // Log that this request is a service worker navigation preload request here, | 1252 if (is_navigation_stream_request) { |
| 1244 // since navigation preload machinery has no access to netlog. | 1253 // PlzNavigate: Always set the method to GET when gaining access to the |
| 1245 // TODO(falken): Figure out how mojom::URLLoaderClient can | 1254 // stream that contains the response body of a navigation. Otherwise the |
| 1246 // access the request's netlog. | 1255 // data that was already fetched by the browser will not be transmitted to |
| 1247 if (requester_info->IsNavigationPreload()) { | 1256 // the renderer. |
| 1248 new_request->net_log().AddEvent( | 1257 new_request->set_method("GET"); |
| 1249 net::NetLogEventType::SERVICE_WORKER_NAVIGATION_PRELOAD_REQUEST); | 1258 } else { |
| 1250 } | 1259 // Log that this request is a service worker navigation preload request |
| 1260 // here, since navigation preload machinery has no access to netlog. |
| 1261 // TODO(falken): Figure out how mojom::URLLoaderClient can |
| 1262 // access the request's netlog. |
| 1263 if (requester_info->IsNavigationPreload()) { |
| 1264 new_request->net_log().AddEvent( |
| 1265 net::NetLogEventType::SERVICE_WORKER_NAVIGATION_PRELOAD_REQUEST); |
| 1266 } |
| 1251 | 1267 |
| 1252 // PlzNavigate: Always set the method to GET when gaining access to the | |
| 1253 // stream that contains the response body of a navigation. Otherwise the data | |
| 1254 // that was already fetched by the browser will not be transmitted to the | |
| 1255 // renderer. | |
| 1256 if (is_navigation_stream_request) | |
| 1257 new_request->set_method("GET"); | |
| 1258 else | |
| 1259 new_request->set_method(request_data.method); | 1268 new_request->set_method(request_data.method); |
| 1260 | 1269 |
| 1261 new_request->set_first_party_for_cookies( | 1270 new_request->set_first_party_for_cookies( |
| 1262 request_data.first_party_for_cookies); | 1271 request_data.first_party_for_cookies); |
| 1263 | 1272 |
| 1264 // The initiator should normally be present, unless this is a navigation in a | 1273 // The initiator should normally be present, unless this is a navigation in |
| 1265 // top-level frame. It may be null for some top-level navigations (eg: | 1274 // a top-level frame. It may be null for some top-level navigations (eg: |
| 1266 // browser-initiated ones). | 1275 // browser-initiated ones). |
| 1267 DCHECK(request_data.request_initiator.has_value() || | 1276 DCHECK(request_data.request_initiator.has_value() || |
| 1268 request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME); | 1277 request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME); |
| 1269 new_request->set_initiator(request_data.request_initiator); | 1278 new_request->set_initiator(request_data.request_initiator); |
| 1270 | 1279 |
| 1271 if (request_data.originated_from_service_worker) { | 1280 if (request_data.originated_from_service_worker) { |
| 1272 new_request->SetUserData(URLRequestServiceWorkerData::kUserDataKey, | 1281 new_request->SetUserData(URLRequestServiceWorkerData::kUserDataKey, |
| 1273 base::MakeUnique<URLRequestServiceWorkerData>()); | 1282 base::MakeUnique<URLRequestServiceWorkerData>()); |
| 1274 } | 1283 } |
| 1275 | 1284 |
| 1276 // If the request is a MAIN_FRAME request, the first-party URL gets updated on | 1285 // If the request is a MAIN_FRAME request, the first-party URL gets updated |
| 1277 // redirects. | 1286 // on redirects. |
| 1278 if (request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME) { | 1287 if (request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME) { |
| 1279 new_request->set_first_party_url_policy( | 1288 new_request->set_first_party_url_policy( |
| 1280 net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT); | 1289 net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT); |
| 1281 } | 1290 } |
| 1282 | 1291 |
| 1283 // For PlzNavigate, this request has already been made and the referrer was | 1292 // For PlzNavigate, this request has already been made and the referrer was |
| 1284 // checked previously. So don't set the referrer for this stream request, or | 1293 // checked previously. So don't set the referrer for this stream request, or |
| 1285 // else it will fail for SSL redirects since net/ will think the blob:https | 1294 // else it will fail for SSL redirects since net/ will think the blob:https |
| 1286 // for the stream is not a secure scheme (specifically, in the call to | 1295 // for the stream is not a secure scheme (specifically, in the call to |
| 1287 // ComputeReferrerForRedirect). | 1296 // ComputeReferrerForRedirect). |
| 1288 if (!is_navigation_stream_request) { | |
| 1289 const Referrer referrer( | 1297 const Referrer referrer( |
| 1290 request_data.referrer, request_data.referrer_policy); | 1298 request_data.referrer, request_data.referrer_policy); |
| 1291 Referrer::SetReferrerForRequest(new_request.get(), referrer); | 1299 Referrer::SetReferrerForRequest(new_request.get(), referrer); |
| 1300 |
| 1301 new_request->SetExtraRequestHeaders(headers); |
| 1302 |
| 1303 blob_context = |
| 1304 GetBlobStorageContext(requester_info->blob_storage_context()); |
| 1305 // Resolve elements from request_body and prepare upload data. |
| 1306 if (request_data.request_body.get()) { |
| 1307 // |blob_context| could be null when the request is from the plugins |
| 1308 // because ResourceMessageFilters created in PluginProcessHost don't have |
| 1309 // the blob context. |
| 1310 if (blob_context) { |
| 1311 // Attaches the BlobDataHandles to request_body not to free the blobs |
| 1312 // and any attached shareable files until upload completion. These data |
| 1313 // will be used in UploadDataStream and ServiceWorkerURLRequestJob. |
| 1314 AttachRequestBodyBlobDataHandles(request_data.request_body.get(), |
| 1315 resource_context); |
| 1316 } |
| 1317 new_request->set_upload(UploadDataStreamBuilder::Build( |
| 1318 request_data.request_body.get(), blob_context, |
| 1319 requester_info->file_system_context(), |
| 1320 BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE).get())); |
| 1321 } |
| 1322 |
| 1323 allow_download = request_data.allow_download && |
| 1324 IsResourceTypeFrame(request_data.resource_type); |
| 1325 do_not_prompt_for_login = request_data.do_not_prompt_for_login; |
| 1326 |
| 1327 // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only |
| 1328 // allow requesting them if requester has ReadRawCookies permission. |
| 1329 ChildProcessSecurityPolicyImpl* policy = |
| 1330 ChildProcessSecurityPolicyImpl::GetInstance(); |
| 1331 report_raw_headers = request_data.report_raw_headers; |
| 1332 if (report_raw_headers && !policy->CanReadRawCookies(child_id) && |
| 1333 !requester_info->IsNavigationPreload()) { |
| 1334 // For navigation preload, the child_id is -1 so CanReadRawCookies would |
| 1335 // return false. But |report_raw_headers| of the navigation preload |
| 1336 // request was copied from the original request, so this check has already |
| 1337 // been carried out. |
| 1338 // TODO: crbug.com/523063 can we call bad_message::ReceivedBadMessage |
| 1339 // here? |
| 1340 VLOG(1) << "Denied unauthorized request for raw headers"; |
| 1341 report_raw_headers = false; |
| 1342 } |
| 1343 |
| 1344 if (request_data.resource_type == RESOURCE_TYPE_PREFETCH || |
| 1345 request_data.resource_type == RESOURCE_TYPE_FAVICON) { |
| 1346 do_not_prompt_for_login = true; |
| 1347 } |
| 1348 if (request_data.resource_type == RESOURCE_TYPE_IMAGE && |
| 1349 HTTP_AUTH_RELATION_BLOCKED_CROSS == |
| 1350 HttpAuthRelationTypeOf(request_data.url, |
| 1351 request_data.first_party_for_cookies)) { |
| 1352 // Prevent third-party image content from prompting for login, as this |
| 1353 // is often a scam to extract credentials for another domain from the |
| 1354 // user. Only block image loads, as the attack applies largely to the |
| 1355 // "src" property of the <img> tag. It is common for web properties to |
| 1356 // allow untrusted values for <img src>; this is considered a fair thing |
| 1357 // for an HTML sanitizer to do. Conversely, any HTML sanitizer that didn't |
| 1358 // filter sources for <script>, <link>, <embed>, <object>, <iframe> tags |
| 1359 // would be considered vulnerable in and of itself. |
| 1360 do_not_prompt_for_login = true; |
| 1361 load_flags |= net::LOAD_DO_NOT_USE_EMBEDDED_IDENTITY; |
| 1362 } |
| 1363 |
| 1364 // Sync loads should have maximum priority and should be the only |
| 1365 // requets that have the ignore limits flag set. |
| 1366 if (is_sync_load) { |
| 1367 DCHECK_EQ(request_data.priority, net::MAXIMUM_PRIORITY); |
| 1368 DCHECK_NE(load_flags & net::LOAD_IGNORE_LIMITS, 0); |
| 1369 } else { |
| 1370 DCHECK_EQ(load_flags & net::LOAD_IGNORE_LIMITS, 0); |
| 1371 } |
| 1292 } | 1372 } |
| 1293 | 1373 |
| 1294 new_request->SetExtraRequestHeaders(headers); | |
| 1295 | |
| 1296 storage::BlobStorageContext* blob_context = | |
| 1297 GetBlobStorageContext(requester_info->blob_storage_context()); | |
| 1298 // Resolve elements from request_body and prepare upload data. | |
| 1299 if (request_data.request_body.get()) { | |
| 1300 // |blob_context| could be null when the request is from the plugins because | |
| 1301 // ResourceMessageFilters created in PluginProcessHost don't have the blob | |
| 1302 // context. | |
| 1303 if (blob_context) { | |
| 1304 // Attaches the BlobDataHandles to request_body not to free the blobs and | |
| 1305 // any attached shareable files until upload completion. These data will | |
| 1306 // be used in UploadDataStream and ServiceWorkerURLRequestJob. | |
| 1307 AttachRequestBodyBlobDataHandles(request_data.request_body.get(), | |
| 1308 resource_context); | |
| 1309 } | |
| 1310 new_request->set_upload(UploadDataStreamBuilder::Build( | |
| 1311 request_data.request_body.get(), blob_context, | |
| 1312 requester_info->file_system_context(), | |
| 1313 BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE).get())); | |
| 1314 } | |
| 1315 | |
| 1316 bool allow_download = request_data.allow_download && | |
| 1317 IsResourceTypeFrame(request_data.resource_type); | |
| 1318 bool do_not_prompt_for_login = request_data.do_not_prompt_for_login; | |
| 1319 bool is_sync_load = !!sync_result_handler; | |
| 1320 | |
| 1321 // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only | |
| 1322 // allow requesting them if requester has ReadRawCookies permission. | |
| 1323 ChildProcessSecurityPolicyImpl* policy = | |
| 1324 ChildProcessSecurityPolicyImpl::GetInstance(); | |
| 1325 bool report_raw_headers = request_data.report_raw_headers; | |
| 1326 if (report_raw_headers && !policy->CanReadRawCookies(child_id) && | |
| 1327 !requester_info->IsNavigationPreload()) { | |
| 1328 // For navigation preload, the child_id is -1 so CanReadRawCookies would | |
| 1329 // return false. But |report_raw_headers| of the navigation preload request | |
| 1330 // was copied from the original request, so this check has already been | |
| 1331 // carried out. | |
| 1332 // TODO: crbug.com/523063 can we call bad_message::ReceivedBadMessage here? | |
| 1333 VLOG(1) << "Denied unauthorized request for raw headers"; | |
| 1334 report_raw_headers = false; | |
| 1335 } | |
| 1336 int load_flags = BuildLoadFlagsForRequest(request_data, is_sync_load); | |
| 1337 if (request_data.resource_type == RESOURCE_TYPE_PREFETCH || | |
| 1338 request_data.resource_type == RESOURCE_TYPE_FAVICON) { | |
| 1339 do_not_prompt_for_login = true; | |
| 1340 } | |
| 1341 if (request_data.resource_type == RESOURCE_TYPE_IMAGE && | |
| 1342 HTTP_AUTH_RELATION_BLOCKED_CROSS == | |
| 1343 HttpAuthRelationTypeOf(request_data.url, | |
| 1344 request_data.first_party_for_cookies)) { | |
| 1345 // Prevent third-party image content from prompting for login, as this | |
| 1346 // is often a scam to extract credentials for another domain from the user. | |
| 1347 // Only block image loads, as the attack applies largely to the "src" | |
| 1348 // property of the <img> tag. It is common for web properties to allow | |
| 1349 // untrusted values for <img src>; this is considered a fair thing for an | |
| 1350 // HTML sanitizer to do. Conversely, any HTML sanitizer that didn't | |
| 1351 // filter sources for <script>, <link>, <embed>, <object>, <iframe> tags | |
| 1352 // would be considered vulnerable in and of itself. | |
| 1353 do_not_prompt_for_login = true; | |
| 1354 load_flags |= net::LOAD_DO_NOT_USE_EMBEDDED_IDENTITY; | |
| 1355 } | |
| 1356 | |
| 1357 // Sync loads should have maximum priority and should be the only | |
| 1358 // requets that have the ignore limits flag set. | |
| 1359 if (is_sync_load) { | |
| 1360 DCHECK_EQ(request_data.priority, net::MAXIMUM_PRIORITY); | |
| 1361 DCHECK_NE(load_flags & net::LOAD_IGNORE_LIMITS, 0); | |
| 1362 } else { | |
| 1363 DCHECK_EQ(load_flags & net::LOAD_IGNORE_LIMITS, 0); | |
| 1364 } | |
| 1365 new_request->SetLoadFlags(load_flags); | 1374 new_request->SetLoadFlags(load_flags); |
| 1366 | 1375 |
| 1367 // Make extra info and read footer (contains request ID). | 1376 // Make extra info and read footer (contains request ID). |
| 1368 ResourceRequestInfoImpl* extra_info = new ResourceRequestInfoImpl( | 1377 ResourceRequestInfoImpl* extra_info = new ResourceRequestInfoImpl( |
| 1369 requester_info, route_id, | 1378 requester_info, route_id, |
| 1370 -1, // frame_tree_node_id | 1379 -1, // frame_tree_node_id |
| 1371 request_data.origin_pid, request_id, request_data.render_frame_id, | 1380 request_data.origin_pid, request_id, request_data.render_frame_id, |
| 1372 request_data.is_main_frame, request_data.parent_is_main_frame, | 1381 request_data.is_main_frame, request_data.parent_is_main_frame, |
| 1373 request_data.resource_type, request_data.transition_type, | 1382 request_data.resource_type, request_data.transition_type, |
| 1374 request_data.should_replace_current_entry, | 1383 request_data.should_replace_current_entry, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1388 | 1397 |
| 1389 if (new_request->url().SchemeIs(url::kBlobScheme)) { | 1398 if (new_request->url().SchemeIs(url::kBlobScheme)) { |
| 1390 // Hang on to a reference to ensure the blob is not released prior | 1399 // Hang on to a reference to ensure the blob is not released prior |
| 1391 // to the job being started. | 1400 // to the job being started. |
| 1392 storage::BlobProtocolHandler::SetRequestedBlobDataHandle( | 1401 storage::BlobProtocolHandler::SetRequestedBlobDataHandle( |
| 1393 new_request.get(), requester_info->blob_storage_context() | 1402 new_request.get(), requester_info->blob_storage_context() |
| 1394 ->context() | 1403 ->context() |
| 1395 ->GetBlobDataFromPublicURL(new_request->url())); | 1404 ->GetBlobDataFromPublicURL(new_request->url())); |
| 1396 } | 1405 } |
| 1397 | 1406 |
| 1398 // Initialize the service worker handler for the request. We don't use | 1407 std::unique_ptr<ResourceHandler> handler; |
| 1399 // ServiceWorker for synchronous loads to avoid renderer deadlocks. | 1408 if (is_navigation_stream_request) { |
| 1400 const ServiceWorkerMode service_worker_mode = | 1409 // PlzNavigate: do not add ResourceThrottles for main resource requests from |
| 1401 is_sync_load ? ServiceWorkerMode::NONE : request_data.service_worker_mode; | 1410 // the renderer. Decisions about the navigation should have been done in |
| 1402 ServiceWorkerRequestHandler::InitializeHandler( | 1411 // the initial request. |
| 1403 new_request.get(), requester_info->service_worker_context(), blob_context, | 1412 handler = CreateBaseResourceHandler( |
| 1404 child_id, request_data.service_worker_provider_id, | 1413 new_request.get(), std::move(mojo_request), |
| 1405 service_worker_mode != ServiceWorkerMode::ALL, | 1414 std::move(url_loader_client), request_data.resource_type); |
| 1406 request_data.fetch_request_mode, request_data.fetch_credentials_mode, | 1415 } else { |
| 1407 request_data.fetch_redirect_mode, request_data.resource_type, | 1416 // Initialize the service worker handler for the request. We don't use |
| 1408 request_data.fetch_request_context_type, request_data.fetch_frame_type, | 1417 // ServiceWorker for synchronous loads to avoid renderer deadlocks. |
| 1409 request_data.request_body); | 1418 const ServiceWorkerMode service_worker_mode = |
| 1419 is_sync_load ? ServiceWorkerMode::NONE |
| 1420 : request_data.service_worker_mode; |
| 1421 ServiceWorkerRequestHandler::InitializeHandler( |
| 1422 new_request.get(), requester_info->service_worker_context(), |
| 1423 blob_context, child_id, request_data.service_worker_provider_id, |
| 1424 service_worker_mode != ServiceWorkerMode::ALL, |
| 1425 request_data.fetch_request_mode, request_data.fetch_credentials_mode, |
| 1426 request_data.fetch_redirect_mode, request_data.resource_type, |
| 1427 request_data.fetch_request_context_type, request_data.fetch_frame_type, |
| 1428 request_data.request_body); |
| 1410 | 1429 |
| 1411 ForeignFetchRequestHandler::InitializeHandler( | 1430 ForeignFetchRequestHandler::InitializeHandler( |
| 1412 new_request.get(), requester_info->service_worker_context(), blob_context, | 1431 new_request.get(), requester_info->service_worker_context(), |
| 1413 child_id, request_data.service_worker_provider_id, service_worker_mode, | 1432 blob_context, child_id, request_data.service_worker_provider_id, |
| 1414 request_data.fetch_request_mode, request_data.fetch_credentials_mode, | 1433 service_worker_mode, request_data.fetch_request_mode, |
| 1415 request_data.fetch_redirect_mode, request_data.resource_type, | 1434 request_data.fetch_credentials_mode, request_data.fetch_redirect_mode, |
| 1416 request_data.fetch_request_context_type, request_data.fetch_frame_type, | 1435 request_data.resource_type, request_data.fetch_request_context_type, |
| 1417 request_data.request_body, request_data.initiated_in_secure_context); | 1436 request_data.fetch_frame_type, request_data.request_body, |
| 1437 request_data.initiated_in_secure_context); |
| 1418 | 1438 |
| 1419 // Have the appcache associate its extra info with the request. | 1439 // Have the appcache associate its extra info with the request. |
| 1420 AppCacheInterceptor::SetExtraRequestInfo( | 1440 AppCacheInterceptor::SetExtraRequestInfo( |
| 1421 new_request.get(), requester_info->appcache_service(), child_id, | 1441 new_request.get(), requester_info->appcache_service(), child_id, |
| 1422 request_data.appcache_host_id, request_data.resource_type, | 1442 request_data.appcache_host_id, request_data.resource_type, |
| 1423 request_data.should_reset_appcache); | 1443 request_data.should_reset_appcache); |
| 1424 | 1444 handler = CreateResourceHandler( |
| 1425 std::unique_ptr<ResourceHandler> handler(CreateResourceHandler( | 1445 requester_info.get(), new_request.get(), request_data, |
| 1426 requester_info.get(), new_request.get(), request_data, | 1446 sync_result_handler, route_id, child_id, resource_context, |
| 1427 sync_result_handler, route_id, child_id, resource_context, | 1447 std::move(mojo_request), std::move(url_loader_client)); |
| 1428 std::move(mojo_request), std::move(url_loader_client))); | 1448 } |
| 1429 | |
| 1430 if (handler) | 1449 if (handler) |
| 1431 BeginRequestInternal(std::move(new_request), std::move(handler)); | 1450 BeginRequestInternal(std::move(new_request), std::move(handler)); |
| 1432 } | 1451 } |
| 1433 | 1452 |
| 1434 std::unique_ptr<ResourceHandler> | 1453 std::unique_ptr<ResourceHandler> |
| 1435 ResourceDispatcherHostImpl::CreateResourceHandler( | 1454 ResourceDispatcherHostImpl::CreateResourceHandler( |
| 1436 ResourceRequesterInfo* requester_info, | 1455 ResourceRequesterInfo* requester_info, |
| 1437 net::URLRequest* request, | 1456 net::URLRequest* request, |
| 1438 const ResourceRequest& request_data, | 1457 const ResourceRequest& request_data, |
| 1439 const SyncLoadResultCallback& sync_result_handler, | 1458 const SyncLoadResultCallback& sync_result_handler, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1455 DCHECK(requester_info->IsRenderer()); | 1474 DCHECK(requester_info->IsRenderer()); |
| 1456 bad_message::ReceivedBadMessage(requester_info->filter(), | 1475 bad_message::ReceivedBadMessage(requester_info->filter(), |
| 1457 bad_message::RDH_BAD_DOWNLOAD); | 1476 bad_message::RDH_BAD_DOWNLOAD); |
| 1458 return std::unique_ptr<ResourceHandler>(); | 1477 return std::unique_ptr<ResourceHandler>(); |
| 1459 } | 1478 } |
| 1460 | 1479 |
| 1461 DCHECK(!mojo_request.is_pending()); | 1480 DCHECK(!mojo_request.is_pending()); |
| 1462 DCHECK(!url_loader_client); | 1481 DCHECK(!url_loader_client); |
| 1463 handler.reset(new SyncResourceHandler(request, sync_result_handler, this)); | 1482 handler.reset(new SyncResourceHandler(request, sync_result_handler, this)); |
| 1464 } else { | 1483 } else { |
| 1465 if (mojo_request.is_pending()) { | 1484 handler = CreateBaseResourceHandler(request, std::move(mojo_request), |
| 1466 handler.reset(new MojoAsyncResourceHandler(request, this, | 1485 std::move(url_loader_client), |
| 1467 std::move(mojo_request), | 1486 request_data.resource_type); |
| 1468 std::move(url_loader_client), | |
| 1469 request_data.resource_type)); | |
| 1470 } else { | |
| 1471 handler.reset(new AsyncResourceHandler(request, this)); | |
| 1472 } | |
| 1473 | 1487 |
| 1474 // The RedirectToFileResourceHandler depends on being next in the chain. | 1488 // The RedirectToFileResourceHandler depends on being next in the chain. |
| 1475 if (request_data.download_to_file) { | 1489 if (request_data.download_to_file) { |
| 1476 handler.reset( | 1490 handler.reset( |
| 1477 new RedirectToFileResourceHandler(std::move(handler), request)); | 1491 new RedirectToFileResourceHandler(std::move(handler), request)); |
| 1478 } | 1492 } |
| 1479 } | 1493 } |
| 1480 | 1494 |
| 1481 bool start_detached = request_data.download_to_network_cache_only; | 1495 bool start_detached = request_data.download_to_network_cache_only; |
| 1482 | 1496 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1495 } | 1509 } |
| 1496 | 1510 |
| 1497 std::unique_ptr<DetachableResourceHandler> detachable_handler = | 1511 std::unique_ptr<DetachableResourceHandler> detachable_handler = |
| 1498 base::MakeUnique<DetachableResourceHandler>(request, timeout, | 1512 base::MakeUnique<DetachableResourceHandler>(request, timeout, |
| 1499 std::move(handler)); | 1513 std::move(handler)); |
| 1500 if (start_detached) | 1514 if (start_detached) |
| 1501 detachable_handler->Detach(); | 1515 detachable_handler->Detach(); |
| 1502 handler = std::move(detachable_handler); | 1516 handler = std::move(detachable_handler); |
| 1503 } | 1517 } |
| 1504 | 1518 |
| 1505 // PlzNavigate: do not add ResourceThrottles for main resource requests from | |
| 1506 // the renderer. Decisions about the navigation should have been done in the | |
| 1507 // initial request. | |
| 1508 if (IsBrowserSideNavigationEnabled() && | |
| 1509 IsResourceTypeFrame(request_data.resource_type)) { | |
| 1510 DCHECK(request->url().SchemeIs(url::kBlobScheme)); | |
| 1511 return handler; | |
| 1512 } | |
| 1513 | |
| 1514 return AddStandardHandlers(request, request_data.resource_type, | 1519 return AddStandardHandlers(request, request_data.resource_type, |
| 1515 resource_context, | 1520 resource_context, |
| 1516 request_data.fetch_request_context_type, | 1521 request_data.fetch_request_context_type, |
| 1517 request_data.fetch_mixed_content_context_type, | 1522 request_data.fetch_mixed_content_context_type, |
| 1518 requester_info->appcache_service(), child_id, | 1523 requester_info->appcache_service(), child_id, |
| 1519 route_id, std::move(handler), nullptr, nullptr); | 1524 route_id, std::move(handler), nullptr, nullptr); |
| 1520 } | 1525 } |
| 1521 | 1526 |
| 1522 std::unique_ptr<ResourceHandler> | 1527 std::unique_ptr<ResourceHandler> |
| 1528 ResourceDispatcherHostImpl::CreateBaseResourceHandler( |
| 1529 net::URLRequest* request, |
| 1530 mojom::URLLoaderAssociatedRequest mojo_request, |
| 1531 mojom::URLLoaderClientPtr url_loader_client, |
| 1532 ResourceType resource_type) { |
| 1533 std::unique_ptr<ResourceHandler> handler; |
| 1534 if (mojo_request.is_pending()) { |
| 1535 handler.reset(new MojoAsyncResourceHandler( |
| 1536 request, this, std::move(mojo_request), std::move(url_loader_client), |
| 1537 resource_type)); |
| 1538 } else { |
| 1539 handler.reset(new AsyncResourceHandler(request, this)); |
| 1540 } |
| 1541 return handler; |
| 1542 } |
| 1543 |
| 1544 std::unique_ptr<ResourceHandler> |
| 1523 ResourceDispatcherHostImpl::AddStandardHandlers( | 1545 ResourceDispatcherHostImpl::AddStandardHandlers( |
| 1524 net::URLRequest* request, | 1546 net::URLRequest* request, |
| 1525 ResourceType resource_type, | 1547 ResourceType resource_type, |
| 1526 ResourceContext* resource_context, | 1548 ResourceContext* resource_context, |
| 1527 RequestContextType fetch_request_context_type, | 1549 RequestContextType fetch_request_context_type, |
| 1528 blink::WebMixedContentContextType fetch_mixed_content_context_type, | 1550 blink::WebMixedContentContextType fetch_mixed_content_context_type, |
| 1529 AppCacheService* appcache_service, | 1551 AppCacheService* appcache_service, |
| 1530 int child_id, | 1552 int child_id, |
| 1531 int route_id, | 1553 int route_id, |
| 1532 std::unique_ptr<ResourceHandler> handler, | 1554 std::unique_ptr<ResourceHandler> handler, |
| (...skipping 1070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2603 } | 2625 } |
| 2604 | 2626 |
| 2605 bool ResourceDispatcherHostImpl::ShouldServiceRequest( | 2627 bool ResourceDispatcherHostImpl::ShouldServiceRequest( |
| 2606 int child_id, | 2628 int child_id, |
| 2607 const ResourceRequest& request_data, | 2629 const ResourceRequest& request_data, |
| 2608 const net::HttpRequestHeaders& headers, | 2630 const net::HttpRequestHeaders& headers, |
| 2609 ResourceRequesterInfo* requester_info, | 2631 ResourceRequesterInfo* requester_info, |
| 2610 ResourceContext* resource_context) { | 2632 ResourceContext* resource_context) { |
| 2611 ChildProcessSecurityPolicyImpl* policy = | 2633 ChildProcessSecurityPolicyImpl* policy = |
| 2612 ChildProcessSecurityPolicyImpl::GetInstance(); | 2634 ChildProcessSecurityPolicyImpl::GetInstance(); |
| 2613 | 2635 bool is_navigation_stream_request = |
| 2636 IsBrowserSideNavigationEnabled() && |
| 2637 IsResourceTypeFrame(request_data.resource_type); |
| 2614 // Check if the renderer is permitted to request the requested URL. | 2638 // Check if the renderer is permitted to request the requested URL. |
| 2615 if (!policy->CanRequestURL(child_id, request_data.url)) { | 2639 // PlzNavigate: no need to check the URL here. The browser already picked the |
| 2640 // right renderer to send the request to. The original URL isn't used, as the |
| 2641 // renderer is fetching the stream URL. Checking the original URL doesn't work |
| 2642 // in case of redirects across schemes, since the original URL might not be |
| 2643 // granted to the final URL's renderer. |
| 2644 if (!is_navigation_stream_request && |
| 2645 !policy->CanRequestURL(child_id, request_data.url)) { |
| 2616 VLOG(1) << "Denied unauthorized request for " | 2646 VLOG(1) << "Denied unauthorized request for " |
| 2617 << request_data.url.possibly_invalid_spec(); | 2647 << request_data.url.possibly_invalid_spec(); |
| 2618 return false; | 2648 return false; |
| 2619 } | 2649 } |
| 2620 | 2650 |
| 2621 // Check if the renderer is using an illegal Origin header. If so, kill it. | 2651 // Check if the renderer is using an illegal Origin header. If so, kill it. |
| 2622 std::string origin_string; | 2652 std::string origin_string; |
| 2623 bool has_origin = | 2653 bool has_origin = |
| 2624 headers.GetHeader("Origin", &origin_string) && origin_string != "null"; | 2654 headers.GetHeader("Origin", &origin_string) && origin_string != "null"; |
| 2625 if (has_origin) { | 2655 if (has_origin) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2676 &throttles); | 2706 &throttles); |
| 2677 if (!throttles.empty()) { | 2707 if (!throttles.empty()) { |
| 2678 handler.reset(new ThrottlingResourceHandler(std::move(handler), request, | 2708 handler.reset(new ThrottlingResourceHandler(std::move(handler), request, |
| 2679 std::move(throttles))); | 2709 std::move(throttles))); |
| 2680 } | 2710 } |
| 2681 } | 2711 } |
| 2682 return handler; | 2712 return handler; |
| 2683 } | 2713 } |
| 2684 | 2714 |
| 2685 } // namespace content | 2715 } // namespace content |
| OLD | NEW |