/*
 * Copyright (C) 2006, 2007, 2010, 2011 Apple Inc. All rights reserved.
 *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "platform/loader/fetch/ResourceLoader.h"

#include "platform/SharedBuffer.h"
#include "platform/exported/WrappedResourceRequest.h"
#include "platform/exported/WrappedResourceResponse.h"
#include "platform/loader/fetch/CrossOriginAccessControl.h"
#include "platform/loader/fetch/FetchContext.h"
#include "platform/loader/fetch/Resource.h"
#include "platform/loader/fetch/ResourceFetcher.h"
#include "platform/network/NetworkInstrumentation.h"
#include "platform/network/ResourceError.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCachePolicy.h"
#include "public/platform/WebData.h"
#include "public/platform/WebURLError.h"
#include "public/platform/WebURLRequest.h"
#include "public/platform/WebURLResponse.h"
#include "wtf/Assertions.h"
#include "wtf/CurrentTime.h"
#include "wtf/PtrUtil.h"
#include "wtf/text/StringBuilder.h"
#include <memory>

namespace blink {

ResourceLoader* ResourceLoader::create(ResourceFetcher* fetcher,
                                       Resource* resource) {
  return new ResourceLoader(fetcher, resource);
}

ResourceLoader::ResourceLoader(ResourceFetcher* fetcher, Resource* resource)
    : m_fetcher(fetcher),
      m_resource(resource),
      m_isCacheAwareLoadingActivated(false) {
  DCHECK(m_resource);
  DCHECK(m_fetcher);

  m_resource->setLoader(this);
}

ResourceLoader::~ResourceLoader() {}

DEFINE_TRACE(ResourceLoader) {
  visitor->trace(m_fetcher);
  visitor->trace(m_resource);
}

void ResourceLoader::start(const ResourceRequest& request) {
  DCHECK(!m_loader);

  if (m_resource->options().synchronousPolicy == RequestSynchronously &&
      context().defersLoading()) {
    cancel();
    return;
  }

  m_loader = WTF::wrapUnique(Platform::current()->createURLLoader());
  DCHECK(m_loader);
  m_loader->setDefersLoading(context().defersLoading());
  m_loader->setLoadingTaskRunner(context().loadingTaskRunner().get());

  if (m_isCacheAwareLoadingActivated) {
    // Override cache policy for cache-aware loading. If this request fails, a
    // reload with original request will be triggered in didFail().
    ResourceRequest cacheAwareRequest(request);
    cacheAwareRequest.setCachePolicy(WebCachePolicy::ReturnCacheDataIfValid);
    m_loader->loadAsynchronously(WrappedResourceRequest(cacheAwareRequest),
                                 this);
    return;
  }

  if (m_resource->options().synchronousPolicy == RequestSynchronously)
    requestSynchronously(request);
  else
    m_loader->loadAsynchronously(WrappedResourceRequest(request), this);
}

void ResourceLoader::restart(const ResourceRequest& request) {
  CHECK_EQ(m_resource->options().synchronousPolicy, RequestAsynchronously);

  m_loader.reset();
  start(request);
}

void ResourceLoader::setDefersLoading(bool defers) {
  DCHECK(m_loader);

  m_loader->setDefersLoading(defers);
}

void ResourceLoader::didChangePriority(ResourceLoadPriority loadPriority,
                                       int intraPriorityValue) {
  if (m_loader) {
    m_loader->didChangePriority(
        static_cast<WebURLRequest::Priority>(loadPriority), intraPriorityValue);
  }
}

void ResourceLoader::cancel() {
  handleError(
      ResourceError::cancelledError(m_resource->lastResourceRequest().url()));
}

void ResourceLoader::cancelForRedirectAccessCheckError(
    const KURL& newURL,
    ResourceRequestBlockedReason blockedReason) {
  m_resource->willNotFollowRedirect();

  if (m_loader) {
    handleError(
        ResourceError::cancelledDueToAccessCheckError(newURL, blockedReason));
  }
}

static bool isManualRedirectFetchRequest(const ResourceRequest& request) {
  return request.fetchRedirectMode() ==
             WebURLRequest::FetchRedirectModeManual &&
         request.requestContext() == WebURLRequest::RequestContextFetch;
}

bool ResourceLoader::willFollowRedirect(
    WebURLRequest& passedNewRequest,
    const WebURLResponse& passedRedirectResponse) {
  DCHECK(!passedNewRequest.isNull());
  DCHECK(!passedRedirectResponse.isNull());

  if (m_isCacheAwareLoadingActivated) {
    // Fail as cache miss if cached response is a redirect.
    handleError(
        ResourceError::cacheMissError(m_resource->lastResourceRequest().url()));
    return false;
  }

  ResourceRequest& newRequest(passedNewRequest.toMutableResourceRequest());
  const ResourceResponse& redirectResponse(
      passedRedirectResponse.toResourceResponse());

  newRequest.setRedirectStatus(
      ResourceRequest::RedirectStatus::FollowedRedirect);

  const KURL originalURL = newRequest.url();

  if (!isManualRedirectFetchRequest(m_resource->resourceRequest())) {
    ResourceRequestBlockedReason blockedReason = context().canRequest(
        m_resource->getType(), newRequest, newRequest.url(),
        m_resource->options(),
        /* Don't send security violation reports for unused preloads */
        (m_resource->isUnusedPreload()
             ? FetchContext::SecurityViolationReportingPolicy::SuppressReporting
             : FetchContext::SecurityViolationReportingPolicy::Report),
        FetchRequest::UseDefaultOriginRestrictionForType);
    if (blockedReason != ResourceRequestBlockedReason::None) {
      cancelForRedirectAccessCheckError(newRequest.url(), blockedReason);
      return false;
    }

    if (m_resource->options().corsEnabled == IsCORSEnabled) {
      RefPtr<SecurityOrigin> sourceOrigin =
          m_resource->options().securityOrigin;
      if (!sourceOrigin.get())
        sourceOrigin = context().getSecurityOrigin();

      String errorMessage;
      StoredCredentials withCredentials =
          m_resource->lastResourceRequest().allowStoredCredentials()
              ? AllowStoredCredentials
              : DoNotAllowStoredCredentials;
      if (!CrossOriginAccessControl::handleRedirect(
              sourceOrigin, newRequest, redirectResponse, withCredentials,
              m_resource->mutableOptions(), errorMessage)) {
        m_resource->setCORSFailed();
        context().addConsoleMessage(errorMessage);
        cancelForRedirectAccessCheckError(newRequest.url(),
                                          ResourceRequestBlockedReason::Other);
        return false;
      }
    }
    if (m_resource->getType() == Resource::Image &&
        m_fetcher->shouldDeferImageLoad(newRequest.url())) {
      cancelForRedirectAccessCheckError(newRequest.url(),
                                        ResourceRequestBlockedReason::Other);
      return false;
    }
  }

  bool crossOrigin = !SecurityOrigin::areSameSchemeHostPort(
      redirectResponse.url(), newRequest.url());
  m_fetcher->recordResourceTimingOnRedirect(m_resource.get(), redirectResponse,
                                            crossOrigin);

  newRequest.setAllowStoredCredentials(m_resource->options().allowCredentials ==
                                       AllowStoredCredentials);

  context().dispatchWillSendRequest(m_resource->identifier(), newRequest,
                                    redirectResponse,
                                    m_resource->options().initiatorInfo);

  // ResourceFetcher::willFollowRedirect() may rewrite the URL to
  // something else not for rejecting redirect but for other reasons.
  // E.g. WebFrameTestClient::willSendRequest() and
  // RenderFrameImpl::willSendRequest(). We should reflect the
  // rewriting but currently we cannot. So, return false to make the
  // redirect fail.
  if (newRequest.url() != originalURL) {
    cancelForRedirectAccessCheckError(newRequest.url(),
                                      ResourceRequestBlockedReason::Other);
    return false;
  }

  if (!m_resource->willFollowRedirect(newRequest, redirectResponse)) {
    cancelForRedirectAccessCheckError(newRequest.url(),
                                      ResourceRequestBlockedReason::Other);
    return false;
  }

  return true;
}

void ResourceLoader::didReceiveCachedMetadata(const char* data, int length) {
  m_resource->setSerializedCachedMetadata(data, length);
}

void ResourceLoader::didSendData(unsigned long long bytesSent,
                                 unsigned long long totalBytesToBeSent) {
  m_resource->didSendData(bytesSent, totalBytesToBeSent);
}

FetchContext& ResourceLoader::context() const {
  return m_fetcher->context();
}

ResourceRequestBlockedReason ResourceLoader::canAccessResponse(
    Resource* resource,
    const ResourceResponse& response) const {
  // Redirects can change the response URL different from one of request.
  bool unusedPreload = resource->isUnusedPreload();
  ResourceRequestBlockedReason blockedReason = context().canRequest(
      resource->getType(), resource->resourceRequest(), response.url(),
      resource->options(),
      /* Don't send security violation reports for unused preloads */
      (unusedPreload
           ? FetchContext::SecurityViolationReportingPolicy::SuppressReporting
           : FetchContext::SecurityViolationReportingPolicy::Report),
      FetchRequest::UseDefaultOriginRestrictionForType);
  if (blockedReason != ResourceRequestBlockedReason::None)
    return blockedReason;

  SecurityOrigin* sourceOrigin = resource->options().securityOrigin.get();
  if (!sourceOrigin)
    sourceOrigin = context().getSecurityOrigin();

  if (sourceOrigin->canRequestNoSuborigin(response.url()))
    return ResourceRequestBlockedReason::None;

  // Use the original response instead of the 304 response for a successful
  // revaldiation.
  const ResourceResponse& responseForAccessControl =
      (resource->isCacheValidator() && response.httpStatusCode() == 304)
          ? resource->response()
          : response;

  CrossOriginAccessControl::AccessStatus corsStatus =
      CrossOriginAccessControl::checkAccess(
          responseForAccessControl, resource->options().allowCredentials,
          sourceOrigin);
  if (corsStatus != CrossOriginAccessControl::kAccessAllowed) {
    resource->setCORSFailed();
    if (!unusedPreload) {
      String resourceType = Resource::resourceTypeToString(
          resource->getType(), resource->options().initiatorInfo.name);
      StringBuilder builder;
      builder.append("Access to ");
      builder.append(resourceType);
      builder.append(" at '");
      builder.append(response.url().getString());
      builder.append("' from origin '");
      builder.append(sourceOrigin->toString());
      builder.append("' has been blocked by CORS policy: ");
      CrossOriginAccessControl::accessControlErrorString(
          builder, corsStatus, responseForAccessControl, sourceOrigin,
          resource->lastResourceRequest().requestContext());
      context().addConsoleMessage(builder.toString());
    }
    return ResourceRequestBlockedReason::Other;
  }
  return ResourceRequestBlockedReason::None;
}

void ResourceLoader::didReceiveResponse(
    const WebURLResponse& webURLResponse,
    std::unique_ptr<WebDataConsumerHandle> handle) {
  DCHECK(!webURLResponse.isNull());

  const ResourceResponse& response = webURLResponse.toResourceResponse();

  if (response.wasFetchedViaServiceWorker()) {
    if (m_resource->options().corsEnabled == IsCORSEnabled &&
        response.wasFallbackRequiredByServiceWorker()) {
      ResourceRequest request = m_resource->lastResourceRequest();
      DCHECK_EQ(request.getServiceWorkerMode(),
                WebURLRequest::ServiceWorkerMode::All);
      // This code handles the case when a regular controlling service worker
      // doesn't handle a cross origin request. When this happens we still want
      // to give foreign fetch a chance to handle the request, so only skip the
      // controlling service worker for the fallback request. This is currently
      // safe because of http://crbug.com/604084 the
      // wasFallbackRequiredByServiceWorker flag is never set when foreign fetch
      // handled a request.
      if (!context().shouldLoadNewResource(m_resource->getType())) {
        // Cancel the request if we should not trigger a reload now.
        handleError(ResourceError::cancelledError(response.url()));
        return;
      }
      request.setServiceWorkerMode(WebURLRequest::ServiceWorkerMode::Foreign);
      restart(request);
      return;
    }

    // If the response is fetched via ServiceWorker, the original URL of the
    // response could be different from the URL of the request. We check the URL
    // not to load the resources which are forbidden by the page CSP.
    // https://w3c.github.io/webappsec-csp/#should-block-response
    const KURL& originalURL = response.originalURLViaServiceWorker();
    if (!originalURL.isEmpty()) {
      ResourceRequestBlockedReason blockedReason = context().allowResponse(
          m_resource->getType(), m_resource->resourceRequest(), originalURL,
          m_resource->options());
      if (blockedReason != ResourceRequestBlockedReason::None) {
        handleError(ResourceError::cancelledDueToAccessCheckError(
            originalURL, blockedReason));
        return;
      }
    }
  } else if (m_resource->options().corsEnabled == IsCORSEnabled) {
    ResourceRequestBlockedReason blockedReason =
        canAccessResponse(m_resource, response);
    if (blockedReason != ResourceRequestBlockedReason::None) {
      handleError(ResourceError::cancelledDueToAccessCheckError(response.url(),
                                                                blockedReason));
      return;
    }
  }

  context().dispatchDidReceiveResponse(
      m_resource->identifier(), response,
      m_resource->resourceRequest().frameType(),
      m_resource->resourceRequest().requestContext(), m_resource);

  m_resource->responseReceived(response, std::move(handle));
  if (!m_resource->loader())
    return;

  if (response.httpStatusCode() >= 400 &&
      !m_resource->shouldIgnoreHTTPStatusCodeErrors())
    handleError(ResourceError::cancelledError(response.url()));
}

void ResourceLoader::didReceiveResponse(const WebURLResponse& response) {
  didReceiveResponse(response, nullptr);
}

void ResourceLoader::didDownloadData(int length, int encodedDataLength) {
  context().dispatchDidDownloadData(m_resource->identifier(), length,
                                    encodedDataLength);
  m_resource->didDownloadData(length);
}

void ResourceLoader::didReceiveData(const char* data, int length) {
  CHECK_GE(length, 0);

  context().dispatchDidReceiveData(m_resource->identifier(), data, length);
  m_resource->addToDecodedBodyLength(length);
  m_resource->appendData(data, length);
}

void ResourceLoader::didReceiveTransferSizeUpdate(int transferSizeDiff) {
  DCHECK_GT(transferSizeDiff, 0);
  context().dispatchDidReceiveEncodedData(m_resource->identifier(),
                                          transferSizeDiff);
}

void ResourceLoader::didFinishLoadingFirstPartInMultipart() {
  network_instrumentation::endResourceLoad(
      m_resource->identifier(),
      network_instrumentation::RequestOutcome::Success);

  m_fetcher->handleLoaderFinish(m_resource.get(), 0,
                                ResourceFetcher::DidFinishFirstPartInMultipart);
}

void ResourceLoader::didFinishLoading(double finishTime,
                                      int64_t encodedDataLength,
                                      int64_t encodedBodyLength) {
  m_resource->setEncodedDataLength(encodedDataLength);
  m_resource->addToEncodedBodyLength(encodedBodyLength);

  m_loader.reset();

  network_instrumentation::endResourceLoad(
      m_resource->identifier(),
      network_instrumentation::RequestOutcome::Success);

  m_fetcher->handleLoaderFinish(m_resource.get(), finishTime,
                                ResourceFetcher::DidFinishLoading);
}

void ResourceLoader::didFail(const WebURLError& error,
                             int64_t encodedDataLength,
                             int64_t encodedBodyLength) {
  m_resource->setEncodedDataLength(encodedDataLength);
  m_resource->addToEncodedBodyLength(encodedBodyLength);
  handleError(error);
}

void ResourceLoader::handleError(const ResourceError& error) {
  if (m_isCacheAwareLoadingActivated && error.isCacheMiss() &&
      context().shouldLoadNewResource(m_resource->getType())) {
    m_resource->willReloadAfterDiskCacheMiss();
    m_isCacheAwareLoadingActivated = false;
    restart(m_resource->resourceRequest());
    return;
  }

  m_loader.reset();

  network_instrumentation::endResourceLoad(
      m_resource->identifier(), network_instrumentation::RequestOutcome::Fail);

  m_fetcher->handleLoaderError(m_resource.get(), error);
}

void ResourceLoader::requestSynchronously(const ResourceRequest& request) {
  // downloadToFile is not supported for synchronous requests.
  DCHECK(!request.downloadToFile());
  DCHECK(m_loader);
  DCHECK_EQ(request.priority(), ResourceLoadPriorityHighest);

  WrappedResourceRequest requestIn(request);
  WebURLResponse responseOut;
  WebURLError errorOut;
  WebData dataOut;
  int64_t encodedDataLength = WebURLLoaderClient::kUnknownEncodedDataLength;
  int64_t encodedBodyLength = 0;
  m_loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut,
                              encodedDataLength, encodedBodyLength);

  // A message dispatched while synchronously fetching the resource
  // can bring about the cancellation of this load.
  if (!m_loader)
    return;
  if (errorOut.reason) {
    didFail(errorOut, encodedDataLength, encodedBodyLength);
    return;
  }
  didReceiveResponse(responseOut);
  if (!m_loader)
    return;
  DCHECK_GE(responseOut.toResourceResponse().encodedBodyLength(), 0);

  // Follow the async case convention of not calling didReceiveData or
  // appending data to m_resource if the response body is empty. Copying the
  // empty buffer is a noop in most cases, but is destructive in the case of
  // a 304, where it will overwrite the cached data we should be reusing.
  if (dataOut.size()) {
    context().dispatchDidReceiveData(m_resource->identifier(), dataOut.data(),
                                     dataOut.size());
    m_resource->setResourceBuffer(dataOut);
  }
  didFinishLoading(monotonicallyIncreasingTime(), encodedDataLength,
                   encodedBodyLength);
}

void ResourceLoader::dispose() {
  m_loader = nullptr;
}

void ResourceLoader::activateCacheAwareLoadingIfNeeded(
    const ResourceRequest& request) {
  DCHECK(!m_isCacheAwareLoadingActivated);

  if (m_resource->options().cacheAwareLoadingEnabled !=
      IsCacheAwareLoadingEnabled)
    return;

  // Synchronous requests are not supported.
  if (m_resource->options().synchronousPolicy == RequestSynchronously)
    return;

  // Don't activate on Resource revalidation.
  if (m_resource->isCacheValidator())
    return;

  // Don't activate if cache policy is explicitly set.
  if (request.getCachePolicy() != WebCachePolicy::UseProtocolCachePolicy)
    return;

  m_isCacheAwareLoadingActivated = true;
}

}  // namespace blink
