15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_request_handler.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_job.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "webkit/browser/appcache/appcache_backend_impl.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_policy.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_url_request_job.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace appcache { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheRequestHandler::AppCacheRequestHandler( 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppCacheHost* host, ResourceType::Type resource_type) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : host_(host), resource_type_(resource_type), 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_waiting_for_cache_selection_(false), found_group_id_(0), 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_cache_id_(0), found_network_namespace_(false), 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_entry_not_found_(false), maybe_load_resource_executed_(false) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(host_); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->AddObserver(this); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheRequestHandler::~AppCacheRequestHandler() { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host_) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage()->CancelDelegateCallbacks(this); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->RemoveObserver(this); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheStorage* AppCacheRequestHandler::storage() const { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(host_); 351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return host_->storage(); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadResource( 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequest* request, net::NetworkDelegate* network_delegate) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maybe_load_resource_executed_ = true; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!host_ || !IsSchemeAndMethodSupported(request) || cache_entry_not_found_) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This method can get called multiple times over the life 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of a request. The case we detect here is having scheduled 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // delivery of a "network response" using a job setup on an 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // earlier call thru this method. To send the request thru 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the network involves restarting the request altogether, 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which will call thru to our interception layer again. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This time thru, we return NULL so the request hits the wire. 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (job_.get()) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(job_->is_delivering_network_response() || 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_->cache_entry_not_found()); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (job_->cache_entry_not_found()) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_entry_not_found_ = true; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_ = NULL; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage()->CancelDelegateCallbacks(this); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear out our 'found' fields since we're starting a request for a 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new resource, any values in those fields are no longer valid. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_entry_ = AppCacheEntry(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_fallback_entry_ = AppCacheEntry(); 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) found_cache_id_ = kAppCacheNoCacheId; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_manifest_url_ = GURL(); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_network_namespace_ = false; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_main_resource()) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MaybeLoadMainResource(request, network_delegate); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MaybeLoadSubResource(request, network_delegate); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If its been setup to deliver a network response, we can just delete 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it now and return NULL instead to achieve that since it couldn't 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have been started yet. 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (job_.get() && job_->is_delivering_network_response()) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!job_->has_been_started()); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_ = NULL; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return job_.get(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadFallbackForRedirect( 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequest* request, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::NetworkDelegate* network_delegate, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& location) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!host_ || !IsSchemeAndMethodSupported(request) || cache_entry_not_found_) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_main_resource()) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(vabr) This is a temporary fix (see crbug/141114). We should get rid of 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it once a more general solution to crbug/121325 is in place. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!maybe_load_resource_executed_) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->url().GetOrigin() == location.GetOrigin()) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!job_.get()); // our jobs never generate redirects 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found_fallback_entry_.has_response_id()) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6.9.6, step 4: If this results in a redirect to another origin, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // get the resource of the fallback entry. 1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) job_ = new AppCacheURLRequestJob(request, network_delegate, 106effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch storage(), host_, is_main_resource()); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeliverAppCachedResponse( 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_fallback_entry_, found_cache_id_, found_group_id_, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_manifest_url_, true, found_namespace_entry_url_); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!found_network_namespace_) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6.9.6, step 6: Fail the resource load. 1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) job_ = new AppCacheURLRequestJob(request, network_delegate, 113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch storage(), host_, is_main_resource()); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeliverErrorResponse(); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6.9.6 step 3 and 5: Fetch the resource normally. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return job_.get(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadFallbackForResponse( 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequest* request, net::NetworkDelegate* network_delegate) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!host_ || !IsSchemeAndMethodSupported(request) || cache_entry_not_found_) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!found_fallback_entry_.has_response_id()) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->status().status() == net::URLRequestStatus::CANCELED) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6.9.6, step 4: But not if the user canceled the download. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't fallback for responses that we delivered. 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (job_.get()) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!job_->is_delivering_network_response()); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->status().is_success()) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int code_major = request->GetResponseCode() / 100; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (code_major !=4 && code_major != 5) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Servers can override the fallback behavior with a response header. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string kFallbackOverrideHeader( 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "x-chromium-appcache-fallback-override"); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string kFallbackOverrideValue( 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "disallow-fallback"); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string header_value; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->GetResponseHeaderByName(kFallbackOverrideHeader, &header_value); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_value == kFallbackOverrideValue) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6.9.6, step 4: If this results in a 4xx or 5xx status code 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or there were network errors, get the resource of the fallback entry. 1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) job_ = new AppCacheURLRequestJob(request, network_delegate, 159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch storage(), host_, is_main_resource()); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeliverAppCachedResponse( 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_fallback_entry_, found_cache_id_, found_group_id_, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_manifest_url_, true, found_namespace_entry_url_); 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return job_.get(); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppCacheRequestHandler::GetExtraResponseInfo( 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64* cache_id, GURL* manifest_url) { 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (job_.get() && job_->is_delivering_appcache_response()) { 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *cache_id = job_->cache_id(); 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *manifest_url = job_->manifest_url(); 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppCacheRequestHandler::PrepareForCrossSiteTransfer(int old_process_id) { 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!host_) 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppCacheBackendImpl* backend = host_->service()->GetBackend(old_process_id); 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) host_for_cross_site_transfer_ = backend->TransferHostOut(host_->host_id()); 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(host_, host_for_cross_site_transfer_.get()); 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppCacheRequestHandler::CompleteCrossSiteTransfer( 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int new_process_id, int new_host_id) { 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!host_for_cross_site_transfer_.get()) 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(host_, host_for_cross_site_transfer_.get()); 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppCacheBackendImpl* backend = host_->service()->GetBackend(new_process_id); 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend->TransferHostIn(new_host_id, host_for_cross_site_transfer_.Pass()); 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheRequestHandler::OnDestructionImminent(AppCacheHost* host) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage()->CancelDelegateCallbacks(this); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_ = NULL; // no need to RemoveObserver, the host is being deleted 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since the host is being deleted, we don't have to complete any job 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that is current running. It's destined for the bit bucket anyway. 197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (job_.get()) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_->Kill(); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_ = NULL; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheRequestHandler::DeliverAppCachedResponse( 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AppCacheEntry& entry, int64 cache_id, int64 group_id, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& manifest_url, bool is_fallback, 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& namespace_entry_url) { 207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(host_ && job_.get() && job_->is_waiting()); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(entry.has_response_id()); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ResourceType::IsFrame(resource_type_) && !namespace_entry_url.is_empty()) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->NotifyMainResourceIsNamespaceEntry(namespace_entry_url); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_->DeliverAppCachedResponse(manifest_url, group_id, cache_id, 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry, is_fallback); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheRequestHandler::DeliverErrorResponse() { 218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(job_.get() && job_->is_waiting()); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_->DeliverErrorResponse(); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheRequestHandler::DeliverNetworkResponse() { 223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(job_.get() && job_->is_waiting()); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_->DeliverNetworkResponse(); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Main-resource handling ---------------------------------------------- 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheRequestHandler::MaybeLoadMainResource( 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequest* request, net::NetworkDelegate* network_delegate) { 231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!job_.get()); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(host_); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AppCacheHost* spawning_host = 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceType::IsSharedWorker(resource_type_) ? 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_ : host_->GetSpawningHost(); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL preferred_manifest_url = spawning_host ? 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spawning_host->preferred_manifest_url() : GURL(); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We may have to wait for our storage query to complete, but 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this query can also complete syncrhonously. 2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) job_ = new AppCacheURLRequestJob(request, network_delegate, 243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch storage(), host_, is_main_resource()); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage()->FindResponseForMainRequest( 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->url(), preferred_manifest_url, this); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheRequestHandler::OnMainResponseFound( 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, const AppCacheEntry& entry, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& namespace_entry_url, const AppCacheEntry& fallback_entry, 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 cache_id, int64 group_id, const GURL& manifest_url) { 252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(job_.get()); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(host_); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(is_main_resource()); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!entry.IsForeign()); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fallback_entry.IsForeign()); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!(entry.has_response_id() && fallback_entry.has_response_id())); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!job_.get()) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppCachePolicy* policy = host_->service()->appcache_policy(); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_blocked_by_policy = !manifest_url.is_empty() && policy && 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !policy->CanLoadAppCache(manifest_url, host_->first_party_url()); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (was_blocked_by_policy) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ResourceType::IsFrame(resource_type_)) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->NotifyMainResourceBlocked(manifest_url); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ResourceType::IsSharedWorker(resource_type_)); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->frontend()->OnContentBlocked(host_->host_id(), manifest_url); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeliverNetworkResponse(); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (ResourceType::IsFrame(resource_type_) && cache_id != kAppCacheNoCacheId) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AppCacheHost loads and holds a reference to the main resource cache 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for two reasons, firstly to preload the cache into the working set 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in advance of subresource loads happening, secondly to prevent the 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AppCache from falling out of the working set on frame navigations. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->LoadMainResourceCache(cache_id); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->set_preferred_manifest_url(manifest_url); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6.11.1 Navigating across documents, steps 10 and 14. 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_entry_ = entry; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_namespace_entry_url_ = namespace_entry_url; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_fallback_entry_ = fallback_entry; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_cache_id_ = cache_id; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_group_id_ = group_id; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_manifest_url_ = manifest_url; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_network_namespace_ = false; // not applicable to main requests 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found_entry_.has_response_id()) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!found_fallback_entry_.has_response_id()); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeliverAppCachedResponse( 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_entry_, found_cache_id_, found_group_id_, found_manifest_url_, 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, found_namespace_entry_url_); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeliverNetworkResponse(); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sub-resource handling ---------------------------------------------- 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheRequestHandler::MaybeLoadSubResource( 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequest* request, net::NetworkDelegate* network_delegate) { 310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!job_.get()); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host_->is_selection_pending()) { 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have to wait until cache selection is complete and the 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // selected cache is loaded. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_waiting_for_cache_selection_ = true; 3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) job_ = new AppCacheURLRequestJob(request, network_delegate, 317effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch storage(), host_, is_main_resource()); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!host_->associated_cache() || 322effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch !host_->associated_cache()->is_complete() || 323effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch host_->associated_cache()->owning_group()->is_being_deleted()) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) job_ = new AppCacheURLRequestJob(request, network_delegate, 328effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch storage(), host_, is_main_resource()); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContinueMaybeLoadSubResource(); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheRequestHandler::ContinueMaybeLoadSubResource() { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6.9.6 Changes to the networking model 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the resource is not to be fetched using the HTTP GET mechanism or 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // equivalent ... then fetch the resource normally. 336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(job_.get()); 337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(host_->associated_cache() && host_->associated_cache()->is_complete()); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url = job_->request()->url(); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppCache* cache = host_->associated_cache(); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage()->FindResponseForSubRequest( 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->associated_cache(), url, 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &found_entry_, &found_fallback_entry_, &found_network_namespace_); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found_entry_.has_response_id()) { 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Step 2: If there's an entry, get it instead. 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!found_network_namespace_ && 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !found_fallback_entry_.has_response_id()); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_cache_id_ = cache->cache_id(); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_group_id_ = cache->owning_group()->group_id(); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_manifest_url_ = cache->owning_group()->manifest_url(); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeliverAppCachedResponse( 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_entry_, found_cache_id_, found_group_id_, found_manifest_url_, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, GURL()); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found_fallback_entry_.has_response_id()) { 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Step 4: Fetch the resource normally, if this results 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in certain conditions, then use the fallback. 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!found_network_namespace_ && 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !found_entry_.has_response_id()); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_cache_id_ = cache->cache_id(); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_manifest_url_ = cache->owning_group()->manifest_url(); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeliverNetworkResponse(); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found_network_namespace_) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Step 3 and 5: Fetch the resource normally. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!found_entry_.has_response_id() && 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !found_fallback_entry_.has_response_id()); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeliverNetworkResponse(); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Step 6: Fail the resource load. 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeliverErrorResponse(); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheRequestHandler::OnCacheSelectionComplete(AppCacheHost* host) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(host == host_); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_main_resource()) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_waiting_for_cache_selection_) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_waiting_for_cache_selection_ = false; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!host_->associated_cache() || 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !host_->associated_cache()->is_complete()) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeliverNetworkResponse(); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContinueMaybeLoadSubResource(); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace appcache 400