Commit 08eac966 authored by Chase Phillips's avatar Chase Phillips Committed by Commit Bot

AppCache: code health improvements

* Update README.md with notes about where data model items are
  stored (db, disk/mem cache)

* Update comment to point to HandleResourceFetchCompleted

* Update section pointers for update spec items

At some point, the AppCache spec gained a new section such that
"6.9.4" became "7.9.4".  This updates any "6.9.4" entries to
"7.9.4".  In at least one place, there were other spec changes so
that the update steps within 7.9.4 also changed.  I've tried to
map them to the correct update step as best I could.

* Update spec pointers for 6.9.5/6.9.6 to 7.9.5/7.9.6

Bug: 1014587
Change-Id: I0a787bd1eae6f5ffbc84dff225d863e8dc80ffc6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1862124
Commit-Queue: Chase Phillips <cmp@chromium.org>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706319}
parent f6b1beac
...@@ -36,7 +36,7 @@ pages. ...@@ -36,7 +36,7 @@ pages.
AppCache aims for comparable ease by automatically updating its locally cached AppCache aims for comparable ease by automatically updating its locally cached
copy of the manifest and its resources whenever a page is visited. This comes copy of the manifest and its resources whenever a page is visited. This comes
with some significant caveats. with some significant caveats:
1. AppCache bails early in the update process if the manifest hasn't changed 1. AppCache bails early in the update process if the manifest hasn't changed
(byte for byte). This behavior is intended to save network bandwidth. (byte for byte). This behavior is intended to save network bandwidth.
...@@ -72,7 +72,7 @@ the same manifest, and therefore use the same cached resources. ...@@ -72,7 +72,7 @@ the same manifest, and therefore use the same cached resources.
Manifest sharing is particularly complex when combined with implicit caching. Manifest sharing is particularly complex when combined with implicit caching.
An AppCache manifest is not required to list the HTML pages that refer to it An AppCache manifest is not required to list the HTML pages that refer to it
via an `<html manifest>` attribute. (Listing the pages is however recommended.) via an `<html manifest>` attribute. (Listing the pages is however recommended.)
This allowance introduces the following complexities. This allowance introduces the following complexities:
1. When a browser encounters an HTML page that refers to a manifest it hasn't 1. When a browser encounters an HTML page that refers to a manifest it hasn't
seen before, the browser creates an implicit resource entry for the HTML seen before, the browser creates an implicit resource entry for the HTML
...@@ -109,13 +109,20 @@ downloading two manifests and all the resources associated with them. ...@@ -109,13 +109,20 @@ downloading two manifests and all the resources associated with them.
## Data Model ## Data Model
AppCache uses the following terms. AppCache uses the following terms:
* A **manifest** is a list of URLs to resources. The listed resources should be * A **manifest** is a list of URLs to resources. The listed resources should be
be sufficient for the page to be used while offline. be sufficient for the page to be used while offline.
* An **application cache** contains one version of a manifest and all the * An **application cache** contains one version of a manifest and all the
resources associated with it. This includes the resources explicitly listed in resources associated with it. This includes the resources explicitly listed in
the manifest, and the implicitly cached HTML pages that refer to the manifest. the manifest, and the implicitly cached HTML pages that refer to the manifest.
The HTTP responses are stored in a disk_cache (//net term), then all other
AppCache information is stored in a per-profile SQLite database that points
into the disk_cache. The disk_cache scope is per-profile.
* A **response** represents the headers and body for a given server response.
This response is first served by a server and may then be stored and retrieved
in the disk_cache. The application cache in the SQLite database updates each
entry to track the associated response id in the disk_cache for that entry.
* An **application cache group** is a collection of all the application caches * An **application cache group** is a collection of all the application caches
that have the same manifest. that have the same manifest.
* A **cache host** is a name used to refer to a Document (HTML page) when the * A **cache host** is a name used to refer to a Document (HTML page) when the
...@@ -124,14 +131,16 @@ AppCache uses the following terms. ...@@ -124,14 +131,16 @@ AppCache uses the following terms.
### Application Cache ### Application Cache
An application cache has the following components. An application cache has the following components:
1. **Entries** that identify resources to be cached. 1. **Entries** that identify resources to be cached.
2. **Namespaces** that direct the loading of sub-resource URLs for a page 2. **Namespaces** that direct the loading of sub-resource URLs for a page
associated with the cache. associated with the cache.
3. **Flags** that influence the cache's behavior. 3. **Flags** that influence the cache's behavior.
Entries have the following types. All of these components are stored in and retrieved from a SQLite database.
Entries have the following types:
* **manifest** - the AppCache manifest; the absolute URL of this entry is used * **manifest** - the AppCache manifest; the absolute URL of this entry is used
to identify the group that this application cache belongs to to identify the group that this application cache belongs to
...@@ -145,8 +154,11 @@ Explicit and fallback entries can also be marked as **foreign**. A foreign entry ...@@ -145,8 +154,11 @@ Explicit and fallback entries can also be marked as **foreign**. A foreign entry
indicates a document whose `<html manifest>` attribute does not point to this indicates a document whose `<html manifest>` attribute does not point to this
cache's manifest. cache's manifest.
Each entry can refer to its response, which allows AppCache to know where to
find a given entry's cached response data in its disk or memory cache.
Namespaces are conceptually patterns that match resource URLs. AppCache supports Namespaces are conceptually patterns that match resource URLs. AppCache supports
the following namespaces. the following namespaces:
* **fallback** - URLs matching the namespace are first fetched from the network. * **fallback** - URLs matching the namespace are first fetched from the network.
If the fetch fails, a cached fallback resource is used instead. Fallback If the fetch fails, a cached fallback resource is used instead. Fallback
...@@ -171,7 +183,7 @@ expressions that match URLs. This extension is invoked by adding the `isPattern` ...@@ -171,7 +183,7 @@ expressions that match URLs. This extension is invoked by adding the `isPattern`
keyword after the namespace in the manifest. keyword after the namespace in the manifest.
*** ***
An application cache has the following flags. An application cache has the following flags:
* **completeness** - the application cache is *complete* when all the resources * **completeness** - the application cache is *complete* when all the resources
in the manifest have been fetched and cached, and *incomplete* otherwise in the manifest have been fetched and cached, and *incomplete* otherwise
......
...@@ -179,7 +179,7 @@ void AppCacheHost::SelectCache(const GURL& document_url, ...@@ -179,7 +179,7 @@ void AppCacheHost::SelectCache(const GURL& document_url,
if (main_resource_blocked_) if (main_resource_blocked_)
OnContentBlocked(blocked_manifest_url_); OnContentBlocked(blocked_manifest_url_);
// 6.9.6 The application cache selection algorithm. // 7.9.5 The application cache selection algorithm.
// The algorithm is started here and continues in FinishCacheSelection, // The algorithm is started here and continues in FinishCacheSelection,
// after cache or group loading is complete. // after cache or group loading is complete.
// Note: Foreign entries are detected on the client side and // Note: Foreign entries are detected on the client side and
...@@ -469,7 +469,7 @@ void AppCacheHost::FinishCacheSelection( ...@@ -469,7 +469,7 @@ void AppCacheHost::FinishCacheSelection(
mojo::ReportBadMessageCallback bad_message_callback) { mojo::ReportBadMessageCallback bad_message_callback) {
DCHECK(!associated_cache()); DCHECK(!associated_cache());
// 6.9.6 The application cache selection algorithm // 7.9.5 The application cache selection algorithm
if (cache) { if (cache) {
// If document was loaded from an application cache, Associate document // If document was loaded from an application cache, Associate document
// with the application cache from which it was loaded. Invoke the // with the application cache from which it was loaded. Invoke the
......
...@@ -146,18 +146,18 @@ AppCacheJob* AppCacheRequestHandler::MaybeLoadFallbackForRedirect( ...@@ -146,18 +146,18 @@ AppCacheJob* AppCacheRequestHandler::MaybeLoadFallbackForRedirect(
std::unique_ptr<AppCacheJob> job; std::unique_ptr<AppCacheJob> job;
if (found_fallback_entry_.has_response_id()) { if (found_fallback_entry_.has_response_id()) {
// 6.9.6, step 4: If this results in a redirect to another origin, // 7.9.6, step 4: If this results in a redirect to another origin,
// get the resource of the fallback entry. // get the resource of the fallback entry.
job = CreateJob(network_delegate); job = CreateJob(network_delegate);
DeliverAppCachedResponse(found_fallback_entry_, found_cache_id_, DeliverAppCachedResponse(found_fallback_entry_, found_cache_id_,
found_manifest_url_, true, found_manifest_url_, true,
found_namespace_entry_url_); found_namespace_entry_url_);
} else if (!found_network_namespace_) { } else if (!found_network_namespace_) {
// 6.9.6, step 6: Fail the resource load. // 7.9.6, step 6: Fail the resource load.
job = CreateJob(network_delegate); job = CreateJob(network_delegate);
DeliverErrorResponse(); DeliverErrorResponse();
} else { } else {
// 6.9.6 step 3 and 5: Fetch the resource normally. // 7.9.6 step 3 and 5: Fetch the resource normally.
} }
return job.release(); return job.release();
...@@ -173,7 +173,7 @@ AppCacheJob* AppCacheRequestHandler::MaybeLoadFallbackForResponse( ...@@ -173,7 +173,7 @@ AppCacheJob* AppCacheRequestHandler::MaybeLoadFallbackForResponse(
return nullptr; return nullptr;
if (request_->IsCancelled()) { if (request_->IsCancelled()) {
// 6.9.6, step 4: But not if the user canceled the download. // 7.9.6, step 4: But not if the user canceled the download.
return nullptr; return nullptr;
} }
...@@ -201,7 +201,7 @@ AppCacheJob* AppCacheRequestHandler::MaybeLoadFallbackForResponse( ...@@ -201,7 +201,7 @@ AppCacheJob* AppCacheRequestHandler::MaybeLoadFallbackForResponse(
return nullptr; return nullptr;
} }
// 6.9.6, step 4: If this results in a 4xx or 5xx status code // 7.9.6, step 4: If this results in a 4xx or 5xx status code
// or there were network errors, get the resource of the fallback entry. // or there were network errors, get the resource of the fallback entry.
std::unique_ptr<AppCacheJob> job = CreateJob(network_delegate); std::unique_ptr<AppCacheJob> job = CreateJob(network_delegate);
...@@ -441,7 +441,7 @@ std::unique_ptr<AppCacheJob> AppCacheRequestHandler::MaybeLoadSubResource( ...@@ -441,7 +441,7 @@ std::unique_ptr<AppCacheJob> AppCacheRequestHandler::MaybeLoadSubResource(
} }
void AppCacheRequestHandler::ContinueMaybeLoadSubResource() { void AppCacheRequestHandler::ContinueMaybeLoadSubResource() {
// 6.9.6 Changes to the networking model // 7.9.6 Changes to the networking model
// If the resource is not to be fetched using the HTTP GET mechanism or // If the resource is not to be fetched using the HTTP GET mechanism or
// equivalent ... then fetch the resource normally. // equivalent ... then fetch the resource normally.
DCHECK(job_.get()); DCHECK(job_.get());
......
...@@ -81,9 +81,10 @@ bool CanUseExistingResource(const net::HttpResponseInfo* http_info) { ...@@ -81,9 +81,10 @@ bool CanUseExistingResource(const net::HttpResponseInfo* http_info) {
// 1) If a cached response contains a Last-Modified header, // 1) If a cached response contains a Last-Modified header,
// AppCacheUpdateJob::URLFetcher::AddConditionalHeaders() adds an // AppCacheUpdateJob::URLFetcher::AddConditionalHeaders() adds an
// If-Modified-Since header, so the server may return an HTTP 304 Not Modified // If-Modified-Since header, so the server may return an HTTP 304 Not Modified
// response. AppCacheUpdateJob::HandleUrlFetchCompleted() reuses the existing // response. AppCacheUpdateJob::HandleResourceFetchCompleted() reuses the
// cache entry when a 304 is received, even though the HTTP specification // existing cache entry when a 304 is received, even though the HTTP
// mandates updating the cached headers with the headers in the 304 response. // specification mandates updating the cached headers with the headers in the
// 304 response.
// //
// This deviation from the HTTP specification is Web-observable when AppCache // This deviation from the HTTP specification is Web-observable when AppCache
// resources are served with Last-Modified and Cache-Control: max-age headers. // resources are served with Last-Modified and Cache-Control: max-age headers.
...@@ -350,7 +351,7 @@ void AppCacheUpdateJob::HandleCacheFailure( ...@@ -350,7 +351,7 @@ void AppCacheUpdateJob::HandleCacheFailure(
const blink::mojom::AppCacheErrorDetails& error_details, const blink::mojom::AppCacheErrorDetails& error_details,
ResultType result, ResultType result,
const GURL& failed_resource_url) { const GURL& failed_resource_url) {
// 6.9.4 cache failure steps 2-8. // 7.9.4 cache failure steps 2-8.
DCHECK(internal_state_ != CACHE_FAILURE); DCHECK(internal_state_ != CACHE_FAILURE);
DCHECK(!error_details.message.empty()); DCHECK(!error_details.message.empty());
DCHECK(result != UPDATE_OK); DCHECK(result != UPDATE_OK);
...@@ -502,7 +503,7 @@ void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { ...@@ -502,7 +503,7 @@ void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) {
// Wait for pending master entries to download. // Wait for pending master entries to download.
FetchMasterEntries(); FetchMasterEntries();
MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps MaybeCompleteUpdate(); // if not done, run async 7.9.4 step 7 substeps
return; return;
} }
...@@ -526,7 +527,7 @@ void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { ...@@ -526,7 +527,7 @@ void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) {
return; return;
} }
// Proceed with update process. Section 6.9.4 steps 8-20. // Proceed with update process. Section 7.9.4 steps 8-20.
internal_state_ = DOWNLOADING; internal_state_ = DOWNLOADING;
inprogress_cache_ = inprogress_cache_ =
base::MakeRefCounted<AppCache>(storage_, storage_->NewCacheId()); base::MakeRefCounted<AppCache>(storage_, storage_->NewCacheId());
...@@ -605,7 +606,7 @@ void AppCacheUpdateJob::HandleResourceFetchCompleted(URLFetcher* url_fetcher, ...@@ -605,7 +606,7 @@ void AppCacheUpdateJob::HandleResourceFetchCompleted(URLFetcher* url_fetcher,
// if (!manifestAttribute) skip it // if (!manifestAttribute) skip it
// Foreign entries will be detected during cache selection. // Foreign entries will be detected during cache selection.
// Note: 6.9.4, step 17.9 possible optimization: if resource is HTML or XML // Note: 7.9.4, step 17.9 possible optimization: if resource is HTML or XML
// file whose root element is an html element with a manifest attribute // file whose root element is an html element with a manifest attribute
// whose value doesn't match the manifest url of the application cache // whose value doesn't match the manifest url of the application cache
// being processed, mark the entry as being foreign. // being processed, mark the entry as being foreign.
...@@ -707,7 +708,7 @@ void AppCacheUpdateJob::HandleNewMasterEntryFetchCompleted( ...@@ -707,7 +708,7 @@ void AppCacheUpdateJob::HandleNewMasterEntryFetchCompleted(
DCHECK(found != pending_master_entries_.end()); DCHECK(found != pending_master_entries_.end());
std::vector<AppCacheHost*>& hosts = found->second; std::vector<AppCacheHost*>& hosts = found->second;
// Section 6.9.4. No update case: step 7.3, else step 22. // Section 7.9.4. No update case: step 7.3, else step 22.
if (response_code / 100 == 2) { if (response_code / 100 == 2) {
// Add fetched master entry to the appropriate cache. // Add fetched master entry to the appropriate cache.
AppCache* cache = inprogress_cache_.get() ? inprogress_cache_.get() AppCache* cache = inprogress_cache_.get() ? inprogress_cache_.get()
...@@ -760,7 +761,7 @@ void AppCacheUpdateJob::HandleNewMasterEntryFetchCompleted( ...@@ -760,7 +761,7 @@ void AppCacheUpdateJob::HandleNewMasterEntryFetchCompleted(
pending_master_entries_.erase(found); pending_master_entries_.erase(found);
--master_entries_completed_; --master_entries_completed_;
// Section 6.9.4, step 22.3. // Section 7.9.4, step 22.3.
if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) {
HandleCacheFailure( HandleCacheFailure(
blink::mojom::AppCacheErrorDetails( blink::mojom::AppCacheErrorDetails(
...@@ -1086,7 +1087,7 @@ void AppCacheUpdateJob::AddUrlToFileList(const GURL& url, int type) { ...@@ -1086,7 +1087,7 @@ void AppCacheUpdateJob::AddUrlToFileList(const GURL& url, int type) {
void AppCacheUpdateJob::FetchUrls() { void AppCacheUpdateJob::FetchUrls() {
DCHECK_EQ(internal_state_, DOWNLOADING); DCHECK_EQ(internal_state_, DOWNLOADING);
// Fetch each URL in the list according to section 6.9.4 step 17.1-17.3. // Fetch each URL in the list according to section 7.9.4 step 18.1-18.3.
// Fetch up to the concurrent limit. Other fetches will be triggered as each // Fetch up to the concurrent limit. Other fetches will be triggered as each
// each fetch completes. // each fetch completes.
while (pending_url_fetches_.size() < kMaxConcurrentUrlFetches && while (pending_url_fetches_.size() < kMaxConcurrentUrlFetches &&
...@@ -1378,7 +1379,7 @@ void AppCacheUpdateJob::MaybeCompleteUpdate() { ...@@ -1378,7 +1379,7 @@ void AppCacheUpdateJob::MaybeCompleteUpdate() {
storage_->StoreEvictionTimes(group_); storage_->StoreEvictionTimes(group_);
} }
group_->SetUpdateAppCacheStatus(AppCacheGroup::IDLE); group_->SetUpdateAppCacheStatus(AppCacheGroup::IDLE);
// 6.9.4 steps 7.3-7.7. // 7.9.4 steps 7.3-7.7.
NotifyAllAssociatedHosts( NotifyAllAssociatedHosts(
blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT); blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT);
DiscardDuplicateResponses(); DiscardDuplicateResponses();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment