// Copyright 2017 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 "extensions/browser/api/web_request/web_request_info.h"

#include <memory>
#include <string>

#include "base/files/file_path.h"
#include "base/values.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/websocket_handshake_request_info.h"
#include "extensions/browser/api/web_request/upload_data_presenter.h"
#include "extensions/browser/api/web_request/web_request_api_constants.h"
#include "extensions/browser/extension_api_frame_id_map.h"
#include "extensions/browser/extension_navigation_ui_data.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/base/upload_file_element_reader.h"
#include "net/log/net_log_with_source.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/resource_response.h"

namespace keys = extension_web_request_api_constants;

namespace extensions {

namespace {

// UploadDataSource abstracts an interface for feeding an arbitrary data element
// to an UploadDataPresenter. This is helpful because in the Network Service vs
// non-Network Service case, upload data comes from different types of source
// objects, but we'd like to share parsing code.
class UploadDataSource {
 public:
  virtual ~UploadDataSource() {}

  virtual void FeedToPresenter(UploadDataPresenter* presenter) = 0;
};

class BytesUploadDataSource : public UploadDataSource {
 public:
  BytesUploadDataSource(const base::StringPiece& bytes) : bytes_(bytes) {}
  ~BytesUploadDataSource() override = default;

  // UploadDataSource:
  void FeedToPresenter(UploadDataPresenter* presenter) override {
    presenter->FeedBytes(bytes_);
  }

 private:
  base::StringPiece bytes_;

  DISALLOW_COPY_AND_ASSIGN(BytesUploadDataSource);
};

class FileUploadDataSource : public UploadDataSource {
 public:
  FileUploadDataSource(const base::FilePath& path) : path_(path) {}
  ~FileUploadDataSource() override = default;

  // UploadDataSource:
  void FeedToPresenter(UploadDataPresenter* presenter) override {
    presenter->FeedFile(path_);
  }

 private:
  base::FilePath path_;

  DISALLOW_COPY_AND_ASSIGN(FileUploadDataSource);
};

std::unique_ptr<base::Value> NetLogExtensionIdCallback(
    const std::string& extension_id,
    net::NetLogCaptureMode capture_mode) {
  auto params = std::make_unique<base::DictionaryValue>();
  params->SetString("extension_id", extension_id);
  return params;
}

// Implements Logger using NetLog, mirroring the logging facilities used prior
// to the introduction of WebRequestInfo.
// TODO(crbug.com/721414): Transition away from using NetLog.
class NetLogLogger : public WebRequestInfo::Logger {
 public:
  explicit NetLogLogger(net::URLRequest* request) : request_(request) {}
  ~NetLogLogger() override = default;

  // WebRequestInfo::Logger:
  void LogEvent(net::NetLogEventType event_type,
                const std::string& extension_id) override {
    request_->net_log().AddEvent(
        event_type,
        base::BindRepeating(&NetLogExtensionIdCallback, extension_id));
  }

  void LogBlockedBy(const std::string& blocker_info) override {
    // LogAndReport allows extensions that block requests to be displayed in the
    // load status bar.
    request_->LogAndReportBlockedBy(blocker_info.c_str());
  }

  void LogUnblocked() override { request_->LogUnblocked(); }

 private:
  net::URLRequest* const request_;

  DISALLOW_COPY_AND_ASSIGN(NetLogLogger);
};

// TODO(https://crbug.com/721414): Need a real implementation here to support
// the Network Service case. For now this is only to prevent crashing.
class NetworkServiceLogger : public WebRequestInfo::Logger {
 public:
  NetworkServiceLogger() = default;
  ~NetworkServiceLogger() override = default;

  // WebRequestInfo::Logger:
  void LogEvent(net::NetLogEventType event_type,
                const std::string& extension_id) override {}
  void LogBlockedBy(const std::string& blocker_info) override {}
  void LogUnblocked() override {}

 private:
  DISALLOW_COPY_AND_ASSIGN(NetworkServiceLogger);
};

bool CreateUploadDataSourcesFromURLRequest(
    net::URLRequest* url_request,
    std::vector<std::unique_ptr<UploadDataSource>>* data_sources) {
  const net::UploadDataStream* upload_data = url_request->get_upload();
  if (!upload_data)
    return false;

  const std::vector<std::unique_ptr<net::UploadElementReader>>* readers =
      upload_data->GetElementReaders();
  if (!readers)
    return true;

  for (const auto& reader : *readers) {
    if (const auto* bytes_reader = reader->AsBytesReader()) {
      data_sources->push_back(std::make_unique<BytesUploadDataSource>(
          base::StringPiece(bytes_reader->bytes(), bytes_reader->length())));
    } else if (const auto* file_reader = reader->AsFileReader()) {
      data_sources->push_back(
          std::make_unique<FileUploadDataSource>(file_reader->path()));
    } else {
      DVLOG(1) << "Ignoring upsupported upload data type for WebRequest API.";
    }
  }

  return true;
}

bool CreateUploadDataSourcesFromResourceRequest(
    const network::ResourceRequest& request,
    std::vector<std::unique_ptr<UploadDataSource>>* data_sources) {
  if (!request.request_body)
    return false;

  for (auto& element : *request.request_body->elements()) {
    switch (element.type()) {
      case network::DataElement::TYPE_DATA_PIPE:
        // TODO(https://crbug.com/721414): Support data pipe elements.
        break;

      case network::DataElement::TYPE_BYTES:
        data_sources->push_back(std::make_unique<BytesUploadDataSource>(
            base::StringPiece(element.bytes(), element.length())));
        break;

      case network::DataElement::TYPE_FILE:
        // Should not be hit in the Network Service case.
        NOTREACHED();
        break;

      default:
        NOTIMPLEMENTED();
        break;
    }
  }

  return true;
}

std::unique_ptr<base::DictionaryValue> CreateRequestBodyData(
    const std::string& method,
    const net::HttpRequestHeaders& request_headers,
    const std::vector<std::unique_ptr<UploadDataSource>>& data_sources) {
  if (method != "POST" && method != "PUT")
    return nullptr;

  auto request_body_data = std::make_unique<base::DictionaryValue>();

  // Get the data presenters, ordered by how specific they are.
  ParsedDataPresenter parsed_data_presenter(request_headers);
  RawDataPresenter raw_data_presenter;
  UploadDataPresenter* const presenters[] = {
      &parsed_data_presenter,  // 1: any parseable forms? (Specific to forms.)
      &raw_data_presenter      // 2: any data at all? (Non-specific.)
  };
  // Keys for the results of the corresponding presenters.
  static const char* const kKeys[] = {keys::kRequestBodyFormDataKey,
                                      keys::kRequestBodyRawKey};
  bool some_succeeded = false;
  if (!data_sources.empty()) {
    for (size_t i = 0; i < arraysize(presenters); ++i) {
      for (auto& source : data_sources)
        source->FeedToPresenter(presenters[i]);
      if (presenters[i]->Succeeded()) {
        request_body_data->Set(kKeys[i], presenters[i]->Result());
        some_succeeded = true;
        break;
      }
    }
  }

  if (!some_succeeded)
    request_body_data->SetString(keys::kRequestBodyErrorKey, "Unknown error.");

  return request_body_data;
}

}  // namespace

WebRequestInfo::WebRequestInfo() = default;

WebRequestInfo::WebRequestInfo(net::URLRequest* url_request)
    : id(url_request->identifier()),
      url(url_request->url()),
      site_for_cookies(url_request->site_for_cookies()),
      method(url_request->method()),
      initiator(url_request->initiator()),
      extra_request_headers(url_request->extra_request_headers()),
      is_pac_request(url_request->is_pac_request()),
      logger(std::make_unique<NetLogLogger>(url_request)) {
  if (url.SchemeIsWSOrWSS()) {
    web_request_type = WebRequestResourceType::WEB_SOCKET;

    // TODO(pkalinnikov): Consider embedding WebSocketHandshakeRequestInfo into
    // UrlRequestUserData.
    const content::WebSocketHandshakeRequestInfo* ws_info =
        content::WebSocketHandshakeRequestInfo::ForRequest(url_request);
    if (ws_info) {
      render_process_id = ws_info->GetChildId();
      frame_id = ws_info->GetRenderFrameId();
    }
  } else if (auto* info =
                 content::ResourceRequestInfo::ForRequest(url_request)) {
    render_process_id = info->GetChildID();
    routing_id = info->GetRouteID();
    frame_id = info->GetRenderFrameID();
    type = info->GetResourceType();
    web_request_type = ToWebRequestResourceType(type.value());
    is_async = info->IsAsync();
    resource_context = info->GetContext();
  } else {
    // There may be basic process and frame info associated with the request
    // even when |info| is null. Attempt to grab it as a last ditch effort. If
    // this fails, we have no frame info.
    content::ResourceRequestInfo::GetRenderFrameForRequest(
        url_request, &render_process_id, &frame_id);
  }

  ExtensionsBrowserClient* browser_client = ExtensionsBrowserClient::Get();
  ExtensionNavigationUIData* navigation_ui_data =
      browser_client ? browser_client->GetExtensionNavigationUIData(url_request)
                     : nullptr;
  if (navigation_ui_data)
    is_browser_side_navigation = true;

  InitializeWebViewAndFrameData(navigation_ui_data);

  std::vector<std::unique_ptr<UploadDataSource>> data_sources;
  if (CreateUploadDataSourcesFromURLRequest(url_request, &data_sources)) {
    request_body_data =
        CreateRequestBodyData(method, extra_request_headers, data_sources);
  }
}

WebRequestInfo::WebRequestInfo(
    uint64_t request_id,
    int render_process_id,
    int render_frame_id,
    std::unique_ptr<ExtensionNavigationUIData> navigation_ui_data,
    int32_t routing_id,
    content::ResourceContext* resource_context,
    const network::ResourceRequest& request)
    : id(request_id),
      url(request.url),
      site_for_cookies(request.site_for_cookies),
      render_process_id(render_process_id),
      routing_id(routing_id),
      frame_id(render_frame_id),
      method(request.method),
      is_browser_side_navigation(!!navigation_ui_data),
      initiator(request.request_initiator),
      type(static_cast<content::ResourceType>(request.resource_type)),
      extra_request_headers(request.headers),
      logger(std::make_unique<NetworkServiceLogger>()),
      resource_context(resource_context) {
  if (url.SchemeIsWSOrWSS())
    web_request_type = WebRequestResourceType::WEB_SOCKET;
  else
    web_request_type = ToWebRequestResourceType(type.value());

  InitializeWebViewAndFrameData(navigation_ui_data.get());

  std::vector<std::unique_ptr<UploadDataSource>> data_sources;
  if (CreateUploadDataSourcesFromResourceRequest(request, &data_sources)) {
    request_body_data =
        CreateRequestBodyData(method, extra_request_headers, data_sources);
  }

  // TODO(https://crbug.com/721414): For this constructor (i.e. the Network
  // Service case), we are still missing information for |is_async| and
  // |is_pac_request|.
}

WebRequestInfo::~WebRequestInfo() = default;

void WebRequestInfo::AddResponseInfoFromURLRequest(
    net::URLRequest* url_request) {
  response_code = url_request->GetResponseCode();
  response_headers = url_request->response_headers();
  response_ip = url_request->GetSocketAddress().host();
  response_from_cache = url_request->was_cached();
}

void WebRequestInfo::AddResponseInfoFromResourceResponse(
    const network::ResourceResponseHead& response) {
  response_headers = response.headers;
  if (response_headers)
    response_code = response_headers->response_code();
  response_ip = response.socket_address.host();

  // TODO(https://crbug.com/721414): We have no apparent source for this
  // information yet in the Network Service case. Should indicate whether or not
  // the response data came from cache.
  response_from_cache = false;
}

void WebRequestInfo::InitializeWebViewAndFrameData(
    const ExtensionNavigationUIData* navigation_ui_data) {
  if (navigation_ui_data) {
    is_web_view = navigation_ui_data->is_web_view();
    web_view_instance_id = navigation_ui_data->web_view_instance_id();
    web_view_rules_registry_id =
        navigation_ui_data->web_view_rules_registry_id();
    frame_data = navigation_ui_data->frame_data();
  } else if (frame_id >= 0) {
    // Grab any WebView-related information if relevant.
    WebViewRendererState::WebViewInfo web_view_info;
    if (WebViewRendererState::GetInstance()->GetInfo(
            render_process_id, routing_id, &web_view_info)) {
      is_web_view = true;
      web_view_instance_id = web_view_info.instance_id;
      web_view_rules_registry_id = web_view_info.rules_registry_id;
      web_view_embedder_process_id = web_view_info.embedder_process_id;
    }

    // For subresource loads we attempt to resolve the FrameData immediately
    // anyway using cached information.
    ExtensionApiFrameIdMap::FrameData data;
    bool was_cached = ExtensionApiFrameIdMap::Get()->GetCachedFrameDataOnIO(
        render_process_id, frame_id, &data);
    if (was_cached)
      frame_data = data;
  }
}

}  // namespace extensions
