Commit 2c8e4662 authored by Sam McNally's avatar Sam McNally Committed by Commit Bot

Report native messaging connection errors back to the native app.

When a native application attempts to initiate a native messaging
connection with a cooperating extension, that extension may not be
installed; in this case, the native app should be informed by launching
its native messaging host to notify it of this error. This is also
needed if the native app provides invalid input when requesting this
communication channel.

Add NativeMessagingHostErrorReporter, a self-owning class responsible
for starting the native messaging host with flag specific to the error
and keeping Chrome alive until either the native messaging host
terminates (upon informing the original native app of the error), or a
10 second timeout to avoid Chrome getting stuck due to a misbehaving
native messaging host.

Add plumbing to the existing native messaging host launch code to handle
the additional parameter.

Bug: 967262
Change-Id: Ie68cbae094de226fa43244719abda434d6200590
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1675587Reviewed-by: default avatarBen Wells <benwells@chromium.org>
Reviewed-by: default avatarSergey Ulanov <sergeyu@chromium.org>
Commit-Queue: Sam McNally <sammc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712836}
parent f81b392f
...@@ -1046,6 +1046,7 @@ jumbo_static_library("extensions") { ...@@ -1046,6 +1046,7 @@ jumbo_static_library("extensions") {
"default_apps.cc", "default_apps.cc",
"default_apps.h", "default_apps.h",
] ]
deps += [ "//components/keep_alive_registry" ]
if (is_posix) { if (is_posix) {
sources += [ "api/messaging/native_process_launcher_posix.cc" ] sources += [ "api/messaging/native_process_launcher_posix.cc" ]
} }
......
...@@ -108,7 +108,7 @@ std::unique_ptr<NativeMessageHost> NativeMessageHost::Create( ...@@ -108,7 +108,7 @@ std::unique_ptr<NativeMessageHost> NativeMessageHost::Create(
GetProfilePathIfEnabled(Profile::FromBrowserContext(browser_context), GetProfilePathIfEnabled(Profile::FromBrowserContext(browser_context),
source_extension_id, native_host_name), source_extension_id, native_host_name),
/* require_native_initiated_connections = */ false, /* require_native_initiated_connections = */ false,
/* connect_id = */ "")); /* connect_id = */ "", /* error_arg = */ ""));
} }
// static // static
......
...@@ -7,14 +7,26 @@ ...@@ -7,14 +7,26 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/timer/timer.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/messaging/native_message_port.h" #include "chrome/browser/extensions/api/messaging/native_message_port.h"
#include "chrome/browser/extensions/api/messaging/native_message_process_host.h" #include "chrome/browser/extensions/api/messaging/native_message_process_host.h"
#include "chrome/browser/extensions/api/messaging/native_process_launcher.h" #include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/manifest_handlers/natively_connectable_handler.h" #include "chrome/common/extensions/manifest_handlers/natively_connectable_handler.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/api/messaging/channel_endpoint.h" #include "extensions/browser/api/messaging/channel_endpoint.h"
#include "extensions/browser/api/messaging/message_service.h" #include "extensions/browser/api/messaging/message_service.h"
#include "extensions/browser/api/messaging/native_message_host.h"
#include "extensions/browser/event_router.h" #include "extensions/browser/event_router.h"
#include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry.h"
#include "extensions/common/api/messaging/messaging_endpoint.h" #include "extensions/common/api/messaging/messaging_endpoint.h"
...@@ -27,6 +39,88 @@ namespace { ...@@ -27,6 +39,88 @@ namespace {
ScopedAllowNativeAppConnectionForTest* g_allow_native_app_connection_for_test = ScopedAllowNativeAppConnectionForTest* g_allow_native_app_connection_for_test =
nullptr; nullptr;
constexpr base::TimeDelta kNativeMessagingHostErrorTimeout =
base::TimeDelta::FromSeconds(10);
ScopedNativeMessagingErrorTimeoutOverrideForTest*
g_native_messaging_host_timeout_override = nullptr;
// A self-owning class responsible for starting a native messaging host with
// command-line parameters reporting an error, keeping Chrome alive until the
// host terminates, or a timeout is reached.
//
// This lives on the IO thread, but its public factory static method should be
// called on the UI thread.
class NativeMessagingHostErrorReporter : public NativeMessageHost::Client {
public:
using MovableScopedKeepAlive =
std::unique_ptr<ScopedKeepAlive,
content::BrowserThread::DeleteOnUIThread>;
static void Report(const std::string& extension_id,
const std::string& host_id,
const std::string& connection_id,
Profile* profile,
const std::string& error_arg) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
std::unique_ptr<NativeMessageHost> host =
NativeMessageProcessHost::CreateWithLauncher(
extension_id, host_id,
NativeProcessLauncher::CreateDefault(
/* allow_user_level = */ true,
/* native_view = */ nullptr, profile->GetPath(),
/* require_native_initiated_connections = */ false,
connection_id, error_arg));
MovableScopedKeepAlive keep_alive(
new ScopedKeepAlive(KeepAliveOrigin::NATIVE_MESSAGING_HOST_ERROR_REPORT,
KeepAliveRestartOption::DISABLED));
base::PostTask(
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&NativeMessagingHostErrorReporter::ReportOnIoThread,
std::move(host), std::move(keep_alive)));
}
private:
static void ReportOnIoThread(std::unique_ptr<NativeMessageHost> process,
MovableScopedKeepAlive keep_alive) {
new NativeMessagingHostErrorReporter(std::move(process),
std::move(keep_alive));
}
NativeMessagingHostErrorReporter(std::unique_ptr<NativeMessageHost> process,
MovableScopedKeepAlive keep_alive)
: keep_alive_(std::move(keep_alive)), process_(std::move(process)) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
timeout_.Start(
FROM_HERE,
g_native_messaging_host_timeout_override
? g_native_messaging_host_timeout_override->timeout()
: kNativeMessagingHostErrorTimeout,
base::BindOnce(&base::DeletePointer<NativeMessagingHostErrorReporter>,
base::Unretained(this)));
process_->Start(this);
}
private:
// NativeMessageHost::Client:
void PostMessageFromNativeHost(const std::string& message) override {}
void CloseChannel(const std::string& error_message) override {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
timeout_.AbandonAndStop();
base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}
MovableScopedKeepAlive keep_alive_;
std::unique_ptr<NativeMessageHost> process_;
base::OneShotTimer timeout_;
DISALLOW_COPY_AND_ASSIGN(NativeMessagingHostErrorReporter);
};
} // namespace } // namespace
bool ExtensionSupportsConnectionFromNativeApp(const std::string& extension_id, bool ExtensionSupportsConnectionFromNativeApp(const std::string& extension_id,
...@@ -95,6 +189,19 @@ ScopedAllowNativeAppConnectionForTest:: ...@@ -95,6 +189,19 @@ ScopedAllowNativeAppConnectionForTest::
g_allow_native_app_connection_for_test = nullptr; g_allow_native_app_connection_for_test = nullptr;
} }
ScopedNativeMessagingErrorTimeoutOverrideForTest::
ScopedNativeMessagingErrorTimeoutOverrideForTest(base::TimeDelta timeout)
: timeout_(timeout) {
DCHECK(!g_native_messaging_host_timeout_override);
g_native_messaging_host_timeout_override = this;
}
ScopedNativeMessagingErrorTimeoutOverrideForTest::
~ScopedNativeMessagingErrorTimeoutOverrideForTest() {
DCHECK_EQ(this, g_native_messaging_host_timeout_override);
g_native_messaging_host_timeout_override = nullptr;
}
bool IsValidConnectionId(const base::StringPiece connection_id) { bool IsValidConnectionId(const base::StringPiece connection_id) {
return connection_id.size() <= 20 && return connection_id.size() <= 20 &&
base::ContainsOnlyChars( base::ContainsOnlyChars(
...@@ -107,12 +214,16 @@ void LaunchNativeMessageHostFromNativeApp(const std::string& extension_id, ...@@ -107,12 +214,16 @@ void LaunchNativeMessageHostFromNativeApp(const std::string& extension_id,
const std::string& connection_id, const std::string& connection_id,
Profile* profile) { Profile* profile) {
if (!IsValidConnectionId(connection_id)) { if (!IsValidConnectionId(connection_id)) {
// TODO(crbug.com/967262): Report errors to the native messaging host. NativeMessagingHostErrorReporter::Report(extension_id, host_id,
/* connect_id = */ {}, profile,
"--invalid-connect-id");
return; return;
} }
if (!ExtensionSupportsConnectionFromNativeApp(extension_id, host_id, profile, if (!ExtensionSupportsConnectionFromNativeApp(extension_id, host_id, profile,
/* log_errors = */ true)) { /* log_errors = */ true)) {
// TODO(crbug.com/967262): Report errors to the native messaging host. NativeMessagingHostErrorReporter::Report(extension_id, host_id,
connection_id, profile,
"--extension-not-installed");
return; return;
} }
const extensions::PortId port_id(base::UnguessableToken::Create(), const extensions::PortId port_id(base::UnguessableToken::Create(),
...@@ -125,7 +236,8 @@ void LaunchNativeMessageHostFromNativeApp(const std::string& extension_id, ...@@ -125,7 +236,8 @@ void LaunchNativeMessageHostFromNativeApp(const std::string& extension_id,
NativeProcessLauncher::CreateDefault( NativeProcessLauncher::CreateDefault(
/* allow_user_level = */ true, /* native_view = */ nullptr, /* allow_user_level = */ true, /* native_view = */ nullptr,
profile->GetPath(), profile->GetPath(),
/* require_native_initiated_connections = */ true, connection_id)); /* require_native_initiated_connections = */ true, connection_id,
""));
auto native_message_port = std::make_unique<extensions::NativeMessagePort>( auto native_message_port = std::make_unique<extensions::NativeMessagePort>(
message_service->GetChannelDelegate(), port_id, message_service->GetChannelDelegate(), port_id,
std::move(native_message_host)); std::move(native_message_host));
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <string> #include <string>
#include "base/macros.h" #include "base/macros.h"
#include "base/time/time.h"
class Profile; class Profile;
...@@ -40,6 +41,19 @@ class ScopedAllowNativeAppConnectionForTest { ...@@ -40,6 +41,19 @@ class ScopedAllowNativeAppConnectionForTest {
DISALLOW_COPY_AND_ASSIGN(ScopedAllowNativeAppConnectionForTest); DISALLOW_COPY_AND_ASSIGN(ScopedAllowNativeAppConnectionForTest);
}; };
class ScopedNativeMessagingErrorTimeoutOverrideForTest {
public:
explicit ScopedNativeMessagingErrorTimeoutOverrideForTest(
base::TimeDelta timeout);
~ScopedNativeMessagingErrorTimeoutOverrideForTest();
base::TimeDelta timeout() const { return timeout_; }
private:
const base::TimeDelta timeout_;
DISALLOW_COPY_AND_ASSIGN(ScopedNativeMessagingErrorTimeoutOverrideForTest);
};
} // namespace extensions } // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGING_LAUNCH_FROM_NATIVE_H_ #endif // CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGING_LAUNCH_FROM_NATIVE_H_
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <utility> #include <utility>
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_file_value_serializer.h" #include "base/json/json_file_value_serializer.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
...@@ -95,10 +96,19 @@ void ScopedTestNativeMessagingHost::RegisterTestHost(bool user_level) { ...@@ -95,10 +96,19 @@ void ScopedTestNativeMessagingHost::RegisterTestHost(bool user_level) {
temp_dir_.GetPath())); temp_dir_.GetPath()));
#endif #endif
base::CopyFile(test_user_data_dir.AppendASCII("echo.py"),
temp_dir_.GetPath().AppendASCII("echo.py"));
#if defined(OS_WIN)
base::FilePath host_path = temp_dir_.GetPath().AppendASCII("echo.bat");
base::CopyFile(test_user_data_dir.AppendASCII("echo.bat"), host_path);
#endif
#if defined(OS_POSIX) #if defined(OS_POSIX)
base::FilePath host_path = test_user_data_dir.AppendASCII("echo.py"); base::FilePath host_path = temp_dir_.GetPath().AppendASCII("echo.py");
#else ASSERT_TRUE(base::SetPosixFilePermissions(
base::FilePath host_path = test_user_data_dir.AppendASCII("echo.bat"); host_path, base::FILE_PERMISSION_READ_BY_USER |
base::FILE_PERMISSION_WRITE_BY_USER |
base::FILE_PERMISSION_EXECUTE_BY_USER));
#endif #endif
ASSERT_NO_FATAL_FAILURE(WriteTestNativeHostManifest( ASSERT_NO_FATAL_FAILURE(WriteTestNativeHostManifest(
temp_dir_.GetPath(), kHostName, host_path, user_level, false)); temp_dir_.GetPath(), kHostName, host_path, user_level, false));
......
...@@ -38,6 +38,8 @@ class ScopedTestNativeMessagingHost { ...@@ -38,6 +38,8 @@ class ScopedTestNativeMessagingHost {
void RegisterTestHost(bool user_level); void RegisterTestHost(bool user_level);
const base::FilePath& temp_dir() { return temp_dir_.GetPath(); }
private: private:
base::ScopedTempDir temp_dir_; base::ScopedTempDir temp_dir_;
......
...@@ -49,7 +49,8 @@ class NativeProcessLauncherImpl : public NativeProcessLauncher { ...@@ -49,7 +49,8 @@ class NativeProcessLauncherImpl : public NativeProcessLauncher {
intptr_t native_window, intptr_t native_window,
const base::FilePath& profile_directory, const base::FilePath& profile_directory,
bool require_native_initiated_connections, bool require_native_initiated_connections,
const std::string& connect_id); const std::string& connect_id,
const std::string& error_arg);
~NativeProcessLauncherImpl() override; ~NativeProcessLauncherImpl() override;
void Launch(const GURL& origin, void Launch(const GURL& origin,
...@@ -63,7 +64,8 @@ class NativeProcessLauncherImpl : public NativeProcessLauncher { ...@@ -63,7 +64,8 @@ class NativeProcessLauncherImpl : public NativeProcessLauncher {
intptr_t native_window, intptr_t native_window,
const base::FilePath& profile_directory, const base::FilePath& profile_directory,
bool require_native_initiated_connections, bool require_native_initiated_connections,
const std::string& connect_id); const std::string& connect_id,
const std::string& error_arg);
void Launch(const GURL& origin, void Launch(const GURL& origin,
const std::string& native_host_name, const std::string& native_host_name,
const LaunchedCallback& callback); const LaunchedCallback& callback);
...@@ -96,6 +98,8 @@ class NativeProcessLauncherImpl : public NativeProcessLauncher { ...@@ -96,6 +98,8 @@ class NativeProcessLauncherImpl : public NativeProcessLauncher {
const bool require_native_initiated_connections_; const bool require_native_initiated_connections_;
const std::string connect_id_; const std::string connect_id_;
const std::string error_arg_;
#if defined(OS_WIN) #if defined(OS_WIN)
// Handle of the native window corresponding to the extension. // Handle of the native window corresponding to the extension.
intptr_t window_handle_; intptr_t window_handle_;
...@@ -113,13 +117,15 @@ NativeProcessLauncherImpl::Core::Core(bool allow_user_level_hosts, ...@@ -113,13 +117,15 @@ NativeProcessLauncherImpl::Core::Core(bool allow_user_level_hosts,
intptr_t window_handle, intptr_t window_handle,
const base::FilePath& profile_directory, const base::FilePath& profile_directory,
bool require_native_initiated_connections, bool require_native_initiated_connections,
const std::string& connect_id) const std::string& connect_id,
const std::string& error_arg)
: detached_(false), : detached_(false),
allow_user_level_hosts_(allow_user_level_hosts), allow_user_level_hosts_(allow_user_level_hosts),
profile_directory_(profile_directory), profile_directory_(profile_directory),
require_native_initiated_connections_( require_native_initiated_connections_(
require_native_initiated_connections), require_native_initiated_connections),
connect_id_(connect_id) connect_id_(connect_id),
error_arg_(error_arg)
#if defined(OS_WIN) #if defined(OS_WIN)
, ,
window_handle_(window_handle) window_handle_(window_handle)
...@@ -234,8 +240,13 @@ void NativeProcessLauncherImpl::Core::DoLaunchOnThreadPool( ...@@ -234,8 +240,13 @@ void NativeProcessLauncherImpl::Core::DoLaunchOnThreadPool(
base::StringPrintf("--parent-window=%" PRIdPTR, window_handle_)); base::StringPrintf("--parent-window=%" PRIdPTR, window_handle_));
#endif // !defined(OS_WIN) #endif // !defined(OS_WIN)
if (manifest->supports_native_initiated_connections() && bool send_connect_id = false;
if (!error_arg_.empty()) {
send_connect_id = true;
command_line.AppendArg(error_arg_);
} else if (manifest->supports_native_initiated_connections() &&
!profile_directory_.empty()) { !profile_directory_.empty()) {
send_connect_id = true;
base::FilePath exe_path; base::FilePath exe_path;
base::PathService::Get(base::FILE_EXE, &exe_path); base::PathService::Get(base::FILE_EXE, &exe_path);
...@@ -267,12 +278,12 @@ void NativeProcessLauncherImpl::Core::DoLaunchOnThreadPool( ...@@ -267,12 +278,12 @@ void NativeProcessLauncherImpl::Core::DoLaunchOnThreadPool(
base::Base64Encode(encoded_reconnect_command, &encoded_reconnect_command); base::Base64Encode(encoded_reconnect_command, &encoded_reconnect_command);
command_line.AppendArg( command_line.AppendArg(
base::StrCat({"--reconnect-command=", encoded_reconnect_command})); base::StrCat({"--reconnect-command=", encoded_reconnect_command}));
}
if (!connect_id_.empty()) { if (send_connect_id && !connect_id_.empty()) {
command_line.AppendArg(base::StrCat( command_line.AppendArg(base::StrCat(
{"--", switches::kNativeMessagingConnectId, "=", connect_id_})); {"--", switches::kNativeMessagingConnectId, "=", connect_id_}));
} }
}
base::Process process; base::Process process;
base::File read_file; base::File read_file;
...@@ -327,12 +338,14 @@ NativeProcessLauncherImpl::NativeProcessLauncherImpl( ...@@ -327,12 +338,14 @@ NativeProcessLauncherImpl::NativeProcessLauncherImpl(
intptr_t window_handle, intptr_t window_handle,
const base::FilePath& profile_directory, const base::FilePath& profile_directory,
bool require_native_initiated_connections, bool require_native_initiated_connections,
const std::string& connect_id) const std::string& connect_id,
const std::string& error_arg)
: core_(base::MakeRefCounted<Core>(allow_user_level_hosts, : core_(base::MakeRefCounted<Core>(allow_user_level_hosts,
window_handle, window_handle,
profile_directory, profile_directory,
require_native_initiated_connections, require_native_initiated_connections,
connect_id)) {} connect_id,
error_arg)) {}
NativeProcessLauncherImpl::~NativeProcessLauncherImpl() { NativeProcessLauncherImpl::~NativeProcessLauncherImpl() {
core_->Detach(); core_->Detach();
...@@ -352,7 +365,8 @@ std::unique_ptr<NativeProcessLauncher> NativeProcessLauncher::CreateDefault( ...@@ -352,7 +365,8 @@ std::unique_ptr<NativeProcessLauncher> NativeProcessLauncher::CreateDefault(
gfx::NativeView native_view, gfx::NativeView native_view,
const base::FilePath& profile_directory, const base::FilePath& profile_directory,
bool require_native_initiated_connections, bool require_native_initiated_connections,
const std::string& connect_id) { const std::string& connect_id,
const std::string& error_arg) {
intptr_t window_handle = 0; intptr_t window_handle = 0;
#if defined(OS_WIN) #if defined(OS_WIN)
window_handle = reinterpret_cast<intptr_t>( window_handle = reinterpret_cast<intptr_t>(
...@@ -360,7 +374,7 @@ std::unique_ptr<NativeProcessLauncher> NativeProcessLauncher::CreateDefault( ...@@ -360,7 +374,7 @@ std::unique_ptr<NativeProcessLauncher> NativeProcessLauncher::CreateDefault(
#endif #endif
return std::make_unique<NativeProcessLauncherImpl>( return std::make_unique<NativeProcessLauncherImpl>(
allow_user_level_hosts, window_handle, profile_directory, allow_user_level_hosts, window_handle, profile_directory,
require_native_initiated_connections, connect_id); require_native_initiated_connections, connect_id, error_arg);
} }
} // namespace extensions } // namespace extensions
...@@ -47,12 +47,15 @@ class NativeProcessLauncher { ...@@ -47,12 +47,15 @@ class NativeProcessLauncher {
// the host. If |require_native_initiated_connections| is true, the connection // the host. If |require_native_initiated_connections| is true, the connection
// will be allowed only if the native messaging host sets // will be allowed only if the native messaging host sets
// "supports_native_initiated_connections" to true in its manifest. // "supports_native_initiated_connections" to true in its manifest.
// If |error_arg| is non-empty, the reconnect args are omitted, and instead
// the error value is passed as a command line argument to the host.
static std::unique_ptr<NativeProcessLauncher> CreateDefault( static std::unique_ptr<NativeProcessLauncher> CreateDefault(
bool allow_user_level_hosts, bool allow_user_level_hosts,
gfx::NativeView native_view, gfx::NativeView native_view,
const base::FilePath& profile_directory, const base::FilePath& profile_directory,
bool require_native_initiated_connections, bool require_native_initiated_connections,
const std::string& connect_id); const std::string& connect_id,
const std::string& error_arg);
NativeProcessLauncher() {} NativeProcessLauncher() {}
virtual ~NativeProcessLauncher() {} virtual ~NativeProcessLauncher() {}
......
...@@ -19,6 +19,9 @@ class ServiceWorkerMessagingTest : public ExtensionApiTest { ...@@ -19,6 +19,9 @@ class ServiceWorkerMessagingTest : public ExtensionApiTest {
ServiceWorkerMessagingTest() = default; ServiceWorkerMessagingTest() = default;
~ServiceWorkerMessagingTest() override = default; ~ServiceWorkerMessagingTest() override = default;
protected:
extensions::ScopedTestNativeMessagingHost test_host_;
private: private:
ScopedWorkerBasedExtensionsChannel current_channel_; ScopedWorkerBasedExtensionsChannel current_channel_;
...@@ -76,8 +79,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, TabToWorker) { ...@@ -76,8 +79,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, TabToWorker) {
// Tests chrome.runtime.sendNativeMessage from SW extension to a native // Tests chrome.runtime.sendNativeMessage from SW extension to a native
// messaging host. // messaging host.
IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, NativeMessagingBasic) { IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, NativeMessagingBasic) {
extensions::ScopedTestNativeMessagingHost test_host; ASSERT_NO_FATAL_FAILURE(test_host_.RegisterTestHost(false));
ASSERT_NO_FATAL_FAILURE(test_host.RegisterTestHost(false));
ASSERT_TRUE(RunExtensionTest("service_worker/messaging/send_native_message")) ASSERT_TRUE(RunExtensionTest("service_worker/messaging/send_native_message"))
<< message_; << message_;
} }
...@@ -85,8 +87,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, NativeMessagingBasic) { ...@@ -85,8 +87,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, NativeMessagingBasic) {
// Tests chrome.runtime.connectNative from SW extension to a native messaging // Tests chrome.runtime.connectNative from SW extension to a native messaging
// host. // host.
IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, ConnectNative) { IN_PROC_BROWSER_TEST_F(ServiceWorkerMessagingTest, ConnectNative) {
extensions::ScopedTestNativeMessagingHost test_host; ASSERT_NO_FATAL_FAILURE(test_host_.RegisterTestHost(false));
ASSERT_NO_FATAL_FAILURE(test_host.RegisterTestHost(false));
ASSERT_TRUE(RunExtensionTest("service_worker/messaging/connect_native")) ASSERT_TRUE(RunExtensionTest("service_worker/messaging/connect_native"))
<< message_; << message_;
} }
......
...@@ -13,6 +13,7 @@ import os ...@@ -13,6 +13,7 @@ import os
import platform import platform
import sys import sys
import struct import struct
import time
def WriteMessage(message): def WriteMessage(message):
try: try:
...@@ -29,6 +30,10 @@ def ParseArgs(): ...@@ -29,6 +30,10 @@ def ParseArgs():
parser.add_argument('--parent-window', type=int) parser.add_argument('--parent-window', type=int)
parser.add_argument('--reconnect-command') parser.add_argument('--reconnect-command')
parser.add_argument('--native-messaging-connect-id') parser.add_argument('--native-messaging-connect-id')
parser.add_argument('--extension-not-installed', action='store_true',
default=False)
parser.add_argument('--invalid-connect-id', action='store_true',
default=False)
parser.add_argument('origin') parser.add_argument('origin')
return parser.parse_args() return parser.parse_args()
...@@ -43,6 +48,25 @@ def Main(): ...@@ -43,6 +48,25 @@ def Main():
"URL of the calling application is not specified as the first arg.\n") "URL of the calling application is not specified as the first arg.\n")
return 1 return 1
if args.extension_not_installed:
with open('connect_id.txt', 'w') as f:
if args.reconnect_command:
f.write('Unexpected reconnect command: ' + args.reconnect_command)
else:
f.write('--connect-id=' + args.native_messaging_connect_id)
# The timeout in the test is 2 seconds, so sleep for longer than that to
# force a timeout.
time.sleep(5)
return 1
if args.invalid_connect_id:
with open('invalid_connect_id.txt', 'w') as f:
if args.reconnect_command:
f.write('Unexpected reconnect command: ' + args.reconnect_command)
else:
f.write('--invalid-connect-id')
return 1
# Verify that the process was started in the correct directory. # Verify that the process was started in the correct directory.
cwd = os.getcwd() cwd = os.getcwd()
script_path = os.path.dirname(os.path.abspath(sys.argv[0])) script_path = os.path.dirname(os.path.abspath(sys.argv[0]))
......
...@@ -51,6 +51,8 @@ std::ostream& operator<<(std::ostream& out, const KeepAliveOrigin& origin) { ...@@ -51,6 +51,8 @@ std::ostream& operator<<(std::ostream& out, const KeepAliveOrigin& origin) {
return out << "USER_MANAGER_VIEW"; return out << "USER_MANAGER_VIEW";
case KeepAliveOrigin::CREDENTIAL_PROVIDER_SIGNIN_DIALOG: case KeepAliveOrigin::CREDENTIAL_PROVIDER_SIGNIN_DIALOG:
return out << "CREDENTIAL_PROVIDER_SIGNIN_DIALOG"; return out << "CREDENTIAL_PROVIDER_SIGNIN_DIALOG";
case KeepAliveOrigin::NATIVE_MESSAGING_HOST_ERROR_REPORT:
return out << "NATIVE_MESSAGING_HOST_ERROR_REPORT";
} }
NOTREACHED(); NOTREACHED();
......
...@@ -31,6 +31,9 @@ enum class KeepAliveOrigin { ...@@ -31,6 +31,9 @@ enum class KeepAliveOrigin {
LOGIN_DISPLAY_HOST_WEBUI, LOGIN_DISPLAY_HOST_WEBUI,
PIN_MIGRATION, PIN_MIGRATION,
// c/b/extensions
NATIVE_MESSAGING_HOST_ERROR_REPORT,
// c/b/notifications // c/b/notifications
NOTIFICATION, NOTIFICATION,
PENDING_NOTIFICATION_CLICK_EVENT, PENDING_NOTIFICATION_CLICK_EVENT,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment