namespace IPC {

void ParamTraits<net::AuthCredentials>::Write(base::Pickle* m,
                                              const param_type& p) {
  WriteParam(m, p.username());
  WriteParam(m, p.password());
}

bool ParamTraits<net::AuthCredentials>::Read(const base::Pickle* m,
                                             base::PickleIterator* iter,
                                             param_type* r) {
  std::u16string username;
  bool read_username = ReadParam(m, iter, &username);
  std::u16string password;
  bool read_password = ReadParam(m, iter, &password);

  if (!read_username || !read_password)
    return false;

  r->Set(username, password);
  return true;
}

void ParamTraits<net::AuthCredentials>::Log(const param_type& p,
                                            std::string* l) {
  l->append("<AuthCredentials>");
}

void ParamTraits<net::CertVerifyResult>::Write(base::Pickle* m,
                                               const param_type& p) {
  WriteParam(m, p.verified_cert);
  WriteParam(m, p.cert_status);
  WriteParam(m, p.has_md2);
  WriteParam(m, p.has_md4);
  WriteParam(m, p.has_md5);
  WriteParam(m, p.has_sha1);
  WriteParam(m, p.has_sha1_leaf);
  WriteParam(m, p.public_key_hashes);
  WriteParam(m, p.is_issued_by_known_root);
  WriteParam(m, p.is_issued_by_additional_trust_anchor);
  WriteParam(m, p.ocsp_result);
  WriteParam(m, p.scts);
  WriteParam(m, p.policy_compliance);
}

bool ParamTraits<net::CertVerifyResult>::Read(const base::Pickle* m,
                                              base::PickleIterator* iter,
                                              param_type* r) {
  return ReadParam(m, iter, &r->verified_cert) &&
         ReadParam(m, iter, &r->cert_status) &&
         ReadParam(m, iter, &r->has_md2) && ReadParam(m, iter, &r->has_md4) &&
         ReadParam(m, iter, &r->has_md5) && ReadParam(m, iter, &r->has_sha1) &&
         ReadParam(m, iter, &r->has_sha1_leaf) &&
         ReadParam(m, iter, &r->public_key_hashes) &&
         ReadParam(m, iter, &r->is_issued_by_known_root) &&
         ReadParam(m, iter, &r->is_issued_by_additional_trust_anchor) &&
         ReadParam(m, iter, &r->ocsp_result) && ReadParam(m, iter, &r->scts) &&
         ReadParam(m, iter, &r->policy_compliance);
}

void ParamTraits<net::CertVerifyResult>::Log(const param_type& p,
                                             std::string* l) {
  l->append("<CertVerifyResult>");
}

void ParamTraits<net::HashValue>::Write(base::Pickle* m, const param_type& p) {
  WriteParam(m, p.ToString());
}

bool ParamTraits<net::HashValue>::Read(const base::Pickle* m,
                                       base::PickleIterator* iter,
                                       param_type* r) {
  std::string str;
  return ReadParam(m, iter, &str) && r->FromString(str);
}

void ParamTraits<net::HashValue>::Log(const param_type& p, std::string* l) {
  l->append("<HashValue>");
}

void ParamTraits<net::HostPortPair>::Write(base::Pickle* m,
                                           const param_type& p) {
  WriteParam(m, p.host());
  WriteParam(m, p.port());
}

bool ParamTraits<net::HostPortPair>::Read(const base::Pickle* m,
                                          base::PickleIterator* iter,
                                          param_type* r) {
  std::string host;
  uint16_t port;
  if (!ReadParam(m, iter, &host) || !ReadParam(m, iter, &port))
    return false;

  r->set_host(host);
  r->set_port(port);
  return true;
}

void ParamTraits<net::HostPortPair>::Log(const param_type& p, std::string* l) {
  l->append(p.ToString());
}

void ParamTraits<net::IPEndPoint>::Write(base::Pickle* m, const param_type& p) {
  WriteParam(m, p.address());
  WriteParam(m, p.port());
}

bool ParamTraits<net::IPEndPoint>::Read(const base::Pickle* m,
                                        base::PickleIterator* iter,
                                        param_type* p) {
  net::IPAddress address;
  uint16_t port;
  if (!ReadParam(m, iter, &address) || !ReadParam(m, iter, &port))
    return false;

  *p = net::IPEndPoint(address, port);
  return true;
}

void ParamTraits<net::IPEndPoint>::Log(const param_type& p, std::string* l) {
  LogParam("IPEndPoint:" + p.ToString(), l);
}

void ParamTraits<net::IPAddress>::Write(base::Pickle* m, const param_type& p) {
  base::StackVector<uint8_t, 16> bytes;
  for (uint8_t byte : p.bytes())
    bytes->push_back(byte);
  WriteParam(m, bytes);
}

bool ParamTraits<net::IPAddress>::Read(const base::Pickle* m,
                                       base::PickleIterator* iter,
                                       param_type* p) {
  base::StackVector<uint8_t, 16> bytes;
  if (!ReadParam(m, iter, &bytes))
    return false;
  if (bytes->size() > 16)
    return false;
  *p = net::IPAddress(bytes->data(), bytes->size());
  return true;
}

void ParamTraits<net::IPAddress>::Log(const param_type& p, std::string* l) {
  LogParam("IPAddress:" + (p.empty() ? "(empty)" : p.ToString()), l);
}

void ParamTraits<net::HttpRequestHeaders>::Write(base::Pickle* m,
                                                 const param_type& p) {
  WriteParam(m, static_cast<int>(p.GetHeaderVector().size()));
  for (size_t i = 0; i < p.GetHeaderVector().size(); ++i)
    WriteParam(m, p.GetHeaderVector()[i]);
}

bool ParamTraits<net::HttpRequestHeaders>::Read(const base::Pickle* m,
                                                base::PickleIterator* iter,
                                                param_type* r) {
  // Sanity check.
  int size;
  if (!iter->ReadLength(&size))
    return false;
  for (int i = 0; i < size; ++i) {
    net::HttpRequestHeaders::HeaderKeyValuePair pair;
    if (!ReadParam(m, iter, &pair) ||
        !net::HttpUtil::IsValidHeaderName(pair.key) ||
        !net::HttpUtil::IsValidHeaderValue(pair.value))
      return false;
    r->SetHeader(pair.key, pair.value);
  }
  return true;
}

void ParamTraits<net::HttpRequestHeaders>::Log(const param_type& p,
                                               std::string* l) {
  l->append(p.ToString());
}

void ParamTraits<scoped_refptr<net::HttpResponseHeaders>>::Write(
    base::Pickle* m,
    const param_type& p) {
  WriteParam(m, p.get() != nullptr);
  if (p.get()) {
    // Do not disclose Set-Cookie headers over IPC.
    p->Persist(m, net::HttpResponseHeaders::PERSIST_SANS_COOKIES);
  }
}

bool ParamTraits<scoped_refptr<net::HttpResponseHeaders>>::Read(
    const base::Pickle* m,
    base::PickleIterator* iter,
    param_type* r) {
  bool has_object;
  if (!ReadParam(m, iter, &has_object))
    return false;
  if (has_object)
    *r = base::MakeRefCounted<net::HttpResponseHeaders>(iter);
  return true;
}

void ParamTraits<scoped_refptr<net::HttpResponseHeaders>>::Log(
    const param_type& p,
    std::string* l) {
  l->append("<HttpResponseHeaders>");
}

void ParamTraits<net::ProxyServer>::Write(base::Pickle* m,
                                          const param_type& p) {
  net::ProxyServer::Scheme scheme = p.scheme();
  WriteParam(m, scheme);
  // When scheme is either 'direct' or 'invalid' |host_port_pair|
  // should not be called, as per the method implementation body.
  if (scheme != net::ProxyServer::SCHEME_DIRECT &&
      scheme != net::ProxyServer::SCHEME_INVALID) {
    WriteParam(m, p.host_port_pair());
  }
}

bool ParamTraits<net::ProxyServer>::Read(const base::Pickle* m,
                                         base::PickleIterator* iter,
                                         param_type* r) {
  net::ProxyServer::Scheme scheme;
  if (!ReadParam(m, iter, &scheme))
    return false;

  // When scheme is either 'direct' or 'invalid' |host_port_pair|
  // should not be called, as per the method implementation body.
  net::HostPortPair host_port_pair;
  if (scheme != net::ProxyServer::SCHEME_DIRECT &&
      scheme != net::ProxyServer::SCHEME_INVALID &&
      !ReadParam(m, iter, &host_port_pair)) {
    return false;
  }

  *r = net::ProxyServer(scheme, host_port_pair);
  return true;
}

void ParamTraits<net::ProxyServer>::Log(const param_type& p, std::string* l) {
  l->append("<ProxyServer>");
}

void ParamTraits<net::OCSPVerifyResult>::Write(base::Pickle* m,
                                               const param_type& p) {
  WriteParam(m, p.response_status);
  WriteParam(m, p.revocation_status);
}

bool ParamTraits<net::OCSPVerifyResult>::Read(const base::Pickle* m,
                                              base::PickleIterator* iter,
                                              param_type* r) {
  return ReadParam(m, iter, &r->response_status) &&
         ReadParam(m, iter, &r->revocation_status);
}

void ParamTraits<net::OCSPVerifyResult>::Log(const param_type& p,
                                             std::string* l) {
  l->append("<OCSPVerifyResult>");
}

void ParamTraits<net::ResolveErrorInfo>::Write(base::Pickle* m,
                                               const param_type& p) {
  WriteParam(m, p.error);
  WriteParam(m, p.is_secure_network_error);
}
bool ParamTraits<net::ResolveErrorInfo>::Read(const base::Pickle* m,
                                              base::PickleIterator* iter,
                                              param_type* r) {
  return ReadParam(m, iter, &r->error) &&
         ReadParam(m, iter, &r->is_secure_network_error);
}
void ParamTraits<net::ResolveErrorInfo>::Log(const param_type& p,
                                             std::string* l) {
  l->append("<ResolveErrorInfo>");
}

void ParamTraits<scoped_refptr<net::SSLCertRequestInfo>>::Write(
    base::Pickle* m,
    const param_type& p) {
  DCHECK(p);
  WriteParam(m, p->host_and_port);
  WriteParam(m, p->is_proxy);
  WriteParam(m, p->cert_authorities);
  WriteParam(m, p->cert_key_types);
}

bool ParamTraits<scoped_refptr<net::SSLCertRequestInfo>>::Read(
    const base::Pickle* m,
    base::PickleIterator* iter,
    param_type* r) {
  *r = base::MakeRefCounted<net::SSLCertRequestInfo>();
  return ReadParam(m, iter, &(*r)->host_and_port) &&
         ReadParam(m, iter, &(*r)->is_proxy) &&
         ReadParam(m, iter, &(*r)->cert_authorities) &&
         ReadParam(m, iter, &(*r)->cert_key_types);
}

void ParamTraits<scoped_refptr<net::SSLCertRequestInfo>>::Log(
    const param_type& p,
    std::string* l) {
  l->append("<SSLCertRequestInfo>");
}

void ParamTraits<net::SSLInfo>::Write(base::Pickle* m, const param_type& p) {
  WriteParam(m, p.is_valid());
  if (!p.is_valid())
    return;
  WriteParam(m, p.cert);
  WriteParam(m, p.unverified_cert);
  WriteParam(m, p.cert_status);
  WriteParam(m, p.key_exchange_group);
  WriteParam(m, p.peer_signature_algorithm);
  WriteParam(m, p.connection_status);
  WriteParam(m, p.is_issued_by_known_root);
  WriteParam(m, p.pkp_bypassed);
  WriteParam(m, p.client_cert_sent);
  WriteParam(m, p.handshake_type);
  WriteParam(m, p.public_key_hashes);
  WriteParam(m, p.pinning_failure_log);
  WriteParam(m, p.signed_certificate_timestamps);
  WriteParam(m, p.ct_policy_compliance);
  WriteParam(m, p.ocsp_result);
  WriteParam(m, p.is_fatal_cert_error);
}

bool ParamTraits<net::SSLInfo>::Read(const base::Pickle* m,
                                     base::PickleIterator* iter,
                                     param_type* r) {
  bool is_valid = false;
  if (!ReadParam(m, iter, &is_valid))
    return false;
  if (!is_valid)
    return true;
  return ReadParam(m, iter, &r->cert) &&
         ReadParam(m, iter, &r->unverified_cert) &&
         ReadParam(m, iter, &r->cert_status) &&
         ReadParam(m, iter, &r->key_exchange_group) &&
         ReadParam(m, iter, &r->peer_signature_algorithm) &&
         ReadParam(m, iter, &r->connection_status) &&
         ReadParam(m, iter, &r->is_issued_by_known_root) &&
         ReadParam(m, iter, &r->pkp_bypassed) &&
         ReadParam(m, iter, &r->client_cert_sent) &&
         ReadParam(m, iter, &r->handshake_type) &&
         ReadParam(m, iter, &r->public_key_hashes) &&
         ReadParam(m, iter, &r->pinning_failure_log) &&
         ReadParam(m, iter, &r->signed_certificate_timestamps) &&
         ReadParam(m, iter, &r->ct_policy_compliance) &&
         ReadParam(m, iter, &r->ocsp_result) &&
         ReadParam(m, iter, &r->is_fatal_cert_error);
}

void ParamTraits<net::SSLInfo>::Log(const param_type& p, std::string* l) {
  l->append("<SSLInfo>");
}

void ParamTraits<scoped_refptr<net::ct::SignedCertificateTimestamp>>::Write(
    base::Pickle* m,
    const param_type& p) {
  WriteParam(m, p.get() != nullptr);
  if (p.get())
    p->Persist(m);
}

bool ParamTraits<scoped_refptr<net::ct::SignedCertificateTimestamp>>::Read(
    const base::Pickle* m,
    base::PickleIterator* iter,
    param_type* r) {
  bool has_object;
  if (!ReadParam(m, iter, &has_object))
    return false;
  if (has_object)
    *r = net::ct::SignedCertificateTimestamp::CreateFromPickle(iter);
  return true;
}

void ParamTraits<scoped_refptr<net::ct::SignedCertificateTimestamp>>::Log(
    const param_type& p,
    std::string* l) {
  l->append("<SignedCertificateTimestamp>");
}

void ParamTraits<scoped_refptr<net::X509Certificate>>::Write(
    base::Pickle* m,
    const param_type& p) {
  WriteParam(m, !!p);
  if (p)
    p->Persist(m);
}

bool ParamTraits<scoped_refptr<net::X509Certificate>>::Read(
    const base::Pickle* m,
    base::PickleIterator* iter,
    param_type* r) {
  DCHECK(!*r);
  bool has_object;
  if (!ReadParam(m, iter, &has_object))
    return false;
  if (!has_object)
    return true;
  net::X509Certificate::UnsafeCreateOptions options;
  // Setting the |printable_string_is_utf8| option to be true here is necessary
  // to round-trip any X509Certificate objects that were parsed with this
  // option in the first place.
  // See https://crbug.com/770323 and https://crbug.com/788655.
  options.printable_string_is_utf8 = true;
  *r = net::X509Certificate::CreateFromPickleUnsafeOptions(iter, options);
  return !!r->get();
}

void ParamTraits<scoped_refptr<net::X509Certificate>>::Log(const param_type& p,
                                                           std::string* l) {
  l->append("<X509Certificate>");
}

void ParamTraits<net::LoadTimingInfo>::Write(base::Pickle* m,
                                             const param_type& p) {
  WriteParam(m, p.socket_log_id);
  WriteParam(m, p.socket_reused);
  WriteParam(m, p.request_start_time.is_null());
  if (p.request_start_time.is_null())
    return;
  WriteParam(m, p.request_start_time);
  WriteParam(m, p.request_start);
  WriteParam(m, p.proxy_resolve_start);
  WriteParam(m, p.proxy_resolve_end);
  WriteParam(m, p.connect_timing.dns_start);
  WriteParam(m, p.connect_timing.dns_end);
  WriteParam(m, p.connect_timing.connect_start);
  WriteParam(m, p.connect_timing.connect_end);
  WriteParam(m, p.connect_timing.ssl_start);
  WriteParam(m, p.connect_timing.ssl_end);
  WriteParam(m, p.send_start);
  WriteParam(m, p.send_end);
  WriteParam(m, p.receive_headers_start);
  WriteParam(m, p.receive_headers_end);
  WriteParam(m, p.receive_non_informational_headers_start);
  WriteParam(m, p.first_early_hints_time);
  WriteParam(m, p.push_start);
  WriteParam(m, p.push_end);
}

bool ParamTraits<net::LoadTimingInfo>::Read(const base::Pickle* m,
                                            base::PickleIterator* iter,
                                            param_type* r) {
  bool has_no_times;
  if (!ReadParam(m, iter, &r->socket_log_id) ||
      !ReadParam(m, iter, &r->socket_reused) ||
      !ReadParam(m, iter, &has_no_times)) {
    return false;
  }
  if (has_no_times)
    return true;

  return ReadParam(m, iter, &r->request_start_time) &&
         ReadParam(m, iter, &r->request_start) &&
         ReadParam(m, iter, &r->proxy_resolve_start) &&
         ReadParam(m, iter, &r->proxy_resolve_end) &&
         ReadParam(m, iter, &r->connect_timing.dns_start) &&
         ReadParam(m, iter, &r->connect_timing.dns_end) &&
         ReadParam(m, iter, &r->connect_timing.connect_start) &&
         ReadParam(m, iter, &r->connect_timing.connect_end) &&
         ReadParam(m, iter, &r->connect_timing.ssl_start) &&
         ReadParam(m, iter, &r->connect_timing.ssl_end) &&
         ReadParam(m, iter, &r->send_start) &&
         ReadParam(m, iter, &r->send_end) &&
         ReadParam(m, iter, &r->receive_headers_start) &&
         ReadParam(m, iter, &r->receive_headers_end) &&
         ReadParam(m, iter, &r->receive_non_informational_headers_start) &&
         ReadParam(m, iter, &r->first_early_hints_time) &&
         ReadParam(m, iter, &r->push_start) && ReadParam(m, iter, &r->push_end);
}

void ParamTraits<net::LoadTimingInfo>::Log(const param_type& p,
                                           std::string* l) {
  l->append("(");
  LogParam(p.socket_log_id, l);
  l->append(",");
  LogParam(p.socket_reused, l);
  l->append(",");
  LogParam(p.request_start_time, l);
  l->append(", ");
  LogParam(p.request_start, l);
  l->append(", ");
  LogParam(p.proxy_resolve_start, l);
  l->append(", ");
  LogParam(p.proxy_resolve_end, l);
  l->append(", ");
  LogParam(p.connect_timing.dns_start, l);
  l->append(", ");
  LogParam(p.connect_timing.dns_end, l);
  l->append(", ");
  LogParam(p.connect_timing.connect_start, l);
  l->append(", ");
  LogParam(p.connect_timing.connect_end, l);
  l->append(", ");
  LogParam(p.connect_timing.ssl_start, l);
  l->append(", ");
  LogParam(p.connect_timing.ssl_end, l);
  l->append(", ");
  LogParam(p.send_start, l);
  l->append(", ");
  LogParam(p.send_end, l);
  l->append(", ");
  LogParam(p.receive_headers_start, l);
  l->append(", ");
  LogParam(p.receive_headers_end, l);
  l->append(", ");
  LogParam(p.receive_non_informational_headers_start, l);
  l->append(", ");
  LogParam(p.first_early_hints_time, l);
  l->append(", ");
  LogParam(p.push_start, l);
  l->append(", ");
  LogParam(p.push_end, l);
  l->append(")");
}

void ParamTraits<net::SiteForCookies>::Write(base::Pickle* m,
                                             const param_type& p) {
  WriteParam(m, p.site());
  WriteParam(m, p.schemefully_same());
}

bool ParamTraits<net::SiteForCookies>::Read(const base::Pickle* m,
                                            base::PickleIterator* iter,
                                            param_type* r) {
  net::SchemefulSite site;
  bool schemefully_same;
  if (!ReadParam(m, iter, &site) || !ReadParam(m, iter, &schemefully_same))
    return false;

  return net::SiteForCookies::FromWire(site, schemefully_same, r);
}

void ParamTraits<net::SiteForCookies>::Log(const param_type& p,
                                           std::string* l) {
  l->append("(");
  LogParam(p.scheme(), l);
  l->append(",");
  LogParam(p.registrable_domain(), l);
  l->append(",");
  LogParam(p.schemefully_same(), l);
  l->append(")");
}

void ParamTraits<url::Origin>::Write(base::Pickle* m, const url::Origin& p) {
  WriteParam(m, p.GetTupleOrPrecursorTupleIfOpaque().scheme());
  WriteParam(m, p.GetTupleOrPrecursorTupleIfOpaque().host());
  WriteParam(m, p.GetTupleOrPrecursorTupleIfOpaque().port());
  WriteParam(m, p.GetNonceForSerialization());
}

bool ParamTraits<url::Origin>::Read(const base::Pickle* m,
                                    base::PickleIterator* iter,
                                    url::Origin* p) {
  std::string scheme;
  std::string host;
  uint16_t port;
  absl::optional<base::UnguessableToken> nonce_if_opaque;
  if (!ReadParam(m, iter, &scheme) || !ReadParam(m, iter, &host) ||
      !ReadParam(m, iter, &port) || !ReadParam(m, iter, &nonce_if_opaque)) {
    return false;
  }

  absl::optional<url::Origin> creation_result =
      nonce_if_opaque
          ? url::Origin::UnsafelyCreateOpaqueOriginWithoutNormalization(
                scheme, host, port, url::Origin::Nonce(*nonce_if_opaque))
          : url::Origin::UnsafelyCreateTupleOriginWithoutNormalization(
                scheme, host, port);
  if (!creation_result)
    return false;

  *p = std::move(creation_result.value());
  return true;
}

void ParamTraits<url::Origin>::Log(const url::Origin& p, std::string* l) {
  l->append(p.Serialize());
}

void ParamTraits<net::SchemefulSite>::Write(base::Pickle* m,
                                            const net::SchemefulSite& p) {
  WriteParam(m, p.site_as_origin_);
}

bool ParamTraits<net::SchemefulSite>::Read(const base::Pickle* m,
                                           base::PickleIterator* iter,
                                           net::SchemefulSite* p) {
  url::Origin site_as_origin;
  if (!ReadParam(m, iter, &site_as_origin))
    return false;

  return net::SchemefulSite::FromWire(site_as_origin, p);
}

void ParamTraits<net::SchemefulSite>::Log(const net::SchemefulSite& p,
                                          std::string* l) {
  l->append(p.Serialize());
}

}  // namespace IPC

// Generation of IPC definitions.

// Generate constructors.
#undef SERVICES_NETWORK_PUBLIC_CPP_NET_IPC_PARAM_TRAITS_H_
#include "ipc/struct_constructor_macros.h"
#include "net_ipc_param_traits.h"

// Generate param traits write methods.
#undef SERVICES_NETWORK_PUBLIC_CPP_NET_IPC_PARAM_TRAITS_H_
#include "ipc/param_traits_write_macros.h"
namespace IPC {
#include "net_ipc_param_traits.h"
}  // namespace IPC

// Generate param traits read methods.
#undef SERVICES_NETWORK_PUBLIC_CPP_NET_IPC_PARAM_TRAITS_H_
#include "ipc/param_traits_read_macros.h"
namespace IPC {
#include "net_ipc_param_traits.h"
}  // namespace IPC

// Generate param traits log methods.
#undef SERVICES_NETWORK_PUBLIC_CPP_NET_IPC_PARAM_TRAITS_H_
#include "ipc/param_traits_log_macros.h"
namespace IPC {
#include "net_ipc_param_traits.h"
}  // namespace IPC
