// third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.cc is auto generated by mojom_bindings_generator.py, do not edit

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

#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"

// Used to support stream output operator for enums.
// TODO(dcheng): Consider omitting this somehow if not needed.
#include <ostream>
#include <utility>

#include "base/strings/stringprintf.h"
#include "mojo/public/cpp/bindings/lib/validate_params.h"
#include "mojo/public/cpp/bindings/lib/validation_errors.h"
#include "mojo/public/cpp/bindings/lib/validation_util.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"

#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-params-data.h"
namespace blink {
namespace mojom {

NOINLINE static const char* MediaStreamTypeToStringHelper(MediaStreamType value) {
  // Defined in a helper function to ensure that Clang generates a lookup table.
  switch(value) {
    case MediaStreamType::NO_SERVICE:
      return "NO_SERVICE";
    case MediaStreamType::DEVICE_AUDIO_CAPTURE:
      return "DEVICE_AUDIO_CAPTURE";
    case MediaStreamType::DEVICE_VIDEO_CAPTURE:
      return "DEVICE_VIDEO_CAPTURE";
    case MediaStreamType::GUM_TAB_AUDIO_CAPTURE:
      return "GUM_TAB_AUDIO_CAPTURE";
    case MediaStreamType::GUM_TAB_VIDEO_CAPTURE:
      return "GUM_TAB_VIDEO_CAPTURE";
    case MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE:
      return "GUM_DESKTOP_VIDEO_CAPTURE";
    case MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE:
      return "GUM_DESKTOP_AUDIO_CAPTURE";
    case MediaStreamType::DISPLAY_VIDEO_CAPTURE:
      return "DISPLAY_VIDEO_CAPTURE";
    case MediaStreamType::DISPLAY_AUDIO_CAPTURE:
      return "DISPLAY_AUDIO_CAPTURE";
    case MediaStreamType::DISPLAY_VIDEO_CAPTURE_THIS_TAB:
      return "DISPLAY_VIDEO_CAPTURE_THIS_TAB";
    case MediaStreamType::DISPLAY_VIDEO_CAPTURE_SET:
      return "DISPLAY_VIDEO_CAPTURE_SET";
    case MediaStreamType::NUM_MEDIA_TYPES:
      return "NUM_MEDIA_TYPES";
    default:
      return nullptr;
  }
}

std::string MediaStreamTypeToString(MediaStreamType value) {
  const char *str = MediaStreamTypeToStringHelper(value);
  if (!str) {
    return base::StringPrintf("Unknown MediaStreamType value: %i", static_cast<int32_t>(value));
  }
  return str;
}

std::ostream& operator<<(std::ostream& os, MediaStreamType value) {
  return os << MediaStreamTypeToString(value);
}

NOINLINE static const char* MediaStreamRequestResultToStringHelper(MediaStreamRequestResult value) {
  // Defined in a helper function to ensure that Clang generates a lookup table.
  switch(value) {
    case MediaStreamRequestResult::OK:
      return "OK";
    case MediaStreamRequestResult::PERMISSION_DENIED:
      return "PERMISSION_DENIED";
    case MediaStreamRequestResult::PERMISSION_DISMISSED:
      return "PERMISSION_DISMISSED";
    case MediaStreamRequestResult::INVALID_STATE:
      return "INVALID_STATE";
    case MediaStreamRequestResult::NO_HARDWARE:
      return "NO_HARDWARE";
    case MediaStreamRequestResult::INVALID_SECURITY_ORIGIN:
      return "INVALID_SECURITY_ORIGIN";
    case MediaStreamRequestResult::TAB_CAPTURE_FAILURE:
      return "TAB_CAPTURE_FAILURE";
    case MediaStreamRequestResult::SCREEN_CAPTURE_FAILURE:
      return "SCREEN_CAPTURE_FAILURE";
    case MediaStreamRequestResult::CAPTURE_FAILURE:
      return "CAPTURE_FAILURE";
    case MediaStreamRequestResult::CONSTRAINT_NOT_SATISFIED:
      return "CONSTRAINT_NOT_SATISFIED";
    case MediaStreamRequestResult::TRACK_START_FAILURE_AUDIO:
      return "TRACK_START_FAILURE_AUDIO";
    case MediaStreamRequestResult::TRACK_START_FAILURE_VIDEO:
      return "TRACK_START_FAILURE_VIDEO";
    case MediaStreamRequestResult::NOT_SUPPORTED:
      return "NOT_SUPPORTED";
    case MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN:
      return "FAILED_DUE_TO_SHUTDOWN";
    case MediaStreamRequestResult::KILL_SWITCH_ON:
      return "KILL_SWITCH_ON";
    case MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED:
      return "SYSTEM_PERMISSION_DENIED";
    case MediaStreamRequestResult::DEVICE_IN_USE:
      return "DEVICE_IN_USE";
    case MediaStreamRequestResult::REQUEST_CANCELLED:
      return "REQUEST_CANCELLED";
    case MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS:
      return "NUM_MEDIA_REQUEST_RESULTS";
    default:
      return nullptr;
  }
}

std::string MediaStreamRequestResultToString(MediaStreamRequestResult value) {
  const char *str = MediaStreamRequestResultToStringHelper(value);
  if (!str) {
    return base::StringPrintf("Unknown MediaStreamRequestResult value: %i", static_cast<int32_t>(value));
  }
  return str;
}

std::ostream& operator<<(std::ostream& os, MediaStreamRequestResult value) {
  return os << MediaStreamRequestResultToString(value);
}

NOINLINE static const char* MediaStreamStateChangeToStringHelper(MediaStreamStateChange value) {
  // Defined in a helper function to ensure that Clang generates a lookup table.
  switch(value) {
    case MediaStreamStateChange::PLAY:
      return "PLAY";
    case MediaStreamStateChange::PAUSE:
      return "PAUSE";
    default:
      return nullptr;
  }
}

std::string MediaStreamStateChangeToString(MediaStreamStateChange value) {
  const char *str = MediaStreamStateChangeToStringHelper(value);
  if (!str) {
    return base::StringPrintf("Unknown MediaStreamStateChange value: %i", static_cast<int32_t>(value));
  }
  return str;
}

std::ostream& operator<<(std::ostream& os, MediaStreamStateChange value) {
  return os << MediaStreamStateChangeToString(value);
}

NOINLINE static const char* PreferredDisplaySurfaceToStringHelper(PreferredDisplaySurface value) {
  // Defined in a helper function to ensure that Clang generates a lookup table.
  switch(value) {
    case PreferredDisplaySurface::NO_PREFERENCE:
      return "NO_PREFERENCE";
    case PreferredDisplaySurface::MONITOR:
      return "MONITOR";
    case PreferredDisplaySurface::WINDOW:
      return "WINDOW";
    case PreferredDisplaySurface::BROWSER:
      return "BROWSER";
    default:
      return nullptr;
  }
}

std::string PreferredDisplaySurfaceToString(PreferredDisplaySurface value) {
  const char *str = PreferredDisplaySurfaceToStringHelper(value);
  if (!str) {
    return base::StringPrintf("Unknown PreferredDisplaySurface value: %i", static_cast<int32_t>(value));
  }
  return str;
}

std::ostream& operator<<(std::ostream& os, PreferredDisplaySurface value) {
  return os << PreferredDisplaySurfaceToString(value);
}

NOINLINE static const char* CapturedSurfaceControlResultToStringHelper(CapturedSurfaceControlResult value) {
  // Defined in a helper function to ensure that Clang generates a lookup table.
  switch(value) {
    case CapturedSurfaceControlResult::kSuccess:
      return "kSuccess";
    case CapturedSurfaceControlResult::kUnknownError:
      return "kUnknownError";
    case CapturedSurfaceControlResult::kNoPermissionError:
      return "kNoPermissionError";
    case CapturedSurfaceControlResult::kCapturerNotFoundError:
      return "kCapturerNotFoundError";
    case CapturedSurfaceControlResult::kCapturedSurfaceNotFoundError:
      return "kCapturedSurfaceNotFoundError";
    case CapturedSurfaceControlResult::kDisallowedForSelfCaptureError:
      return "kDisallowedForSelfCaptureError";
    case CapturedSurfaceControlResult::kCapturerNotFocusedError:
      return "kCapturerNotFocusedError";
    default:
      return nullptr;
  }
}

std::string CapturedSurfaceControlResultToString(CapturedSurfaceControlResult value) {
  const char *str = CapturedSurfaceControlResultToStringHelper(value);
  if (!str) {
    return base::StringPrintf("Unknown CapturedSurfaceControlResult value: %i", static_cast<int32_t>(value));
  }
  return str;
}

std::ostream& operator<<(std::ostream& os, CapturedSurfaceControlResult value) {
  return os << CapturedSurfaceControlResultToString(value);
}

namespace internal {
// static
bool StreamSelectionInfo_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context,
    bool inlined) {
  if (!data) {
    DCHECK(!inlined);
    return true;
  }

  // If it is inlined, the alignment is already enforced by its enclosing
  // object. We don't have to validate that.
  DCHECK(!inlined || mojo::internal::IsAligned(data));

  if (!inlined &&
      !mojo::internal::ValidateNonInlinedUnionHeaderAndClaimMemory(
          data, validation_context)) {
    return false;
  }

  const StreamSelectionInfo_Data* object = static_cast<const StreamSelectionInfo_Data*>(data);

  if (inlined && object->is_null())
    return true;

  switch (object->tag) {

    case StreamSelectionInfo_Tag::kSearchOnlyByDeviceId: {

      if (!mojo::internal::ValidatePointerNonNullable(
              object->data.f_search_only_by_device_id, 1, validation_context)) {
        return false;
      }
      if (!mojo::internal::ValidateStruct(object->data.f_search_only_by_device_id, validation_context))
        return false;
      return true;
    }
    case StreamSelectionInfo_Tag::kSearchBySessionId: {

      if (!mojo::internal::ValidatePointerNonNullable(
              object->data.f_search_by_session_id, 2, validation_context)) {
        return false;
      }
      if (!mojo::internal::ValidateStruct(object->data.f_search_by_session_id, validation_context))
        return false;
      return true;
    }
    default: {

      ReportValidationError(
          validation_context,
          mojo::internal::VALIDATION_ERROR_UNKNOWN_UNION_TAG,
          "unknown tag in StreamSelectionInfo");
      return false;
    }
  }
}


// static
bool SearchOnlyByDeviceId_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 8, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const SearchOnlyByDeviceId_Data* object =
      static_cast<const SearchOnlyByDeviceId_Data*>(data);

  return true;
}

SearchOnlyByDeviceId_Data::SearchOnlyByDeviceId_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool SearchBySessionId_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 16, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const SearchBySessionId_Data* object =
      static_cast<const SearchBySessionId_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->session_id_map, 1, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& session_id_map_validate_params =
      mojo::internal::GetMapValidator<*&mojo::internal::GetArrayValidator<0, false, &mojo::internal::GetArrayValidator<0, false, nullptr>()>(), *&mojo::internal::GetArrayValidator<0, false, nullptr>()>();
  if (!mojo::internal::ValidateContainer(object->session_id_map, validation_context,
                                         &session_id_map_validate_params)) {
    return false;
  }

  return true;
}

SearchBySessionId_Data::SearchBySessionId_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDevice_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 80, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDevice_Data* object =
      static_cast<const MediaStreamDevice_Data*>(data);


  if (!::blink::mojom::internal::MediaStreamType_Data
        ::Validate(object->type, validation_context))
    return false;

  if (!mojo::internal::ValidatePointerNonNullable(
          object->id, 2, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& id_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->id, validation_context,
                                         &id_validate_params)) {
    return false;
  }


  if (!::media::mojom::internal::VideoFacingMode_Data
        ::Validate(object->video_facing, validation_context))
    return false;

  constexpr const mojo::internal::ContainerValidateParams& group_id_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->group_id, validation_context,
                                         &group_id_validate_params)) {
    return false;
  }

  constexpr const mojo::internal::ContainerValidateParams& matched_output_device_id_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->matched_output_device_id, validation_context,
                                         &matched_output_device_id_validate_params)) {
    return false;
  }

  if (!mojo::internal::ValidatePointerNonNullable(
          object->name, 7, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& name_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->name, validation_context,
                                         &name_validate_params)) {
    return false;
  }

  if (!mojo::internal::ValidatePointerNonNullable(
          object->input, 8, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->input, validation_context))
    return false;

  if (!mojo::internal::ValidateStruct(object->session_id, validation_context))
    return false;

  if (!mojo::internal::ValidateStruct(object->display_media_info, validation_context))
    return false;

  return true;
}

MediaStreamDevice_Data::MediaStreamDevice_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool TrackControls_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const TrackControls_Data* object =
      static_cast<const TrackControls_Data*>(data);


  if (!::blink::mojom::internal::MediaStreamType_Data
        ::Validate(object->stream_type, validation_context))
    return false;

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device_ids, 2, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& device_ids_validate_params =
      mojo::internal::GetArrayValidator<0, false, &mojo::internal::GetArrayValidator<0, false, nullptr>()>();
  if (!mojo::internal::ValidateContainer(object->device_ids, validation_context,
                                         &device_ids_validate_params)) {
    return false;
  }

  return true;
}

TrackControls_Data::TrackControls_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool StreamControls_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 32, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const StreamControls_Data* object =
      static_cast<const StreamControls_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->audio, 1, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->audio, validation_context))
    return false;

  if (!mojo::internal::ValidatePointerNonNullable(
          object->video, 2, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->video, validation_context))
    return false;


  if (!::blink::mojom::internal::PreferredDisplaySurface_Data
        ::Validate(object->preferred_display_surface, validation_context))
    return false;

  return true;
}

StreamControls_Data::StreamControls_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool GetOpenDeviceResponse_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 32, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const GetOpenDeviceResponse_Data* object =
      static_cast<const GetOpenDeviceResponse_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->label, 1, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& label_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->label, validation_context,
                                         &label_validate_params)) {
    return false;
  }

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device, 2, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->device, validation_context))
    return false;

  return true;
}

GetOpenDeviceResponse_Data::GetOpenDeviceResponse_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool CapturedWheelAction_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 32, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const CapturedWheelAction_Data* object =
      static_cast<const CapturedWheelAction_Data*>(data);

  return true;
}

CapturedWheelAction_Data::CapturedWheelAction_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool StreamDevices_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const StreamDevices_Data* object =
      static_cast<const StreamDevices_Data*>(data);

  if (!mojo::internal::ValidateStruct(object->audio_device, validation_context))
    return false;

  if (!mojo::internal::ValidateStruct(object->video_device, validation_context))
    return false;

  return true;
}

StreamDevices_Data::StreamDevices_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool StreamDevicesSet_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 16, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const StreamDevicesSet_Data* object =
      static_cast<const StreamDevicesSet_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->stream_devices, 1, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& stream_devices_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->stream_devices, validation_context,
                                         &stream_devices_validate_params)) {
    return false;
  }

  return true;
}

StreamDevicesSet_Data::StreamDevicesSet_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDeviceObserver_OnDeviceStopped_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDeviceObserver_OnDeviceStopped_Params_Data* object =
      static_cast<const MediaStreamDeviceObserver_OnDeviceStopped_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->label, 1, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& label_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->label, validation_context,
                                         &label_validate_params)) {
    return false;
  }

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device, 2, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->device, validation_context))
    return false;

  return true;
}

MediaStreamDeviceObserver_OnDeviceStopped_Params_Data::MediaStreamDeviceObserver_OnDeviceStopped_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDeviceObserver_OnDeviceChanged_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 32, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDeviceObserver_OnDeviceChanged_Params_Data* object =
      static_cast<const MediaStreamDeviceObserver_OnDeviceChanged_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->label, 1, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& label_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->label, validation_context,
                                         &label_validate_params)) {
    return false;
  }

  if (!mojo::internal::ValidatePointerNonNullable(
          object->old_device, 2, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->old_device, validation_context))
    return false;

  if (!mojo::internal::ValidatePointerNonNullable(
          object->new_device, 3, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->new_device, validation_context))
    return false;

  return true;
}

MediaStreamDeviceObserver_OnDeviceChanged_Params_Data::MediaStreamDeviceObserver_OnDeviceChanged_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDeviceObserver_OnDeviceRequestStateChange_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 32, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDeviceObserver_OnDeviceRequestStateChange_Params_Data* object =
      static_cast<const MediaStreamDeviceObserver_OnDeviceRequestStateChange_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->label, 1, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& label_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->label, validation_context,
                                         &label_validate_params)) {
    return false;
  }

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device, 2, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->device, validation_context))
    return false;


  if (!::blink::mojom::internal::MediaStreamStateChange_Data
        ::Validate(object->new_state, validation_context))
    return false;

  return true;
}

MediaStreamDeviceObserver_OnDeviceRequestStateChange_Params_Data::MediaStreamDeviceObserver_OnDeviceRequestStateChange_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDeviceObserver_OnDeviceCaptureConfigurationChange_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDeviceObserver_OnDeviceCaptureConfigurationChange_Params_Data* object =
      static_cast<const MediaStreamDeviceObserver_OnDeviceCaptureConfigurationChange_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->label, 1, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& label_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->label, validation_context,
                                         &label_validate_params)) {
    return false;
  }

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device, 2, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->device, validation_context))
    return false;

  return true;
}

MediaStreamDeviceObserver_OnDeviceCaptureConfigurationChange_Params_Data::MediaStreamDeviceObserver_OnDeviceCaptureConfigurationChange_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDeviceObserver_OnDeviceCaptureHandleChange_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDeviceObserver_OnDeviceCaptureHandleChange_Params_Data* object =
      static_cast<const MediaStreamDeviceObserver_OnDeviceCaptureHandleChange_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->label, 1, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& label_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->label, validation_context,
                                         &label_validate_params)) {
    return false;
  }

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device, 2, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->device, validation_context))
    return false;

  return true;
}

MediaStreamDeviceObserver_OnDeviceCaptureHandleChange_Params_Data::MediaStreamDeviceObserver_OnDeviceCaptureHandleChange_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDeviceObserver_OnZoomLevelChange_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 32, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDeviceObserver_OnZoomLevelChange_Params_Data* object =
      static_cast<const MediaStreamDeviceObserver_OnZoomLevelChange_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->label, 1, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& label_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->label, validation_context,
                                         &label_validate_params)) {
    return false;
  }

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device, 2, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->device, validation_context))
    return false;

  return true;
}

MediaStreamDeviceObserver_OnZoomLevelChange_Params_Data::MediaStreamDeviceObserver_OnZoomLevelChange_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_GenerateStreams_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 40, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_GenerateStreams_Params_Data* object =
      static_cast<const MediaStreamDispatcherHost_GenerateStreams_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->controls, 2, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->controls, validation_context))
    return false;

  if (!mojo::internal::ValidateInlinedUnionNonNullable(
          object->audio_stream_selection_info, 4, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateInlinedUnion(object->audio_stream_selection_info, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_GenerateStreams_Params_Data::MediaStreamDispatcherHost_GenerateStreams_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_GenerateStreams_ResponseParams_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 32, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_GenerateStreams_ResponseParams_Data* object =
      static_cast<const MediaStreamDispatcherHost_GenerateStreams_ResponseParams_Data*>(data);


  if (!::blink::mojom::internal::MediaStreamRequestResult_Data
        ::Validate(object->result, validation_context))
    return false;

  if (!mojo::internal::ValidatePointerNonNullable(
          object->label, 2, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& label_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->label, validation_context,
                                         &label_validate_params)) {
    return false;
  }

  if (!mojo::internal::ValidateStruct(object->stream_devices, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_GenerateStreams_ResponseParams_Data::MediaStreamDispatcherHost_GenerateStreams_ResponseParams_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_FocusCapturedSurface_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_FocusCapturedSurface_Params_Data* object =
      static_cast<const MediaStreamDispatcherHost_FocusCapturedSurface_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->label, 1, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& label_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->label, validation_context,
                                         &label_validate_params)) {
    return false;
  }

  return true;
}

MediaStreamDispatcherHost_FocusCapturedSurface_Params_Data::MediaStreamDispatcherHost_FocusCapturedSurface_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_CancelRequest_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 16, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_CancelRequest_Params_Data* object =
      static_cast<const MediaStreamDispatcherHost_CancelRequest_Params_Data*>(data);

  return true;
}

MediaStreamDispatcherHost_CancelRequest_Params_Data::MediaStreamDispatcherHost_CancelRequest_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_StopStreamDevice_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_StopStreamDevice_Params_Data* object =
      static_cast<const MediaStreamDispatcherHost_StopStreamDevice_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device_id, 1, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& device_id_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->device_id, validation_context,
                                         &device_id_validate_params)) {
    return false;
  }

  if (!mojo::internal::ValidateStruct(object->session_id, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_StopStreamDevice_Params_Data::MediaStreamDispatcherHost_StopStreamDevice_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_OpenDevice_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_OpenDevice_Params_Data* object =
      static_cast<const MediaStreamDispatcherHost_OpenDevice_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device_id, 2, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& device_id_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->device_id, validation_context,
                                         &device_id_validate_params)) {
    return false;
  }


  if (!::blink::mojom::internal::MediaStreamType_Data
        ::Validate(object->type, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_OpenDevice_Params_Data::MediaStreamDispatcherHost_OpenDevice_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_OpenDevice_ResponseParams_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 32, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_OpenDevice_ResponseParams_Data* object =
      static_cast<const MediaStreamDispatcherHost_OpenDevice_ResponseParams_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->label, 2, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& label_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->label, validation_context,
                                         &label_validate_params)) {
    return false;
  }

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device, 3, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->device, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_OpenDevice_ResponseParams_Data::MediaStreamDispatcherHost_OpenDevice_ResponseParams_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_CloseDevice_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 16, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_CloseDevice_Params_Data* object =
      static_cast<const MediaStreamDispatcherHost_CloseDevice_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->label, 1, validation_context)) {
    return false;
  }
  constexpr const mojo::internal::ContainerValidateParams& label_validate_params =
      mojo::internal::GetArrayValidator<0, false, nullptr>();
  if (!mojo::internal::ValidateContainer(object->label, validation_context,
                                         &label_validate_params)) {
    return false;
  }

  return true;
}

MediaStreamDispatcherHost_CloseDevice_Params_Data::MediaStreamDispatcherHost_CloseDevice_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_SetCapturingLinkSecured_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_SetCapturingLinkSecured_Params_Data* object =
      static_cast<const MediaStreamDispatcherHost_SetCapturingLinkSecured_Params_Data*>(data);

  if (!mojo::internal::ValidateStruct(object->session_id, validation_context))
    return false;


  if (!::blink::mojom::internal::MediaStreamType_Data
        ::Validate(object->type, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_SetCapturingLinkSecured_Params_Data::MediaStreamDispatcherHost_SetCapturingLinkSecured_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_ApplySubCaptureTarget_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 32, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_ApplySubCaptureTarget_Params_Data* object =
      static_cast<const MediaStreamDispatcherHost_ApplySubCaptureTarget_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device_id, 1, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->device_id, validation_context))
    return false;


  if (!::media::mojom::internal::SubCaptureTargetType_Data
        ::Validate(object->type, validation_context))
    return false;

  if (!mojo::internal::ValidatePointerNonNullable(
          object->sub_capture_target, 3, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->sub_capture_target, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_ApplySubCaptureTarget_Params_Data::MediaStreamDispatcherHost_ApplySubCaptureTarget_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_ApplySubCaptureTarget_ResponseParams_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 16, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_ApplySubCaptureTarget_ResponseParams_Data* object =
      static_cast<const MediaStreamDispatcherHost_ApplySubCaptureTarget_ResponseParams_Data*>(data);


  if (!::media::mojom::internal::ApplySubCaptureTargetResult_Data
        ::Validate(object->result, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_ApplySubCaptureTarget_ResponseParams_Data::MediaStreamDispatcherHost_ApplySubCaptureTarget_ResponseParams_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_SendWheel_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_SendWheel_Params_Data* object =
      static_cast<const MediaStreamDispatcherHost_SendWheel_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device_id, 1, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->device_id, validation_context))
    return false;

  if (!mojo::internal::ValidatePointerNonNullable(
          object->action, 2, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->action, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_SendWheel_Params_Data::MediaStreamDispatcherHost_SendWheel_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_SendWheel_ResponseParams_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 16, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_SendWheel_ResponseParams_Data* object =
      static_cast<const MediaStreamDispatcherHost_SendWheel_ResponseParams_Data*>(data);


  if (!::blink::mojom::internal::CapturedSurfaceControlResult_Data
        ::Validate(object->result, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_SendWheel_ResponseParams_Data::MediaStreamDispatcherHost_SendWheel_ResponseParams_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_SetZoomLevel_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_SetZoomLevel_Params_Data* object =
      static_cast<const MediaStreamDispatcherHost_SetZoomLevel_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->device_id, 1, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->device_id, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_SetZoomLevel_Params_Data::MediaStreamDispatcherHost_SetZoomLevel_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_SetZoomLevel_ResponseParams_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 16, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_SetZoomLevel_ResponseParams_Data* object =
      static_cast<const MediaStreamDispatcherHost_SetZoomLevel_ResponseParams_Data*>(data);


  if (!::blink::mojom::internal::CapturedSurfaceControlResult_Data
        ::Validate(object->result, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_SetZoomLevel_ResponseParams_Data::MediaStreamDispatcherHost_SetZoomLevel_ResponseParams_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_GetOpenDevice_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 32, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_GetOpenDevice_Params_Data* object =
      static_cast<const MediaStreamDispatcherHost_GetOpenDevice_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->session_id, 2, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->session_id, validation_context))
    return false;

  if (!mojo::internal::ValidatePointerNonNullable(
          object->transfer_id, 3, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->transfer_id, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_GetOpenDevice_Params_Data::MediaStreamDispatcherHost_GetOpenDevice_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_GetOpenDevice_ResponseParams_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_GetOpenDevice_ResponseParams_Data* object =
      static_cast<const MediaStreamDispatcherHost_GetOpenDevice_ResponseParams_Data*>(data);


  if (!::blink::mojom::internal::MediaStreamRequestResult_Data
        ::Validate(object->result, validation_context))
    return false;

  if (!mojo::internal::ValidateStruct(object->response, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_GetOpenDevice_ResponseParams_Data::MediaStreamDispatcherHost_GetOpenDevice_ResponseParams_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_KeepDeviceAliveForTransfer_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_KeepDeviceAliveForTransfer_Params_Data* object =
      static_cast<const MediaStreamDispatcherHost_KeepDeviceAliveForTransfer_Params_Data*>(data);

  if (!mojo::internal::ValidatePointerNonNullable(
          object->session_id, 1, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->session_id, validation_context))
    return false;

  if (!mojo::internal::ValidatePointerNonNullable(
          object->transfer_id, 2, validation_context)) {
    return false;
  }
  if (!mojo::internal::ValidateStruct(object->transfer_id, validation_context))
    return false;

  return true;
}

MediaStreamDispatcherHost_KeepDeviceAliveForTransfer_Params_Data::MediaStreamDispatcherHost_KeepDeviceAliveForTransfer_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamDispatcherHost_KeepDeviceAliveForTransfer_ResponseParams_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 16, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamDispatcherHost_KeepDeviceAliveForTransfer_ResponseParams_Data* object =
      static_cast<const MediaStreamDispatcherHost_KeepDeviceAliveForTransfer_ResponseParams_Data*>(data);

  return true;
}

MediaStreamDispatcherHost_KeepDeviceAliveForTransfer_ResponseParams_Data::MediaStreamDispatcherHost_KeepDeviceAliveForTransfer_ResponseParams_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamTrackMetricsHost_AddTrack_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 24, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamTrackMetricsHost_AddTrack_Params_Data* object =
      static_cast<const MediaStreamTrackMetricsHost_AddTrack_Params_Data*>(data);

  return true;
}

MediaStreamTrackMetricsHost_AddTrack_Params_Data::MediaStreamTrackMetricsHost_AddTrack_Params_Data()
    : header_({sizeof(*this), 0}) {}


// static
bool MediaStreamTrackMetricsHost_RemoveTrack_Params_Data::Validate(
    const void* data,
    mojo::internal::ValidationContext* validation_context) {
  if (!data)
    return true;
  if (!ValidateUnversionedStructHeaderAndSizeAndClaimMemory(
          data, 16, validation_context)) {
    return false;
  }

  // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
  // the message comes from an older version.
  [[maybe_unused]] const MediaStreamTrackMetricsHost_RemoveTrack_Params_Data* object =
      static_cast<const MediaStreamTrackMetricsHost_RemoveTrack_Params_Data*>(data);

  return true;
}

MediaStreamTrackMetricsHost_RemoveTrack_Params_Data::MediaStreamTrackMetricsHost_RemoveTrack_Params_Data()
    : header_({sizeof(*this), 0}) {}

}  // namespace internal
}  // namespace mojom
}  // namespace blink

namespace perfetto {

// static
void TraceFormatTraits<::blink::mojom::MediaStreamType>::WriteIntoTrace(
   perfetto::TracedValue context, ::blink::mojom::MediaStreamType value) {
  return std::move(context).WriteString(::blink::mojom::MediaStreamTypeToString(value));
}

} // namespace perfetto

namespace perfetto {

// static
void TraceFormatTraits<::blink::mojom::MediaStreamRequestResult>::WriteIntoTrace(
   perfetto::TracedValue context, ::blink::mojom::MediaStreamRequestResult value) {
  return std::move(context).WriteString(::blink::mojom::MediaStreamRequestResultToString(value));
}

} // namespace perfetto

namespace perfetto {

// static
void TraceFormatTraits<::blink::mojom::MediaStreamStateChange>::WriteIntoTrace(
   perfetto::TracedValue context, ::blink::mojom::MediaStreamStateChange value) {
  return std::move(context).WriteString(::blink::mojom::MediaStreamStateChangeToString(value));
}

} // namespace perfetto

namespace perfetto {

// static
void TraceFormatTraits<::blink::mojom::PreferredDisplaySurface>::WriteIntoTrace(
   perfetto::TracedValue context, ::blink::mojom::PreferredDisplaySurface value) {
  return std::move(context).WriteString(::blink::mojom::PreferredDisplaySurfaceToString(value));
}

} // namespace perfetto

namespace perfetto {

// static
void TraceFormatTraits<::blink::mojom::CapturedSurfaceControlResult>::WriteIntoTrace(
   perfetto::TracedValue context, ::blink::mojom::CapturedSurfaceControlResult value) {
  return std::move(context).WriteString(::blink::mojom::CapturedSurfaceControlResultToString(value));
}

} // namespace perfetto