/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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 "core/loader/PingLoader.h"

#include "core/dom/ContextLifecycleObserver.h"
#include "core/dom/DOMArrayBufferView.h"
#include "core/dom/Document.h"
#include "core/dom/SecurityContext.h"
#include "core/fileapi/File.h"
#include "core/frame/FrameConsole.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/LocalFrameClient.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/FormData.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/MixedContentChecker.h"
#include "core/page/Page.h"
#include "platform/WebFrameScheduler.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/FetchInitiatorTypeNames.h"
#include "platform/loader/fetch/FetchUtils.h"
#include "platform/loader/fetch/ResourceError.h"
#include "platform/loader/fetch/ResourceFetcher.h"
#include "platform/loader/fetch/ResourceRequest.h"
#include "platform/loader/fetch/ResourceResponse.h"
#include "platform/loader/fetch/UniqueIdentifier.h"
#include "platform/network/EncodedFormData.h"
#include "platform/network/ParsedContentType.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/weborigin/SecurityPolicy.h"
#include "public/platform/Platform.h"
#include "public/platform/WebURLLoader.h"
#include "public/platform/WebURLRequest.h"
#include "public/platform/WebURLResponse.h"
#include "wtf/Compiler.h"
#include "wtf/Functional.h"
#include "wtf/PtrUtil.h"

namespace blink {

namespace {

class Beacon {
  STACK_ALLOCATED();

 public:
  virtual void serialize(ResourceRequest&) const = 0;
  virtual unsigned long long size() const = 0;
  virtual const AtomicString getContentType() const = 0;
};

class BeaconString final : public Beacon {
 public:
  explicit BeaconString(const String& data) : m_data(data) {}

  unsigned long long size() const override {
    return m_data.charactersSizeInBytes();
  }

  void serialize(ResourceRequest& request) const override {
    RefPtr<EncodedFormData> entityBody = EncodedFormData::create(m_data.utf8());
    request.setHTTPBody(entityBody);
    request.setHTTPContentType(getContentType());
  }

  const AtomicString getContentType() const {
    return AtomicString("text/plain;charset=UTF-8");
  }

 private:
  const String m_data;
};

class BeaconBlob final : public Beacon {
 public:
  explicit BeaconBlob(Blob* data) : m_data(data) {
    const String& blobType = m_data->type();
    if (!blobType.isEmpty() && ParsedContentType(blobType).isValid())
      m_contentType = AtomicString(blobType);
  }

  unsigned long long size() const override { return m_data->size(); }

  void serialize(ResourceRequest& request) const override {
    DCHECK(m_data);

    RefPtr<EncodedFormData> entityBody = EncodedFormData::create();
    if (m_data->hasBackingFile())
      entityBody->appendFile(toFile(m_data)->path());
    else
      entityBody->appendBlob(m_data->uuid(), m_data->blobDataHandle());

    request.setHTTPBody(std::move(entityBody));

    if (!m_contentType.isEmpty())
      request.setHTTPContentType(m_contentType);
  }

  const AtomicString getContentType() const { return m_contentType; }

 private:
  const Member<Blob> m_data;
  AtomicString m_contentType;
};

class BeaconDOMArrayBufferView final : public Beacon {
 public:
  explicit BeaconDOMArrayBufferView(DOMArrayBufferView* data) : m_data(data) {}

  unsigned long long size() const override { return m_data->byteLength(); }

  void serialize(ResourceRequest& request) const override {
    DCHECK(m_data);

    RefPtr<EncodedFormData> entityBody =
        EncodedFormData::create(m_data->baseAddress(), m_data->byteLength());
    request.setHTTPBody(std::move(entityBody));

    // FIXME: a reasonable choice, but not in the spec; should it give a
    // default?
    request.setHTTPContentType(AtomicString("application/octet-stream"));
  }

  const AtomicString getContentType() const { return nullAtom; }

 private:
  const Member<DOMArrayBufferView> m_data;
};

class BeaconFormData final : public Beacon {
 public:
  explicit BeaconFormData(FormData* data)
      : m_data(data), m_entityBody(m_data->encodeMultiPartFormData()) {
    m_contentType = AtomicString("multipart/form-data; boundary=") +
                    m_entityBody->boundary().data();
  }

  unsigned long long size() const override {
    return m_entityBody->sizeInBytes();
  }

  void serialize(ResourceRequest& request) const override {
    request.setHTTPBody(m_entityBody.get());
    request.setHTTPContentType(m_contentType);
  }

  const AtomicString getContentType() const { return m_contentType; }

 private:
  const Member<FormData> m_data;
  RefPtr<EncodedFormData> m_entityBody;
  AtomicString m_contentType;
};

class PingLoaderImpl : public GarbageCollectedFinalized<PingLoaderImpl>,
                       public ContextClient,
                       private WebURLLoaderClient {
  USING_GARBAGE_COLLECTED_MIXIN(PingLoaderImpl);
  WTF_MAKE_NONCOPYABLE(PingLoaderImpl);

 public:
  PingLoaderImpl(LocalFrame*,
                 ResourceRequest&,
                 const AtomicString&,
                 StoredCredentials,
                 bool);
  ~PingLoaderImpl() override;

  DECLARE_VIRTUAL_TRACE();

 private:
  void dispose();

  // WebURLLoaderClient
  bool willFollowRedirect(WebURLRequest&, const WebURLResponse&) override;
  void didReceiveResponse(const WebURLResponse&) final;
  void didReceiveData(const char*, int) final;
  void didFinishLoading(double, int64_t, int64_t encodedDataLength) final;
  void didFail(const WebURLError&, int64_t, int64_t encodedDataLength) final;

  void timeout(TimerBase*);

  void didFailLoading(LocalFrame*);

  std::unique_ptr<WebURLLoader> m_loader;
  Timer<PingLoaderImpl> m_timeout;
  String m_url;
  unsigned long m_identifier;
  SelfKeepAlive<PingLoaderImpl> m_keepAlive;
  AtomicString m_initiator;

  bool m_isBeacon;

  RefPtr<SecurityOrigin> m_origin;
  CORSEnabled m_corsMode;
};

PingLoaderImpl::PingLoaderImpl(LocalFrame* frame,
                               ResourceRequest& request,
                               const AtomicString& initiator,
                               StoredCredentials credentialsAllowed,
                               bool isBeacon)
    : ContextClient(frame),
      m_timeout(this, &PingLoaderImpl::timeout),
      m_url(request.url()),
      m_identifier(createUniqueIdentifier()),
      m_keepAlive(this),
      m_initiator(initiator),
      m_isBeacon(isBeacon),
      m_origin(frame->document()->getSecurityOrigin()),
      m_corsMode(IsCORSEnabled) {
  const AtomicString contentType = request.httpContentType();
  if (!contentType.isNull() &&
      FetchUtils::isSimpleHeader(AtomicString("content-type"), contentType))
    m_corsMode = NotCORSEnabled;

  frame->loader().client()->didDispatchPingLoader(request.url());

  FetchContext& fetchContext = frame->document()->fetcher()->context();

  fetchContext.willStartLoadingResource(
      m_identifier, request, Resource::Image, initiator,
      FetchContext::V8ActivityLoggingPolicy::Log);

  FetchInitiatorInfo initiatorInfo;
  initiatorInfo.name = initiator;
  fetchContext.dispatchWillSendRequest(m_identifier, request,
                                       ResourceResponse(), initiatorInfo);

  // Make sure the scheduler doesn't wait for the ping.
  if (frame->frameScheduler())
    frame->frameScheduler()->didStopLoading(m_identifier);

  m_loader = WTF::wrapUnique(Platform::current()->createURLLoader());
  DCHECK(m_loader);
  WrappedResourceRequest wrappedRequest(request);
  wrappedRequest.setAllowStoredCredentials(credentialsAllowed ==
                                           AllowStoredCredentials);
  m_loader->loadAsynchronously(wrappedRequest, this);

  // If the server never responds, FrameLoader won't be able to cancel this load
  // and we'll sit here waiting forever. Set a very generous timeout, just in
  // case.
  m_timeout.startOneShot(60000, BLINK_FROM_HERE);
}

PingLoaderImpl::~PingLoaderImpl() {
  if (m_loader)
    m_loader->cancel();
}

void PingLoaderImpl::dispose() {
  if (m_loader) {
    m_loader->cancel();
    m_loader = nullptr;
  }
  m_timeout.stop();
  m_keepAlive.clear();
}

bool PingLoaderImpl::willFollowRedirect(
    WebURLRequest& passedNewRequest,
    const WebURLResponse& passedRedirectResponse) {
  if (m_isBeacon && m_corsMode == IsCORSEnabled) {
    DCHECK(passedNewRequest.allowStoredCredentials());

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

    DCHECK(!newRequest.isNull());
    DCHECK(!redirectResponse.isNull());

    String errorDescription;
    ResourceLoaderOptions options;
    // TODO(tyoshino): Save updated data in options.securityOrigin and pass it
    // on the next time.
    if (!CrossOriginAccessControl::handleRedirect(
            m_origin, newRequest, redirectResponse, AllowStoredCredentials,
            options, errorDescription)) {
      if (frame()) {
        if (frame()->document()) {
          frame()->document()->addConsoleMessage(ConsoleMessage::create(
              JSMessageSource, ErrorMessageLevel, errorDescription));
        }
      }
      // Cancel the load and self destruct.
      dispose();

      return false;
    }
  }
  // FIXME: http://crbug.com/427429 is needed to correctly propagate updates of
  // Origin: following this successful redirect.

  if (frame() && frame()->document()) {
    FetchInitiatorInfo initiatorInfo;
    initiatorInfo.name = m_initiator;
    FetchContext& fetchContext = frame()->document()->fetcher()->context();
    fetchContext.dispatchWillSendRequest(
        m_identifier, passedNewRequest.toMutableResourceRequest(),
        passedRedirectResponse.toResourceResponse(), initiatorInfo);
  }

  return true;
}

void PingLoaderImpl::didReceiveResponse(const WebURLResponse& response) {
  if (frame()) {
    const ResourceResponse& resourceResponse = response.toResourceResponse();
    probe::didReceiveResourceResponse(frame(), m_identifier, 0,
                                      resourceResponse, 0);
    didFailLoading(frame());
  }
  dispose();
}

void PingLoaderImpl::didReceiveData(const char*, int dataLength) {
  if (frame())
    didFailLoading(frame());
  dispose();
}

void PingLoaderImpl::didFinishLoading(double,
                                      int64_t,
                                      int64_t encodedDataLength) {
  if (frame())
    didFailLoading(frame());
  dispose();
}

void PingLoaderImpl::didFail(const WebURLError& resourceError,
                             int64_t,
                             int64_t encodedDataLength) {
  if (frame())
    didFailLoading(frame());
  dispose();
}

void PingLoaderImpl::timeout(TimerBase*) {
  if (frame())
    didFailLoading(frame());
  dispose();
}

void PingLoaderImpl::didFailLoading(LocalFrame* frame) {
  probe::didFailLoading(frame, m_identifier,
                        ResourceError::cancelledError(m_url));
  frame->console().didFailLoading(m_identifier,
                                  ResourceError::cancelledError(m_url));
}

DEFINE_TRACE(PingLoaderImpl) {
  ContextClient::trace(visitor);
}

void finishPingRequestInitialization(
    ResourceRequest& request,
    LocalFrame* frame,
    WebURLRequest::RequestContext requestContext) {
  request.setRequestContext(requestContext);
  FetchContext& fetchContext = frame->document()->fetcher()->context();
  fetchContext.addAdditionalRequestHeaders(request, FetchSubresource);
  // TODO(tyoshino): Call populateResourceRequest() if appropriate.
  fetchContext.setFirstPartyCookieAndRequestorOrigin(request);
}

bool sendPingCommon(LocalFrame* frame,
                    ResourceRequest& request,
                    const AtomicString& initiator,
                    StoredCredentials credentialsAllowed,
                    bool isBeacon) {
  if (MixedContentChecker::shouldBlockFetch(frame, request, request.url()))
    return false;

  // The loader keeps itself alive until it receives a response and disposes
  // itself.
  PingLoaderImpl* loader =
      new PingLoaderImpl(frame, request, initiator, credentialsAllowed, true);
  DCHECK(loader);

  return true;
}

bool sendBeaconCommon(LocalFrame* frame,
                      int allowance,
                      const KURL& url,
                      const Beacon& beacon,
                      int& payloadLength) {
  if (!frame->document())
    return false;

  unsigned long long entitySize = beacon.size();
  if (allowance < 0 || static_cast<unsigned long long>(allowance) < entitySize)
    return false;

  payloadLength = entitySize;

  ResourceRequest request(url);
  request.setHTTPMethod(HTTPNames::POST);
  request.setHTTPHeaderField(HTTPNames::Cache_Control, "max-age=0");
  finishPingRequestInitialization(request, frame,
                                  WebURLRequest::RequestContextBeacon);

  beacon.serialize(request);

  return sendPingCommon(frame, request, FetchInitiatorTypeNames::beacon,
                        AllowStoredCredentials, true);
}

}  // namespace

void PingLoader::loadImage(LocalFrame* frame, const KURL& url) {
  if (!frame->document()->getSecurityOrigin()->canDisplay(url)) {
    FrameLoader::reportLocalLoadFailed(frame, url.getString());
    return;
  }

  ResourceRequest request(url);
  request.setHTTPHeaderField(HTTPNames::Cache_Control, "max-age=0");
  finishPingRequestInitialization(request, frame,
                                  WebURLRequest::RequestContextPing);

  sendPingCommon(frame, request, FetchInitiatorTypeNames::ping,
                 AllowStoredCredentials, false);
}

// http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#hyperlink-auditing
void PingLoader::sendLinkAuditPing(LocalFrame* frame,
                                   const KURL& pingURL,
                                   const KURL& destinationURL) {
  if (!pingURL.protocolIsInHTTPFamily())
    return;

  if (ContentSecurityPolicy* policy =
          frame->securityContext()->contentSecurityPolicy()) {
    if (!policy->allowConnectToSource(pingURL))
      return;
  }

  ResourceRequest request(pingURL);
  request.setHTTPMethod(HTTPNames::POST);
  request.setHTTPContentType("text/ping");
  request.setHTTPBody(EncodedFormData::create("PING"));
  request.setHTTPHeaderField(HTTPNames::Cache_Control, "max-age=0");
  finishPingRequestInitialization(request, frame,
                                  WebURLRequest::RequestContextPing);

  // addAdditionalRequestHeaders() will have added a referrer for same origin
  // requests, but the spec omits the referrer.
  request.clearHTTPReferrer();

  request.setHTTPHeaderField(HTTPNames::Ping_To,
                             AtomicString(destinationURL.getString()));

  RefPtr<SecurityOrigin> pingOrigin = SecurityOrigin::create(pingURL);
  if (protocolIs(frame->document()->url().getString(), "http") ||
      frame->document()->getSecurityOrigin()->canAccess(pingOrigin.get())) {
    request.setHTTPHeaderField(
        HTTPNames::Ping_From,
        AtomicString(frame->document()->url().getString()));
  }

  sendPingCommon(frame, request, FetchInitiatorTypeNames::ping,
                 AllowStoredCredentials, false);
}

void PingLoader::sendViolationReport(LocalFrame* frame,
                                     const KURL& reportURL,
                                     PassRefPtr<EncodedFormData> report,
                                     ViolationReportType type) {
  ResourceRequest request(reportURL);
  request.setHTTPMethod(HTTPNames::POST);
  switch (type) {
    case ContentSecurityPolicyViolationReport:
      request.setHTTPContentType("application/csp-report");
      break;
    case XSSAuditorViolationReport:
      request.setHTTPContentType("application/xss-auditor-report");
      break;
  }
  request.setHTTPBody(std::move(report));
  finishPingRequestInitialization(request, frame,
                                  WebURLRequest::RequestContextCSPReport);

  StoredCredentials credentialsAllowed =
      SecurityOrigin::create(reportURL)->isSameSchemeHostPort(
          frame->document()->getSecurityOrigin())
          ? AllowStoredCredentials
          : DoNotAllowStoredCredentials;
  sendPingCommon(frame, request, FetchInitiatorTypeNames::violationreport,
                 credentialsAllowed, false);
}

bool PingLoader::sendBeacon(LocalFrame* frame,
                            int allowance,
                            const KURL& beaconURL,
                            const String& data,
                            int& payloadLength) {
  BeaconString beacon(data);
  return sendBeaconCommon(frame, allowance, beaconURL, beacon, payloadLength);
}

bool PingLoader::sendBeacon(LocalFrame* frame,
                            int allowance,
                            const KURL& beaconURL,
                            DOMArrayBufferView* data,
                            int& payloadLength) {
  BeaconDOMArrayBufferView beacon(data);
  return sendBeaconCommon(frame, allowance, beaconURL, beacon, payloadLength);
}

bool PingLoader::sendBeacon(LocalFrame* frame,
                            int allowance,
                            const KURL& beaconURL,
                            FormData* data,
                            int& payloadLength) {
  BeaconFormData beacon(data);
  return sendBeaconCommon(frame, allowance, beaconURL, beacon, payloadLength);
}

bool PingLoader::sendBeacon(LocalFrame* frame,
                            int allowance,
                            const KURL& beaconURL,
                            Blob* data,
                            int& payloadLength) {
  BeaconBlob beacon(data);
  return sendBeaconCommon(frame, allowance, beaconURL, beacon, payloadLength);
}

}  // namespace blink
