/*
    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
    Copyright (C) 2001 Dirk Mueller <mueller@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.
*/

#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_H_

#include <memory>
#include "base/auto_reset.h"
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/mojom/loader/code_cache.mojom-shared.h"
#include "third_party/blink/public/platform/web_data_consumer_handle.h"
#include "third_party/blink/public/platform/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_priority.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_status.h"
#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
#include "third_party/blink/renderer/platform/loader/subresource_integrity.h"
#include "third_party/blink/renderer/platform/memory_coordinator.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_counted_set.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/time.h"

namespace blink {

class FetchParameters;
class ResourceClient;
class ResourceFetcher;
class ResourceFinishObserver;
class ResourceTimingInfo;
class ResourceLoader;
class SecurityOrigin;

// |ResourceType| enum values are used in UMAs, so do not change the values of
// existing types. When adding a new type, append it at the end.
enum class ResourceType : uint8_t {
  kMainResource,
  kImage,
  kCSSStyleSheet,
  kScript,
  kFont,
  kRaw,
  kSVGDocument,
  kXSLStyleSheet,
  kLinkPrefetch,
  kTextTrack,
  kImportResource,
  kAudio,
  kVideo,
  kManifest,
  kMock  // Only for testing
};

// A callback for sending the serialized data of cached metadata back to the
// platform.
class CachedMetadataSender {
 public:
  virtual ~CachedMetadataSender() = default;
  virtual void Send(const char*, size_t) = 0;

  // IsServedFromCacheStorage is used to alter caching strategy to be more
  // aggressive. See ScriptController.cpp CacheOptions() for an example.
  virtual bool IsServedFromCacheStorage() = 0;
};

// A resource that is held in the cache. Classes who want to use this object
// should derive from ResourceClient, to get the function calls in case the
// requested data has arrived. This class also does the actual communication
// with the loader to obtain the resource from the network.
class PLATFORM_EXPORT Resource : public GarbageCollectedFinalized<Resource>,
                                 public MemoryCoordinatorClient {
  USING_GARBAGE_COLLECTED_MIXIN(Resource);
  WTF_MAKE_NONCOPYABLE(Resource);

 public:
  // An enum representing whether a resource match with another resource.
  // There are three kinds of status.
  // - kOk, which represents the success.
  // - kUnknownFailure, which represents miscellaneous failures. This includes
  //   failures which cannot happen for preload matching (for example,
  //   a failure due to non-cacheable request method cannot be happen for
  //   preload matching).
  // - other specific error status
  enum class MatchStatus {
    // Match succeeds.
    kOk,

    // Match fails because of an unknown reason.
    kUnknownFailure,

    // Subresource integrity value doesn't match.
    kIntegrityMismatch,

    // Match fails because the new request wants to load the content
    // as a blob.
    kBlobRequest,

    // Match fails because loading image is disabled.
    kImageLoadingDisabled,

    // Match fails due to different synchronous flags.
    kSynchronousFlagDoesNotMatch,

    // Match fails due to different request modes.
    kRequestModeDoesNotMatch,

    // Match fails due to different request credentials modes.
    kRequestCredentialsModeDoesNotMatch,

    // Match fails because keepalive flag is set on either requests.
    kKeepaliveSet,

    // Match fails due to different request methods.
    kRequestMethodDoesNotMatch,

    // Match fails due to different request headers.
    kRequestHeadersDoNotMatch,

    // Match fails due to different image placeholder policies.
    kImagePlaceholder,
  };

  // Used by reloadIfLoFiOrPlaceholderImage().
  enum ReloadLoFiOrPlaceholderPolicy {
    kReloadIfNeeded,
    kReloadAlways,
  };

  ~Resource() override;

  void Trace(blink::Visitor*) override;

  virtual WTF::TextEncoding Encoding() const { return WTF::TextEncoding(); }
  virtual void AppendData(const char*, size_t);
  virtual void FinishAsError(const ResourceError&,
                             base::SingleThreadTaskRunner*);

  void SetLinkPreload(bool is_link_preload) { link_preload_ = is_link_preload; }
  bool IsLinkPreload() const { return link_preload_; }

  const ResourceError& GetResourceError() const {
    DCHECK(error_);
    return *error_;
  }

  void SetIdentifier(unsigned long identifier) { identifier_ = identifier; }
  unsigned long Identifier() const { return identifier_; }

  virtual bool ShouldIgnoreHTTPStatusCodeErrors() const { return false; }

  const ResourceRequest& GetResourceRequest() const {
    return resource_request_;
  }
  const ResourceRequest& LastResourceRequest() const;

  virtual void SetRevalidatingRequest(const ResourceRequest&);

  // This url can have a fragment, but it can match resources that differ by the
  // fragment only.
  const KURL& Url() const { return GetResourceRequest().Url(); }
  ResourceType GetType() const { return static_cast<ResourceType>(type_); }
  const ResourceLoaderOptions& Options() const { return options_; }
  ResourceLoaderOptions& MutableOptions() { return options_; }

  void DidChangePriority(ResourceLoadPriority, int intra_priority_value);
  virtual ResourcePriority PriorityFromObservers() {
    return ResourcePriority();
  }

  // If this Resource is already finished when AddClient is called, the
  // ResourceClient will be notified asynchronously by a task scheduled
  // on the given base::SingleThreadTaskRunner. Otherwise, the given
  // base::SingleThreadTaskRunner is unused.
  void AddClient(ResourceClient*, base::SingleThreadTaskRunner*);
  void RemoveClient(ResourceClient*);

  // If this Resource is already finished when AddFinishObserver is called, the
  // ResourceFinishObserver will be notified asynchronously by a task scheduled
  // on the given base::SingleThreadTaskRunner. Otherwise, the given
  // base::SingleThreadTaskRunner is unused.
  void AddFinishObserver(ResourceFinishObserver*,
                         base::SingleThreadTaskRunner*);
  void RemoveFinishObserver(ResourceFinishObserver*);

  bool IsUnusedPreload() const { return is_unused_preload_; }

  ResourceStatus GetStatus() const { return status_; }
  void SetStatus(ResourceStatus status) { status_ = status; }

  size_t size() const { return EncodedSize() + DecodedSize() + OverheadSize(); }

  // Returns the size of content (response body) before decoding. Adding a new
  // usage of this function is not recommended (See the TODO below).
  //
  // TODO(hiroshige): Now EncodedSize/DecodedSize states are inconsistent and
  // need to be refactored (crbug/643135).
  size_t EncodedSize() const { return encoded_size_; }

  // Returns the current memory usage for the encoded data. Adding a new usage
  // of this function is not recommended as the same reason as |EncodedSize()|.
  //
  // |EncodedSize()| and |EncodedSizeMemoryUsageForTesting()| can return
  // different values, e.g., when ImageResource purges encoded image data after
  // finishing loading.
  size_t EncodedSizeMemoryUsageForTesting() const {
    return encoded_size_memory_usage_;
  }

  size_t DecodedSize() const { return decoded_size_; }
  size_t OverheadSize() const { return overhead_size_; }

  bool IsLoaded() const { return status_ > ResourceStatus::kPending; }

  bool IsLoading() const { return status_ == ResourceStatus::kPending; }
  bool StillNeedsLoad() const { return status_ < ResourceStatus::kPending; }

  void SetLoader(ResourceLoader*);
  ResourceLoader* Loader() const { return loader_.Get(); }

  bool ShouldBlockLoadEvent() const;
  bool IsLoadEventBlockingResourceType() const;

  // Computes the status of an object after loading. Updates the expire date on
  // the cache entry file
  virtual void Finish(TimeTicks finish_time, base::SingleThreadTaskRunner*);
  void FinishForTest() { Finish(TimeTicks(), nullptr); }

  virtual scoped_refptr<const SharedBuffer> ResourceBuffer() const {
    return data_;
  }
  void SetResourceBuffer(scoped_refptr<SharedBuffer>);

  virtual bool WillFollowRedirect(const ResourceRequest&,
                                  const ResourceResponse&);

  // Called when a redirect response was received but a decision has already
  // been made to not follow it.
  virtual void WillNotFollowRedirect() {}

  virtual void ResponseReceived(const ResourceResponse&,
                                std::unique_ptr<WebDataConsumerHandle>);
  void SetResponse(const ResourceResponse&);
  const ResourceResponse& GetResponse() const { return response_; }

  virtual void ReportResourceTimingToClients(const ResourceTimingInfo&) {}

  // Sets the serialized metadata retrieved from the platform's cache.
  // Subclasses of Resource that support cached metadata should override this
  // method with one that fills the current CachedMetadataHandler.
  virtual void SetSerializedCachedMetadata(const char*, size_t);

  AtomicString HttpContentType() const;

  bool WasCanceled() const { return error_ && error_->IsCancellation(); }
  bool ErrorOccurred() const {
    return status_ == ResourceStatus::kLoadError ||
           status_ == ResourceStatus::kDecodeError;
  }
  bool LoadFailedOrCanceled() const { return !!error_; }

  DataBufferingPolicy GetDataBufferingPolicy() const {
    return options_.data_buffering_policy;
  }
  void SetDataBufferingPolicy(DataBufferingPolicy);

  void MarkAsPreload();
  // Returns true if |this| resource is matched with the given parameters.
  virtual bool MatchPreload(const FetchParameters&,
                            base::SingleThreadTaskRunner*);

  bool CanReuseRedirectChain() const;
  bool MustRevalidateDueToCacheHeaders(bool allow_stale) const;
  bool ShouldRevalidateStaleResponse() const;
  virtual bool CanUseCacheValidator() const;
  bool IsCacheValidator() const { return is_revalidating_; }
  bool HasCacheControlNoStoreHeader() const;
  bool MustReloadDueToVaryHeader(const ResourceRequest& new_request) const;

  // Returns true if any response returned from the upstream in the redirect
  // chain is stale and requires triggering async stale revalidation. Once
  // revalidation is started SetStaleRevalidationStarted() should be called.
  bool StaleRevalidationRequested() const;

  // Set that stale revalidation has been started so that subsequent
  // requests won't trigger it again. When stale revalidation is completed
  // this resource will be removed from the MemoryCache so there is no
  // need to reset it back to false.
  bool StaleRevalidationStarted() const { return stale_revalidation_started_; }
  void SetStaleRevalidationStarted() { stale_revalidation_started_ = true; }

  const IntegrityMetadataSet& IntegrityMetadata() const {
    return options_.integrity_metadata;
  }
  ResourceIntegrityDisposition IntegrityDisposition() const {
    return integrity_disposition_;
  }
  const SubresourceIntegrity::ReportInfo& IntegrityReportInfo() const {
    return integrity_report_info_;
  }
  bool MustRefetchDueToIntegrityMetadata(const FetchParameters&) const;

  bool IsAlive() const { return is_alive_; }

  void SetCacheIdentifier(const String& cache_identifier) {
    cache_identifier_ = cache_identifier;
  }
  String CacheIdentifier() const { return cache_identifier_; }

  // https://fetch.spec.whatwg.org/#concept-request-origin
  const scoped_refptr<const SecurityOrigin>& GetOrigin() const;

  virtual void DidSendData(unsigned long long /* bytesSent */,
                           unsigned long long /* totalBytesToBeSent */) {}
  virtual void DidDownloadData(int) {}
  virtual void DidDownloadToBlob(scoped_refptr<BlobDataHandle>) {}

  TimeTicks LoadFinishTime() const { return load_finish_time_; }

  void SetEncodedDataLength(int64_t value) {
    response_.SetEncodedDataLength(value);
  }
  void SetEncodedBodyLength(int value) {
    response_.SetEncodedBodyLength(value);
  }
  void SetDecodedBodyLength(int value) {
    response_.SetDecodedBodyLength(value);
  }

  // Returns |kOk| when |this| can be resused for the given arguments.
  virtual MatchStatus CanReuse(const FetchParameters& params) const;

  // TODO(yhirano): Remove this once out-of-blink CORS is fully enabled.
  void SetResponseType(network::mojom::FetchResponseType response_type) {
    response_.SetType(response_type);
  }

  // If cache-aware loading is activated, this callback is called when the first
  // disk-cache-only request failed due to cache miss. After this callback,
  // cache-aware loading is deactivated and a reload with original request will
  // be triggered right away in ResourceLoader.
  virtual void WillReloadAfterDiskCacheMiss() {}

  // TODO(shaochuan): This is for saving back the actual ResourceRequest sent
  // in ResourceFetcher::StartLoad() for retry in cache-aware loading, remove
  // once ResourceRequest is not modified in StartLoad(). crbug.com/632580
  void SetResourceRequest(const ResourceRequest& resource_request) {
    resource_request_ = resource_request;
  }

  // Used by the MemoryCache to reduce the memory consumption of the entry.
  void Prune();

  virtual void OnMemoryDump(WebMemoryDumpLevelOfDetail,
                            WebProcessMemoryDump*) const;

  // If this Resource is ImageResource and has the Lo-Fi response headers or is
  // a placeholder, reload the full original image with the Lo-Fi state set to
  // off and optionally bypassing the cache.
  virtual void ReloadIfLoFiOrPlaceholderImage(ResourceFetcher*,
                                              ReloadLoFiOrPlaceholderPolicy) {}

  // Used to notify ImageResourceContent of the start of actual loading.
  // JavaScript calls or client/observer notifications are disallowed inside
  // NotifyStartLoad().
  virtual void NotifyStartLoad() {
    CHECK_EQ(status_, ResourceStatus::kNotStarted);
    status_ = ResourceStatus::kPending;
  }

  static const char* ResourceTypeToString(
      ResourceType,
      const AtomicString& fetch_initiator_name);

  static blink::mojom::CodeCacheType ResourceTypeToCodeCacheType(ResourceType);

  class ProhibitAddRemoveClientInScope : public base::AutoReset<bool> {
   public:
    ProhibitAddRemoveClientInScope(Resource* resource)
        : AutoReset(&resource->is_add_remove_client_prohibited_, true) {}
  };

  class RevalidationStartForbiddenScope : public base::AutoReset<bool> {
   public:
    RevalidationStartForbiddenScope(Resource* resource)
        : AutoReset(&resource->is_revalidation_start_forbidden_, true) {}
  };

  WebScopedVirtualTimePauser& VirtualTimePauser() {
    return virtual_time_pauser_;
  }

 protected:
  Resource(const ResourceRequest&, ResourceType, const ResourceLoaderOptions&);

  // Returns true if the resource has finished any processing it wanted to do
  // after loading. Should only be used to decide whether to call
  // NotifyFinished.
  //
  // By default this is the same as being loaded (i.e. no processing), but it is
  // used by ScriptResource to signal that streaming JavaScript compilation
  // completed. Note that classes overloading this method should also overload
  // NotifyFinished to not call Resource::NotifyFinished until this value
  // becomes true.
  // TODO(hiroshige): Remove this when ScriptResourceContent is introduced.
  virtual bool IsFinishedInternal() const { return IsLoaded(); }

  virtual void NotifyDataReceived(const char* data, size_t size);
  virtual void NotifyFinished();

  void MarkClientFinished(ResourceClient*);

  virtual bool HasClientsOrObservers() const {
    return !clients_.IsEmpty() || !clients_awaiting_callback_.IsEmpty() ||
           !finished_clients_.IsEmpty() || !finish_observers_.IsEmpty();
  }
  virtual void DestroyDecodedDataForFailedRevalidation() {}

  void SetEncodedSize(size_t);
  void SetDecodedSize(size_t);

  void FinishPendingClients();

  virtual void DidAddClient(ResourceClient*);
  void WillAddClientOrObserver();

  void DidRemoveClientOrObserver();
  virtual void AllClientsAndObserversRemoved();

  bool HasClient(ResourceClient* client) const {
    return clients_.Contains(client) ||
           clients_awaiting_callback_.Contains(client) ||
           finished_clients_.Contains(client);
  }

  struct RedirectPair {
    DISALLOW_NEW();

   public:
    explicit RedirectPair(const ResourceRequest& request,
                          const ResourceResponse& redirect_response)
        : request_(request), redirect_response_(redirect_response) {}

    ResourceRequest request_;
    ResourceResponse redirect_response_;
  };
  const Vector<RedirectPair>& RedirectChain() const { return redirect_chain_; }

  virtual void DestroyDecodedDataIfPossible() {}

  // Returns the memory dump name used for tracing. See Resource::OnMemoryDump.
  String GetMemoryDumpName() const;

  const HeapHashCountedSet<WeakMember<ResourceClient>>& Clients() const {
    return clients_;
  }

  void SetCachePolicyBypassingCache();
  void SetPreviewsState(WebURLRequest::PreviewsState);
  void ClearRangeRequestHeader();

  SharedBuffer* Data() const { return data_.get(); }
  void ClearData();

  virtual void SetEncoding(const String&) {}

  // Create a handler for the cached metadata of this resource. Subclasses of
  // Resource that support cached metadata should override this method with one
  // that creates an appropriate CachedMetadataHandler implementation, and
  // override SetSerializedCachedMetadata with an implementation that fills the
  // cache handler.
  virtual CachedMetadataHandler* CreateCachedMetadataHandler(
      std::unique_ptr<CachedMetadataSender> send_callback) {
    return nullptr;
  }

  CachedMetadataHandler* CacheHandler() { return cache_handler_.Get(); }

 private:
  friend class ResourceLoader;

  void RevalidationSucceeded(const ResourceResponse&);
  void RevalidationFailed();

  size_t CalculateOverheadSize() const;

  String ReasonNotDeletable() const;

  // MemoryCoordinatorClient overrides:
  void OnPurgeMemory() override;

  void CheckResourceIntegrity();
  void TriggerNotificationForFinishObservers(base::SingleThreadTaskRunner*);

  // Helper for creating the send callback function for the cached metadata
  // handler.
  std::unique_ptr<CachedMetadataSender> CreateCachedMetadataSender() const;

  ResourceType type_;
  ResourceStatus status_;

  Member<CachedMetadataHandler> cache_handler_;

  base::Optional<ResourceError> error_;

  TimeTicks load_finish_time_;

  unsigned long identifier_;

  size_t encoded_size_;
  size_t encoded_size_memory_usage_;
  size_t decoded_size_;

  // Resource::CalculateOverheadSize() is affected by changes in
  // |m_resourceRequest.url()|, but |m_overheadSize| is not updated after
  // initial |m_resourceRequest| is given, to reduce MemoryCache manipulation
  // and thus potential bugs. crbug.com/594644
  const size_t overhead_size_;

  String cache_identifier_;

  bool link_preload_;
  bool is_revalidating_;
  bool is_alive_;
  bool is_add_remove_client_prohibited_;
  bool is_revalidation_start_forbidden_ = false;
  bool is_unused_preload_ = false;
  bool stale_revalidation_started_ = false;

  ResourceIntegrityDisposition integrity_disposition_;
  SubresourceIntegrity::ReportInfo integrity_report_info_;

  // Ordered list of all redirects followed while fetching this resource.
  Vector<RedirectPair> redirect_chain_;

  HeapHashCountedSet<WeakMember<ResourceClient>> clients_;
  HeapHashCountedSet<WeakMember<ResourceClient>> clients_awaiting_callback_;
  HeapHashCountedSet<WeakMember<ResourceClient>> finished_clients_;
  HeapHashSet<WeakMember<ResourceFinishObserver>> finish_observers_;

  ResourceLoaderOptions options_;

  double response_timestamp_;

  TaskHandle async_finish_pending_clients_task_;

  ResourceRequest resource_request_;
  Member<ResourceLoader> loader_;
  ResourceResponse response_;

  scoped_refptr<SharedBuffer> data_;

  WebScopedVirtualTimePauser virtual_time_pauser_;
};

class ResourceFactory {
  STACK_ALLOCATED();

 public:
  virtual Resource* Create(const ResourceRequest&,
                           const ResourceLoaderOptions&,
                           const TextResourceDecoderOptions&) const = 0;

  ResourceType GetType() const { return type_; }
  TextResourceDecoderOptions::ContentType ContentType() const {
    return content_type_;
  }

 protected:
  explicit ResourceFactory(ResourceType type,
                           TextResourceDecoderOptions::ContentType content_type)
      : type_(type), content_type_(content_type) {}

  ResourceType type_;
  TextResourceDecoderOptions::ContentType content_type_;
};

class NonTextResourceFactory : public ResourceFactory {
 protected:
  explicit NonTextResourceFactory(ResourceType type)
      : ResourceFactory(type, TextResourceDecoderOptions::kPlainTextContent) {}

  virtual Resource* Create(const ResourceRequest&,
                           const ResourceLoaderOptions&) const = 0;

  Resource* Create(const ResourceRequest& request,
                   const ResourceLoaderOptions& options,
                   const TextResourceDecoderOptions&) const final {
    return Create(request, options);
  }
};

#define DEFINE_RESOURCE_TYPE_CASTS(typeName)                          \
  DEFINE_TYPE_CASTS(typeName##Resource, Resource, resource,           \
                    resource->GetType() == ResourceType::k##typeName, \
                    resource.GetType() == ResourceType::k##typeName);

}  // namespace blink

#endif
