| Index: third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp | 
| diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp | 
| index 1816f8d687c68baf6db35b3566b50c292c224325..86806176d34dcc9843ad2a8e21bc7d446f8e0db3 100644 | 
| --- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp | 
| +++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp | 
| @@ -366,12 +366,50 @@ static std::unique_ptr<TracedValue> UrlForTraceEvent(const KURL& url) { | 
| return value; | 
| } | 
|  | 
| -Resource* ResourceFetcher::ResourceForStaticData( | 
| -    const FetchParameters& params, | 
| +Resource* ResourceFetcher::ResourceForStaticDataFromCache( | 
| +    const FetchParameters& request) { | 
| +  if (Resource* old_resource = GetMemoryCache()->ResourceForURL( | 
| +          request.GetResourceRequest().Url(), GetCacheIdentifier())) { | 
| +    // There's no reason to re-parse if we saved the data from the previous | 
| +    // parse. | 
| +    if (request.Options().data_buffering_policy != kDoNotBufferData) | 
| +      return old_resource; | 
| +    GetMemoryCache()->Remove(old_resource); | 
| +  } | 
| +  return nullptr; | 
| +} | 
| + | 
| +Resource* ResourceFetcher::ResourceForSubstituteData( | 
| +    const FetchParameters& request, | 
| const ResourceFactory& factory, | 
| const SubstituteData& substitute_data) { | 
| -  const KURL& url = params.GetResourceRequest().Url(); | 
| -  DCHECK(url.ProtocolIsData() || substitute_data.IsValid() || archive_); | 
| +  DCHECK(substitute_data.IsValid()); | 
| +  // TODO(arthursonzogni): should we use the cache? Even with substitute data? | 
| +  if (Resource* resource = ResourceForStaticDataFromCache(request)) { | 
| +    return resource; | 
| +  } | 
| + | 
| +  ResourceResponse response; | 
| +  RefPtr<SharedBuffer> data; | 
| +  data = substitute_data.Content(); | 
| +  response.SetURL(request.GetResourceRequest().Url()); | 
| +  response.SetMimeType(substitute_data.MimeType()); | 
| +  response.SetExpectedContentLength(data->size()); | 
| +  response.SetTextEncodingName(substitute_data.TextEncoding()); | 
| + | 
| +  return CreateResourceFromStaticData(request, factory, response, data, | 
| +                                      substitute_data); | 
| +} | 
| + | 
| +Resource* ResourceFetcher::ResourceForDataUrl( | 
| +    const FetchParameters& request, | 
| +    const ResourceFactory& factory, | 
| +    const SubstituteData& substitute_data) { | 
| +  const KURL& url = request.GetResourceRequest().Url(); | 
| +  DCHECK(url.ProtocolIsData()); | 
| +  if (Resource* resource = ResourceForStaticDataFromCache(request)) { | 
| +    return resource; | 
| +  } | 
|  | 
| // TODO(japhet): We only send main resource data: urls through WebURLLoader | 
| // for the benefit of a service worker test | 
| @@ -379,50 +417,63 @@ Resource* ResourceFetcher::ResourceForStaticData( | 
| // where it isn't easy to mock out a network load. It uses data: urls to | 
| // emulate the behavior it wants to test, which would otherwise be reserved | 
| // for network loads. | 
| -  if (!archive_ && !substitute_data.IsValid() && | 
| -      (factory.GetType() == Resource::kMainResource || | 
| -       factory.GetType() == Resource::kRaw)) | 
| +  if (factory.GetType() == Resource::kMainResource || | 
| +      factory.GetType() == Resource::kRaw) { | 
| return nullptr; | 
| - | 
| -  const String cache_identifier = GetCacheIdentifier(); | 
| -  if (Resource* old_resource = | 
| -          GetMemoryCache()->ResourceForURL(url, cache_identifier)) { | 
| -    // There's no reason to re-parse if we saved the data from the previous | 
| -    // parse. | 
| -    if (params.Options().data_buffering_policy != kDoNotBufferData) | 
| -      return old_resource; | 
| -    GetMemoryCache()->Remove(old_resource); | 
| } | 
|  | 
| ResourceResponse response; | 
| -  RefPtr<SharedBuffer> data; | 
| -  if (substitute_data.IsValid()) { | 
| -    data = substitute_data.Content(); | 
| -    response.SetURL(url); | 
| -    response.SetMimeType(substitute_data.MimeType()); | 
| -    response.SetExpectedContentLength(data->size()); | 
| -    response.SetTextEncodingName(substitute_data.TextEncoding()); | 
| -  } else if (url.ProtocolIsData()) { | 
| -    data = NetworkUtils::ParseDataURLAndPopulateResponse(url, response); | 
| -    if (!data) | 
| -      return nullptr; | 
| +  if (RefPtr<SharedBuffer> data = | 
| +          NetworkUtils::ParseDataURLAndPopulateResponse(url, response)) { | 
| // |response| is modified by parseDataURLAndPopulateResponse() and is | 
| // ready to be used. | 
| -  } else { | 
| -    ArchiveResource* archive_resource = | 
| -        archive_->SubresourceForURL(params.Url()); | 
| -    // Fall back to the network if the archive doesn't contain the resource. | 
| -    if (!archive_resource) | 
| -      return nullptr; | 
| -    data = archive_resource->Data(); | 
| +    Resource* resource = CreateResourceFromStaticData( | 
| +        request, factory, response, data, substitute_data); | 
| + | 
| +    GetMemoryCache()->Add(resource); | 
| +    return resource; | 
| +  } | 
| + | 
| +  return nullptr; | 
| +} | 
| + | 
| +Resource* ResourceFetcher::ResourceForArchive( | 
| +    const FetchParameters& request, | 
| +    const ResourceFactory& factory, | 
| +    const SubstituteData& substitute_data) { | 
| +  const KURL& url = request.GetResourceRequest().Url(); | 
| +  DCHECK(archive_); | 
| +  if (Resource* resource = ResourceForStaticDataFromCache(request)) { | 
| +    return resource; | 
| +  } | 
| + | 
| +  if (ArchiveResource* archive_resource = | 
| +          archive_->SubresourceForURL(request.Url())) { | 
| +    RefPtr<SharedBuffer> data = archive_resource->Data(); | 
| +    ResourceResponse response; | 
| response.SetURL(url); | 
| response.SetMimeType(archive_resource->MimeType()); | 
| response.SetExpectedContentLength(data->size()); | 
| response.SetTextEncodingName(archive_resource->TextEncoding()); | 
| + | 
| +    Resource* resource = CreateResourceFromStaticData( | 
| +        request, factory, response, data, substitute_data); | 
| + | 
| +    GetMemoryCache()->Add(resource); | 
| +    return resource; | 
| } | 
|  | 
| -  Resource* resource = factory.Create(params.GetResourceRequest(), | 
| -                                      params.Options(), params.Charset()); | 
| +  return nullptr; | 
| +} | 
| + | 
| +Resource* ResourceFetcher::CreateResourceFromStaticData( | 
| +    const FetchParameters& request, | 
| +    const ResourceFactory& factory, | 
| +    const ResourceResponse& response, | 
| +    const RefPtr<SharedBuffer>& data, | 
| +    const SubstituteData& substitute_data) { | 
| +  Resource* resource = factory.Create(request.GetResourceRequest(), | 
| +                                      request.Options(), request.Charset()); | 
| resource->SetNeedsSynchronousCacheHit(substitute_data.ForceSynchronousLoad()); | 
| // FIXME: We should provide a body stream here. | 
| resource->ResponseReceived(response, nullptr); | 
| @@ -430,12 +481,9 @@ Resource* ResourceFetcher::ResourceForStaticData( | 
| if (data->size()) | 
| resource->SetResourceBuffer(data); | 
| resource->SetIdentifier(CreateUniqueIdentifier()); | 
| -  resource->SetCacheIdentifier(cache_identifier); | 
| +  resource->SetCacheIdentifier(GetCacheIdentifier()); | 
| resource->Finish(); | 
|  | 
| -  if (!substitute_data.IsValid()) | 
| -    GetMemoryCache()->Add(resource); | 
| - | 
| return resource; | 
| } | 
|  | 
| @@ -556,7 +604,6 @@ Resource* ResourceFetcher::RequestResource( | 
| TRACE_EVENT1("blink", "ResourceFetcher::requestResource", "url", | 
| UrlForTraceEvent(params.Url())); | 
|  | 
| -  Resource* resource = nullptr; | 
| ResourceRequestBlockedReason blocked_reason = | 
| ResourceRequestBlockedReason::kNone; | 
|  | 
| @@ -574,17 +621,29 @@ Resource* ResourceFetcher::RequestResource( | 
| params.Options().initiator_info.name); | 
| } | 
|  | 
| +  Resource* resource = nullptr; | 
| bool is_data_url = resource_request.Url().ProtocolIsData(); | 
| bool is_static_data = is_data_url || substitute_data.IsValid() || archive_; | 
| -  if (is_static_data) { | 
| -    resource = ResourceForStaticData(params, factory, substitute_data); | 
| -    // Abort the request if the archive doesn't contain the resource, except in | 
| -    // the case of data URLs which might have resources such as fonts that need | 
| -    // to be decoded only on demand.  These data URLs are allowed to be | 
| + | 
| +  if (substitute_data.IsValid()) { | 
| +    resource = ResourceForSubstituteData(params, factory, substitute_data); | 
| +  } else if (is_data_url) { | 
| +    resource = ResourceForDataUrl(params, factory, substitute_data); | 
| +    // In the some cases, the data URLs might have resources such as fonts that | 
| +    // need to be decoded only on demand. These data URLs are allowed to be | 
| // processed using the normal ResourceFetcher machinery. | 
| -    if (!resource && !is_data_url && archive_) | 
| +  } else if (archive_) { | 
| +    resource = ResourceForArchive(params, factory, substitute_data); | 
| +    // TODO(arthursonzogni): In past version of ResourceForStaticData, when | 
| +    // there is an |archive_| but the resource is not found. It is stated: | 
| +    // "Fall back to the network if the archive doesn't contain the resource.", | 
| +    // but then the caller abort the request whatever happens: | 
| +    // "Abort the request if the archive doesn't contain the resource". | 
| +    // It is contradictory. | 
| +    if (!resource) | 
| return nullptr; | 
| } | 
| + | 
| if (!resource) { | 
| resource = | 
| GetMemoryCache()->ResourceForURL(params.Url(), GetCacheIdentifier()); | 
|  |