chromium/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc

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

#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/task/single_thread_task_runner.h"
#include "chromeos/ash/components/dbus/media_analytics/fake_media_analytics_client.h"
#include "chromeos/ash/components/dbus/media_analytics/media_analytics_client.h"
#include "chromeos/ash/components/dbus/media_perception/media_perception.pb.h"
#include "chromeos/ash/components/dbus/upstart/upstart_client.h"
#include "extensions/browser/api/media_perception_private/media_perception_api_delegate.h"
#include "extensions/browser/api/media_perception_private/media_perception_private_api.h"
#include "extensions/common/api/media_perception_private.h"
#include "extensions/common/features/feature_session_type.h"
#include "extensions/common/mojom/feature_session_type.mojom.h"
#include "extensions/common/switches.h"
#include "extensions/shell/browser/shell_extensions_api_client.h"
#include "extensions/shell/test/shell_apitest.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"

namespace extensions {

namespace media_perception = extensions::api::media_perception_private;

namespace {

class TestMediaPerceptionAPIDelegate : public MediaPerceptionAPIDelegate {
 public:
  void LoadCrOSComponent(const media_perception::ComponentType& type,
                         LoadCrOSComponentCallback load_callback) override {
    // For testing both success and failure cases, test class has the LIGHT
    // component succeed install and the others fail.
    if (type == media_perception::ComponentType::kLight) {
      base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
          FROM_HERE,
          base::BindOnce(
              std::move(load_callback),
              media_perception::ComponentInstallationError::kNone,
              base::FilePath("/run/imageloader/rtanalytics-light/1.0")));
      return;
    }

    base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE,
        base::BindOnce(std::move(load_callback),
                       media_perception::ComponentInstallationError::kNotFound,
                       base::FilePath()));
  }

  void BindVideoSourceProvider(
      mojo::PendingReceiver<video_capture::mojom::VideoSourceProvider> receiver)
      override {
    NOTIMPLEMENTED();
  }

  void SetMediaPerceptionRequestHandler(
      MediaPerceptionRequestHandler handler) override {
    NOTIMPLEMENTED();
  }

  void ForwardMediaPerceptionReceiver(
      content::RenderFrameHost* render_frame_host,
      mojo::PendingReceiver<chromeos::media_perception::mojom::MediaPerception>
          receiver) override {
    NOTIMPLEMENTED();
  }
};

class TestExtensionsAPIClient : public ShellExtensionsAPIClient {
 public:
  TestExtensionsAPIClient() : ShellExtensionsAPIClient() {}

  MediaPerceptionAPIDelegate* GetMediaPerceptionAPIDelegate() override {
    if (!test_media_perception_api_delegate_) {
      test_media_perception_api_delegate_ =
          std::make_unique<TestMediaPerceptionAPIDelegate>();
    }
    return test_media_perception_api_delegate_.get();
  }

 private:
  std::unique_ptr<TestMediaPerceptionAPIDelegate>
      test_media_perception_api_delegate_;
};

}  // namespace

class MediaPerceptionPrivateApiTest : public ShellApiTest {
 public:
  MediaPerceptionPrivateApiTest() {}

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

  ~MediaPerceptionPrivateApiTest() override {}

  void SetUpCommandLine(base::CommandLine* command_line) override {
    ShellApiTest::SetUpCommandLine(command_line);
    // Allowlist of the extension ID of the test extension.
    command_line->AppendSwitchASCII(
        extensions::switches::kAllowlistedExtensionID,
        "epcifkihnkjgphfkloaaleeakhpmgdmn");
  }

  void SetUpInProcessBrowserTestFixture() override {
    // MediaAnalyticsClient and UpstartClient are required by
    // MediaPerceptionAPIManager.
    ash::MediaAnalyticsClient::InitializeFake();
    ash::UpstartClient::InitializeFake();
  }

  void TearDownInProcessBrowserTestFixture() override {
    ash::UpstartClient::Shutdown();
    ash::MediaAnalyticsClient::Shutdown();
  }

  void SetUpOnMainThread() override {
    session_feature_type_ = extensions::ScopedCurrentFeatureSessionType(
        extensions::mojom::FeatureSessionType::kKiosk);
    ShellApiTest::SetUpOnMainThread();
  }

 private:
  std::unique_ptr<base::AutoReset<extensions::mojom::FeatureSessionType>>
      session_feature_type_;
};

// Verify that we can execute the setAnalyticsComponent API and deal with
// failures.
IN_PROC_BROWSER_TEST_F(MediaPerceptionPrivateApiTest, SetAnalyticsComponent) {
  // Constructing a TestExtensionsAPIClient to set the behavior of the
  // ExtensionsAPIClient.
  TestExtensionsAPIClient test_api_client;
  ASSERT_TRUE(RunAppTest("media_perception_private/component")) << message_;
}

// Verify that we can use the new interface to set the process state of the
// media perception component.
IN_PROC_BROWSER_TEST_F(MediaPerceptionPrivateApiTest,
                       SetComponentProcessState) {
  // Constructing a TestExtensionsAPIClient to set the behavior of the
  // ExtensionsAPIClient.
  TestExtensionsAPIClient test_api_client;
  ASSERT_TRUE(RunAppTest("media_perception_private/process_state")) << message_;
}

// Verify that we can set and get mediaPerception system state.
IN_PROC_BROWSER_TEST_F(MediaPerceptionPrivateApiTest, State) {
  ASSERT_TRUE(RunAppTest("media_perception_private/state")) << message_;
}

// Verify that we can request Diagnostics.
IN_PROC_BROWSER_TEST_F(MediaPerceptionPrivateApiTest, GetDiagnostics) {
  // Allows us to validate that the right data comes through the code path.
  mri::Diagnostics diagnostics;
  diagnostics.add_perception_sample()->mutable_frame_perception()->set_frame_id(
      1);
  ash::FakeMediaAnalyticsClient::Get()->SetDiagnostics(diagnostics);

  ASSERT_TRUE(RunAppTest("media_perception_private/diagnostics")) << message_;
}

// Verify that we can listen for MediaPerceptionDetection signals and handle
// them.
IN_PROC_BROWSER_TEST_F(MediaPerceptionPrivateApiTest, MediaPerception) {
  extensions::ResultCatcher catcher;
  catcher.RestrictToBrowserContext(browser_context());

  ExtensionTestMessageListener handler_registered_listener(
      "mediaPerceptionListenerSet");
  ASSERT_TRUE(LoadApp("media_perception_private/media_perception")) << message_;
  ASSERT_TRUE(handler_registered_listener.WaitUntilSatisfied());

  mri::MediaPerception media_perception;
  media_perception.add_frame_perception()->set_frame_id(1);
  ASSERT_TRUE(ash::FakeMediaAnalyticsClient::Get()->FireMediaPerceptionEvent(
      media_perception));
  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

}  // namespace extensions