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

#include "content/browser/devtools/protocol/emulation_handler.h"

#include <utility>

#include "base/check_deref.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "base/types/expected.h"
#include "base/types/expected_macros.h"
#include "build/build_config.h"
#include "components/download/public/common/download_url_parameters.h"
#include "content/browser/compute_pressure/web_contents_pressure_manager_proxy.h"
#include "content/browser/device_posture/device_posture_provider_impl.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/protocol/emulation.h"
#include "content/browser/generic_sensor/web_contents_sensor_provider_proxy.h"
#include "content/browser/idle/idle_manager_impl.h"
#include "content/browser/renderer_host/input/touch_emulator_impl.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/screen_orientation/screen_orientation_provider.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
#include "net/http/http_util.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
#include "services/device/public/cpp/geolocation/geoposition.h"
#include "services/device/public/mojom/geolocation_context.mojom.h"
#include "services/device/public/mojom/geoposition.mojom.h"
#include "services/device/public/mojom/pressure_manager.mojom.h"
#include "services/device/public/mojom/pressure_update.mojom.h"
#include "services/device/public/mojom/sensor.mojom-shared.h"
#include "services/network/public/cpp/client_hints.h"
#include "third_party/blink/public/mojom/device_posture/device_posture_provider.mojom.h"
#include "third_party/blink/public/mojom/page/widget.mojom-shared.h"
#include "ui/display/mojom/screen_orientation.mojom.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"

namespace content {
namespace protocol {

namespace {

constexpr char kCommandIsOnlyAvailableAtTopTarget[] =
    "Command can only be executed on top-level targets";
#if BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
constexpr char kPressureSourceIsAlreadyOverridden[] =
    "The specified pressure source is already overridden";
constexpr char kPressureSourceIsNotOverridden[] =
    "The specified pressure source is not being overridden";
#endif  // BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
constexpr char kSensorIsAlreadyOverridden[] =
    "The specified sensor type is already overridden";
constexpr char kSensorIsNotOverridden[] =
    "This sensor type is not being overridden with a virtual sensor";

display::mojom::ScreenOrientation WebScreenOrientationTypeFromString(
    const std::string& type) {
  if (type == Emulation::ScreenOrientation::TypeEnum::PortraitPrimary)
    return display::mojom::ScreenOrientation::kPortraitPrimary;
  if (type == Emulation::ScreenOrientation::TypeEnum::PortraitSecondary)
    return display::mojom::ScreenOrientation::kPortraitSecondary;
  if (type == Emulation::ScreenOrientation::TypeEnum::LandscapePrimary)
    return display::mojom::ScreenOrientation::kLandscapePrimary;
  if (type == Emulation::ScreenOrientation::TypeEnum::LandscapeSecondary)
    return display::mojom::ScreenOrientation::kLandscapeSecondary;
  return display::mojom::ScreenOrientation::kUndefined;
}

std::optional<content::DisplayFeature::Orientation>
DisplayFeatureOrientationTypeFromString(const std::string& type) {
  if (type == Emulation::DisplayFeature::OrientationEnum::Vertical)
    return content::DisplayFeature::Orientation::kVertical;
  if (type == Emulation::DisplayFeature::OrientationEnum::Horizontal)
    return content::DisplayFeature::Orientation::kHorizontal;
  return std::nullopt;
}

base::expected<blink::mojom::DevicePostureType, protocol::Response>
DevicePostureTypeFromString(const std::string& type) {
  if (type == Emulation::DevicePosture::TypeEnum::Continuous) {
    return blink::mojom::DevicePostureType::kContinuous;
  } else if (type == Emulation::DevicePosture::TypeEnum::Folded) {
    return blink::mojom::DevicePostureType::kFolded;
  } else {
    return base::unexpected(
        protocol::Response::InvalidParams("Invalid posture type"));
  }
}

ui::GestureProviderConfigType TouchEmulationConfigurationToType(
    const std::string& protocol_value) {
  ui::GestureProviderConfigType result =
      ui::GestureProviderConfigType::CURRENT_PLATFORM;
  if (protocol_value ==
      Emulation::SetEmitTouchEventsForMouse::ConfigurationEnum::Mobile) {
    result = ui::GestureProviderConfigType::GENERIC_MOBILE;
  }
  if (protocol_value ==
      Emulation::SetEmitTouchEventsForMouse::ConfigurationEnum::Desktop) {
    result = ui::GestureProviderConfigType::GENERIC_DESKTOP;
  }
  return result;
}

bool ValidateClientHintString(const std::string& s) {
  // Matches definition in structured headers:
  // https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-17#section-3.3.3
  for (char c : s) {
    if (!base::IsAsciiPrintable(c))
      return false;
  }
  return true;
}

}  // namespace

EmulationHandler::EmulationHandler()
    : DevToolsDomainHandler(Emulation::Metainfo::domainName),
      touch_emulation_enabled_(false),
      device_emulation_enabled_(false),
      focus_emulation_enabled_(false),
      host_(nullptr) {}

EmulationHandler::~EmulationHandler() = default;

// static
std::vector<EmulationHandler*> EmulationHandler::ForAgentHost(
    DevToolsAgentHostImpl* host) {
  return host->HandlersByName<EmulationHandler>(
      Emulation::Metainfo::domainName);
}

void EmulationHandler::SetRenderer(int process_host_id,
                                   RenderFrameHostImpl* frame_host) {
  if (host_ == frame_host)
    return;
  if (!frame_host) {
    sensor_overrides_.clear();
#if BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
    pressure_overrides_.clear();
#endif  // BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
  }
  host_ = frame_host;
  if (touch_emulation_enabled_)
    UpdateTouchEventEmulationState();
  if (device_emulation_enabled_)
    UpdateDeviceEmulationState(
        blink::mojom::DeviceEmulationCacheBehavior::kKeepCache);
}

void EmulationHandler::Wire(UberDispatcher* dispatcher) {
  frontend_ = std::make_unique<Emulation::Frontend>(dispatcher->channel());
  Emulation::Dispatcher::wire(dispatcher, this);
}

Response EmulationHandler::Disable() {
  if (touch_emulation_enabled_) {
    touch_emulation_enabled_ = false;
    UpdateTouchEventEmulationState();
  }
  user_agent_ = std::string();
  if (device_emulation_enabled_) {
    device_emulation_enabled_ = false;
    if (screen_orientation_lock_emulation_enabled_) {
      screen_orientation_lock_emulation_enabled_ = false;
      UpdateScreenOrientationEmulation(false);
    }
    UpdateDeviceEmulationState();
  }
  if (focus_emulation_enabled_)
    SetFocusEmulationEnabled(false);
  prefers_color_scheme_ = "";
  prefers_reduced_motion_ = "";
  prefers_reduced_transparency_ = "";
  sensor_overrides_.clear();
#if BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
  pressure_overrides_.clear();
#endif  // BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
  ClearDevicePostureOverride();
  return Response::Success();
}

namespace {

Response ConvertSensorType(const Emulation::SensorType& type,
                           device::mojom::SensorType* out_type) {
  if (type == Emulation::SensorTypeEnum::AbsoluteOrientation) {
    *out_type = device::mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION;
  } else if (type == Emulation::SensorTypeEnum::Accelerometer) {
    *out_type = device::mojom::SensorType::ACCELEROMETER;
  } else if (type == Emulation::SensorTypeEnum::AmbientLight) {
    *out_type = device::mojom::SensorType::AMBIENT_LIGHT;
  } else if (type == Emulation::SensorTypeEnum::Gravity) {
    *out_type = device::mojom::SensorType::GRAVITY;
  } else if (type == Emulation::SensorTypeEnum::Gyroscope) {
    *out_type = device::mojom::SensorType::GYROSCOPE;
  } else if (type == Emulation::SensorTypeEnum::LinearAcceleration) {
    *out_type = device::mojom::SensorType::LINEAR_ACCELERATION;
  } else if (type == Emulation::SensorTypeEnum::Magnetometer) {
    *out_type = device::mojom::SensorType::MAGNETOMETER;
  } else if (type == Emulation::SensorTypeEnum::RelativeOrientation) {
    *out_type = device::mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION;
  } else {
    return Response::InvalidParams("Invalid sensor type: " + type);
  }

  return Response::Success();
}

Response ConvertSensorReading(device::mojom::SensorType type,
                              Emulation::SensorReading* const reading,
                              device::SensorReading* out_reading) {
  switch (type) {
    case device::mojom::SensorType::AMBIENT_LIGHT: {
      if (!reading->HasSingle()) {
        return Response::InvalidParams(
            "This sensor type requires a 'single' parameter");
      }
      auto* single_value = reading->GetSingle(nullptr);
      out_reading->als.value = single_value->GetValue();
      break;
    }
    case device::mojom::SensorType::ACCELEROMETER:
    case device::mojom::SensorType::GRAVITY:
    case device::mojom::SensorType::GYROSCOPE:
    case device::mojom::SensorType::LINEAR_ACCELERATION:
    case device::mojom::SensorType::MAGNETOMETER: {
      if (!reading->HasXyz()) {
        return Response::InvalidParams(
            "This sensor type requires an 'xyz' parameter");
      }
      auto* xyz = reading->GetXyz(nullptr);
      out_reading->accel.x = xyz->GetX();
      out_reading->accel.y = xyz->GetY();
      out_reading->accel.z = xyz->GetZ();
      break;
    }
    case device::mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION:
    case device::mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION: {
      if (!reading->HasQuaternion()) {
        return Response::InvalidParams(
            "This sensor type requires a 'quaternion' parameter");
      }
      auto* quaternion = reading->GetQuaternion(nullptr);
      out_reading->orientation_quat.x = quaternion->GetX();
      out_reading->orientation_quat.y = quaternion->GetY();
      out_reading->orientation_quat.z = quaternion->GetZ();
      out_reading->orientation_quat.w = quaternion->GetW();
      break;
    }
    case device::mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES:
    case device::mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES:
      return Response::InvalidParams("Unsupported sensor type");
  }
  out_reading->raw.timestamp =
      (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
  return Response::Success();
}

base::expected<device::mojom::VirtualSensorMetadataPtr, Response>
ParseSensorMetadata(std::unique_ptr<Emulation::SensorMetadata>& metadata) {
  if (!metadata) {
    return device::mojom::VirtualSensorMetadata::New();
  }

  if (metadata->HasMinimumFrequency() && metadata->HasMaximumFrequency() &&
      metadata->GetMinimumFrequency(0) > metadata->GetMaximumFrequency(0)) {
    return base::unexpected(
        Response::InvalidParams("The specified minimum frequency is higher "
                                "than the maximum frequency"));
  }

  auto virtual_sensor_metadata = device::mojom::VirtualSensorMetadata::New();
  if (metadata->HasAvailable()) {
    virtual_sensor_metadata->available = metadata->GetAvailable(true);
  }
  if (metadata->HasMinimumFrequency()) {
    virtual_sensor_metadata->minimum_frequency =
        metadata->GetMinimumFrequency(0);
  }
  if (metadata->HasMaximumFrequency()) {
    virtual_sensor_metadata->maximum_frequency =
        metadata->GetMaximumFrequency(0);
  }
  return virtual_sensor_metadata;
}

}  // namespace

void EmulationHandler::GetOverriddenSensorInformation(
    const Emulation::SensorType& type,
    std::unique_ptr<GetOverriddenSensorInformationCallback> callback) {
  if (!host_) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  device::mojom::SensorType sensor_type;
  if (auto response = ConvertSensorType(type, &sensor_type);
      !response.IsSuccess()) {
    callback->sendFailure(response);
    return;
  }

  auto it = sensor_overrides_.find(sensor_type);
  if (it == sensor_overrides_.end()) {
    callback->sendFailure(Response::InvalidParams(kSensorIsNotOverridden));
    return;
  }

  it->second->GetVirtualSensorInformation(base::BindOnce(
      [](std::unique_ptr<GetOverriddenSensorInformationCallback> callback,
         device::mojom::GetVirtualSensorInformationResultPtr result) {
        if (result->is_error()) {
          switch (result->get_error()) {
            case device::mojom::GetVirtualSensorInformationError::
                kSensorTypeNotOverridden:
              callback->sendFailure(
                  Response::InvalidParams(kSensorIsNotOverridden));
              return;
          }
        }
        CHECK(result->is_info());
        callback->sendSuccess(result->get_info()->sampling_frequency);
      },
      std::move(callback)));
}

Response EmulationHandler::SetSensorOverrideEnabled(
    bool enabled,
    const Emulation::SensorType& type,
    std::unique_ptr<Emulation::SensorMetadata> metadata) {
  if (!host_) {
    return Response::InternalError();
  }

  device::mojom::SensorType sensor_type;
  if (auto response = ConvertSensorType(type, &sensor_type);
      !response.IsSuccess()) {
    return response;
  }

  if (enabled) {
    auto virtual_sensor_metadata = ParseSensorMetadata(metadata);
    if (!virtual_sensor_metadata.has_value()) {
      return virtual_sensor_metadata.error();
    }

    if (sensor_overrides_.contains(sensor_type)) {
      return Response::InvalidParams(kSensorIsAlreadyOverridden);
    }

    auto virtual_sensor =
        WebContentsSensorProviderProxy::GetOrCreate(GetWebContents())
            ->CreateVirtualSensorForDevTools(
                sensor_type, std::move(virtual_sensor_metadata.value()));
    if (!virtual_sensor) {
      return Response::InvalidParams(kSensorIsAlreadyOverridden);
    }
    sensor_overrides_[sensor_type] = std::move(virtual_sensor);
  } else {
    sensor_overrides_.erase(sensor_type);
  }
  return Response::Success();
}

void EmulationHandler::SetSensorOverrideReadings(
    const Emulation::SensorType& type,
    std::unique_ptr<Emulation::SensorReading> reading,
    std::unique_ptr<SetSensorOverrideReadingsCallback> callback) {
  if (!host_) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  device::mojom::SensorType sensor_type;
  if (auto response = ConvertSensorType(type, &sensor_type);
      !response.IsSuccess()) {
    callback->sendFailure(response);
    return;
  }

  device::SensorReading device_reading;
  if (auto response =
          ConvertSensorReading(sensor_type, reading.get(), &device_reading);
      !response.IsSuccess()) {
    callback->sendFailure(response);
    return;
  }

  auto it = sensor_overrides_.find(sensor_type);
  if (it == sensor_overrides_.end()) {
    callback->sendFailure(Response::InvalidParams(kSensorIsNotOverridden));
    return;
  }

  it->second->UpdateVirtualSensor(
      device_reading,
      base::BindOnce(
          [](std::unique_ptr<SetSensorOverrideReadingsCallback> callback,
             device::mojom::UpdateVirtualSensorResult result) {
            switch (result) {
              case device::mojom::UpdateVirtualSensorResult::
                  kSensorTypeNotOverridden:
                callback->sendFailure(
                    Response::InvalidParams(kSensorIsNotOverridden));
                break;
              case device::mojom::UpdateVirtualSensorResult::kSuccess:
                callback->sendSuccess();
                break;
            }
          },
          std::move(callback)));
}

#if BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
namespace {

device::mojom::VirtualPressureSourceMetadataPtr ConvertPressureMetadata(
    std::unique_ptr<Emulation::PressureMetadata>& metadata) {
  auto pressure_metadata = device::mojom::VirtualPressureSourceMetadata::New();
  if (metadata) {
    pressure_metadata->available = metadata->GetAvailable(true);
  }
  return pressure_metadata;
}

Response ConvertPressureSource(const Emulation::PressureSource& source,
                               device::mojom::PressureSource* out_type) {
  if (source == Emulation::PressureSourceEnum::Cpu) {
    *out_type = device::mojom::PressureSource::kCpu;
  } else {
    return Response::InvalidParams("Invalid pressure source: " + source);
  }
  return Response::Success();
}

Response ConvertPressureState(const Emulation::PressureState& state,
                              device::mojom::PressureState* out_type) {
  if (state == Emulation::PressureStateEnum::Nominal) {
    *out_type = device::mojom::PressureState::kNominal;
  } else if (state == Emulation::PressureStateEnum::Fair) {
    *out_type = device::mojom::PressureState::kFair;
  } else if (state == Emulation::PressureStateEnum::Serious) {
    *out_type = device::mojom::PressureState::kSerious;
  } else if (state == Emulation::PressureStateEnum::Critical) {
    *out_type = device::mojom::PressureState::kCritical;
  } else {
    return Response::InvalidParams("Invalid pressure state: " + state);
  }
  return Response::Success();
}

}  // namespace
#endif  // BUILDFLAG(ENABLE_COMPUTE_PRESSURE)

Response EmulationHandler::SetPressureSourceOverrideEnabled(
    bool enabled,
    const Emulation::PressureSource& source,
    std::unique_ptr<Emulation::PressureMetadata> metadata) {
#if BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
  if (!host_) {
    return Response::InternalError();
  }
  device::mojom::PressureSource mojo_source;
  if (auto response = ConvertPressureSource(source, &mojo_source);
      !response.IsSuccess()) {
    return response;
  }
  if (enabled) {
    if (pressure_overrides_.contains(mojo_source)) {
      return Response::InvalidParams(kPressureSourceIsAlreadyOverridden);
    }
    auto virtual_pressure_source =
        WebContentsPressureManagerProxy::GetOrCreate(GetWebContents())
            ->CreateVirtualPressureSourceForDevTools(
                mojo_source, ConvertPressureMetadata(metadata));
    if (!virtual_pressure_source) {
      return Response::InvalidParams(kPressureSourceIsAlreadyOverridden);
    }
    pressure_overrides_[mojo_source] = std::move(virtual_pressure_source);
  } else {
    pressure_overrides_.erase(mojo_source);
  }
  return Response::Success();
#else
  return Response::InternalError();
#endif  // BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
}

// TODO: Remove obsolete method.
// `SetPressureStateOverride` will be replaced by SetPressureDataOverride.
// The method UpdateVirtualPressureSourceState called previously
// was removed in //content.
void EmulationHandler::SetPressureStateOverride(
    const Emulation::PressureSource& source,
    const Emulation::PressureState& state,
    std::unique_ptr<SetPressureStateOverrideCallback> callback) {
  callback->sendFailure(Response::InternalError());
  return;
}

void EmulationHandler::SetPressureDataOverride(
    const Emulation::PressureSource& source,
    const Emulation::PressureState& state,
    std::optional<double> own_contribution_estimate,
    std::unique_ptr<SetPressureDataOverrideCallback> callback) {
  if (!host_) {
    callback->sendFailure(Response::InternalError());
    return;
  }

#if BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
  device::mojom::PressureSource mojo_source;
  if (auto response = ConvertPressureSource(source, &mojo_source);
      !response.IsSuccess()) {
    callback->sendFailure(response);
    return;
  }
  device::mojom::PressureState mojo_state;
  if (auto response = ConvertPressureState(state, &mojo_state);
      !response.IsSuccess()) {
    callback->sendFailure(response);
    return;
  }
  auto it = pressure_overrides_.find(mojo_source);
  if (it == pressure_overrides_.end()) {
    callback->sendFailure(
        Response::InvalidParams(kPressureSourceIsNotOverridden));
    return;
  }
  it->second->UpdateVirtualPressureSourceData(
      mojo_state, own_contribution_estimate.value_or(0.0),
      base::BindOnce(&SetPressureDataOverrideCallback::sendSuccess,
                     std::move(callback)));
#else
  callback->sendFailure(Response::InternalError());
#endif  // BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
}

Response EmulationHandler::SetIdleOverride(bool is_user_active,
                                           bool is_screen_unlocked) {
  if (!host_)
    return Response::InternalError();
  host_->GetIdleManager()->SetIdleOverride(is_user_active, is_screen_unlocked);
  return Response::Success();
}

Response EmulationHandler::ClearIdleOverride() {
  if (!host_)
    return Response::InternalError();
  host_->GetIdleManager()->ClearIdleOverride();
  return Response::Success();
}

Response EmulationHandler::SetGeolocationOverride(
    std::optional<double> latitude,
    std::optional<double> longitude,
    std::optional<double> accuracy,
    std::optional<double> altitude,
    std::optional<double> altitude_accuracy,
    std::optional<double> heading,
    std::optional<double> speed
) {
  if (!host_)
    return Response::InternalError();

  auto* geolocation_context = GetWebContents()->GetGeolocationContext();
  device::mojom::GeopositionResultPtr override_result;
  if (latitude.has_value() && longitude.has_value() && accuracy.has_value()) {
    auto position = device::mojom::Geoposition::New();
    position->latitude = latitude.value();
    position->longitude = longitude.value();
    position->accuracy = accuracy.value();
    if (altitude.has_value()) {
      position->altitude = altitude.value();
    }
    if (altitude_accuracy.has_value()) {
      position->altitude_accuracy = altitude_accuracy.value();
    }
    if (heading.has_value()) {
      position->heading = heading.value();
    }
    if (speed.has_value()) {
      position->speed = speed.value();
    }
    position->timestamp = base::Time::Now();
    if (!device::ValidateGeoposition(*position)) {
      return Response::ServerError("Invalid geolocation");
    }
    override_result =
        device::mojom::GeopositionResult::NewPosition(std::move(position));
  } else {
    override_result = device::mojom::GeopositionResult::NewError(
        device::mojom::GeopositionError::New(
            device::mojom::GeopositionErrorCode::kPositionUnavailable,
            /*error_message=*/"", /*error_technical=*/""));
  }
  geolocation_context->SetOverride(std::move(override_result));
  return Response::Success();
}

Response EmulationHandler::ClearGeolocationOverride() {
  if (!host_)
    return Response::InternalError();

  auto* geolocation_context = GetWebContents()->GetGeolocationContext();
  geolocation_context->ClearOverride();
  return Response::Success();
}

Response EmulationHandler::SetEmitTouchEventsForMouse(
    bool enabled,
    std::optional<std::string> configuration) {
  if (!host_)
    return Response::InternalError();

  if (host_->GetParentOrOuterDocument())
    return Response::ServerError(kCommandIsOnlyAvailableAtTopTarget);

  touch_emulation_enabled_ = enabled;
  touch_emulation_configuration_ = configuration.value_or("");
  UpdateTouchEventEmulationState();
  return Response::Success();
}

Response EmulationHandler::CanEmulate(bool* result) {
#if BUILDFLAG(IS_ANDROID)
  *result = false;
#else
  *result = true;
  if (host_) {
    if (GetWebContents()->GetVisibleURL().SchemeIs(kChromeDevToolsScheme) ||
        host_->GetRenderWidgetHost()->auto_resize_enabled())
      *result = false;
  }
#endif  // BUILDFLAG(IS_ANDROID)
  return Response::Success();
}

Response EmulationHandler::SetDeviceMetricsOverride(
    int width,
    int height,
    double device_scale_factor,
    bool mobile,
    std::optional<double> scale,
    std::optional<int> screen_width,
    std::optional<int> screen_height,
    std::optional<int> position_x,
    std::optional<int> position_y,
    std::optional<bool> dont_set_visible_size,
    std::unique_ptr<Emulation::ScreenOrientation> screen_orientation,
    std::unique_ptr<protocol::Page::Viewport> viewport,
    std::unique_ptr<protocol::Emulation::DisplayFeature> display_feature,
    std::unique_ptr<protocol::Emulation::DevicePosture> device_posture,
    std::optional<std::string> scrollbar_type,
    std::optional<bool> screen_orientation_lock_emulation) {
  const static int max_size = 10000000;
  const static double max_scale = 10;
  const static int max_orientation_angle = 360;

  if (!host_ || host_->GetRenderWidgetHost()->auto_resize_enabled()) {
    return Response::ServerError("Target does not support metrics override");
  }

  if (host_->GetParentOrOuterDocument())
    return Response::ServerError(kCommandIsOnlyAvailableAtTopTarget);

  if (screen_width.value_or(0) < 0 || screen_height.value_or(0) < 0 ||
      screen_width.value_or(0) > max_size ||
      screen_height.value_or(0) > max_size) {
    return Response::InvalidParams(
        "Screen width and height values must be positive, not greater than " +
        base::NumberToString(max_size));
  }

  if (position_x.value_or(0) < 0 || position_y.value_or(0) < 0 ||
      position_x.value_or(0) > screen_width.value_or(0) ||
      position_y.value_or(0) > screen_height.value_or(0)) {
    return Response::InvalidParams("View position should be on the screen");
  }

  if (width < 0 || height < 0 || width > max_size || height > max_size) {
    return Response::InvalidParams(
        "Width and height values must be positive, not greater than " +
        base::NumberToString(max_size));
  }

  if (device_scale_factor < 0)
    return Response::InvalidParams("deviceScaleFactor must be non-negative");

  if (scale.value_or(1) <= 0 || scale.value_or(1) > max_scale) {
    return Response::InvalidParams("scale must be positive, not greater than " +
                                   base::NumberToString(max_scale));
  }

  display::mojom::ScreenOrientation orientationType =
      display::mojom::ScreenOrientation::kUndefined;
  int orientationAngle = 0;
  if (screen_orientation) {
    Emulation::ScreenOrientation& orientation = *screen_orientation;
    orientationType = WebScreenOrientationTypeFromString(orientation.GetType());
    if (orientationType == display::mojom::ScreenOrientation::kUndefined)
      return Response::InvalidParams("Invalid screen orientation type value");
    orientationAngle = orientation.GetAngle();
    if (orientationAngle < 0 || orientationAngle >= max_orientation_angle) {
      return Response::InvalidParams(
          "Screen orientation angle must be non-negative, less than " +
          base::NumberToString(max_orientation_angle));
    }
  }

  std::optional<content::DisplayFeature> content_display_feature = std::nullopt;
  if (display_feature) {
    protocol::Emulation::DisplayFeature& emu_display_feature = *display_feature;
    std::optional<content::DisplayFeature::Orientation> disp_orientation =
        DisplayFeatureOrientationTypeFromString(
            emu_display_feature.GetOrientation());
    if (!disp_orientation) {
      return Response::InvalidParams(
          "Invalid display feature orientation type");
    }
    content::DisplayFeature::ParamErrorEnum error;
    content_display_feature = content::DisplayFeature::Create(
        *disp_orientation, emu_display_feature.GetOffset(),
        emu_display_feature.GetMaskLength(), width, height, &error);

    if (!content_display_feature) {
      switch (error) {
        case content::DisplayFeature::ParamErrorEnum::
            kDisplayFeatureWithZeroScreenSize:
          return Response::InvalidParams(
              "Cannot specify a display feature with zero width and height");
        case content::DisplayFeature::ParamErrorEnum::
            kNegativeDisplayFeatureParams:
          return Response::InvalidParams("Negative display feature parameters");
        case content::DisplayFeature::ParamErrorEnum::kOutsideScreenWidth:
          return Response::InvalidParams(
              "Display feature viewport segments outside screen width");
        case content::DisplayFeature::ParamErrorEnum::kOutsideScreenHeight:
          return Response::InvalidParams(
              "Display feature viewport segments outside screen height");
      }
    }
  }

  blink::DeviceEmulationParams params;
  params.screen_type = mobile ? blink::mojom::EmulatedScreenType::kMobile
                              : blink::mojom::EmulatedScreenType::kDesktop;
  params.screen_size =
      gfx::Size(screen_width.value_or(0), screen_height.value_or(0));
  if (position_x.has_value() && position_y.has_value()) {
    params.view_position =
        gfx::Point(position_x.value_or(0), position_y.value_or(0));
  }
  params.device_scale_factor = device_scale_factor;
  if (width > 0 || height > 0) {
    params.view_size = gfx::Size(width, height);
  }
  params.scale = scale.value_or(1);
  params.screen_orientation_type = orientationType;
  params.screen_orientation_angle = orientationAngle;

  if (content_display_feature) {
    params.viewport_segments =
        content_display_feature->ComputeViewportSegments(params.view_size);
  }

  if (device_posture) {
    params.device_posture =
        DevicePostureTypeFromString(device_posture->GetType()).value();
  }

  if (mobile ||
      (scrollbar_type &&
       *scrollbar_type ==
           Emulation::SetDeviceMetricsOverride::ScrollbarTypeEnum::Overlay)) {
    params.force_android_overlay_scrollbar = true;
  } else {
    params.force_android_overlay_scrollbar = false;
  }

  if (viewport) {
    params.viewport_offset.SetPoint(viewport->GetX(), viewport->GetY());

    double dpfactor =
        device_scale_factor
            ? device_scale_factor /
                  host_->GetRenderWidgetHost()->GetDeviceScaleFactor()
            : 1;
    params.viewport_scale = viewport->GetScale() * dpfactor;

    // Resize the RenderWidgetHostView to the size of the overridden viewport.
    width = base::ClampRound(viewport->GetWidth() * params.viewport_scale);
    height = base::ClampRound(viewport->GetHeight() * params.viewport_scale);
  }

  bool size_changed = false;
  if (!dont_set_visible_size.value_or(false) && width > 0 && height > 0) {
    if (GetWebContents()) {
      size_changed =
          GetWebContents()->SetDeviceEmulationSize(gfx::Size(width, height));
    } else {
      return Response::ServerError("Can't find the associated web contents");
    }
  }

  bool enable_orientation_lock =
      screen_orientation_lock_emulation.value_or(false);
  if (enable_orientation_lock != screen_orientation_lock_emulation_enabled_) {
    screen_orientation_lock_emulation_enabled_ = enable_orientation_lock;
    UpdateScreenOrientationEmulation(enable_orientation_lock);
  }

  if (device_emulation_enabled_ && params == device_emulation_params_) {
    // Renderer should answer after size was changed, so that the response is
    // only sent to the client once updates were applied.
    if (size_changed)
      return Response::FallThrough();
    return Response::Success();
  }

  device_emulation_enabled_ = true;
  device_emulation_params_ = params;
  UpdateDeviceEmulationState();

  // Renderer should answer after emulation params were updated, so that the
  // response is only sent to the client once updates were applied.
  // Unless the renderer has crashed.
  if (GetWebContents() && GetWebContents()->IsCrashed())
    return Response::Success();
  return Response::FallThrough();
}

Response EmulationHandler::ClearDeviceMetricsOverride() {
  if (!host_)
    return Response::ServerError("Can't find the associated web contents");
  if (host_->GetParentOrOuterDocument())
    return Response::ServerError(kCommandIsOnlyAvailableAtTopTarget);
  if (!device_emulation_enabled_)
    return Response::Success();

  GetWebContents()->ClearDeviceEmulationSize();
  device_emulation_enabled_ = false;
  device_emulation_params_ = blink::DeviceEmulationParams();
  if (screen_orientation_lock_emulation_enabled_) {
    screen_orientation_lock_emulation_enabled_ = false;
    UpdateScreenOrientationEmulation(false);
  }
  UpdateDeviceEmulationState();
  // Renderer should answer after emulation was disabled, so that the response
  // is only sent to the client once updates were applied.
  // Unless the renderer has crashed.
  if (GetWebContents()->IsCrashed())
    return Response::Success();
  return Response::FallThrough();
}

Response EmulationHandler::SetVisibleSize(int width, int height) {
  if (width < 0 || height < 0)
    return Response::InvalidParams("Width and height must be non-negative");

  if (!host_)
    return Response::ServerError("Can't find the associated web contents");
  GetWebContents()->SetDeviceEmulationSize(gfx::Size(width, height));
  return Response::Success();
}

Response EmulationHandler::SetUserAgentOverride(
    const std::string& user_agent,
    std::optional<std::string> accept_language,
    std::optional<std::string> platform,
    std::unique_ptr<Emulation::UserAgentMetadata> ua_metadata_override) {
  if (!user_agent.empty() && !net::HttpUtil::IsValidHeaderValue(user_agent))
    return Response::InvalidParams("Invalid characters found in userAgent");
  std::string accept_lang = accept_language.value_or(std::string());
  if (!accept_lang.empty() && !net::HttpUtil::IsValidHeaderValue(accept_lang)) {
    return Response::InvalidParams(
        "Invalid characters found in acceptLanguage");
  }

  user_agent_ = user_agent;
  accept_language_ = accept_lang;

  user_agent_metadata_ = std::nullopt;
  if (!ua_metadata_override) {
    return Response::FallThrough();
  }

  if (user_agent.empty()) {
    return Response::InvalidParams(
        "Empty userAgent invalid with userAgentMetadata provided");
  }

  Emulation::UserAgentMetadata& ua_metadata = *ua_metadata_override;
  blink::UserAgentMetadata new_ua_metadata;
  blink::UserAgentMetadata default_ua_metadata =
      GetContentClient()->browser()->GetUserAgentMetadata();

  if (ua_metadata.HasBrands()) {
    for (const auto& bv : *ua_metadata.GetBrands(nullptr)) {
      blink::UserAgentBrandVersion out_bv;
      if (!ValidateClientHintString(bv->GetBrand()))
        return Response::InvalidParams("Invalid brand string");
      out_bv.brand = bv->GetBrand();

      if (!ValidateClientHintString(bv->GetVersion()))
        return Response::InvalidParams("Invalid brand version string");
      out_bv.version = bv->GetVersion();

      new_ua_metadata.brand_version_list.push_back(std::move(out_bv));
    }
  } else {
    new_ua_metadata.brand_version_list =
        std::move(default_ua_metadata.brand_version_list);
  }

  if (ua_metadata.HasFullVersionList()) {
    for (const auto& bv : *ua_metadata.GetFullVersionList(nullptr)) {
      blink::UserAgentBrandVersion out_bv;
      if (!ValidateClientHintString(bv->GetBrand()))
        return Response::InvalidParams("Invalid brand string");
      out_bv.brand = bv->GetBrand();

      if (!ValidateClientHintString(bv->GetVersion()))
        return Response::InvalidParams("Invalid brand version string");
      out_bv.version = bv->GetVersion();

      new_ua_metadata.brand_full_version_list.push_back(std::move(out_bv));
    }
  } else {
    new_ua_metadata.brand_full_version_list =
        std::move(default_ua_metadata.brand_full_version_list);
  }

  if (ua_metadata.HasFullVersion()) {
    String full_version = ua_metadata.GetFullVersion("");
    if (!ValidateClientHintString(full_version))
      return Response::InvalidParams("Invalid full version string");
    new_ua_metadata.full_version = full_version;
  } else {
    new_ua_metadata.full_version = std::move(default_ua_metadata.full_version);
  }

  if (!ValidateClientHintString(ua_metadata.GetPlatform())) {
    return Response::InvalidParams("Invalid platform string");
  }
  new_ua_metadata.platform = ua_metadata.GetPlatform();

  if (!ValidateClientHintString(ua_metadata.GetPlatformVersion())) {
    return Response::InvalidParams("Invalid platform version string");
  }
  new_ua_metadata.platform_version = ua_metadata.GetPlatformVersion();

  if (!ValidateClientHintString(ua_metadata.GetArchitecture())) {
    return Response::InvalidParams("Invalid architecture string");
  }
  new_ua_metadata.architecture = ua_metadata.GetArchitecture();

  if (!ValidateClientHintString(ua_metadata.GetModel())) {
    return Response::InvalidParams("Invalid model string");
  }

  new_ua_metadata.model = ua_metadata.GetModel();
  new_ua_metadata.mobile = ua_metadata.GetMobile();

  if (ua_metadata.HasBitness()) {
    String bitness = ua_metadata.GetBitness("");
    if (!ValidateClientHintString(bitness))
      return Response::InvalidParams("Invalid bitness string");
    new_ua_metadata.bitness = std::move(bitness);
  } else {
    new_ua_metadata.bitness = std::move(default_ua_metadata.bitness);
  }
  if (ua_metadata.HasWow64()) {
    new_ua_metadata.wow64 = ua_metadata.GetWow64(false);
  } else {
    new_ua_metadata.wow64 = default_ua_metadata.wow64;
  }

  for (const auto& form_factor :
       *ua_metadata.GetFormFactors(&default_ua_metadata.form_factors)) {
    if (!ValidateClientHintString(form_factor)) {
      return Response::InvalidParams("Invalid form factor string");
    }
    new_ua_metadata.form_factors.push_back(form_factor);
  }

  // All checks OK, can update user_agent_metadata_.
  user_agent_metadata_.emplace(std::move(new_ua_metadata));
  return Response::FallThrough();
}

Response EmulationHandler::SetFocusEmulationEnabled(bool enabled) {
  if (enabled == focus_emulation_enabled_)
    return Response::FallThrough();
  focus_emulation_enabled_ = enabled;
  if (enabled) {
    capture_handle_ = GetWebContents()->IncrementCapturerCount(
        gfx::Size(),
        /*stay_hidden=*/false,
        /*stay_awake=*/false, /*is_activity=*/true);
  } else {
    capture_handle_.RunAndReset();
  }
  return Response::FallThrough();
}

Response EmulationHandler::SetEmulatedMedia(
    std::optional<std::string> media,
    std::unique_ptr<protocol::Array<protocol::Emulation::MediaFeature>>
        features) {
  if (!host_)
    return Response::InternalError();

  prefers_color_scheme_ = "";
  prefers_reduced_motion_ = "";
  prefers_reduced_transparency_ = "";
  if (features) {
    for (auto const& mediaFeature : *features) {
      auto const& name = mediaFeature->GetName();
      auto const& value = mediaFeature->GetValue();
      if (name == "prefers-color-scheme") {
        prefers_color_scheme_ = (value == network::kPrefersColorSchemeLight ||
                                 value == network::kPrefersColorSchemeDark)
                                    ? value
                                    : "";
      } else if (name == "prefers-reduced-motion") {
        prefers_reduced_motion_ =
            (value == network::kPrefersReducedMotionReduce) ? value : "";
      } else if (name == "prefers-reduced-transparency") {
        prefers_reduced_transparency_ =
            (value == network::kPrefersReducedTransparencyReduce) ? value : "";
      }
    }
  }

  return Response::FallThrough();
}

blink::DeviceEmulationParams EmulationHandler::GetDeviceEmulationParams() {
  return device_emulation_params_;
}

void EmulationHandler::SetDeviceEmulationParams(
    const blink::DeviceEmulationParams& params) {
  DCHECK(host_);
  // Device emulation only happens on the outermost main frame.
  DCHECK(!host_->GetParentOrOuterDocument());

  bool enabled = params != blink::DeviceEmulationParams();
  bool enable_changed = enabled != device_emulation_enabled_;
  bool params_changed = params != device_emulation_params_;
  if (!device_emulation_enabled_ && !enable_changed)
    return;  // Still disabled.
  if (!enable_changed && !params_changed)
    return;  // Nothing changed.
  device_emulation_enabled_ = enabled;
  device_emulation_params_ = params;
  UpdateDeviceEmulationState();
}

WebContentsImpl* EmulationHandler::GetWebContents() {
  DCHECK(host_);  // Only call if |host_| is set.
  return static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host_));
}

void EmulationHandler::UpdateTouchEventEmulationState() {
  if (!host_)
    return;

  // We only have a single TouchEmulator for all frames, so let the main frame's
  // EmulationHandler enable/disable it.
  DCHECK(!host_->GetParentOrOuterDocument());

  if (touch_emulation_enabled_) {
    if (auto* touch_emulator = host_->GetRenderWidgetHost()->GetTouchEmulator(
            /*create_if_necessary=*/true)) {
      touch_emulator->Enable(
          input::TouchEmulator::Mode::kEmulatingTouchFromMouse,
          TouchEmulationConfigurationToType(touch_emulation_configuration_));
    }
  } else {
    if (auto* touch_emulator = host_->GetRenderWidgetHost()->GetTouchEmulator(
            /*create_if_necessary=*/true)) {
      touch_emulator->Disable();
    }
  }
  GetWebContents()->SetForceDisableOverscrollContent(touch_emulation_enabled_);
}

void EmulationHandler::UpdateDeviceEmulationState(
    const blink::mojom::DeviceEmulationCacheBehavior& cache_behavior) {
  if (!host_)
    return;

  // Device emulation only happens on the outermost main frame.
  DCHECK(!host_->GetParentOrOuterDocument());

  // TODO(eseckler): Once we change this to mojo, we should wait for an ack to
  // these messages from the renderer. The renderer should send the ack once the
  // emulation params were applied. That way, we can avoid having to handle
  // Set/ClearDeviceMetricsOverride in the renderer. With the old IPC system,
  // this is tricky since we'd have to track the DevTools message id with the
  // WidgetMsg and acknowledgment, as well as plump the acknowledgment back to
  // the EmulationHandler somehow. Mojo callbacks should make this much simpler.
  host_->ForEachRenderFrameHostImplIncludingSpeculative(
      [this, &cache_behavior](RenderFrameHostImpl* host) {
        // The main frame of nested subpages (ex. fenced frames) inside this
        // page are updated as well.
        if (host->is_main_frame())
          UpdateDeviceEmulationStateForHost(host->GetRenderWidgetHost(),
                                            cache_behavior);
      });
}

void EmulationHandler::UpdateDeviceEmulationStateForHost(
    RenderWidgetHostImpl* render_widget_host,
    const blink::mojom::DeviceEmulationCacheBehavior& cache_behavior) {
  auto& frame_widget = render_widget_host->GetAssociatedFrameWidget();
  if (!frame_widget)
    return;
  if (device_emulation_enabled_) {
    frame_widget->EnableDeviceEmulation(device_emulation_params_,
                                        cache_behavior);
  } else {
    frame_widget->DisableDeviceEmulation();
  }
}

Response EmulationHandler::SetDevicePostureOverride(
    std::unique_ptr<protocol::Emulation::DevicePosture> posture) {
  ASSIGN_OR_RETURN(blink::mojom::DevicePostureType posture_type,
                   DevicePostureTypeFromString(posture->GetType()));
  device_posture_emulation_enabled_ = true;
  GetWebContents()
      ->GetDevicePostureProvider()
      ->OverrideDevicePostureForEmulation(posture_type);
  return Response::Success();
}

Response EmulationHandler::ClearDevicePostureOverride() {
  if (device_posture_emulation_enabled_) {
    device_posture_emulation_enabled_ = false;
    GetWebContents()
        ->GetDevicePostureProvider()
        ->DisableDevicePostureOverrideForEmulation();
  }
  return Response::Success();
}

Response EmulationHandler::SetDisplayFeaturesOverride(
    std::unique_ptr<protocol::Array<protocol::Emulation::DisplayFeature>>
        features) {
  if (!host_->GetView()) {
    return Response::InternalError();
  }

  // TODO(crbug.com/40113439): Chromium only supports one display feature at the
  // moment.
  if (features->size() > 1) {
    return Response::InvalidParams("Only one display feature is supported");
  }
  protocol::Emulation::DisplayFeature& emu_display_feature =
      CHECK_DEREF(features->front().get());
  std::optional<content::DisplayFeature::Orientation> disp_orientation =
      DisplayFeatureOrientationTypeFromString(
          emu_display_feature.GetOrientation());
  if (!disp_orientation) {
    return Response::InvalidParams("Invalid display feature orientation type");
  }
  content::DisplayFeature::ParamErrorEnum error;
  const gfx::Size viewport_size = host_->GetView()->GetVisibleViewportSize();
  std::optional<content::DisplayFeature> content_display_feature =
      content::DisplayFeature::Create(
          *disp_orientation, emu_display_feature.GetOffset(),
          emu_display_feature.GetMaskLength(), viewport_size.width(),
          viewport_size.height(), &error);

  if (!content_display_feature) {
    switch (error) {
      case content::DisplayFeature::ParamErrorEnum::
          kDisplayFeatureWithZeroScreenSize:
        return Response::InvalidParams(
            "Cannot specify a display feature with zero width and height");
      case content::DisplayFeature::ParamErrorEnum::
          kNegativeDisplayFeatureParams:
        return Response::InvalidParams("Negative display feature parameters");
      case content::DisplayFeature::ParamErrorEnum::kOutsideScreenWidth:
        return Response::InvalidParams(
            "Display feature viewport segments outside screen width");
      case content::DisplayFeature::ParamErrorEnum::kOutsideScreenHeight:
        return Response::InvalidParams(
            "Display feature viewport segments outside screen height");
    }
  }

  host_->GetView()->OverrideDisplayFeatureForEmulation(
      &content_display_feature.value());
  return Response::Success();
}

Response EmulationHandler::ClearDisplayFeaturesOverride() {
  if (!host_->GetView()) {
    return Response::InternalError();
  }
  host_->GetView()->DisableDisplayFeatureOverrideForEmulation();
  return Response::Success();
}

void EmulationHandler::ApplyOverrides(net::HttpRequestHeaders* headers,
                                      bool* user_agent_overridden,
                                      bool* accept_language_overridden) {
  if (!user_agent_.empty()) {
    headers->SetHeader(net::HttpRequestHeaders::kUserAgent, user_agent_);
  }
  *user_agent_overridden = !user_agent_.empty();
  if (!accept_language_.empty()) {
    headers->SetHeader(
        net::HttpRequestHeaders::kAcceptLanguage,
        net::HttpUtil::GenerateAcceptLanguageHeader(accept_language_));
  }
  *accept_language_overridden = !accept_language_.empty();
  if (!prefers_color_scheme_.empty()) {
    const auto& prefers_color_scheme_client_hint_name =
        network::GetClientHintToNameMap().at(
            network::mojom::WebClientHintsType::kPrefersColorScheme);
    if (headers->HasHeader(prefers_color_scheme_client_hint_name)) {
      headers->SetHeader(prefers_color_scheme_client_hint_name,
                         prefers_color_scheme_);
    }
  }
  if (!prefers_reduced_motion_.empty()) {
    const auto& prefers_reduced_motion_client_hint_name =
        network::GetClientHintToNameMap().at(
            network::mojom::WebClientHintsType::kPrefersReducedMotion);
    if (headers->HasHeader(prefers_reduced_motion_client_hint_name)) {
      headers->SetHeader(prefers_reduced_motion_client_hint_name,
                         prefers_reduced_motion_);
    }
  }
  if (!prefers_reduced_transparency_.empty()) {
    const auto& prefers_reduced_transparency_client_hint_name =
        network::GetClientHintToNameMap().at(
            network::mojom::WebClientHintsType::kPrefersReducedTransparency);
    if (headers->HasHeader(prefers_reduced_transparency_client_hint_name)) {
      headers->SetHeader(prefers_reduced_transparency_client_hint_name,
                         prefers_reduced_transparency_);
    }
  }
}

bool EmulationHandler::ApplyUserAgentMetadataOverrides(
    std::optional<blink::UserAgentMetadata>* override_out) {
  // This is conditional on basic user agent override being on; this helps us
  // emulate a device not sending any UA client hints.
  if (user_agent_.empty())
    return false;
  *override_out = user_agent_metadata_;
  return true;
}

void EmulationHandler::ApplyNetworkOverridesForDownload(
    download::DownloadUrlParameters* parameters) {
  net::HttpRequestHeaders headers;
  bool user_agent_overridden;
  bool accept_language_overridden;
  ApplyOverrides(&headers, &user_agent_overridden, &accept_language_overridden);
  for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();) {
    parameters->add_request_header(it.name(), it.value());
  }
}

void EmulationHandler::UpdateScreenOrientationEmulation(bool enabled) {
  WebContentsImpl* web_contents = GetWebContents();
  if (!web_contents) {
    return;
  }
  ScreenOrientationProvider* provider =
      web_contents->GetScreenOrientationProvider();
  if (!provider) {
    return;
  }
  provider->SetDevToolsEmulationEnabled(enabled);
  if (enabled) {
    provider->SetOrientationLockChangedCallback(base::BindRepeating(
        &EmulationHandler::OnOrientationLockChanged, base::Unretained(this)));
  } else {
    provider->SetOrientationLockChangedCallback(
        ScreenOrientationProvider::OrientationLockChangedCallback());
  }
}

void EmulationHandler::OnOrientationLockChanged(
    bool locked,
    std::optional<device::mojom::ScreenOrientationLockType> orientation) {
  if (!frontend_) {
    return;
  }

  if (locked && orientation.has_value()) {
    std::string type;
    int angle = 0;
    switch (orientation.value()) {
      case device::mojom::ScreenOrientationLockType::PORTRAIT_PRIMARY:
        type = Emulation::ScreenOrientation::TypeEnum::PortraitPrimary;
        angle = 0;
        break;
      case device::mojom::ScreenOrientationLockType::PORTRAIT_SECONDARY:
        type = Emulation::ScreenOrientation::TypeEnum::PortraitSecondary;
        angle = 180;
        break;
      case device::mojom::ScreenOrientationLockType::LANDSCAPE_PRIMARY:
        type = Emulation::ScreenOrientation::TypeEnum::LandscapePrimary;
        angle = 90;
        break;
      case device::mojom::ScreenOrientationLockType::LANDSCAPE_SECONDARY:
        type = Emulation::ScreenOrientation::TypeEnum::LandscapeSecondary;
        angle = 270;
        break;
      case device::mojom::ScreenOrientationLockType::PORTRAIT:
        type = Emulation::ScreenOrientation::TypeEnum::PortraitPrimary;
        angle = 0;
        break;
      case device::mojom::ScreenOrientationLockType::LANDSCAPE:
        type = Emulation::ScreenOrientation::TypeEnum::LandscapePrimary;
        angle = 90;
        break;
      default:
        type = Emulation::ScreenOrientation::TypeEnum::PortraitPrimary;
        angle = 0;
        break;
    }
    auto screen_orientation = Emulation::ScreenOrientation::Create()
                                  .SetType(type)
                                  .SetAngle(angle)
                                  .Build();
    frontend_->ScreenOrientationLockChanged(locked,
                                            std::move(screen_orientation));
  } else {
    frontend_->ScreenOrientationLockChanged(locked);
  }
}

}  // namespace protocol
}  // namespace content
