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

#include "flutter/shell/platform/fuchsia/flutter/platform_view.h"

#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/default.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/sys/cpp/testing/service_directory_provider.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>

#include <memory>
#include <ostream>
#include <string>
#include <vector>

#include "flutter/flow/embedded_views.h"
#include "flutter/lib/ui/window/platform_message.h"
#include "flutter/lib/ui/window/viewport_metrics.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include "surface.h"
#include "task_runner_adapter.h"

namespace flutter_runner::testing {
namespace {

class MockExternalViewEmbedder : public flutter::ExternalViewEmbedder {
 public:
  SkCanvas* GetRootCanvas() override { return nullptr; }
  std::vector<SkCanvas*> GetCurrentCanvases() override {
    return std::vector<SkCanvas*>();
  }

  void CancelFrame() override {}
  void BeginFrame(
      SkISize frame_size,
      GrDirectContext* context,
      double device_pixel_ratio,
      fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override {}
  void SubmitFrame(GrDirectContext* context,
                   std::unique_ptr<flutter::SurfaceFrame> frame,
                   const std::shared_ptr<const fml::SyncSwitch>&
                       gpu_disable_sync_switch) override {
    return;
  }

  void PrerollCompositeEmbeddedView(
      int view_id,
      std::unique_ptr<flutter::EmbeddedViewParams> params) override {}
  SkCanvas* CompositeEmbeddedView(int view_id) override { return nullptr; }
};

class MockPlatformViewDelegate : public flutter::PlatformView::Delegate {
 public:
  void Reset() {
    message_ = nullptr;
    metrics_ = flutter::ViewportMetrics{};
    semantics_features_ = 0;
    semantics_enabled_ = false;
  }

  // |flutter::PlatformView::Delegate|
  void OnPlatformViewCreated(std::unique_ptr<flutter::Surface> surface) {
    ASSERT_EQ(surface_.get(), nullptr);

    surface_ = std::move(surface);
  }
  // |flutter::PlatformView::Delegate|
  void OnPlatformViewDestroyed() {}
  // |flutter::PlatformView::Delegate|
  void OnPlatformViewSetNextFrameCallback(const fml::closure& closure) {}
  // |flutter::PlatformView::Delegate|
  void OnPlatformViewSetViewportMetrics(
      const flutter::ViewportMetrics& metrics) {
    metrics_ = metrics;
  }
  // |flutter::PlatformView::Delegate|
  void OnPlatformViewDispatchPlatformMessage(
      std::unique_ptr<flutter::PlatformMessage> message) {
    message_ = std::move(message);
  }
  // |flutter::PlatformView::Delegate|
  void OnPlatformViewDispatchPointerDataPacket(
      std::unique_ptr<flutter::PointerDataPacket> packet) {}
  // |flutter::PlatformView::Delegate|
  void OnPlatformViewDispatchKeyDataPacket(
      std::unique_ptr<flutter::KeyDataPacket> packet,
      std::function<void(bool)> callback) {}
  // |flutter::PlatformView::Delegate|
  void OnPlatformViewDispatchSemanticsAction(int32_t id,
                                             flutter::SemanticsAction action,
                                             std::vector<uint8_t> args) {}
  // |flutter::PlatformView::Delegate|
  void OnPlatformViewSetSemanticsEnabled(bool enabled) {
    semantics_enabled_ = enabled;
  }
  // |flutter::PlatformView::Delegate|
  void OnPlatformViewSetAccessibilityFeatures(int32_t flags) {
    semantics_features_ = flags;
  }
  // |flutter::PlatformView::Delegate|
  void OnPlatformViewRegisterTexture(
      std::shared_ptr<flutter::Texture> texture) {}
  // |flutter::PlatformView::Delegate|
  void OnPlatformViewUnregisterTexture(int64_t texture_id) {}
  // |flutter::PlatformView::Delegate|
  void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) {}
  // |flutter::PlatformView::Delegate|
  std::unique_ptr<std::vector<std::string>> ComputePlatformViewResolvedLocale(
      const std::vector<std::string>& supported_locale_data) {
    return nullptr;
  }
  // |flutter::PlatformView::Delegate|
  void LoadDartDeferredLibrary(
      intptr_t loading_unit_id,
      std::unique_ptr<const fml::Mapping> snapshot_data,
      std::unique_ptr<const fml::Mapping> snapshot_instructions) {}
  // |flutter::PlatformView::Delegate|
  void LoadDartDeferredLibraryError(intptr_t loading_unit_id,
                                    const std::string error_message,
                                    bool transient) {}
  // |flutter::PlatformView::Delegate|
  void UpdateAssetResolverByType(
      std::unique_ptr<flutter::AssetResolver> updated_asset_resolver,
      flutter::AssetResolver::AssetResolverType type) {}

  flutter::Surface* surface() const { return surface_.get(); }
  flutter::PlatformMessage* message() const { return message_.get(); }
  const flutter::ViewportMetrics& metrics() const { return metrics_; }
  int32_t semantics_features() const { return semantics_features_; }
  bool semantics_enabled() const { return semantics_enabled_; }

 private:
  std::unique_ptr<flutter::Surface> surface_;
  std::unique_ptr<flutter::PlatformMessage> message_;
  flutter::ViewportMetrics metrics_;
  int32_t semantics_features_ = 0;
  bool semantics_enabled_ = false;
};

class MockFocuser : public fuchsia::ui::views::Focuser {
 public:
  MockFocuser(bool fail_request_focus = false)
      : fail_request_focus_(fail_request_focus) {}

  bool request_focus_called() const { return request_focus_called_; }

 private:
  void RequestFocus(fuchsia::ui::views::ViewRef view_ref,
                    RequestFocusCallback callback) override {
    request_focus_called_ = true;
    auto result =
        fail_request_focus_
            ? fuchsia::ui::views::Focuser_RequestFocus_Result::WithErr(
                  fuchsia::ui::views::Error::DENIED)
            : fuchsia::ui::views::Focuser_RequestFocus_Result::WithResponse(
                  fuchsia::ui::views::Focuser_RequestFocus_Response());
    callback(std::move(result));
  }

  bool request_focus_called_ = false;
  bool fail_request_focus_ = false;
};

class MockResponse : public flutter::PlatformMessageResponse {
 public:
  MOCK_METHOD1(Complete, void(std::unique_ptr<fml::Mapping> data));
  MOCK_METHOD0(CompleteEmpty, void());
};

// Used to construct partial instances of PlatformView for testing.  The
// PlatformView constructor has many parameters, not all of which need to
// be filled out for each test.  The builder allows you to initialize only
// those that matter to your specific test.  Not all builder methods are
// provided: if you find some that are missing, feel free to add them.
class PlatformViewBuilder {
 public:
  PlatformViewBuilder(flutter::PlatformView::Delegate& delegate,
                      flutter::TaskRunners task_runners,
                      std::shared_ptr<sys::ServiceDirectory> runner_services)
      : delegate_(delegate),
        debug_label_("test_platform_view"),
        view_ref_(fuchsia::ui::views::ViewRef()),
        task_runners_(task_runners),
        runner_services_(runner_services) {}

  // Add builder methods as required.

  PlatformViewBuilder& SetServiceProvider(
      fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> service_provider) {
    parent_environment_service_provider_ = std::move(service_provider);
    return *this;
  }

  PlatformViewBuilder& SetFocuser(
      fidl::InterfaceHandle<fuchsia::ui::views::Focuser> focuser) {
    focuser_ = std::move(focuser);
    return *this;
  }

  PlatformViewBuilder& SetDestroyViewCallback(OnDestroyView callback) {
    on_destroy_view_callback_ = std::move(callback);
    return *this;
  }

  PlatformViewBuilder& SetUpdateViewCallback(OnUpdateView callback) {
    on_update_view_callback_ = std::move(callback);
    return *this;
  }

  PlatformViewBuilder& SetEnableWireframeCallback(OnEnableWireframe callback) {
    wireframe_enabled_callback_ = std::move(callback);
    return *this;
  }

  PlatformViewBuilder& SetCreateViewCallback(OnCreateView callback) {
    on_create_view_callback_ = std::move(callback);
    return *this;
  }

  PlatformViewBuilder& SetSessionListenerRequest(
      fidl::InterfaceRequest<fuchsia::ui::scenic::SessionListener> request) {
    session_listener_request_ = std::move(request);
    return *this;
  }

  PlatformViewBuilder& SetCreateSurfaceCallback(OnCreateSurface callback) {
    on_create_surface_callback_ = std::move(callback);
    return *this;
  }

  PlatformViewBuilder& SetViewEmbedder(
      std::shared_ptr<flutter::ExternalViewEmbedder> embedder) {
    view_embedder_ = embedder;
    return *this;
  }

  PlatformViewBuilder& SetKeyboardListener(
      fidl::InterfaceRequest<fuchsia::ui::input3::KeyboardListener> listener) {
    keyboard_listener_ = std::move(listener);
    return *this;
  }

  // Once Build is called, the instance is no longer usable.
  PlatformView Build() {
    EXPECT_EQ(false, built_)
        << "Build() was already called, this buider is good for one use only.";
    built_ = true;
    return PlatformView(delegate_, debug_label_, std::move(view_ref_),
                        task_runners_, runner_services_,
                        std::move(parent_environment_service_provider_),
                        std::move(session_listener_request_),
                        std::move(focuser_), std::move(keyboard_listener_),
                        std::move(on_session_listener_error_callback_),
                        std::move(wireframe_enabled_callback_),
                        std::move(on_create_view_callback_),
                        std::move(on_update_view_callback_),
                        std::move(on_destroy_view_callback_),
                        std::move(on_create_surface_callback_), view_embedder_,
                        std::move(vsync_offset_), vsync_event_handle_);
  }

 private:
  PlatformViewBuilder() = delete;

  bool built_{false};

  // Required elements.  Make sure to initialize them.
  flutter::PlatformView::Delegate& delegate_;
  std::string debug_label_;
  fuchsia::ui::views::ViewRef view_ref_;
  flutter::TaskRunners task_runners_;
  std::shared_ptr<sys::ServiceDirectory> runner_services_{nullptr};
  fidl::InterfaceHandle<fuchsia::sys::ServiceProvider>
      parent_environment_service_provider_{nullptr};

  // Optional elements.
  fidl::InterfaceRequest<fuchsia::ui::scenic::SessionListener>
      session_listener_request_{nullptr};
  fidl::InterfaceHandle<fuchsia::ui::views::Focuser> focuser_{nullptr};
  fidl::InterfaceRequest<fuchsia::ui::input3::KeyboardListener>
      keyboard_listener_{nullptr};
  fit::closure on_session_listener_error_callback_{nullptr};
  OnEnableWireframe wireframe_enabled_callback_{nullptr};
  OnCreateView on_create_view_callback_{nullptr};
  OnUpdateView on_update_view_callback_{nullptr};
  OnDestroyView on_destroy_view_callback_{nullptr};
  OnCreateSurface on_create_surface_callback_{nullptr};
  std::shared_ptr<flutter::ExternalViewEmbedder> view_embedder_{nullptr};
  fml::TimeDelta vsync_offset_{fml::TimeDelta::Zero()};
  zx_handle_t vsync_event_handle_{ZX_HANDLE_INVALID};
};

}  // namespace

class PlatformViewTests : public ::testing::Test {
 protected:
  PlatformViewTests() : loop_(&kAsyncLoopConfigAttachToCurrentThread) {}

  async_dispatcher_t* dispatcher() { return loop_.dispatcher(); }

  void RunLoopUntilIdle() {
    loop_.RunUntilIdle();
    loop_.ResetQuit();
  }

  fuchsia::ui::input3::KeyEvent MakeEvent(
      fuchsia::ui::input3::KeyEventType event_type,
      std::optional<fuchsia::ui::input3::Modifiers> modifiers,
      fuchsia::input::Key key) {
    fuchsia::ui::input3::KeyEvent event;
    event.set_timestamp(++event_timestamp_);
    event.set_type(event_type);
    if (modifiers.has_value()) {
      event.set_modifiers(modifiers.value());
    }
    event.set_key(key);
    return event;
  }

 private:
  async::Loop loop_;

  uint64_t event_timestamp_{42};

  FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewTests);
};

// This test makes sure that the PlatformView correctly returns a Surface
// instance that can surface the provided gr_context and view_embedder.
TEST_F(PlatformViewTests, CreateSurfaceTest) {
  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
  MockPlatformViewDelegate delegate;

  flutter::TaskRunners task_runners =
      flutter::TaskRunners("test_runners",  // label
                           nullptr,         // platform
                           flutter_runner::CreateFMLTaskRunner(
                               async_get_default_dispatcher()),  // raster
                           nullptr,                              // ui
                           nullptr                               // io
      );

  // Test create surface callback function.
  sk_sp<GrDirectContext> gr_context =
      GrDirectContext::MakeMock(nullptr, GrContextOptions());
  std::shared_ptr<MockExternalViewEmbedder> view_embedder =
      std::make_shared<MockExternalViewEmbedder>();
  auto CreateSurfaceCallback = [&view_embedder, gr_context]() {
    return std::make_unique<flutter_runner::Surface>(
        "PlatformViewTest", view_embedder, gr_context.get());
  };

  flutter_runner::PlatformView platform_view =
      PlatformViewBuilder(delegate, std::move(task_runners),
                          services_provider.service_directory())
          .SetCreateSurfaceCallback(CreateSurfaceCallback)
          .SetViewEmbedder(view_embedder)
          .Build();
  platform_view.NotifyCreated();

  RunLoopUntilIdle();

  EXPECT_EQ(gr_context.get(), delegate.surface()->GetContext());
  EXPECT_EQ(view_embedder.get(),
            platform_view.CreateExternalViewEmbedder().get());
}

// This test makes sure that the PlatformView correctly registers Scenic
// MetricsEvents sent to it via FIDL, correctly parses the metrics it receives,
// and calls the SetViewportMetrics callback with the appropriate parameters.
TEST_F(PlatformViewTests, SetViewportMetrics) {
  constexpr float invalid_pixel_ratio = -0.75f;
  constexpr float valid_pixel_ratio = 0.75f;
  constexpr float invalid_max_bound = -0.75f;
  constexpr float valid_max_bound = 0.75f;

  MockPlatformViewDelegate delegate;
  EXPECT_EQ(delegate.metrics(), flutter::ViewportMetrics());

  fuchsia::ui::scenic::SessionListenerPtr session_listener;
  std::vector<fuchsia::ui::scenic::Event> events;
  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
  flutter::TaskRunners task_runners("test_runners", nullptr, nullptr, nullptr,
                                    nullptr);
  flutter_runner::PlatformView platform_view =
      PlatformViewBuilder(delegate, std::move(task_runners),
                          services_provider.service_directory())
          .SetSessionListenerRequest(session_listener.NewRequest())
          .Build();
  RunLoopUntilIdle();
  EXPECT_EQ(delegate.metrics(), flutter::ViewportMetrics());

  // Test updating with an invalid pixel ratio.  The final metrics should be
  // unchanged.
  events.clear();
  events.emplace_back(fuchsia::ui::scenic::Event::WithGfx(
      fuchsia::ui::gfx::Event::WithMetrics(fuchsia::ui::gfx::MetricsEvent{
          .node_id = 0,
          .metrics =
              fuchsia::ui::gfx::Metrics{
                  .scale_x = invalid_pixel_ratio,
                  .scale_y = 1.f,
                  .scale_z = 1.f,
              },
      })));
  session_listener->OnScenicEvent(std::move(events));
  RunLoopUntilIdle();
  EXPECT_EQ(delegate.metrics(), flutter::ViewportMetrics());

  // Test updating with an invalid size.  The final metrics should be unchanged.
  events.clear();
  events.emplace_back(
      fuchsia::ui::scenic::Event::WithGfx(
          fuchsia::ui::gfx::Event::WithViewPropertiesChanged(
              fuchsia::ui::gfx::ViewPropertiesChangedEvent{
                  .view_id = 0,
                  .properties =
                      fuchsia::ui::gfx::ViewProperties{
                          .bounding_box =
                              fuchsia::ui::gfx::BoundingBox{
                                  .min =
                                      fuchsia::ui::gfx::vec3{
                                          .x = 0.f,
                                          .y = 0.f,
                                          .z = 0.f,
                                      },
                                  .max =
                                      fuchsia::ui::gfx::vec3{
                                          .x = invalid_max_bound,
                                          .y = invalid_max_bound,
                                          .z = invalid_max_bound,
                                      },
                              },
                      },
              })));
  session_listener->OnScenicEvent(std::move(events));
  RunLoopUntilIdle();
  EXPECT_EQ(delegate.metrics(), flutter::ViewportMetrics());

  // Test updating the size only.  The final metrics should be unchanged until
  // both pixel ratio and size are updated.
  events.clear();
  events.emplace_back(
      fuchsia::ui::scenic::Event::WithGfx(
          fuchsia::ui::gfx::Event::WithViewPropertiesChanged(
              fuchsia::ui::gfx::ViewPropertiesChangedEvent{
                  .view_id = 0,
                  .properties =
                      fuchsia::ui::gfx::ViewProperties{
                          .bounding_box =
                              fuchsia::ui::gfx::BoundingBox{
                                  .min =
                                      fuchsia::ui::gfx::vec3{
                                          .x = 0.f,
                                          .y = 0.f,
                                          .z = 0.f,
                                      },
                                  .max =
                                      fuchsia::ui::gfx::vec3{
                                          .x = valid_max_bound,
                                          .y = valid_max_bound,
                                          .z = valid_max_bound,
                                      },
                              },
                      },
              })));
  session_listener->OnScenicEvent(std::move(events));
  RunLoopUntilIdle();
  EXPECT_EQ(delegate.metrics(), flutter::ViewportMetrics());

  // Test updating the pixel ratio only.  The final metrics should change now.
  events.clear();
  events.emplace_back(fuchsia::ui::scenic::Event::WithGfx(
      fuchsia::ui::gfx::Event::WithMetrics(fuchsia::ui::gfx::MetricsEvent{
          .node_id = 0,
          .metrics =
              fuchsia::ui::gfx::Metrics{
                  .scale_x = valid_pixel_ratio,
                  .scale_y = 1.f,
                  .scale_z = 1.f,
              },
      })));
  session_listener->OnScenicEvent(std::move(events));
  RunLoopUntilIdle();
  EXPECT_EQ(delegate.metrics(),
            flutter::ViewportMetrics(valid_pixel_ratio,
                                     valid_pixel_ratio * valid_max_bound,
                                     valid_pixel_ratio * valid_max_bound));
}

// This test makes sure that the PlatformView correctly registers semantics
// settings changes applied to it and calls the SetSemanticsEnabled /
// SetAccessibilityFeatures callbacks with the appropriate parameters.
TEST_F(PlatformViewTests, ChangesAccessibilitySettings) {
  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());

  MockPlatformViewDelegate delegate;
  flutter::TaskRunners task_runners =
      flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);

  EXPECT_FALSE(delegate.semantics_enabled());
  EXPECT_EQ(delegate.semantics_features(), 0);

  flutter_runner::PlatformView platform_view =
      PlatformViewBuilder(
          delegate,                              // delegate
          std::move(task_runners),               // task_runners
          services_provider.service_directory()  // runner_services
          )
          .Build();

  RunLoopUntilIdle();

  platform_view.SetSemanticsEnabled(true);

  EXPECT_TRUE(delegate.semantics_enabled());
  EXPECT_EQ(delegate.semantics_features(),
            static_cast<int32_t>(
                flutter::AccessibilityFeatureFlag::kAccessibleNavigation));

  platform_view.SetSemanticsEnabled(false);

  EXPECT_FALSE(delegate.semantics_enabled());
  EXPECT_EQ(delegate.semantics_features(), 0);
}

// This test makes sure that the PlatformView forwards messages on the
// "flutter/platform_views" channel for EnableWireframe.
TEST_F(PlatformViewTests, EnableWireframeTest) {
  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
  MockPlatformViewDelegate delegate;
  flutter::TaskRunners task_runners =
      flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);

  // Test wireframe callback function. If the message sent to the platform
  // view was properly handled and parsed, this function should be called,
  // setting |wireframe_enabled| to true.
  bool wireframe_enabled = false;
  auto EnableWireframeCallback = [&wireframe_enabled](bool should_enable) {
    wireframe_enabled = should_enable;
  };

  flutter_runner::PlatformView platform_view =
      PlatformViewBuilder(delegate, std::move(task_runners),
                          services_provider.service_directory())
          .SetEnableWireframeCallback(EnableWireframeCallback)
          .Build();

  // Cast platform_view to its base view so we can have access to the public
  // "HandlePlatformMessage" function.
  auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
  EXPECT_TRUE(base_view);

  // JSON for the message to be passed into the PlatformView.
  const uint8_t txt[] =
      "{"
      "    \"method\":\"View.enableWireframe\","
      "    \"args\": {"
      "       \"enable\":true"
      "    }"
      "}";

  std::unique_ptr<flutter::PlatformMessage> message =
      std::make_unique<flutter::PlatformMessage>(
          "flutter/platform_views",
          std::vector<uint8_t>(txt, txt + sizeof(txt)),
          fml::RefPtr<flutter::PlatformMessageResponse>());
  base_view->HandlePlatformMessage(std::move(message));

  RunLoopUntilIdle();

  EXPECT_TRUE(wireframe_enabled);
}

// This test makes sure that the PlatformView forwards messages on the
// "flutter/platform_views" channel for Createview.
TEST_F(PlatformViewTests, CreateViewTest) {
  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
  MockPlatformViewDelegate delegate;
  flutter::TaskRunners task_runners =
      flutter::TaskRunners("test_runners",  // label
                           flutter_runner::CreateFMLTaskRunner(
                               async_get_default_dispatcher()),  // platform
                           nullptr,                              // raster
                           nullptr,                              // ui
                           nullptr                               // io
      );

  // Test wireframe callback function. If the message sent to the platform
  // view was properly handled and parsed, this function should be called,
  // setting |wireframe_enabled| to true.
  bool create_view_called = false;
  auto CreateViewCallback = [&create_view_called](
                                int64_t view_id,
                                flutter_runner::ViewIdCallback on_view_bound,
                                bool hit_testable, bool focusable) {
    create_view_called = true;
    on_view_bound(0);
  };

  flutter_runner::PlatformView platform_view =
      PlatformViewBuilder(delegate, std::move(task_runners),
                          services_provider.service_directory())
          .SetCreateViewCallback(CreateViewCallback)
          .Build();

  // Cast platform_view to its base view so we can have access to the public
  // "HandlePlatformMessage" function.
  auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
  EXPECT_TRUE(base_view);

  // JSON for the message to be passed into the PlatformView.
  const uint8_t txt[] =
      "{"
      "    \"method\":\"View.create\","
      "    \"args\": {"
      "       \"viewId\":42,"
      "       \"hitTestable\":true,"
      "       \"focusable\":true"
      "    }"
      "}";

  std::unique_ptr<flutter::PlatformMessage> message =
      std::make_unique<flutter::PlatformMessage>(
          "flutter/platform_views",
          std::vector<uint8_t>(txt, txt + sizeof(txt)),
          fml::RefPtr<flutter::PlatformMessageResponse>());
  base_view->HandlePlatformMessage(std::move(message));

  RunLoopUntilIdle();

  EXPECT_TRUE(create_view_called);
}

// This test makes sure that the PlatformView forwards messages on the
// "flutter/platform_views" channel for UpdateView.
TEST_F(PlatformViewTests, UpdateViewTest) {
  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
  MockPlatformViewDelegate delegate;
  flutter::TaskRunners task_runners =
      flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);

  // Test wireframe callback function. If the message sent to the platform
  // view was properly handled and parsed, this function should be called,
  // setting |wireframe_enabled| to true.
  bool update_view_called = false;
  auto UpdateViewCallback = [&update_view_called](
                                int64_t view_id, SkRect occlusion_hint,
                                bool hit_testable,
                                bool focusable) { update_view_called = true; };

  flutter_runner::PlatformView platform_view =
      PlatformViewBuilder(delegate, std::move(task_runners),
                          services_provider.service_directory())
          .SetUpdateViewCallback(UpdateViewCallback)
          .Build();

  // Cast platform_view to its base view so we can have access to the public
  // "HandlePlatformMessage" function.
  auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
  EXPECT_TRUE(base_view);

  // JSON for the message to be passed into the PlatformView.
  const uint8_t txt[] =
      "{"
      "    \"method\":\"View.update\","
      "    \"args\": {"
      "       \"viewId\":42,"
      "       \"hitTestable\":true,"
      "       \"focusable\":true"
      "    }"
      "}";

  std::unique_ptr<flutter::PlatformMessage> message =
      std::make_unique<flutter::PlatformMessage>(
          "flutter/platform_views",
          std::vector<uint8_t>(txt, txt + sizeof(txt)),
          fml::RefPtr<flutter::PlatformMessageResponse>());
  base_view->HandlePlatformMessage(std::move(message));

  RunLoopUntilIdle();

  EXPECT_TRUE(update_view_called);
}

// This test makes sure that the PlatformView forwards messages on the
// "flutter/platform_views" channel for DestroyView.
TEST_F(PlatformViewTests, DestroyViewTest) {
  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
  MockPlatformViewDelegate delegate;
  flutter::TaskRunners task_runners =
      flutter::TaskRunners("test_runners",  // label
                           flutter_runner::CreateFMLTaskRunner(
                               async_get_default_dispatcher()),  // platform
                           nullptr,                              // raster
                           nullptr,                              // ui
                           nullptr                               // io
      );

  // Test wireframe callback function. If the message sent to the platform
  // view was properly handled and parsed, this function should be called,
  // setting |wireframe_enabled| to true.
  bool destroy_view_called = false;
  auto DestroyViewCallback =
      [&destroy_view_called](int64_t view_id,
                             flutter_runner::ViewIdCallback on_view_unbound) {
        destroy_view_called = true;
        on_view_unbound(0);
      };

  flutter_runner::PlatformView platform_view =
      PlatformViewBuilder(delegate, std::move(task_runners),
                          services_provider.service_directory())
          .SetDestroyViewCallback(DestroyViewCallback)
          .Build();

  // Cast platform_view to its base view so we can have access to the public
  // "HandlePlatformMessage" function.
  auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
  EXPECT_TRUE(base_view);

  // JSON for the message to be passed into the PlatformView.
  const uint8_t txt[] =
      "{"
      "    \"method\":\"View.dispose\","
      "    \"args\": {"
      "       \"viewId\":42"
      "    }"
      "}";

  std::unique_ptr<flutter::PlatformMessage> message =
      std::make_unique<flutter::PlatformMessage>(
          "flutter/platform_views",
          std::vector<uint8_t>(txt, txt + sizeof(txt)),
          fml::RefPtr<flutter::PlatformMessageResponse>());
  base_view->HandlePlatformMessage(std::move(message));

  RunLoopUntilIdle();

  EXPECT_TRUE(destroy_view_called);
}

// This test makes sure that the PlatformView forwards messages on the
// "flutter/platform_views" channel for ViewConnected, ViewDisconnected, and
// ViewStateChanged events.
TEST_F(PlatformViewTests, ViewEventsTest) {
  constexpr int64_t kViewId = 33;
  constexpr scenic::ResourceId kViewHolderId = 42;
  MockPlatformViewDelegate delegate;

  fuchsia::ui::scenic::SessionListenerPtr session_listener;
  std::vector<fuchsia::ui::scenic::Event> events;
  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
  flutter::TaskRunners task_runners =
      flutter::TaskRunners("test_runners",  // label
                           flutter_runner::CreateFMLTaskRunner(
                               async_get_default_dispatcher()),  // platform
                           flutter_runner::CreateFMLTaskRunner(
                               async_get_default_dispatcher()),  // raster
                           flutter_runner::CreateFMLTaskRunner(
                               async_get_default_dispatcher()),  // ui
                           nullptr                               // io
      );

  auto on_create_view = [kViewId](int64_t view_id,
                                  flutter_runner::ViewIdCallback on_view_bound,
                                  bool hit_testable, bool focusable) {
    ASSERT_EQ(view_id, kViewId);
    on_view_bound(kViewHolderId);
  };

  flutter_runner::PlatformView platform_view =
      PlatformViewBuilder(delegate, std::move(task_runners),
                          services_provider.service_directory())
          .SetSessionListenerRequest(session_listener.NewRequest())
          .SetCreateViewCallback(on_create_view)
          .Build();
  RunLoopUntilIdle();
  ASSERT_EQ(delegate.message(), nullptr);

  // Create initial view for testing.
  std::ostringstream create_view_message;
  create_view_message << "{"
                      << "  \"method\":\"View.create\","
                      << "  \"args\":{"
                      << "    \"viewId\":" << kViewId << ","
                      << "    \"hitTestable\":true,"
                      << "    \"focusable\":true"
                      << "  }"
                      << "}";
  std::string create_view_call = create_view_message.str();
  static_cast<flutter::PlatformView*>(&platform_view)
      ->HandlePlatformMessage(std::make_unique<flutter::PlatformMessage>(
          "flutter/platform_views",
          std::vector<uint8_t>(create_view_call.begin(),
                               create_view_call.end()),
          fml::RefPtr<flutter::PlatformMessageResponse>()));
  RunLoopUntilIdle();

  // ViewConnected event.
  delegate.Reset();
  events.clear();
  events.emplace_back(fuchsia::ui::scenic::Event::WithGfx(
      fuchsia::ui::gfx::Event::WithViewConnected(
          fuchsia::ui::gfx::ViewConnectedEvent{
              .view_holder_id = kViewHolderId,
          })));
  session_listener->OnScenicEvent(std::move(events));
  RunLoopUntilIdle();

  flutter::PlatformMessage* view_connected_msg = delegate.message();
  ASSERT_NE(view_connected_msg, nullptr);
  std::ostringstream view_connected_expected_out;
  view_connected_expected_out
      << "{"
      << "\"method\":\"View.viewConnected\","
      << "\"args\":{"
      << "  \"viewId\":" << kViewId  // ViewHolderToken handle
      << "  }"
      << "}";
  EXPECT_EQ(view_connected_expected_out.str(),
            std::string(view_connected_msg->data().begin(),
                        view_connected_msg->data().end()));

  // ViewDisconnected event.
  delegate.Reset();
  events.clear();
  events.emplace_back(fuchsia::ui::scenic::Event::WithGfx(
      fuchsia::ui::gfx::Event::WithViewDisconnected(
          fuchsia::ui::gfx::ViewDisconnectedEvent{
              .view_holder_id = kViewHolderId,
          })));
  session_listener->OnScenicEvent(std::move(events));
  RunLoopUntilIdle();

  flutter::PlatformMessage* view_disconnected_msg = delegate.message();
  ASSERT_NE(view_disconnected_msg, nullptr);
  std::ostringstream view_disconnected_expected_out;
  view_disconnected_expected_out
      << "{"
      << "\"method\":\"View.viewDisconnected\","
      << "\"args\":{"
      << "  \"viewId\":" << kViewId  // ViewHolderToken handle
      << "  }"
      << "}";
  EXPECT_EQ(view_disconnected_expected_out.str(),
            std::string(view_disconnected_msg->data().begin(),
                        view_disconnected_msg->data().end()));

  // ViewStateChanged event.
  delegate.Reset();
  events.clear();
  events.emplace_back(fuchsia::ui::scenic::Event::WithGfx(
      fuchsia::ui::gfx::Event::WithViewStateChanged(
          fuchsia::ui::gfx::ViewStateChangedEvent{
              .view_holder_id = kViewHolderId,
              .state =
                  fuchsia::ui::gfx::ViewState{
                      .is_rendering = true,
                  },
          })));
  session_listener->OnScenicEvent(std::move(events));
  RunLoopUntilIdle();

  flutter::PlatformMessage* view_state_changed_msg = delegate.message();
  ASSERT_NE(view_state_changed_msg, nullptr);
  std::ostringstream view_state_changed_expected_out;
  view_state_changed_expected_out
      << "{"
      << "\"method\":\"View.viewStateChanged\","
      << "\"args\":{"
      << "  \"viewId\":" << kViewId << ","  // ViewHolderToken
      << "  \"is_rendering\":true,"         // IsViewRendering
      << "  \"state\":true"                 // IsViewRendering
      << "  }"
      << "}";
  EXPECT_EQ(view_state_changed_expected_out.str(),
            std::string(view_state_changed_msg->data().begin(),
                        view_state_changed_msg->data().end()));
}

// This test makes sure that the PlatformView forwards messages on the
// "flutter/platform_views" channel for RequestFocus.
TEST_F(PlatformViewTests, RequestFocusTest) {
  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
  MockPlatformViewDelegate delegate;
  flutter::TaskRunners task_runners =
      flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);

  MockFocuser mock_focuser;
  fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
  auto focuser_handle = focuser_bindings.AddBinding(&mock_focuser);

  flutter_runner::PlatformView platform_view =
      PlatformViewBuilder(delegate, std::move(task_runners),
                          services_provider.service_directory())
          .SetFocuser(std::move(focuser_handle))
          .Build();

  // Cast platform_view to its base view so we can have access to the public
  // "HandlePlatformMessage" function.
  auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
  EXPECT_TRUE(base_view);

  // This "Mock" ViewRef serves as the target for the RequestFocus operation.
  auto mock_view_ref_pair = scenic::ViewRefPair::New();

  // JSON for the message to be passed into the PlatformView.
  char buff[254];
  snprintf(buff, sizeof(buff),
           "{"
           "    \"method\":\"View.requestFocus\","
           "    \"args\": {"
           "       \"viewRef\":%u"
           "    }"
           "}",
           mock_view_ref_pair.view_ref.reference.get());

  // Define a custom gmock matcher to capture the response to platform message.
  struct DataArg {
    void Complete(std::unique_ptr<fml::Mapping> data) {
      this->data = std::move(data);
    }
    std::unique_ptr<fml::Mapping> data;
  };
  DataArg data_arg;
  fml::RefPtr<MockResponse> response = fml::MakeRefCounted<MockResponse>();
  EXPECT_CALL(*response, Complete(::testing::_))
      .WillOnce(::testing::Invoke(&data_arg, &DataArg::Complete));

  std::unique_ptr<flutter::PlatformMessage> message =
      std::make_unique<flutter::PlatformMessage>(
          "flutter/platform_views",
          std::vector<uint8_t>(buff, buff + sizeof(buff)), response);
  base_view->HandlePlatformMessage(std::move(message));

  RunLoopUntilIdle();

  EXPECT_TRUE(mock_focuser.request_focus_called());
  auto result = std::string((const char*)data_arg.data->GetMapping(),
                            data_arg.data->GetSize());
  EXPECT_EQ(std::string("[0]"), result);
}

// This test makes sure that the PlatformView correctly replies with an error
// response when a RequestFocus call fails.
TEST_F(PlatformViewTests, RequestFocusFailTest) {
  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
  MockPlatformViewDelegate delegate;
  flutter::TaskRunners task_runners =
      flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);

  MockFocuser mock_focuser(true /*fail_request_focus*/);
  fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
  auto focuser_handle = focuser_bindings.AddBinding(&mock_focuser);

  flutter_runner::PlatformView platform_view =
      PlatformViewBuilder(delegate, std::move(task_runners),
                          services_provider.service_directory())
          .SetFocuser(std::move(focuser_handle))
          .Build();

  // Cast platform_view to its base view so we can have access to the public
  // "HandlePlatformMessage" function.
  auto base_view = static_cast<flutter::PlatformView*>(&platform_view);
  EXPECT_TRUE(base_view);

  // This "Mock" ViewRef serves as the target for the RequestFocus operation.
  auto mock_view_ref_pair = scenic::ViewRefPair::New();

  // JSON for the message to be passed into the PlatformView.
  char buff[254];
  snprintf(buff, sizeof(buff),
           "{"
           "    \"method\":\"View.requestFocus\","
           "    \"args\": {"
           "       \"viewRef\":%u"
           "    }"
           "}",
           mock_view_ref_pair.view_ref.reference.get());

  // Define a custom gmock matcher to capture the response to platform message.
  struct DataArg {
    void Complete(std::unique_ptr<fml::Mapping> data) {
      this->data = std::move(data);
    }
    std::unique_ptr<fml::Mapping> data;
  };
  DataArg data_arg;
  fml::RefPtr<MockResponse> response = fml::MakeRefCounted<MockResponse>();
  EXPECT_CALL(*response, Complete(::testing::_))
      .WillOnce(::testing::Invoke(&data_arg, &DataArg::Complete));

  std::unique_ptr<flutter::PlatformMessage> message =
      std::make_unique<flutter::PlatformMessage>(
          "flutter/platform_views",
          std::vector<uint8_t>(buff, buff + sizeof(buff)), response);
  base_view->HandlePlatformMessage(std::move(message));

  RunLoopUntilIdle();

  EXPECT_TRUE(mock_focuser.request_focus_called());
  auto result = std::string((const char*)data_arg.data->GetMapping(),
                            data_arg.data->GetSize());
  std::ostringstream out;
  out << "["
      << static_cast<std::underlying_type_t<fuchsia::ui::views::Error>>(
             fuchsia::ui::views::Error::DENIED)
      << "]";
  EXPECT_EQ(out.str(), result);
}

struct EventFlow {
  fuchsia::ui::input3::KeyEvent event;
  fuchsia::ui::input3::KeyEventStatus expected_key_event_status;
  std::string expected_platform_message;
};

// Makes sure that OnKeyEvent is dispatched as a platform message.
TEST_F(PlatformViewTests, OnKeyEvent) {
  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
  MockPlatformViewDelegate delegate;
  flutter::TaskRunners task_runners =
      flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);

  fidl::InterfacePtr<fuchsia::ui::input3::KeyboardListener> keyboard_listener;

  flutter_runner::PlatformView platform_view =
      PlatformViewBuilder(delegate, std::move(task_runners),
                          services_provider.service_directory())
          .SetKeyboardListener(keyboard_listener.NewRequest(dispatcher()))
          .Build();

  using fuchsia::input::Key;
  using fuchsia::ui::input3::KeyEvent;
  using fuchsia::ui::input3::KeyEventStatus;
  using fuchsia::ui::input3::KeyEventType;
  using fuchsia::ui::input3::Modifiers;

  std::vector<EventFlow> events;
  // Press A.  Get 'a'.
  events.emplace_back(EventFlow{
      MakeEvent(KeyEventType::PRESSED, std::nullopt, Key::A),
      KeyEventStatus::HANDLED,
      R"({"type":"keydown","keymap":"fuchsia","hidUsage":4,"codePoint":97,"modifiers":0})",
  });
  // Release A. Get 'a' release.
  events.emplace_back(EventFlow{
      MakeEvent(KeyEventType::RELEASED, std::nullopt, Key::A),
      KeyEventStatus::HANDLED,
      R"({"type":"keyup","keymap":"fuchsia","hidUsage":4,"codePoint":97,"modifiers":0})",
  });
  // Press CAPS_LOCK.  Modifier now active.
  events.emplace_back(EventFlow{
      MakeEvent(KeyEventType::PRESSED, Modifiers::CAPS_LOCK, Key::CAPS_LOCK),
      KeyEventStatus::HANDLED,
      R"({"type":"keydown","keymap":"fuchsia","hidUsage":57,"codePoint":0,"modifiers":1})",
  });
  // Pres A.  Get 'A'.
  events.emplace_back(EventFlow{
      MakeEvent(KeyEventType::PRESSED, std::nullopt, Key::A),
      KeyEventStatus::HANDLED,
      R"({"type":"keydown","keymap":"fuchsia","hidUsage":4,"codePoint":65,"modifiers":1})",
  });
  // Release CAPS_LOCK.
  events.emplace_back(EventFlow{
      MakeEvent(KeyEventType::RELEASED, Modifiers::CAPS_LOCK, Key::CAPS_LOCK),
      KeyEventStatus::HANDLED,
      R"({"type":"keyup","keymap":"fuchsia","hidUsage":57,"codePoint":0,"modifiers":1})",
  });
  // Press A again.  This time get 'A'.
  // CAPS_LOCK is latched active even if it was just released.
  events.emplace_back(EventFlow{
      MakeEvent(KeyEventType::PRESSED, std::nullopt, Key::A),
      KeyEventStatus::HANDLED,
      R"({"type":"keydown","keymap":"fuchsia","hidUsage":4,"codePoint":65,"modifiers":1})",
  });

  for (const auto& event : events) {
    KeyEvent e;
    event.event.Clone(&e);
    fuchsia::ui::input3::KeyEventStatus key_event_status;
    keyboard_listener->OnKeyEvent(
        std::move(e),
        [&key_event_status](fuchsia::ui::input3::KeyEventStatus status) {
          key_event_status = status;
        });
    RunLoopUntilIdle();
    const std::vector<uint8_t> data = delegate.message()->data();
    const std::string message = std::string(data.begin(), data.end());

    EXPECT_EQ(event.expected_platform_message, message);
    EXPECT_EQ(key_event_status, event.expected_key_event_status);
  }
}

}  // namespace flutter_runner::testing
