// services/network/public/mojom/cookie_encryption_provider.mojom.cc is auto generated by mojom_bindings_generator.py, do not edit

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-private-field"
#endif

#include "services/network/public/mojom/cookie_encryption_provider.mojom.h"

#include <math.h>
#include <stdint.h>
#include <utility>

#include "base/debug/alias.h"
#include "base/hash/md5_constexpr.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/typed_macros.h"
#include "mojo/public/cpp/bindings/features.h"
#include "mojo/public/cpp/bindings/lib/default_construct_tag_internal.h"
#include "mojo/public/cpp/bindings/lib/generated_code_util.h"
#include "mojo/public/cpp/bindings/lib/message_internal.h"
#include "mojo/public/cpp/bindings/lib/proxy_to_responder.h"
#include "mojo/public/cpp/bindings/lib/send_message_helper.h"
#include "mojo/public/cpp/bindings/lib/serialization_util.h"
#include "mojo/public/cpp/bindings/lib/unserialized_message_context.h"
#include "mojo/public/cpp/bindings/lib/validate_params.h"
#include "mojo/public/cpp/bindings/lib/validation_errors.h"
#include "mojo/public/cpp/bindings/mojo_buildflags.h"
#include "mojo/public/cpp/bindings/urgent_message_scope.h"
#include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"

#include "services/network/public/mojom/cookie_encryption_provider.mojom-params-data.h"
#include "services/network/public/mojom/cookie_encryption_provider.mojom-shared-message-ids.h"

#include "services/network/public/mojom/cookie_encryption_provider.mojom-import-headers.h"
#include "services/network/public/mojom/cookie_encryption_provider.mojom-test-utils.h"


namespace network::mojom {
const char CookieEncryptionProvider::Name_[] = "network.mojom.CookieEncryptionProvider";

CookieEncryptionProvider::IPCStableHashFunction CookieEncryptionProvider::MessageToMethodInfo_(mojo::Message& message) {
#if !BUILDFLAG(IS_FUCHSIA)
  switch (static_cast<messages::CookieEncryptionProvider>(message.name())) {
    case messages::CookieEncryptionProvider::kGetEncryptor: {
      return &CookieEncryptionProvider::GetEncryptor_Sym::IPCStableHash;
    }
  }
#endif  // !BUILDFLAG(IS_FUCHSIA)
  return nullptr;
}


const char* CookieEncryptionProvider::MessageToMethodName_(mojo::Message& message) {
#if BUILDFLAG(MOJO_TRACE_ENABLED)
  bool is_response = message.has_flag(mojo::Message::kFlagIsResponse);
  if (!is_response) {
    switch (static_cast<messages::CookieEncryptionProvider>(message.name())) {
      case messages::CookieEncryptionProvider::kGetEncryptor:
            return "Receive network::mojom::CookieEncryptionProvider::GetEncryptor";
    }
  } else {
    switch (static_cast<messages::CookieEncryptionProvider>(message.name())) {
      case messages::CookieEncryptionProvider::kGetEncryptor:
            return "Receive reply network::mojom::CookieEncryptionProvider::GetEncryptor";
    }
  }
  return "Receive unknown mojo message";
#else
  bool is_response = message.has_flag(mojo::Message::kFlagIsResponse);
  if (is_response) {
    return "Receive mojo reply";
  } else {
    return "Receive mojo message";
  }
#endif // BUILDFLAG(MOJO_TRACE_ENABLED)
}

#if !BUILDFLAG(IS_FUCHSIA)
uint32_t CookieEncryptionProvider::GetEncryptor_Sym::IPCStableHash() {
  // This method's address is used for indetifiying the mojo method name after
  // symbolization. So each IPCStableHash should have a unique address.
  // We cannot use NO_CODE_FOLDING() here - it relies on the uniqueness of
  // __LINE__ value, which is not unique accross different mojo modules.
  // The code below is very similar to NO_CODE_FOLDING, but it uses a unique
  // hash instead of __LINE__.
  constexpr uint32_t kHash = base::MD5Hash32Constexpr(
          "(Impl)network::mojom::CookieEncryptionProvider::GetEncryptor");
  const uint32_t hash = kHash;
  base::debug::Alias(&hash);
  return hash;
}
# endif // !BUILDFLAG(IS_FUCHSIA)

class CookieEncryptionProvider_GetEncryptor_ForwardToCallback
    : public mojo::MessageReceiver {
 public:
  CookieEncryptionProvider_GetEncryptor_ForwardToCallback(
      CookieEncryptionProvider::GetEncryptorCallback callback
      ) : callback_(std::move(callback)) {
  }

  CookieEncryptionProvider_GetEncryptor_ForwardToCallback(const CookieEncryptionProvider_GetEncryptor_ForwardToCallback&) = delete;
  CookieEncryptionProvider_GetEncryptor_ForwardToCallback& operator=(const CookieEncryptionProvider_GetEncryptor_ForwardToCallback&) = delete;

  bool Accept(mojo::Message* message) override;
 private:
  CookieEncryptionProvider::GetEncryptorCallback callback_;
};

CookieEncryptionProviderProxy::CookieEncryptionProviderProxy(mojo::MessageReceiverWithResponder* receiver)
    : receiver_(receiver) {
}

void CookieEncryptionProviderProxy::GetEncryptor(
    GetEncryptorCallback callback) {
#if BUILDFLAG(MOJO_TRACE_ENABLED)
  TRACE_EVENT0("mojom", "Send network::mojom::CookieEncryptionProvider::GetEncryptor");
#endif

  const bool kExpectsResponse = true;
  const bool kIsSync = false;
  const bool kAllowInterrupt = true;
  const bool is_urgent = false;

  const uint32_t kFlags =
      ((kExpectsResponse) ? mojo::Message::kFlagExpectsResponse : 0) |
      ((kIsSync) ? mojo::Message::kFlagIsSync : 0) |
      ((kAllowInterrupt) ? 0 : mojo::Message::kFlagNoInterrupt) |
      ((is_urgent) ? mojo::Message::kFlagIsUrgent : 0);

  const size_t estimated_payload_size =
    0;
  mojo::Message message(
      base::to_underlying(messages::CookieEncryptionProvider::kGetEncryptor), kFlags, estimated_payload_size);
  mojo::internal::MessageFragment<
      ::network::mojom::internal::CookieEncryptionProvider_GetEncryptor_Params_Data> params(
          message);
  params.Allocate();

#if defined(ENABLE_IPC_FUZZER)
  message.set_interface_name(CookieEncryptionProvider::Name_);
  message.set_method_name("GetEncryptor");
#endif
  std::unique_ptr<mojo::MessageReceiver> responder(
      new CookieEncryptionProvider_GetEncryptor_ForwardToCallback(
          std::move(callback)));
  ::mojo::internal::SendMojoMessage(*receiver_, message, std::move(responder));
}
class CookieEncryptionProvider_GetEncryptor_ProxyToResponder : public ::mojo::internal::ProxyToResponder {
 public:
  static CookieEncryptionProvider::GetEncryptorCallback CreateCallback(
      ::mojo::Message& message,
      std::unique_ptr<mojo::MessageReceiverWithStatus> responder) {
    std::unique_ptr<CookieEncryptionProvider_GetEncryptor_ProxyToResponder> proxy(
        new CookieEncryptionProvider_GetEncryptor_ProxyToResponder(
            message, std::move(responder)));
    return base::BindOnce(&CookieEncryptionProvider_GetEncryptor_ProxyToResponder::Run,
                          std::move(proxy));
  }

  ~CookieEncryptionProvider_GetEncryptor_ProxyToResponder() {
#if DCHECK_IS_ON()
    if (responder_) {
      // If we're being destroyed without being run, we want to ensure the
      // binding endpoint has been closed. This checks for that asynchronously.
      // We pass a bound generated callback to handle the response so that any
      // resulting DCHECK stack will have useful interface type information.
      // Instantiate a ScopedFizzleBlockShutdownTasks to allow this request to
      // fizzle if this happens after shutdown and the endpoint is bound to a
      // BLOCK_SHUTDOWN sequence.
      base::ThreadPoolInstance::ScopedFizzleBlockShutdownTasks fizzler;
      responder_->IsConnectedAsync(base::BindOnce(&OnIsConnectedComplete));
    }
#endif
  }

 private:
  CookieEncryptionProvider_GetEncryptor_ProxyToResponder(
      ::mojo::Message& message,
      std::unique_ptr<mojo::MessageReceiverWithStatus> responder)
      : ::mojo::internal::ProxyToResponder(message, std::move(responder)) {
  }

#if DCHECK_IS_ON()
  static void OnIsConnectedComplete(bool connected) {
    DCHECK(!connected)
        << "CookieEncryptionProvider::GetEncryptorCallback was destroyed without "
        << "first either being run or its corresponding binding being closed. "
        << "It is an error to drop response callbacks which still correspond "
        << "to an open interface pipe.";
  }
#endif

  void Run(
      ::os_crypt_async::Encryptor in_encryptor);
};

bool CookieEncryptionProvider_GetEncryptor_ForwardToCallback::Accept(
    mojo::Message* message) {
  DCHECK(message->is_serialized());
  internal::CookieEncryptionProvider_GetEncryptor_ResponseParams_Data* params =
      reinterpret_cast<
          internal::CookieEncryptionProvider_GetEncryptor_ResponseParams_Data*>(
              message->mutable_payload());
  
  
  // Validation for CookieEncryptionProvider.0
  bool success = true;
  ::os_crypt_async::Encryptor p_encryptor{mojo::internal::DefaultConstructTag()};
  CookieEncryptionProvider_GetEncryptor_ResponseParamsDataView input_data_view(params, message);
  
  if (success && !input_data_view.ReadEncryptor(&p_encryptor))
    success = false;
  if (!success) {
    ReportValidationErrorForMessage(
        message,
        mojo::internal::VALIDATION_ERROR_DESERIALIZATION_FAILED,
        CookieEncryptionProvider::Name_, 0, true);
    return false;
  }
  if (!callback_.is_null())
    std::move(callback_).Run(
std::move(p_encryptor));
  return true;
}

void CookieEncryptionProvider_GetEncryptor_ProxyToResponder::Run(
    ::os_crypt_async::Encryptor in_encryptor) {
#if BUILDFLAG(MOJO_TRACE_ENABLED)
  TRACE_EVENT1(
    "mojom", "Send reply network::mojom::CookieEncryptionProvider::GetEncryptor", "async_response_parameters",
    [&](perfetto::TracedValue context){
      auto dict = std::move(context).WriteDictionary();
      perfetto::WriteIntoTracedValueWithFallback(
           dict.AddItem("encryptor"), in_encryptor,
                        "<value of type ::os_crypt_async::Encryptor>");
   });
#endif

  const uint32_t kFlags = mojo::Message::kFlagIsResponse |
      ((is_sync_) ? mojo::Message::kFlagIsSync : 0) |
      ((true) ? 0 : mojo::Message::kFlagNoInterrupt) |
      ((false) ? mojo::Message::kFlagIsUrgent : 0);

  const size_t estimated_payload_size =
    0;
  mojo::Message message(
      base::to_underlying(messages::CookieEncryptionProvider::kGetEncryptor), kFlags, estimated_payload_size);
  mojo::internal::MessageFragment<
      ::network::mojom::internal::CookieEncryptionProvider_GetEncryptor_ResponseParams_Data> params(
          message);
  params.Allocate();
  mojo::internal::MessageFragment<
      typename decltype(params->encryptor)::BaseType> encryptor_fragment(
          params.message());
  mojo::internal::Serialize<::os_crypt_async::mojom::EncryptorDataView>(
      in_encryptor, encryptor_fragment);
  params->encryptor.Set(
      encryptor_fragment.is_null() ? nullptr : encryptor_fragment.data());
  MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
      params->encryptor.is_null(),
      mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
      "null encryptor in ");

#if defined(ENABLE_IPC_FUZZER)
  message.set_interface_name(CookieEncryptionProvider::Name_);
  message.set_method_name("GetEncryptor");
#endif

  message.set_request_id(request_id_);
  message.set_trace_nonce(trace_nonce_);
  ::mojo::internal::SendMojoMessage(*responder_, message);
  // SendMojoMessage() fails silently if the responder connection is closed,
  // or if the message is malformed.
  //
  // TODO(darin): If Accept() returns false due to a malformed message, that
  // may be good reason to close the connection. However, we don't have a
  // way to do that from here. We should add a way.
  responder_ = nullptr;
}

// static
bool CookieEncryptionProviderStubDispatch::Accept(
    CookieEncryptionProvider* impl,
    mojo::Message* message) {
  switch (static_cast<messages::CookieEncryptionProvider>(message->header()->name)) {
    case messages::CookieEncryptionProvider::kGetEncryptor: {
      break;
    }
  }
  return false;
}

// static
bool CookieEncryptionProviderStubDispatch::AcceptWithResponder(
    CookieEncryptionProvider* impl,
    mojo::Message* message,
    std::unique_ptr<mojo::MessageReceiverWithStatus> responder) {
  [[maybe_unused]] const bool message_is_sync =
      message->has_flag(mojo::Message::kFlagIsSync);
  [[maybe_unused]] const uint64_t request_id = message->request_id();
  switch (static_cast<messages::CookieEncryptionProvider>(message->header()->name)) {
    case messages::CookieEncryptionProvider::kGetEncryptor: {
      internal::CookieEncryptionProvider_GetEncryptor_Params_Data* params =
          reinterpret_cast<
              internal::CookieEncryptionProvider_GetEncryptor_Params_Data*>(
                  message->mutable_payload());
      
      
      // Validation for CookieEncryptionProvider.0
      bool success = true;
      CookieEncryptionProvider_GetEncryptor_ParamsDataView input_data_view(params, message);
      
      if (!success) {
        ReportValidationErrorForMessage(
            message,
            mojo::internal::VALIDATION_ERROR_DESERIALIZATION_FAILED,
            CookieEncryptionProvider::Name_, 0, false);
        return false;
      }
      CookieEncryptionProvider::GetEncryptorCallback callback =
          CookieEncryptionProvider_GetEncryptor_ProxyToResponder::CreateCallback(
              *message, std::move(responder));
      // A null |impl| means no implementation was bound.
      DCHECK(impl);
      impl->GetEncryptor(std::move(callback));
      return true;
    }
  }
  return false;
}
namespace {
}  // namespace
static const mojo::internal::GenericValidationInfo kCookieEncryptionProviderValidationInfo[] = {
    { &internal::CookieEncryptionProvider_GetEncryptor_Params_Data::Validate,
     &internal::CookieEncryptionProvider_GetEncryptor_ResponseParams_Data::Validate},
};

bool CookieEncryptionProviderRequestValidator::Accept(mojo::Message* message) {
  const char* name = ::network::mojom::CookieEncryptionProvider::Name_;
  return mojo::internal::ValidateRequestGenericPacked(message, name, kCookieEncryptionProviderValidationInfo);
}

bool CookieEncryptionProviderResponseValidator::Accept(mojo::Message* message) {
  const char* name = ::network::mojom::CookieEncryptionProvider::Name_;
  return mojo::internal::ValidateResponseGenericPacked(message, name, kCookieEncryptionProviderValidationInfo);
}


}  // network::mojom


namespace mojo {

}  // namespace mojo


// Symbols declared in the -test-utils.h header are defined here instead of a
// separate .cc file to save compile time.


namespace network::mojom {


void CookieEncryptionProviderInterceptorForTesting::GetEncryptor(GetEncryptorCallback callback) {
  GetForwardingInterface()->GetEncryptor(std::move(callback));
}
CookieEncryptionProviderAsyncWaiter::CookieEncryptionProviderAsyncWaiter(
    CookieEncryptionProvider* proxy) : proxy_(proxy) {}

CookieEncryptionProviderAsyncWaiter::~CookieEncryptionProviderAsyncWaiter() = default;

void CookieEncryptionProviderAsyncWaiter::GetEncryptor(
    ::os_crypt_async::Encryptor* out_encryptor) {
  base::RunLoop loop;
  proxy_->GetEncryptor(
      base::BindOnce(
          [](base::RunLoop* loop,
             ::os_crypt_async::Encryptor* out_encryptor
,
             ::os_crypt_async::Encryptor encryptor) {*out_encryptor = std::move(encryptor);
            loop->Quit();
          },
          &loop,
          out_encryptor));
  loop.Run();
}

::os_crypt_async::Encryptor CookieEncryptionProviderAsyncWaiter::GetEncryptor(
    ) {
  ::os_crypt_async::Encryptor async_wait_result{mojo::internal::DefaultConstructTag()};
  GetEncryptor(&async_wait_result);
  return async_wait_result;
}






}  // network::mojom


#if defined(__clang__)
#pragma clang diagnostic pop
#endif