/*
    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
    Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
    Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
    Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
    rights reserved.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "third_party/blink/renderer/platform/loader/fetch/resource.h"

#include <stdint.h>

#include <algorithm>
#include <cassert>
#include <memory>

#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instance_counters.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_client_walker.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_finish_observer.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"

namespace blink {

namespace {

void NotifyFinishObservers(
    HeapHashSet<WeakMember<ResourceFinishObserver>>* observers) {
  for (const auto& observer : *observers)
    observer->NotifyFinished();
}

}  // namespace

// These response headers are not copied from a revalidated response to the
// cached response headers. For compatibility, this list is based on Chromium's
// net/http/http_response_headers.cc.
const char* const kHeadersToIgnoreAfterRevalidation[] = {
    "allow",
    "connection",
    "etag",
    "expires",
    "keep-alive",
    "last-modified",
    "proxy-authenticate",
    "proxy-connection",
    "trailer",
    "transfer-encoding",
    "upgrade",
    "www-authenticate",
    "x-frame-options",
    "x-xss-protection",
};

// Some header prefixes mean "Don't copy this header from a 304 response.".
// Rather than listing all the relevant headers, we can consolidate them into
// this list, also grabbed from Chromium's net/http/http_response_headers.cc.
const char* const kHeaderPrefixesToIgnoreAfterRevalidation[] = {
    "content-", "x-content-", "x-webkit-"};

static inline bool ShouldUpdateHeaderAfterRevalidation(
    const AtomicString& header) {
  for (size_t i = 0; i < arraysize(kHeadersToIgnoreAfterRevalidation); i++) {
    if (DeprecatedEqualIgnoringCase(header,
                                    kHeadersToIgnoreAfterRevalidation[i]))
      return false;
  }
  for (size_t i = 0; i < arraysize(kHeaderPrefixesToIgnoreAfterRevalidation);
       i++) {
    if (header.StartsWithIgnoringASCIICase(
            kHeaderPrefixesToIgnoreAfterRevalidation[i]))
      return false;
  }
  return true;
}

// This is a CachedMetadataSender implementation for normal responses.
class CachedMetadataSenderImpl : public CachedMetadataSender {
 public:
  CachedMetadataSenderImpl(const Resource*);
  ~CachedMetadataSenderImpl() override = default;

  void Send(const char*, size_t) override;
  bool IsServedFromCacheStorage() override { return false; }

 private:
  const KURL response_url_;
  const Time response_time_;
};

CachedMetadataSenderImpl::CachedMetadataSenderImpl(const Resource* resource)
    : response_url_(resource->GetResponse().Url()),
      response_time_(resource->GetResponse().ResponseTime()) {
  DCHECK(resource->GetResponse().CacheStorageCacheName().IsNull());
}

void CachedMetadataSenderImpl::Send(const char* data, size_t size) {
  Platform::Current()->CacheMetadata(response_url_, response_time_, data, size);
}

// This is a CachedMetadataSender implementation that does nothing.
class NullCachedMetadataSender : public CachedMetadataSender {
 public:
  NullCachedMetadataSender() = default;
  ~NullCachedMetadataSender() override = default;

  void Send(const char*, size_t) override {}
  bool IsServedFromCacheStorage() override { return false; }
};

// This is a CachedMetadataSender implementation for responses that are served
// by a ServiceWorker from cache storage.
class ServiceWorkerCachedMetadataSender : public CachedMetadataSender {
 public:
  ServiceWorkerCachedMetadataSender(const Resource*, const SecurityOrigin*);
  ~ServiceWorkerCachedMetadataSender() override = default;

  void Send(const char*, size_t) override;
  bool IsServedFromCacheStorage() override { return true; }

 private:
  const KURL response_url_;
  const Time response_time_;
  const String cache_storage_cache_name_;
  scoped_refptr<const SecurityOrigin> security_origin_;
};

ServiceWorkerCachedMetadataSender::ServiceWorkerCachedMetadataSender(
    const Resource* resource,
    const SecurityOrigin* security_origin)
    : response_url_(resource->GetResponse().Url()),
      response_time_(resource->GetResponse().ResponseTime()),
      cache_storage_cache_name_(
          resource->GetResponse().CacheStorageCacheName()),
      security_origin_(security_origin) {
  DCHECK(!cache_storage_cache_name_.IsNull());
}

void ServiceWorkerCachedMetadataSender::Send(const char* data, size_t size) {
  Platform::Current()->CacheMetadataInCacheStorage(
      response_url_, response_time_, data, size,
      WebSecurityOrigin(security_origin_), cache_storage_cache_name_);
}

Resource::Resource(const ResourceRequest& request,
                   Type type,
                   const ResourceLoaderOptions& options)
    : type_(type),
      status_(ResourceStatus::kNotStarted),
      load_finish_time_(0),
      identifier_(0),
      preload_discovery_time_(0.0),
      encoded_size_(0),
      encoded_size_memory_usage_(0),
      decoded_size_(0),
      overhead_size_(CalculateOverheadSize()),
      cache_identifier_(MemoryCache::DefaultCacheIdentifier()),
      link_preload_(false),
      is_revalidating_(false),
      is_alive_(false),
      is_add_remove_client_prohibited_(false),
      integrity_disposition_(ResourceIntegrityDisposition::kNotChecked),
      options_(options),
      response_timestamp_(CurrentTime()),
      resource_request_(request) {
  InstanceCounters::IncrementCounter(InstanceCounters::kResourceCounter);

  if (IsMainThread())
    MemoryCoordinator::Instance().RegisterClient(this);
}

Resource::~Resource() {
  InstanceCounters::DecrementCounter(InstanceCounters::kResourceCounter);
}

void Resource::Trace(blink::Visitor* visitor) {
  visitor->Trace(loader_);
  visitor->Trace(cache_handler_);
  visitor->Trace(clients_);
  visitor->Trace(clients_awaiting_callback_);
  visitor->Trace(finished_clients_);
  visitor->Trace(finish_observers_);
  MemoryCoordinatorClient::Trace(visitor);
}

void Resource::SetLoader(ResourceLoader* loader) {
  CHECK(!loader_);
  DCHECK(StillNeedsLoad());
  loader_ = loader;
  status_ = ResourceStatus::kPending;
}

void Resource::CheckResourceIntegrity() {
  // Skip the check and reuse the previous check result, especially on
  // successful revalidation.
  if (IntegrityDisposition() != ResourceIntegrityDisposition::kNotChecked)
    return;

  // Loading error occurred? Then result is uncheckable.
  integrity_report_info_.Clear();
  if (ErrorOccurred()) {
    CHECK(!Data());
    integrity_disposition_ = ResourceIntegrityDisposition::kFailed;
    return;
  }

  // No integrity attributes to check? Then we're passing.
  if (IntegrityMetadata().IsEmpty()) {
    integrity_disposition_ = ResourceIntegrityDisposition::kPassed;
    return;
  }

  const char* data = nullptr;
  size_t data_length = 0;

  // Edge case: If a resource actually has zero bytes then it will not
  // typically have a resource buffer, but we still need to check integrity
  // because people might want to assert a zero-length resource.
  CHECK(DecodedSize() == 0 || Data());
  if (Data()) {
    data = Data()->Data();
    data_length = Data()->size();
  }

  if (SubresourceIntegrity::CheckSubresourceIntegrity(IntegrityMetadata(), data,
                                                      data_length, Url(), *this,
                                                      integrity_report_info_))
    integrity_disposition_ = ResourceIntegrityDisposition::kPassed;
  else
    integrity_disposition_ = ResourceIntegrityDisposition::kFailed;
  DCHECK_NE(IntegrityDisposition(), ResourceIntegrityDisposition::kNotChecked);
}

void Resource::NotifyFinished() {
  DCHECK(IsLoaded());

  ResourceClientWalker<ResourceClient> w(clients_);
  while (ResourceClient* c = w.Next()) {
    MarkClientFinished(c);
    c->NotifyFinished(this);
  }
}

void Resource::MarkClientFinished(ResourceClient* client) {
  if (clients_.Contains(client)) {
    finished_clients_.insert(client);
    clients_.erase(client);
  }
}

void Resource::AppendData(const char* data, size_t length) {
  TRACE_EVENT0("blink", "Resource::appendData");
  DCHECK(!is_revalidating_);
  DCHECK(!ErrorOccurred());
  if (options_.data_buffering_policy == kBufferData) {
    if (data_)
      data_->Append(data, length);
    else
      data_ = SharedBuffer::Create(data, length);
    SetEncodedSize(data_->size());
  }
  ResourceClientWalker<ResourceClient> w(Clients());
  while (ResourceClient* c = w.Next())
    c->DataReceived(this, data, length);
}

void Resource::SetResourceBuffer(scoped_refptr<SharedBuffer> resource_buffer) {
  DCHECK(!is_revalidating_);
  DCHECK(!ErrorOccurred());
  DCHECK_EQ(options_.data_buffering_policy, kBufferData);
  data_ = std::move(resource_buffer);
  SetEncodedSize(data_->size());
}

void Resource::ClearData() {
  data_ = nullptr;
  encoded_size_memory_usage_ = 0;
}

void Resource::TriggerNotificationForFinishObservers(
    base::SingleThreadTaskRunner* task_runner) {
  if (finish_observers_.IsEmpty())
    return;

  auto* new_collections = new HeapHashSet<WeakMember<ResourceFinishObserver>>(
      std::move(finish_observers_));
  finish_observers_.clear();

  task_runner->PostTask(FROM_HERE, WTF::Bind(&NotifyFinishObservers,
                                             WrapPersistent(new_collections)));

  DidRemoveClientOrObserver();
}

void Resource::SetDataBufferingPolicy(
    DataBufferingPolicy data_buffering_policy) {
  options_.data_buffering_policy = data_buffering_policy;
  ClearData();
  SetEncodedSize(0);
}

void Resource::FinishAsError(const ResourceError& error,
                             base::SingleThreadTaskRunner* task_runner) {
  error_ = error;
  is_revalidating_ = false;

  if (IsMainThread())
    GetMemoryCache()->Remove(this);

  if (!ErrorOccurred())
    SetStatus(ResourceStatus::kLoadError);
  DCHECK(ErrorOccurred());
  ClearData();
  loader_ = nullptr;
  CheckResourceIntegrity();
  TriggerNotificationForFinishObservers(task_runner);
  NotifyFinished();
}

void Resource::Finish(double load_finish_time,
                      base::SingleThreadTaskRunner* task_runner) {
  DCHECK(!is_revalidating_);
  load_finish_time_ = load_finish_time;
  if (!ErrorOccurred())
    status_ = ResourceStatus::kCached;
  loader_ = nullptr;
  CheckResourceIntegrity();
  TriggerNotificationForFinishObservers(task_runner);
  NotifyFinished();
}

AtomicString Resource::HttpContentType() const {
  return GetResponse().HttpContentType();
}

bool Resource::PassesAccessControlCheck(
    const SecurityOrigin& security_origin) const {
  base::Optional<network::mojom::CORSError> cors_error = CORS::CheckAccess(
      GetResponse().Url(), GetResponse().HttpStatusCode(),
      GetResponse().HttpHeaderFields(),
      LastResourceRequest().GetFetchCredentialsMode(), security_origin);

  return !cors_error;
}

bool Resource::MustRefetchDueToIntegrityMetadata(
    const FetchParameters& params) const {
  if (params.IntegrityMetadata().IsEmpty())
    return false;

  return !IntegrityMetadata::SetsEqual(IntegrityMetadata(),
                                       params.IntegrityMetadata());
}

static double CurrentAge(const ResourceResponse& response,
                         double response_timestamp) {
  // RFC2616 13.2.3
  // No compensation for latency as that is not terribly important in practice
  double date_value = response.Date();
  double apparent_age = std::isfinite(date_value)
                            ? std::max(0., response_timestamp - date_value)
                            : 0;
  double age_value = response.Age();
  double corrected_received_age = std::isfinite(age_value)
                                      ? std::max(apparent_age, age_value)
                                      : apparent_age;
  double resident_time = CurrentTime() - response_timestamp;
  return corrected_received_age + resident_time;
}

static double FreshnessLifetime(const ResourceResponse& response,
                                double response_timestamp) {
#if !defined(OS_ANDROID)
  // On desktop, local files should be reloaded in case they change.
  if (response.Url().IsLocalFile())
    return 0;
#endif

  // Cache other non-http / non-filesystem resources liberally.
  if (!response.Url().ProtocolIsInHTTPFamily() &&
      !response.Url().ProtocolIs("filesystem"))
    return std::numeric_limits<double>::max();

  // RFC2616 13.2.4
  double max_age_value = response.CacheControlMaxAge();
  if (std::isfinite(max_age_value))
    return max_age_value;
  double expires_value = response.Expires();
  double date_value = response.Date();
  double creation_time =
      std::isfinite(date_value) ? date_value : response_timestamp;
  if (std::isfinite(expires_value))
    return expires_value - creation_time;
  double last_modified_value = response.LastModified();
  if (std::isfinite(last_modified_value))
    return (creation_time - last_modified_value) * 0.1;
  // If no cache headers are present, the specification leaves the decision to
  // the UA. Other browsers seem to opt for 0.
  return 0;
}

static bool CanUseResponse(const ResourceResponse& response,
                           double response_timestamp) {
  if (response.IsNull())
    return false;

  if (response.CacheControlContainsNoCache() ||
      response.CacheControlContainsNoStore())
    return false;

  if (response.HttpStatusCode() == 303) {
    // Must not be cached.
    return false;
  }

  if (response.HttpStatusCode() == 302 || response.HttpStatusCode() == 307) {
    // Default to not cacheable unless explicitly allowed.
    bool has_max_age = std::isfinite(response.CacheControlMaxAge());
    bool has_expires = std::isfinite(response.Expires());
    // TODO: consider catching Cache-Control "private" and "public" here.
    if (!has_max_age && !has_expires)
      return false;
  }

  return CurrentAge(response, response_timestamp) <=
         FreshnessLifetime(response, response_timestamp);
}

const ResourceRequest& Resource::LastResourceRequest() const {
  if (!redirect_chain_.size())
    return GetResourceRequest();
  return redirect_chain_.back().request_;
}

void Resource::SetRevalidatingRequest(const ResourceRequest& request) {
  SECURITY_CHECK(redirect_chain_.IsEmpty());
  SECURITY_CHECK(!is_unused_preload_);
  DCHECK(!request.IsNull());
  CHECK(!is_revalidation_start_forbidden_);
  is_revalidating_ = true;
  resource_request_ = request;
  status_ = ResourceStatus::kNotStarted;
}

bool Resource::WillFollowRedirect(const ResourceRequest& new_request,
                                  const ResourceResponse& redirect_response) {
  if (is_revalidating_)
    RevalidationFailed();
  redirect_chain_.push_back(RedirectPair(new_request, redirect_response));
  return true;
}

void Resource::SetResponse(const ResourceResponse& response) {
  response_ = response;

  // Currently we support the metadata caching only for HTTP family.
  if (!GetResourceRequest().Url().ProtocolIsInHTTPFamily() ||
      !GetResponse().Url().ProtocolIsInHTTPFamily()) {
    cache_handler_.Clear();
    return;
  }

  cache_handler_ = CreateCachedMetadataHandler(CreateCachedMetadataSender());
}

std::unique_ptr<CachedMetadataSender> Resource::CreateCachedMetadataSender()
    const {
  if (GetResponse().WasFetchedViaServiceWorker()) {
    // TODO(leszeks): Check whether it's correct that the source_origin can be
    // null.
    if (!source_origin_ || GetResponse().CacheStorageCacheName().IsNull()) {
      return std::make_unique<NullCachedMetadataSender>();
    }
    return std::make_unique<ServiceWorkerCachedMetadataSender>(
        this, source_origin_.get());
  }
  return std::make_unique<CachedMetadataSenderImpl>(this);
}

void Resource::ResponseReceived(const ResourceResponse& response,
                                std::unique_ptr<WebDataConsumerHandle>) {
  response_timestamp_ = CurrentTime();
  if (preload_discovery_time_) {
    int time_since_discovery = static_cast<int>(
        1000 * (CurrentTimeTicksInSeconds() - preload_discovery_time_));
    DEFINE_STATIC_LOCAL(CustomCountHistogram,
                        preload_discovery_to_first_byte_histogram,
                        ("PreloadScanner.TTFB", 0, 10000, 50));
    preload_discovery_to_first_byte_histogram.Count(time_since_discovery);
  }

  if (is_revalidating_) {
    if (response.HttpStatusCode() == 304) {
      RevalidationSucceeded(response);
      return;
    }
    RevalidationFailed();
  }
  SetResponse(response);
  String encoding = response.TextEncodingName();
  if (!encoding.IsNull())
    SetEncoding(encoding);
}

void Resource::SetSerializedCachedMetadata(const char* data, size_t size) {
  DCHECK(!is_revalidating_);
  DCHECK(!GetResponse().IsNull());
}

String Resource::ReasonNotDeletable() const {
  StringBuilder builder;
  if (HasClientsOrObservers()) {
    builder.Append("hasClients(");
    builder.AppendNumber(clients_.size());
    if (!clients_awaiting_callback_.IsEmpty()) {
      builder.Append(", AwaitingCallback=");
      builder.AppendNumber(clients_awaiting_callback_.size());
    }
    if (!finished_clients_.IsEmpty()) {
      builder.Append(", Finished=");
      builder.AppendNumber(finished_clients_.size());
    }
    builder.Append(')');
  }
  if (loader_) {
    if (!builder.IsEmpty())
      builder.Append(' ');
    builder.Append("loader_");
  }
  if (IsMainThread() && GetMemoryCache()->Contains(this)) {
    if (!builder.IsEmpty())
      builder.Append(' ');
    builder.Append("in_memory_cache");
  }
  return builder.ToString();
}

void Resource::DidAddClient(ResourceClient* c) {
  if (scoped_refptr<SharedBuffer> data = Data()) {
    data->ForEachSegment([this, &c](const char* segment, size_t segment_size,
                                    size_t segment_offset) -> bool {
      c->DataReceived(this, segment, segment_size);

      // Stop pushing data if the client removed itself.
      return HasClient(c);
    });
  }
  if (!HasClient(c))
    return;
  if (IsLoaded()) {
    c->NotifyFinished(this);
    if (clients_.Contains(c)) {
      finished_clients_.insert(c);
      clients_.erase(c);
    }
  }
}

static bool TypeNeedsSynchronousCacheHit(Resource::Type type) {
  // Some resources types default to return data synchronously. For most of
  // these, it's because there are layout tests that expect data to return
  // synchronously in case of cache hit. In the case of fonts, there was a
  // performance regression.
  // FIXME: Get to the point where we don't need to special-case sync/async
  // behavior for different resource types.
  if (type == Resource::kCSSStyleSheet)
    return true;
  if (type == Resource::kScript)
    return true;
  if (type == Resource::kFont)
    return true;
  return false;
}

void Resource::WillAddClientOrObserver() {
  if (!HasClientsOrObservers()) {
    is_alive_ = true;
  }
}

void Resource::AddClient(ResourceClient* client,
                         base::SingleThreadTaskRunner* task_runner) {
  CHECK(!is_add_remove_client_prohibited_);

  WillAddClientOrObserver();

  if (is_revalidating_) {
    clients_.insert(client);
    return;
  }

  // If an error has occurred or we have existing data to send to the new client
  // and the resource type supports it, send it asynchronously.
  if ((ErrorOccurred() || !GetResponse().IsNull()) &&
      !TypeNeedsSynchronousCacheHit(GetType())) {
    clients_awaiting_callback_.insert(client);
    if (!async_finish_pending_clients_task_.IsActive()) {
      async_finish_pending_clients_task_ = PostCancellableTask(
          *task_runner, FROM_HERE,
          WTF::Bind(&Resource::FinishPendingClients, WrapWeakPersistent(this)));
    }
    return;
  }

  clients_.insert(client);
  DidAddClient(client);
  return;
}

void Resource::RemoveClient(ResourceClient* client) {
  CHECK(!is_add_remove_client_prohibited_);

  // This code may be called in a pre-finalizer, where weak members in the
  // HashCountedSet are already swept out.

  if (finished_clients_.Contains(client))
    finished_clients_.erase(client);
  else if (clients_awaiting_callback_.Contains(client))
    clients_awaiting_callback_.erase(client);
  else
    clients_.erase(client);

  if (clients_awaiting_callback_.IsEmpty() &&
      async_finish_pending_clients_task_.IsActive()) {
    async_finish_pending_clients_task_.Cancel();
  }

  DidRemoveClientOrObserver();
}

void Resource::AddFinishObserver(ResourceFinishObserver* client,
                                 base::SingleThreadTaskRunner* task_runner) {
  CHECK(!is_add_remove_client_prohibited_);
  DCHECK(!finish_observers_.Contains(client));

  WillAddClientOrObserver();
  finish_observers_.insert(client);
  if (IsLoaded())
    TriggerNotificationForFinishObservers(task_runner);
}

void Resource::RemoveFinishObserver(ResourceFinishObserver* client) {
  CHECK(!is_add_remove_client_prohibited_);

  finish_observers_.erase(client);
  DidRemoveClientOrObserver();
}

void Resource::DidRemoveClientOrObserver() {
  if (!HasClientsOrObservers() && is_alive_) {
    is_alive_ = false;
    AllClientsAndObserversRemoved();

    // RFC2616 14.9.2:
    // "no-store: ... MUST make a best-effort attempt to remove the information
    // from volatile storage as promptly as possible"
    // "... History buffers MAY store such responses as part of their normal
    // operation."
    // We allow non-secure content to be reused in history, but we do not allow
    // secure content to be reused.
    if (HasCacheControlNoStoreHeader() && Url().ProtocolIs("https") &&
        IsMainThread())
      GetMemoryCache()->Remove(this);
  }
}

void Resource::AllClientsAndObserversRemoved() {
  if (loader_)
    loader_->ScheduleCancel();
}

void Resource::SetDecodedSize(size_t decoded_size) {
  if (decoded_size == decoded_size_)
    return;
  size_t old_size = size();
  decoded_size_ = decoded_size;
  if (IsMainThread())
    GetMemoryCache()->Update(this, old_size, size());
}

void Resource::SetEncodedSize(size_t encoded_size) {
  if (encoded_size == encoded_size_ &&
      encoded_size == encoded_size_memory_usage_)
    return;
  size_t old_size = size();
  encoded_size_ = encoded_size;
  encoded_size_memory_usage_ = encoded_size;
  if (IsMainThread())
    GetMemoryCache()->Update(this, old_size, size());
}

void Resource::FinishPendingClients() {
  // We're going to notify clients one by one. It is simple if the client does
  // nothing. However there are a couple other things that can happen.
  //
  // 1. Clients can be added during the loop. Make sure they are not processed.
  // 2. Clients can be removed during the loop. Make sure they are always
  //    available to be removed. Also don't call removed clients or add them
  //    back.
  //
  // Handle case (1) by saving a list of clients to notify. A separate list also
  // ensure a client is either in cliens_ or clients_awaiting_callback_.
  HeapVector<Member<ResourceClient>> clients_to_notify;
  CopyToVector(clients_awaiting_callback_, clients_to_notify);

  for (const auto& client : clients_to_notify) {
    // Handle case (2) to skip removed clients.
    if (!clients_awaiting_callback_.erase(client))
      continue;
    clients_.insert(client);

    // When revalidation starts after waiting clients are scheduled and
    // before they are added here. In such cases, we just add the clients
    // to |clients_| without DidAddClient(), as in Resource::AddClient().
    if (!is_revalidating_)
      DidAddClient(client);
  }

  // It is still possible for the above loop to finish a new client
  // synchronously. If there's no client waiting we should deschedule.
  bool scheduled = async_finish_pending_clients_task_.IsActive();
  if (scheduled && clients_awaiting_callback_.IsEmpty())
    async_finish_pending_clients_task_.Cancel();

  // Prevent the case when there are clients waiting but no callback scheduled.
  DCHECK(clients_awaiting_callback_.IsEmpty() || scheduled);
}

bool Resource::CanReuse(
    const FetchParameters& params,
    scoped_refptr<const SecurityOrigin> new_source_origin) const {
  const ResourceRequest& new_request = params.GetResourceRequest();
  const ResourceLoaderOptions& new_options = params.Options();

  // Never reuse opaque responses from a service worker for requests that are
  // not no-cors. https://crbug.com/625575
  // TODO(yhirano): Remove this.
  if (GetResponse().WasFetchedViaServiceWorker() &&
      GetResponse().ResponseTypeViaServiceWorker() ==
          network::mojom::FetchResponseType::kOpaque &&
      new_request.GetFetchRequestMode() !=
          network::mojom::FetchRequestMode::kNoCORS) {
    return false;
  }

  // If credentials were sent with the previous request and won't be with this
  // one, or vice versa, re-fetch the resource.
  //
  // This helps with the case where the server sends back
  // "Access-Control-Allow-Origin: *" all the time, but some of the client's
  // requests are made without CORS and some with.
  if (GetResourceRequest().AllowStoredCredentials() !=
      new_request.AllowStoredCredentials())
    return false;

  // Certain requests (e.g., XHRs) might have manually set headers that require
  // revalidation. In theory, this should be a Revalidate case. In practice, the
  // MemoryCache revalidation path assumes a whole bunch of things about how
  // revalidation works that manual headers violate, so punt to Reload instead.
  //
  // Similarly, a request with manually added revalidation headers can lead to a
  // 304 response for a request that wasn't flagged as a revalidation attempt.
  // Normally, successful revalidation will maintain the original response's
  // status code, but for a manual revalidation the response code remains 304.
  // In this case, the Resource likely has insufficient context to provide a
  // useful cache hit or revalidation. See http://crbug.com/643659
  if (new_request.IsConditional() || response_.HttpStatusCode() == 304)
    return false;

  // Answers the question "can a separate request with different options be
  // re-used" (e.g. preload request). The safe (but possibly slow) answer is
  // always false.
  //
  // Data buffering policy differences are believed to be safe for re-use.
  //
  // TODO: Check content_security_policy_option.
  //
  // initiator_info is purely informational and should be benign for re-use.
  //
  // request_initiator_context is benign (indicates document vs. worker).

  // Reuse only if both the existing Resource and the new request are
  // asynchronous. Particularly,
  // 1. Sync and async Resource/requests shouldn't be mixed (crbug.com/652172),
  // 2. Sync existing Resources shouldn't be revalidated, and
  // 3. Sync new requests shouldn't revalidate existing Resources.
  //
  // 2. and 3. are because SyncResourceHandler handles redirects without
  // calling WillFollowRedirect, and causes response URL mismatch
  // (crbug.com/618967) and bypassing redirect restriction around revalidation
  // (crbug.com/613971 for 2. and crbug.com/614989 for 3.).
  if (new_options.synchronous_policy == kRequestSynchronously ||
      options_.synchronous_policy == kRequestSynchronously)
    return false;

  if (resource_request_.GetKeepalive() || new_request.GetKeepalive()) {
    return false;
  }

  DCHECK(source_origin_);
  DCHECK(new_source_origin);

  // Don't reuse an existing resource when the source origin is different.
  if (!source_origin_->IsSameSchemeHostPort(new_source_origin.get()))
    return false;

  // securityOrigin has more complicated checks which callers are responsible
  // for.

  if (new_request.GetFetchCredentialsMode() !=
      resource_request_.GetFetchCredentialsMode())
    return false;

  const auto new_mode = new_request.GetFetchRequestMode();
  const auto existing_mode = resource_request_.GetFetchRequestMode();

  if (new_mode != existing_mode)
    return false;

  switch (new_mode) {
    case network::mojom::FetchRequestMode::kNoCORS:
    case network::mojom::FetchRequestMode::kNavigate:
      break;

    case network::mojom::FetchRequestMode::kCORS:
    case network::mojom::FetchRequestMode::kSameOrigin:
    case network::mojom::FetchRequestMode::kCORSWithForcedPreflight:
      // We have two separate CORS handling logics in DocumentThreadableLoader
      // and ResourceLoader and sharing resources is difficult when they are
      // handled differently.
      if (options_.cors_handling_by_resource_fetcher !=
          new_options.cors_handling_by_resource_fetcher) {
        // If the existing one is handled in DocumentThreadableLoader and the
        // new one is handled in ResourceLoader, reusing the existing one will
        // lead to CORS violations.
        if (!options_.cors_handling_by_resource_fetcher)
          return false;

        // Otherwise (i.e., if the existing one is handled in ResourceLoader
        // and the new one is handled in DocumentThreadableLoader), reusing
        // the existing one will lead to double check which is harmless.
      }
      break;
  }

  return true;
}

void Resource::Prune() {
  DestroyDecodedDataIfPossible();
}

void Resource::OnPurgeMemory() {
  Prune();
  if (!cache_handler_)
    return;
  cache_handler_->ClearCachedMetadata(CachedMetadataHandler::kCacheLocally);
}

void Resource::OnMemoryDump(WebMemoryDumpLevelOfDetail level_of_detail,
                            WebProcessMemoryDump* memory_dump) const {
  static const size_t kMaxURLReportLength = 128;
  static const int kMaxResourceClientToShowInMemoryInfra = 10;

  const String dump_name = GetMemoryDumpName();
  WebMemoryAllocatorDump* dump =
      memory_dump->CreateMemoryAllocatorDump(dump_name);
  dump->AddScalar("encoded_size", "bytes", encoded_size_memory_usage_);
  if (HasClientsOrObservers())
    dump->AddScalar("live_size", "bytes", encoded_size_memory_usage_);
  else
    dump->AddScalar("dead_size", "bytes", encoded_size_memory_usage_);

  if (data_)
    data_->OnMemoryDump(dump_name, memory_dump);

  if (level_of_detail == WebMemoryDumpLevelOfDetail::kDetailed) {
    String url_to_report = Url().GetString();
    if (url_to_report.length() > kMaxURLReportLength) {
      url_to_report.Truncate(kMaxURLReportLength);
      url_to_report = url_to_report + "...";
    }
    dump->AddString("url", "", url_to_report);

    dump->AddString("reason_not_deletable", "", ReasonNotDeletable());

    Vector<String> client_names;
    ResourceClientWalker<ResourceClient> walker(clients_);
    while (ResourceClient* client = walker.Next())
      client_names.push_back(client->DebugName());
    ResourceClientWalker<ResourceClient> walker2(clients_awaiting_callback_);
    while (ResourceClient* client = walker2.Next())
      client_names.push_back("(awaiting) " + client->DebugName());
    ResourceClientWalker<ResourceClient> walker3(finished_clients_);
    while (ResourceClient* client = walker3.Next())
      client_names.push_back("(finished) " + client->DebugName());
    std::sort(client_names.begin(), client_names.end(),
              WTF::CodePointCompareLessThan);

    StringBuilder builder;
    for (size_t i = 0;
         i < client_names.size() && i < kMaxResourceClientToShowInMemoryInfra;
         ++i) {
      if (i > 0)
        builder.Append(" / ");
      builder.Append(client_names[i]);
    }
    if (client_names.size() > kMaxResourceClientToShowInMemoryInfra) {
      builder.Append(" / and ");
      builder.AppendNumber(client_names.size() -
                           kMaxResourceClientToShowInMemoryInfra);
      builder.Append(" more");
    }
    dump->AddString("ResourceClient", "", builder.ToString());
  }

  const String overhead_name = dump_name + "/metadata";
  WebMemoryAllocatorDump* overhead_dump =
      memory_dump->CreateMemoryAllocatorDump(overhead_name);
  overhead_dump->AddScalar("size", "bytes", OverheadSize());
  memory_dump->AddSuballocation(
      overhead_dump->Guid(), String(WTF::Partitions::kAllocatedObjectPoolName));
}

String Resource::GetMemoryDumpName() const {
  return String::Format(
      "web_cache/%s_resources/%ld",
      ResourceTypeToString(GetType(), Options().initiator_info.name),
      identifier_);
}

void Resource::SetCachePolicyBypassingCache() {
  resource_request_.SetCacheMode(mojom::FetchCacheMode::kBypassCache);
}

void Resource::SetPreviewsState(WebURLRequest::PreviewsState previews_state) {
  resource_request_.SetPreviewsState(previews_state);
}

void Resource::ClearRangeRequestHeader() {
  resource_request_.ClearHTTPHeaderField("range");
}

void Resource::RevalidationSucceeded(
    const ResourceResponse& validating_response) {
  SECURITY_CHECK(redirect_chain_.IsEmpty());
  SECURITY_CHECK(EqualIgnoringFragmentIdentifier(validating_response.Url(),
                                                 GetResponse().Url()));
  response_.SetResourceLoadTiming(validating_response.GetResourceLoadTiming());

  // RFC2616 10.3.5
  // Update cached headers from the 304 response
  const HTTPHeaderMap& new_headers = validating_response.HttpHeaderFields();
  for (const auto& header : new_headers) {
    // Entity headers should not be sent by servers when generating a 304
    // response; misconfigured servers send them anyway. We shouldn't allow such
    // headers to update the original request. We'll base this on the list
    // defined by RFC2616 7.1, with a few additions for extension headers we
    // care about.
    if (!ShouldUpdateHeaderAfterRevalidation(header.key))
      continue;
    response_.SetHTTPHeaderField(header.key, header.value);
  }

  is_revalidating_ = false;
}

void Resource::RevalidationFailed() {
  SECURITY_CHECK(redirect_chain_.IsEmpty());
  ClearData();
  cache_handler_.Clear();
  integrity_disposition_ = ResourceIntegrityDisposition::kNotChecked;
  integrity_report_info_.Clear();
  DestroyDecodedDataForFailedRevalidation();
  is_revalidating_ = false;
}

void Resource::MarkAsPreload() {
  DCHECK(!is_unused_preload_);
  is_unused_preload_ = true;
}

bool Resource::MatchPreload(const FetchParameters& params,
                            base::SingleThreadTaskRunner*) {
  DCHECK(is_unused_preload_);
  is_unused_preload_ = false;

  if (preload_discovery_time_) {
    int time_since_discovery = static_cast<int>(
        1000 * (CurrentTimeTicksInSeconds() - preload_discovery_time_));
    DEFINE_STATIC_LOCAL(CustomCountHistogram, preload_discovery_histogram,
                        ("PreloadScanner.ReferenceTime", 0, 10000, 50));
    preload_discovery_histogram.Count(time_since_discovery);
  }
  return true;
}

bool Resource::CanReuseRedirectChain() const {
  for (auto& redirect : redirect_chain_) {
    if (!CanUseResponse(redirect.redirect_response_, response_timestamp_))
      return false;
    if (redirect.request_.CacheControlContainsNoCache() ||
        redirect.request_.CacheControlContainsNoStore())
      return false;
  }
  return true;
}

bool Resource::HasCacheControlNoStoreHeader() const {
  return GetResponse().CacheControlContainsNoStore() ||
         GetResourceRequest().CacheControlContainsNoStore();
}

bool Resource::MustReloadDueToVaryHeader(
    const ResourceRequest& new_request) const {
  const AtomicString& vary = GetResponse().HttpHeaderField(HTTPNames::Vary);
  if (vary.IsNull())
    return false;
  if (vary == "*")
    return true;

  CommaDelimitedHeaderSet vary_headers;
  ParseCommaDelimitedHeader(vary, vary_headers);
  for (const String& header : vary_headers) {
    AtomicString atomic_header(header);
    if (GetResourceRequest().HttpHeaderField(atomic_header) !=
        new_request.HttpHeaderField(atomic_header)) {
      return true;
    }
  }
  return false;
}

bool Resource::MustRevalidateDueToCacheHeaders() const {
  return !CanUseResponse(GetResponse(), response_timestamp_) ||
         GetResourceRequest().CacheControlContainsNoCache() ||
         GetResourceRequest().CacheControlContainsNoStore();
}

bool Resource::CanUseCacheValidator() const {
  if (IsLoading() || ErrorOccurred())
    return false;

  if (HasCacheControlNoStoreHeader())
    return false;

  // Do not revalidate Resource with redirects. https://crbug.com/613971
  if (!RedirectChain().IsEmpty())
    return false;

  return GetResponse().HasCacheValidatorFields() ||
         GetResourceRequest().HasCacheValidatorFields();
}

size_t Resource::CalculateOverheadSize() const {
  static const int kAverageClientsHashMapSize = 384;
  return sizeof(Resource) + GetResponse().MemoryUsage() +
         kAverageClientsHashMapSize +
         GetResourceRequest().Url().GetString().length() * 2;
}

void Resource::DidChangePriority(ResourceLoadPriority load_priority,
                                 int intra_priority_value) {
  resource_request_.SetPriority(load_priority, intra_priority_value);
  if (loader_)
    loader_->DidChangePriority(load_priority, intra_priority_value);
}

// TODO(toyoshim): Consider to generate automatically. https://crbug.com/675515.
static const char* InitiatorTypeNameToString(
    const AtomicString& initiator_type_name) {
  if (initiator_type_name == FetchInitiatorTypeNames::css)
    return "CSS resource";
  if (initiator_type_name == FetchInitiatorTypeNames::document)
    return "Document";
  if (initiator_type_name == FetchInitiatorTypeNames::icon)
    return "Icon";
  if (initiator_type_name == FetchInitiatorTypeNames::internal)
    return "Internal resource";
  if (initiator_type_name == FetchInitiatorTypeNames::link)
    return "Link element resource";
  if (initiator_type_name == FetchInitiatorTypeNames::processinginstruction)
    return "Processing instruction";
  if (initiator_type_name == FetchInitiatorTypeNames::texttrack)
    return "Text track";
  if (initiator_type_name == FetchInitiatorTypeNames::uacss)
    return "User Agent CSS resource";
  if (initiator_type_name == FetchInitiatorTypeNames::xml)
    return "XML resource";
  if (initiator_type_name == FetchInitiatorTypeNames::xmlhttprequest)
    return "XMLHttpRequest";

  static_assert(
      FetchInitiatorTypeNames::FetchInitiatorTypeNamesCount == 13,
      "New FetchInitiatorTypeNames should be handled correctly here.");

  return "Resource";
}

const char* Resource::ResourceTypeToString(
    Type type,
    const AtomicString& fetch_initiator_name) {
  switch (type) {
    case Resource::kMainResource:
      return "Main resource";
    case Resource::kImage:
      return "Image";
    case Resource::kCSSStyleSheet:
      return "CSS stylesheet";
    case Resource::kScript:
      return "Script";
    case Resource::kFont:
      return "Font";
    case Resource::kRaw:
      return InitiatorTypeNameToString(fetch_initiator_name);
    case Resource::kSVGDocument:
      return "SVG document";
    case Resource::kXSLStyleSheet:
      return "XSL stylesheet";
    case Resource::kLinkPrefetch:
      return "Link prefetch resource";
    case Resource::kTextTrack:
      return "Text track";
    case Resource::kImportResource:
      return "Imported resource";
    case Resource::kAudio:
      return "Audio";
    case Resource::kVideo:
      return "Video";
    case Resource::kManifest:
      return "Manifest";
    case Resource::kMock:
      return "Mock";
  }
  NOTREACHED();
  return InitiatorTypeNameToString(fetch_initiator_name);
}

bool Resource::ShouldBlockLoadEvent() const {
  return !link_preload_ && IsLoadEventBlockingResourceType();
}

bool Resource::IsLoadEventBlockingResourceType() const {
  switch (type_) {
    case Resource::kMainResource:
    case Resource::kImage:
    case Resource::kCSSStyleSheet:
    case Resource::kScript:
    case Resource::kFont:
    case Resource::kSVGDocument:
    case Resource::kXSLStyleSheet:
    case Resource::kImportResource:
      return true;
    case Resource::kRaw:
    case Resource::kLinkPrefetch:
    case Resource::kTextTrack:
    case Resource::kAudio:
    case Resource::kVideo:
    case Resource::kManifest:
    case Resource::kMock:
      return false;
  }
  NOTREACHED();
  return false;
}

}  // namespace blink
