// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/renderer/security_filter_peer.h"

#include <memory>
#include <string>
#include <utility>

#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/renderer/fixed_received_data.h"
#include "net/base/escape.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "ui/base/l10n/l10n_util.h"

SecurityFilterPeer::SecurityFilterPeer(
    std::unique_ptr<content::RequestPeer> peer,
    const std::string& mime_type,
    const std::string& data)
    : original_peer_(std::move(peer)), mime_type_(mime_type), data_(data) {}
SecurityFilterPeer::~SecurityFilterPeer() {}

// static
std::unique_ptr<content::RequestPeer>
SecurityFilterPeer::CreateSecurityFilterPeerForDeniedRequest(
    content::ResourceType resource_type,
    std::unique_ptr<content::RequestPeer> peer,
    int os_error) {
  // Create a filter for SSL and CERT errors.
  switch (os_error) {
    case net::ERR_SSL_PROTOCOL_ERROR:
    case net::ERR_CERT_COMMON_NAME_INVALID:
    case net::ERR_CERT_DATE_INVALID:
    case net::ERR_CERT_AUTHORITY_INVALID:
    case net::ERR_CERT_CONTAINS_ERRORS:
    case net::ERR_CERT_NO_REVOCATION_MECHANISM:
    case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
    case net::ERR_CERT_REVOKED:
    case net::ERR_CERT_INVALID:
    case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
    case net::ERR_CERT_WEAK_KEY:
    case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION:
    case net::ERR_INSECURE_RESPONSE:
    case net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN: {
      std::string mime_type;
      std::string data;
      if (content::IsResourceTypeFrame(resource_type)) {
        // TODO(jcampan): use a different message when getting a
        // phishing/malware error.
        data = base::StringPrintf(
            "<html><meta charset='UTF-8'>"
            "<body style='background-color:#990000;color:white;'>"
            "%s</body></html>",
            net::EscapeForHTML(
                l10n_util::GetStringUTF8(IDS_UNSAFE_FRAME_MESSAGE))
                .c_str());
        mime_type = "text/html";
      }
      return base::WrapUnique(
          new SecurityFilterPeer(std::move(peer), mime_type, data));
    }
    default:
      // For other errors, we use our normal error handling.
      return peer;
  }
}

void SecurityFilterPeer::OnUploadProgress(uint64_t position, uint64_t size) {
  NOTREACHED();
}

bool SecurityFilterPeer::OnReceivedRedirect(
    const net::RedirectInfo& redirect_info,
    const network::ResourceResponseInfo& info) {
  NOTREACHED();
  return false;
}

void SecurityFilterPeer::OnReceivedResponse(
    const network::ResourceResponseInfo& info) {
  NOTREACHED();
}

void SecurityFilterPeer::OnStartLoadingResponseBody(
    mojo::ScopedDataPipeConsumerHandle body) {
  NOTREACHED();
}

void SecurityFilterPeer::OnReceivedData(std::unique_ptr<ReceivedData> data) {
  NOTREACHED();
}

void SecurityFilterPeer::OnTransferSizeUpdated(int transfer_size_diff) {
  NOTREACHED();
}

void SecurityFilterPeer::OnCompletedRequest(
    const network::URLLoaderCompletionStatus& status) {
  network::ResourceResponseInfo info;
  info.mime_type = mime_type_;
  info.headers = CreateHeaders(mime_type_);
  info.content_length = static_cast<int>(data_.size());
  original_peer_->OnReceivedResponse(info);
  if (!data_.empty()) {
    original_peer_->OnReceivedData(std::make_unique<content::FixedReceivedData>(
        data_.data(), data_.size()));
  }
  network::URLLoaderCompletionStatus ok_status(status);
  ok_status.error_code = net::OK;
  original_peer_->OnCompletedRequest(ok_status);
}

scoped_refptr<base::TaskRunner> SecurityFilterPeer::GetTaskRunner() {
  return original_peer_->GetTaskRunner();
}

scoped_refptr<net::HttpResponseHeaders> SecurityFilterPeer::CreateHeaders(
    const std::string& mime_type) {
  std::string raw_headers;
  raw_headers.append("HTTP/1.1 200 OK");
  raw_headers.push_back('\0');
  // Don't cache the data we are serving, it is not the real data for that URL
  // (if the filtered resource were to make it into the WebCore cache, then the
  // same URL loaded in a safe scenario would still return the filtered
  // resource).
  raw_headers.append("cache-control: no-cache");
  raw_headers.push_back('\0');
  if (!mime_type.empty()) {
    raw_headers.append("content-type: ");
    raw_headers.append(mime_type);
    raw_headers.push_back('\0');
  }
  raw_headers.push_back('\0');
  return base::MakeRefCounted<net::HttpResponseHeaders>(raw_headers);
}
