chromium/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc

// Copyright 2012 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/command_line.h"
#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/scoped_observation.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/background/background_mode_manager.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/messaging/native_messaging_launch_from_native.h"
#include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/startup/startup_browser_creator.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "components/keep_alive_registry/keep_alive_registry.h"
#include "components/keep_alive_registry/keep_alive_state_observer.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "content/public/test/browser_test.h"
#include "extensions/browser/process_manager.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/extension_id.h"
#include "extensions/test/extension_background_page_waiter.h"
#include "extensions/test/result_catcher.h"

#if BUILDFLAG(IS_WIN)
#include <windows.h>

#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#endif

namespace extensions {
namespace {

ContextType;

class NativeMessagingApiTestBase : public ExtensionApiTest {};

// Tests basic functionality of chrome.runtime.sendNativeMessage in an MV3
// extension.
IN_PROC_BROWSER_TEST_F(NativeMessagingApiTestBase, SendNativeMessage) {}

IN_PROC_BROWSER_TEST_F(NativeMessagingApiTestBase, UserLevelSendNativeMessage) {}

#if BUILDFLAG(IS_WIN)
// On Windows, a new codepath is used to directly launch .EXE-based Native
// Hosts. This codepath allows launching of Native Hosts even when cmd.exe is
// disabled or misconfigured.
class NativeMessagingLaunchExeTest : public NativeMessagingApiTestBase,
                                     public testing::WithParamInterface<bool> {
 public:
  NativeMessagingLaunchExeTest() {
    feature_list_.InitWithFeatureState(
        extensions_features::kLaunchWindowsNativeHostsDirectly,
        IsDirectLaunchEnabled());
  }

  bool IsDirectLaunchEnabled() const { return GetParam(); }

 private:
  base::test::ScopedFeatureList feature_list_;
};

INSTANTIATE_TEST_SUITE_P(NativeMessagingLaunchExe,
                         NativeMessagingLaunchExeTest,
                         testing::Bool());

IN_PROC_BROWSER_TEST_P(NativeMessagingLaunchExeTest,
                       UserLevelSendNativeMessageWinExe) {
  ASSERT_NO_FATAL_FAILURE(test_host_.RegisterTestExeHost(
      "native_messaging_test_echo_host.exe", /*user_level=*/true));

  ASSERT_TRUE(RunExtensionTest("native_messaging_send_native_message_exe"));
}

// The Host's filename deliberately contains the character '&' which causes the
// Host to fail to launch if cmd.exe is used as an intermediary between the
// extension and the host executable, unless extra quotes are used.
// crbug.com/335558
IN_PROC_BROWSER_TEST_P(NativeMessagingLaunchExeTest,
                       SendNativeMessageWinExeAmpersand) {
  ASSERT_NO_FATAL_FAILURE(test_host_.RegisterTestExeHost(
      "native_messaging_test_echo_&_host.exe", /*user_level=*/false));

  ASSERT_TRUE(RunExtensionTest("native_messaging_send_native_message_exe"));
}

// Make sure that a filename with a space is supported.
IN_PROC_BROWSER_TEST_P(NativeMessagingLaunchExeTest,
                       SendNativeMessageWinExeSpace) {
  ASSERT_NO_FATAL_FAILURE(test_host_.RegisterTestExeHost(
      "native_messaging_test_echo_ _host.exe", /*user_level=*/false));

  ASSERT_TRUE(RunExtensionTest("native_messaging_send_native_message_exe"));
}
#endif

class NativeMessagingApiTest : public NativeMessagingApiTestBase,
                               public testing::WithParamInterface<ContextType> {};

INSTANTIATE_TEST_SUITE_P();
INSTANTIATE_TEST_SUITE_P();
INSTANTIATE_TEST_SUITE_P();

// Tests chrome.runtime.sendNativeMessage to a native messaging host.
IN_PROC_BROWSER_TEST_P(NativeMessagingApiTest, NativeMessagingBasic) {}

IN_PROC_BROWSER_TEST_P(NativeMessagingApiTest, UserLevelNativeMessaging) {}

// Tests chrome.runtime.connectNative to a native messaging host.
IN_PROC_BROWSER_TEST_P(NativeMessagingApiTest, ConnectNative) {}

IN_PROC_BROWSER_TEST_P(NativeMessagingApiTest,
                       UserLevelNativeMessagingConnectNative) {}

#if !BUILDFLAG(IS_CHROMEOS)

base::CommandLine CreateNativeMessagingConnectCommandLine(
    const std::string& connect_id,
    const ExtensionId& extension_id =
        ScopedTestNativeMessagingHost::kExtensionId) {}

class NativeMessagingLaunchApiTest : public NativeMessagingApiTestBase {};

IN_PROC_BROWSER_TEST_F(NativeMessagingLaunchApiTest, Success) {}

// Test that a natively-initiated connection from a host not supporting
// natively-initiated connections is not allowed. The test extension expects the
// channel to be immediately closed with an error.
IN_PROC_BROWSER_TEST_F(NativeMessagingLaunchApiTest, UnsupportedByNativeHost) {}

class TestKeepAliveStateObserver : public KeepAliveStateObserver {};

IN_PROC_BROWSER_TEST_F(NativeMessagingLaunchApiTest, Error) {}

IN_PROC_BROWSER_TEST_F(NativeMessagingLaunchApiTest, InvalidConnectId) {}

IN_PROC_BROWSER_TEST_F(NativeMessagingLaunchApiTest, TooLongConnectId) {}

IN_PROC_BROWSER_TEST_F(NativeMessagingLaunchApiTest, InvalidExtensionId) {}

constexpr char kExtensionId[] =;

class NativeMessagingLaunchBackgroundModeApiTest
    : public NativeMessagingLaunchApiTest {};

IN_PROC_BROWSER_TEST_F(NativeMessagingLaunchBackgroundModeApiTest,
                       PRE_Success) {}

// Flaky on a Windows bot. See crbug.com/1030332.
#if BUILDFLAG(IS_WIN)
#define MAYBE_Success
#else
#define MAYBE_Success
#endif
IN_PROC_BROWSER_TEST_F(NativeMessagingLaunchBackgroundModeApiTest,
                       MAYBE_Success) {}

#endif  // !BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_WIN)
class NativeHostExecutablesLaunchDirectlyPolicyTest
    : public extensions::NativeMessagingApiTestBase,
      public testing::WithParamInterface<bool> {
 public:
  NativeHostExecutablesLaunchDirectlyPolicyTest() {
    feature_list_.InitWithFeatureState(
        extensions_features::kLaunchWindowsNativeHostsDirectly,
        IsDirectLaunchEnabled());
  }

  void SetUpOnMainThread() override {
    InProcessBrowserTest::SetUpOnMainThread();
    profile_ = std::make_unique<TestingProfile>();
  }

  void TearDownOnMainThread() override {
    profile_.reset();
    InProcessBrowserTest::TearDownOnMainThread();
  }

  bool IsDirectLaunchEnabled() const { return GetParam(); }

 protected:
  extensions::ScopedTestNativeMessagingHost test_host_;
  std::unique_ptr<TestingProfile> profile_;

 private:
  base::test::ScopedFeatureList feature_list_;
};

IN_PROC_BROWSER_TEST_P(NativeHostExecutablesLaunchDirectlyPolicyTest,
                       PolicyDisabledTest) {
  PrefService* prefs = profile_->GetPrefs();
  prefs->SetBoolean(prefs::kNativeHostsExecutablesLaunchDirectly, true);

  ASSERT_NO_FATAL_FAILURE(test_host_.RegisterTestExeHost(
      "native_messaging_test_echo_&_host.exe", /*user_level=*/false));

  ASSERT_TRUE(RunExtensionTest("native_messaging_send_native_message_exe"));
}

IN_PROC_BROWSER_TEST_P(NativeHostExecutablesLaunchDirectlyPolicyTest,
                       PolicyEnabledTest) {
  PrefService* prefs = profile_->GetPrefs();
  prefs->SetBoolean(prefs::kNativeHostsExecutablesLaunchDirectly, false);

  ASSERT_NO_FATAL_FAILURE(test_host_.RegisterTestExeHost(
      "native_messaging_test_echo_&_host.exe", /*user_level=*/false));

  ASSERT_TRUE(RunExtensionTest("native_messaging_send_native_message_exe"));
}

INSTANTIATE_TEST_SUITE_P(NativeHostExecutablesLaunchDirectlyPolicyTestP,
                         NativeHostExecutablesLaunchDirectlyPolicyTest,
                         testing::Bool());
#endif  // BUILDFLAG(IS_WIN)

}  // namespace
}  // namespace extensions